feat: add Resource type descriptions to the select box (#3091)

This should clarify that Resource is a safe for using private keys
inside them.

<img width="567" alt="image"
src="https://github.com/webstudio-is/webstudio/assets/52824/9c530ff5-3ca2-4aff-857b-225ac7cf95dd">



## Steps for reproduction

1. create a variable
2. hover over type options

## Code Review

- [ ] hi @TrySound , I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
This commit is contained in:
Oleg Isonen authored and GitHub committed 2024-04-04 16:36:21 +02:00
1 parent 49ac5dc032
commit b2ef61ea0a
2 files changed
+79 -55

No files matched your search

@@ -28,7 +28,6 @@ import {
ProBadge,
ScrollArea,
Select,
SelectItem,
Switch,
TextArea,
Tooltip,
@@ -48,7 +47,6 @@ import {
invalidateResource,
} from "~/shared/nano-states";
import { serverSyncStore } from "~/shared/sync";
import { humanizeString } from "~/shared/string-utils";
import {
useField,
type Field,
@@ -390,40 +388,57 @@ const VariablePanel = forwardRef<
}
return "string";
});
const typeOptions: VariableType[] = [
"string",
"number",
"boolean",
"json",
"resource",
];
const getTypeLabel = (value: VariableType) =>
value === "json" ? "JSON" : humanizeString(value);
const typeOptions: Map<
VariableType,
{ label: ReactNode; description: string }
> = new Map([
["string", { label: "String", description: "Any alphanumeric text." }],
[
"number",
{
label: "Number",
description: "Any number, can be used in math expressions.",
},
],
[
"boolean",
{ label: "Boolean", description: "A boolean is a true/false switch." },
],
["json", { label: "JSON", description: "Any JSON value" }],
[
"resource",
{
label: (
<Flex direction="row" gap="2" align="center">
Resource
{allowDynamicData === false && <ProBadge>Pro</ProBadge>}
</Flex>
),
description:
"A Resource is a configuration for secure data fetching. You can safely use secrets in any field.",
},
],
]);
const typeFieldElement = (
<Flex direction="column" css={{ gap: theme.spacing[3] }}>
<Flex direction="column" gap="1">
<Label>Type</Label>
<Select<VariableType>
options={typeOptions}
getLabel={getTypeLabel}
<Select
options={Array.from(typeOptions.keys())}
getLabel={(option: VariableType) => typeOptions.get(option)?.label}
getItemProps={(option) => ({
disabled: option === "resource" && allowDynamicData === false,
})}
getDescription={(option) => {
return (
<Box css={{ width: theme.spacing[25] }}>
{typeOptions.get(option)?.description}
</Box>
);
}}
value={type}
onChange={setType}
>
{typeOptions.map((option) => (
<SelectItem
key={option}
value={option}
textValue={getTypeLabel(option)}
disabled={option === "resource" && allowDynamicData === false}
>
{getTypeLabel(option)}
{option === "resource" && allowDynamicData === false && (
<Box css={{ display: "inline-block", ml: theme.spacing[3] }}>
<ProBadge>Pro</ProBadge>
</Box>
)}
</SelectItem>
))}
</Select>
/>
</Flex>
);
@@ -138,13 +138,16 @@ export type SelectProps<Option = SelectOption> = {
placeholder?: string;
children?: ReactNode;
getDescription?: (option: Option) => ReactNode | undefined;
getItemProps?: (
option: Option
) => Omit<ComponentProps<typeof SelectItem>, "children" | "value">;
} & (Option extends string
? {
getLabel?: (option: Option) => string | undefined;
getLabel?: (option: Option) => ReactNode | undefined;
getValue?: (option: Option) => string | undefined;
}
: {
getLabel: (option: Option) => string | undefined;
getLabel: (option: Option) => ReactNode | undefined;
getValue: (option: Option) => string | undefined;
}) &
TriggerPassThroughProps;
@@ -171,6 +174,7 @@ const SelectBase = <Option,>(
getLabel = defaultGetValue,
getValue = defaultGetValue,
getDescription,
getItemProps,
name,
children,
prefix,
@@ -225,27 +229,32 @@ const SelectBase = <Option,>(
<SelectViewport style={{ order: 1, maxHeight: rawTheme.spacing[34] }}>
{children ||
options.map((option) => (
<SelectItem
key={getValue(option)}
value={getValue(option) ?? ""}
textValue={getLabel(option)}
onMouseEnter={() => {
onItemHighlight?.(option);
setHighlightedItem(option);
}}
onMouseLeave={() => {
onItemHighlight?.();
setHighlightedItem(undefined);
}}
onFocus={() => {
onItemHighlight?.(option);
setHighlightedItem(option);
}}
>
{getLabel(option)}
</SelectItem>
))}
options.map((option, index) => {
const value = getValue(option) ?? "";
const { textValue, ...rest } = getItemProps?.(option) ?? {};
return (
<SelectItem
key={value ?? index}
value={value}
textValue={textValue ?? value}
onMouseEnter={() => {
onItemHighlight?.(option);
setHighlightedItem(option);
}}
onMouseLeave={() => {
onItemHighlight?.();
setHighlightedItem(undefined);
}}
onFocus={() => {
onItemHighlight?.(option);
setHighlightedItem(option);
}}
{...rest}
>
{getLabel(option)}
</SelectItem>
);
})}
</SelectViewport>
<SelectScrollDownButton css={{ order: 2 }}>