@baseline-ui/mcp 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/index.cjs +1799 -427
- package/dist/index.js +1799 -427
- package/package.json +1 -1
- package/sbom.json +65 -65
package/dist/index.js
CHANGED
|
@@ -2219,7 +2219,7 @@ isPrimaryActionDisabled?: boolean
|
|
|
2219
2219
|
* The props that are passed to the text input. If this is provided, a text
|
|
2220
2220
|
* input will be displayed at the bottom of the dialog.
|
|
2221
2221
|
*/
|
|
2222
|
-
textInputProps?:
|
|
2222
|
+
textInputProps?: SingleLineTextInputProps | MultiLineTextInputProps
|
|
2223
2223
|
/**
|
|
2224
2224
|
* The icon that is displayed at the top of the dialog. This is typically used
|
|
2225
2225
|
* to display an icon that represents the type of alert that is being shown.
|
|
@@ -3827,7 +3827,7 @@ children: React.ReactNode
|
|
|
3827
3827
|
"test": "cross-env BABEL_ENV=test jest",
|
|
3828
3828
|
"test:e2e": "cross-env BABEL_ENV=test jest --testPathPattern=e2e --testPathIgnorePatterns='examples,/packages/components/,/packages/react/'"
|
|
3829
3829
|
}
|
|
3830
|
-
}\`}</Code>;`}],implementation:""},similarTo:[],figmaUrl:null},ColorInput:{id:"core-forms-colorinput",breadcrumb:"Core/Forms/ColorInput",importStatement:'import { ColorInput, CustomTriggerButton, IndeterminateExample } from "@baseline-ui/core";',description:"`ColorInput` is a form control that opens a popover with preset swatches and a custom picker so users can choose or define a color. Use it when a user needs to pick a fill, stroke, highlight, or any color value, with optional alpha and persisted custom colors.",documentation:'`ColorInput` is a form control that opens a popover with preset swatches and a custom picker so users can choose or define a color. Use it when a user needs to pick a fill, stroke, highlight, or any color value, with optional alpha and persisted custom colors.\n\n* Includes custom color picker with color area, hue slider, and optional alpha slider\n* Supports alpha channel\n* Exposed to screen readers using ARIA attributes\n* Supports keyboard, touch and mouse interaction\n* Supports disabled and indeterminate states\n* Supports HEX and RGB color modes\n* Persists custom colors in local storage\n* Supports lazy picker mode for adding custom colors without live updates\n\n```jsx\nimport { ColorInput } from "@baseline-ui/core";\n\nconst presets = [\n { label: "Red", color: "#ff0000" },\n { label: "Green", color: "#00ff00" },\n { label: "Blue", color: "#0000ff" },\n { label: "Yellow", color: "#ffff00" },\n { label: "Cyan", color: "#00ffff" },\n { label: "Magenta", color: "#ff00ff" },\n { label: "Black", color: "#000000" },\n { label: "White", color: "#ffffff" },\n { label: "Gray", color: "#808080" },\n { label: "Orange", color: "#ffa500" },\n { label: "Brown", color: "#a52a2a" },\n { label: "Purple", color: "#800080" },\n];\n\n<ColorInput presets={presets} label="Color" />;\n```\n\nBy default, the label is placed above the trigger. Use `labelPosition="start"` to place it inline.\n\n```jsx\n<ColorInput\n presets={presets}\n label="Label"\n labelPosition="start"\n defaultValue="#ff0000"\n/>\n```\n\nHide the visible color name text next to the swatch by setting `colorLabel={false}`.\n\n```jsx\n<ColorInput presets={presets} colorLabel={false} aria-label="Color" />\n```\n\nShow only the preset list without the custom color picker by setting `includePicker={false}`.\n\n```jsx\n<ColorInput presets={presets} includePicker={false} label="Color" />\n```\n\nShow only the custom color picker without any presets.\n\n```jsx\n<ColorInput presets={[]} label="Color" />\n```\n\nYou can enable the alpha channel in the color picker by setting the `allowAlpha` prop to `true`.\n\n```jsx\n<ColorInput presets={presets} allowAlpha />\n```\n\nDisable the alpha slider by setting `allowAlpha={false}`.\n\n```jsx\n<ColorInput presets={presets} allowAlpha={false} label="Color" />\n```\n\n```jsx\n<ColorInput presets={presets} isDisabled label="Color" />\n```\n\nThe `ColorInput` component supports an indeterminate state. This is useful when you want to show a loading state or an unknown state. This property is always controlled and only makes a visual difference. If set to true, the color input trigger button will show "Indeterminate" as the color name. Apart from this, all the other functionality will work as expected.\n\n```jsx\n<ColorInput isIndeterminate presets={presets} />\n```\n\nBy default, you can add colors picked from the picker to the list of custom color presets. These are persisted in local storage under the key specified by the `storePickedColorKey` prop (defaults to `"baselinePickedColor"`). To use a separate storage key per instance, pass a unique value:\n\n```jsx\n<ColorInput storePickedColorKey="my-custom-key" />\n```\n\nBy default, you cannot unset the color. You can enable the ability to unset the color by setting the `allowRemoval` prop to `true`.\n\n```jsx\n<ColorInput presets={presets} allowRemoval />\n```\n\nYou can set the default color by setting the `defaultValue` prop to a color value.\n\n```jsx\n<ColorInput presets={presets} defaultValue="#ff0000" />\n```\n\nYou can make the `ColorInput` component controlled by setting the `value` prop to a color value. You can use the `onChange` prop to update the value.\n\n```jsx\n<ColorInput presets={presets} value="#ff0000" onChange={console.log} />\n```\n\nYou can use the `renderTriggerButton` prop to render a custom trigger.\n\n```jsx\n<ColorInput\n label="label"\n renderTriggerButton={({ colorName, ref, triggerProps }) => (\n <ActionIconButton\n {...triggerProps}\n aria-label={typeof colorName === "string" ? colorName : "Color"}\n icon={EllipseIcon}\n ref={ref}\n aria-haspopup="true"\n />\n )}\n/>\n```\n\nYou can use the `pickerMode="lazy"` prop to render the color picker only to add a custom color to the list of custom color presets. This is useful when you want to prevent the `onChange` event from firing while the user is picking a color from the picker. In case of mobile the picker opens in a modal.\n\n```jsx\n<ColorInput presets={presets} pickerMode="lazy" aria-label="Color" />\n```\n\nThe following CSS class selectors and data attributes are available for styling:\n\n| Selector | Description |\n| -------------------------------------------- | ------------------------------------------------------------------------- |\n| `.BaselineUI-ColorInput-Trigger` | The outer wrapper containing the label and trigger button |\n| `.BaselineUI-ColorInputButton` | The trigger button |\n| `.BaselineUI-ColorInput-Popover` | The popover container |\n| `.BaselineUI-ColorInput-ColorArea` | The color area (saturation/lightness) |\n| `.BaselineUI-ColorInput-ColorAreaThumb` | The draggable thumb on the color area |\n| `.BaselineUI-ColorInput-ColorSlider` | The hue/alpha slider |\n| `.BaselineUI-ColorInput-ColorSliderThumb` | The draggable thumb on a slider |\n| `.BaselineUI-ColorInput-FieldInput` | The hex/RGB text input |\n| `.BaselineUI-ColorInput-Presets` | The preset color list |\n| `.BaselineUI-ColorInput-CustomColors` | The custom colors header |\n| `.BaselineUI-ColorInput-CustomColorsListBox` | The custom colors list |\n| `[data-disabled]` | Applied when the button is disabled |\n| `[data-hovered]` | Applied when the button is hovered |\n| `[data-pressed]` | Applied when the button is pressed |\n| `[data-focus-visible]` | Applied when the button has keyboard focus |\n| `[data-color-mode="hexa"]` | Applied to hex field input when alpha is enabled |\n| `[data-color-mode="hex"]` | Applied to hex field input when alpha is disabled |\n| `[data-color-mode="rgba"]` | Applied to RGB field inputs when alpha is enabled |\n| `[data-color-mode="rgb"]` | Applied to RGB field inputs when alpha is disabled |\n| `[data-channel]` | Applied to color sliders, value is the channel name (e.g. `hue`, `alpha`) |\n\n| Key | Description |\n| ---------- | -------------------------------------------------------------------- |\n| Enter | Opens the popover or selects the focused color if popover is open |\n| Space | Opens the popover or selects the focused color if popover is open |\n| Escape | Closes the popover if open |\n| ArrowRight | Moves focus to the next preset color in the list |\n| ArrowLeft | Moves focus to the previous preset color in the list |\n| Tab | Moves focus between the color area, sliders, fields, and preset list |\n\nThe following strings are used by the `ColorInput` component and can be overridden via `I18nProvider`:\n\n| Key | Default (en) |\n| ------------------------------ | ---------------- |\n| `bui.colorInput.addColor` | Add Color |\n| `bui.colorInput.removeColor` | Remove Color |\n| `bui.colorInput.customColors` | Custom Colors |\n| `bui.colorInput.noColor` | None |\n| `bui.colorInput.transparent` | Transparent |\n| `bui.colorInput.add` | Add |\n| `bui.colorInput.cancel` | Cancel |\n| `bui.colorInput.colorFormat` | Color Format |\n| `bui.colorInput.colorPresets` | Color Presets |\n| `bui.colorInput.newColor` | New Custom Color |\n| `bui.colorInput.indeterminate` | Indeterminate |\n\n
|
|
3830
|
+
}\`}</Code>;`}],implementation:""},similarTo:[],figmaUrl:null},ColorInput:{id:"core-forms-colorinput",breadcrumb:"Core/Forms/ColorInput",importStatement:'import { ColorInput, CustomTriggerButton, IndeterminateExample } from "@baseline-ui/core";',description:"`ColorInput` is a form control that opens a popover with preset swatches and a custom picker so users can choose or define a color. Use it when a user needs to pick a fill, stroke, highlight, or any color value, with optional alpha and persisted custom colors.",documentation:'`ColorInput` is a form control that opens a popover with preset swatches and a custom picker so users can choose or define a color. Use it when a user needs to pick a fill, stroke, highlight, or any color value, with optional alpha and persisted custom colors.\n\n* Includes custom color picker with color area, hue slider, and optional alpha slider\n* Supports alpha channel\n* Exposed to screen readers using ARIA attributes\n* Supports keyboard, touch and mouse interaction\n* Supports disabled and indeterminate states\n* Supports HEX and RGB color modes\n* Persists custom colors in local storage\n* Supports lazy picker mode for adding custom colors without live updates\n\n```jsx\nimport { ColorInput } from "@baseline-ui/core";\n\nconst presets = [\n { label: "Red", color: "#ff0000" },\n { label: "Green", color: "#00ff00" },\n { label: "Blue", color: "#0000ff" },\n { label: "Yellow", color: "#ffff00" },\n { label: "Cyan", color: "#00ffff" },\n { label: "Magenta", color: "#ff00ff" },\n { label: "Black", color: "#000000" },\n { label: "White", color: "#ffffff" },\n { label: "Gray", color: "#808080" },\n { label: "Orange", color: "#ffa500" },\n { label: "Brown", color: "#a52a2a" },\n { label: "Purple", color: "#800080" },\n];\n\n<ColorInput presets={presets} label="Color" />;\n```\n\nBy default, the label is placed above the trigger. Use `labelPosition="start"` to place it inline.\n\n```jsx\n<ColorInput\n presets={presets}\n label="Label"\n labelPosition="start"\n defaultValue="#ff0000"\n/>\n```\n\nHide the visible color name text next to the swatch by setting `colorLabel={false}`.\n\n```jsx\n<ColorInput presets={presets} colorLabel={false} aria-label="Color" />\n```\n\nShow only the preset list without the custom color picker by setting `includePicker={false}`.\n\n```jsx\n<ColorInput presets={presets} includePicker={false} label="Color" />\n```\n\nShow only the custom color picker without any presets.\n\n```jsx\n<ColorInput presets={[]} label="Color" />\n```\n\nYou can enable the alpha channel in the color picker by setting the `allowAlpha` prop to `true`.\n\n```jsx\n<ColorInput presets={presets} allowAlpha />\n```\n\nDisable the alpha slider by setting `allowAlpha={false}`.\n\n```jsx\n<ColorInput presets={presets} allowAlpha={false} label="Color" />\n```\n\n```jsx\n<ColorInput presets={presets} isDisabled label="Color" />\n```\n\nThe `ColorInput` component supports an indeterminate state. This is useful when you want to show a loading state or an unknown state. This property is always controlled and only makes a visual difference. If set to true, the color input trigger button will show "Indeterminate" as the color name. Apart from this, all the other functionality will work as expected.\n\n```jsx\n<ColorInput isIndeterminate presets={presets} />\n```\n\nBy default, you can add colors picked from the picker to the list of custom color presets. These are persisted in local storage under the key specified by the `storePickedColorKey` prop (defaults to `"baselinePickedColor"`). To use a separate storage key per instance, pass a unique value:\n\n```jsx\n<ColorInput storePickedColorKey="my-custom-key" />\n```\n\nBy default, you cannot unset the color. You can enable the ability to unset the color by setting the `allowRemoval` prop to `true`.\n\n```jsx\n<ColorInput presets={presets} allowRemoval />\n```\n\nYou can set the default color by setting the `defaultValue` prop to a color value.\n\n```jsx\n<ColorInput presets={presets} defaultValue="#ff0000" />\n```\n\nYou can make the `ColorInput` component controlled by setting the `value` prop to a color value. You can use the `onChange` prop to update the value.\n\n```jsx\n<ColorInput presets={presets} value="#ff0000" onChange={console.log} />\n```\n\nYou can use the `renderTriggerButton` prop to render a custom trigger.\n\n```jsx\n<ColorInput\n label="label"\n renderTriggerButton={({ colorName, ref, triggerProps }) => (\n <ActionIconButton\n {...triggerProps}\n aria-label={typeof colorName === "string" ? colorName : "Color"}\n icon={EllipseIcon}\n ref={ref}\n aria-haspopup="true"\n />\n )}\n/>\n```\n\nYou can use the `pickerMode="lazy"` prop to render the color picker only to add a custom color to the list of custom color presets. This is useful when you want to prevent the `onChange` event from firing while the user is picking a color from the picker. In case of mobile the picker opens in a modal.\n\n```jsx\n<ColorInput presets={presets} pickerMode="lazy" aria-label="Color" />\n```\n\nThe following CSS class selectors and data attributes are available for styling:\n\n| Selector | Description |\n| -------------------------------------------- | ------------------------------------------------------------------------- |\n| `.BaselineUI-ColorInput-Trigger` | The outer wrapper containing the label and trigger button |\n| `.BaselineUI-ColorInputButton` | The trigger button |\n| `.BaselineUI-ColorInput-Popover` | The popover container |\n| `.BaselineUI-ColorInput-ColorArea` | The color area (saturation/lightness) |\n| `.BaselineUI-ColorInput-ColorAreaThumb` | The draggable thumb on the color area |\n| `.BaselineUI-ColorInput-ColorSlider` | The hue/alpha slider |\n| `.BaselineUI-ColorInput-ColorSliderThumb` | The draggable thumb on a slider |\n| `.BaselineUI-ColorInput-FieldInput` | The hex/RGB text input |\n| `.BaselineUI-ColorInput-Presets` | The preset color list |\n| `.BaselineUI-ColorInput-CustomColors` | The custom colors header |\n| `.BaselineUI-ColorInput-CustomColorsListBox` | The custom colors list |\n| `[data-disabled]` | Applied when the button is disabled |\n| `[data-hovered]` | Applied when the button is hovered |\n| `[data-pressed]` | Applied when the button is pressed |\n| `[data-focus-visible]` | Applied when the button has keyboard focus |\n| `[data-color-mode="hexa"]` | Applied to hex field input when alpha is enabled |\n| `[data-color-mode="hex"]` | Applied to hex field input when alpha is disabled |\n| `[data-color-mode="rgba"]` | Applied to RGB field inputs when alpha is enabled |\n| `[data-color-mode="rgb"]` | Applied to RGB field inputs when alpha is disabled |\n| `[data-channel]` | Applied to color sliders, value is the channel name (e.g. `hue`, `alpha`) |\n\n| Key | Description |\n| ---------- | -------------------------------------------------------------------- |\n| Enter | Opens the popover or selects the focused color if popover is open |\n| Space | Opens the popover or selects the focused color if popover is open |\n| Escape | Closes the popover if open |\n| ArrowRight | Moves focus to the next preset color in the list |\n| ArrowLeft | Moves focus to the previous preset color in the list |\n| Tab | Moves focus between the color area, sliders, fields, and preset list |\n\nThe following strings are used by the `ColorInput` component and can be overridden via `I18nProvider`:\n\n| Key | Default (en) |\n| ------------------------------ | ---------------- |\n| `bui.colorInput.addColor` | Add Color |\n| `bui.colorInput.removeColor` | Remove Color |\n| `bui.colorInput.customColors` | Custom Colors |\n| `bui.colorInput.noColor` | None |\n| `bui.colorInput.transparent` | Transparent |\n| `bui.colorInput.add` | Add |\n| `bui.colorInput.cancel` | Cancel |\n| `bui.colorInput.colorFormat` | Color Format |\n| `bui.colorInput.colorPresets` | Color Presets |\n| `bui.colorInput.newColor` | New Custom Color |\n| `bui.colorInput.indeterminate` | Indeterminate |\n\n```jsx\nimport { I18nProvider, ColorInput } from "@baseline-ui/core";\n\n<I18nProvider\n locale="en"\n messages={{\n en: {\n "bui.colorInput.addColor": "Pick a Color",\n "bui.colorInput.cancel": "Dismiss",\n },\n }}\n>\n <ColorInput />\n</I18nProvider>;\n```\n\nThe `IconColorInput` component is a wrapper around the `ColorInput` component that allows you to render an icon next to the color input. This basically overrides the `renderTriggerButton` prop of the `ColorInput` component to\nprovide a predefined trigger button with an icon.\n\n```jsx\nimport { IconColorInput } from "@baseline-ui/core";\nimport { BorderColorIcon } from "@baseline-ui/icons/24";\n\n<IconColorInput icon={BorderColorIcon} aria-label="Color Picker" />;\n```\n\nYou can use the `variant` prop to change the appearance of the `IconColorInput` component. The `variant` prop accepts the following values: `standard` and `compact`.\n\n```jsx\n<IconColorInput icon={BorderColorIcon} aria-label="Color Picker" isDisabled />\n```\n\nThe `IconColorInput` component supports adding tooltip to the trigger button which is enabled by default. The tooltip will be the same as the `aria-label` of the trigger button. If you want to disable the tooltip, you can set the `tooltip` and `iconTooltip` props to `false`.\n\nThe `ColorSwatch` component is used to display a color swatch. The `ColorSwatch` component is used in the `ColorInput` component to display the selected color.\n\n```jsx\nimport { ColorSwatch } from "@baseline-ui/core";\n\n<ColorSwatch color="#ff0000" />;\n```',props:`interface ColorInputProps {
|
|
3831
3831
|
/**
|
|
3832
3832
|
* Whether the overlay is open by default (controlled).
|
|
3833
3833
|
*/
|
|
@@ -3948,19 +3948,19 @@ storePickedColorKey?: string
|
|
|
3948
3948
|
/**
|
|
3949
3949
|
* The label to show on the add color button.
|
|
3950
3950
|
*
|
|
3951
|
-
* @default Add
|
|
3951
|
+
* @default Add Color
|
|
3952
3952
|
*/
|
|
3953
3953
|
addColorButtonLabel?: string
|
|
3954
3954
|
/**
|
|
3955
3955
|
* The label to show on the remove color button.
|
|
3956
3956
|
*
|
|
3957
|
-
* @default Remove
|
|
3957
|
+
* @default Remove Color
|
|
3958
3958
|
*/
|
|
3959
3959
|
removeColorButtonLabel?: string
|
|
3960
3960
|
/**
|
|
3961
3961
|
* The label to show on the custom colors section.
|
|
3962
3962
|
*
|
|
3963
|
-
* @default Custom
|
|
3963
|
+
* @default Custom Colors
|
|
3964
3964
|
*/
|
|
3965
3965
|
customColorsLabel?: string
|
|
3966
3966
|
/**
|
|
@@ -4695,7 +4695,10 @@ inputStyle?: React.CSSProperties
|
|
|
4695
4695
|
*/
|
|
4696
4696
|
inputClassName?: string
|
|
4697
4697
|
/**
|
|
4698
|
-
*
|
|
4698
|
+
* Accessible name for the toggle button. Not rendered visually.
|
|
4699
|
+
*
|
|
4700
|
+
* A blank string is treated as unset, keeping the built-in name. Setting this
|
|
4701
|
+
* overrides any \`aria-labelledby\` the toggle would otherwise inherit.
|
|
4699
4702
|
*/
|
|
4700
4703
|
toggleLabel?: string
|
|
4701
4704
|
filterItems?: boolean
|
|
@@ -4740,13 +4743,15 @@ filter?: ComboBoxStateOptions<ListItem>["defaultFilter"]
|
|
|
4740
4743
|
*/
|
|
4741
4744
|
inputType?: "text" | "number"
|
|
4742
4745
|
/**
|
|
4743
|
-
* The minimum value for the input field.
|
|
4744
|
-
*
|
|
4746
|
+
* The minimum value for the input field. Only applies when \`inputType="number"\`.
|
|
4747
|
+
*
|
|
4748
|
+
* Requires \`onValueChange\` or \`onInputSubmit\` to receive and apply the clamped value.
|
|
4745
4749
|
*/
|
|
4746
4750
|
minValue?: number
|
|
4747
4751
|
/**
|
|
4748
|
-
* The maximum value for the input field.
|
|
4749
|
-
*
|
|
4752
|
+
* The maximum value for the input field. Only applies when \`inputType="number"\`.
|
|
4753
|
+
*
|
|
4754
|
+
* Requires \`onValueChange\` or \`onInputSubmit\` to receive and apply the clamped value.
|
|
4750
4755
|
*/
|
|
4751
4756
|
maxValue?: number
|
|
4752
4757
|
/**
|
|
@@ -4754,7 +4759,17 @@ maxValue?: number
|
|
|
4754
4759
|
*/
|
|
4755
4760
|
onInputSubmit?: (value: string) => void
|
|
4756
4761
|
/**
|
|
4757
|
-
* Listener to call when the selected value changes
|
|
4762
|
+
* Listener to call when the selected value changes.
|
|
4763
|
+
*
|
|
4764
|
+
* Also called when the selected item's label changes after selection (e.g. the consumer
|
|
4765
|
+
* relabels the item, or an async collection resolves), so the reported \`value\` converges on
|
|
4766
|
+
* the item's current label once the field settles. While the user has unsubmitted text, a
|
|
4767
|
+
* label-only change is deferred; it is reported on the next selection, submit, or blur that
|
|
4768
|
+
* settles the input back onto the selection. With a controlled \`inputValue\` the consumer owns
|
|
4769
|
+
* that sync, so a deferred label is only reported once they settle the input themselves.
|
|
4770
|
+
*
|
|
4771
|
+
* Do not relabel the selected item from inside this callback \u2014 the new label re-triggers the
|
|
4772
|
+
* listener, which loops unless the relabel is idempotent.
|
|
4758
4773
|
*/
|
|
4759
4774
|
onValueChange?: (option: { value?: string; key?: string | null }) => void
|
|
4760
4775
|
}`,stories:{usage:[{id:"core-forms-combobox--basic",name:"Basic",snippet:`const Basic = () => <ComboBox
|
|
@@ -4965,7 +4980,33 @@ onValueChange?: (option: { value?: string; key?: string | null }) => void
|
|
|
4965
4980
|
defaultInputValue="42"
|
|
4966
4981
|
allowsCustomValue
|
|
4967
4982
|
inputType="number"
|
|
4968
|
-
minValue={0} />;`},{id:"core-forms-combobox--with-
|
|
4983
|
+
minValue={0} />;`},{id:"core-forms-combobox--with-min-max-value",name:"With Min Max Value",snippet:`const WithMinMaxValue = () => {
|
|
4984
|
+
const [inputValue, setInputValue] = React.useState("");
|
|
4985
|
+
|
|
4986
|
+
return (
|
|
4987
|
+
<ComboBox
|
|
4988
|
+
items={[
|
|
4989
|
+
{ id: "10", label: "10" },
|
|
4990
|
+
{ id: "25", label: "25" },
|
|
4991
|
+
{ id: "50", label: "50" },
|
|
4992
|
+
]}
|
|
4993
|
+
aria-label="ComboBox"
|
|
4994
|
+
label="Type a number outside 10-50 range and blur"
|
|
4995
|
+
description="Values are clamped to minValue=10, maxValue=50 on blur"
|
|
4996
|
+
placeholder="Enter a number"
|
|
4997
|
+
allowsCustomValue
|
|
4998
|
+
inputType="number"
|
|
4999
|
+
minValue={10}
|
|
5000
|
+
maxValue={50}
|
|
5001
|
+
inputValue={inputValue}
|
|
5002
|
+
onInputChange={setInputValue}
|
|
5003
|
+
onValueChange={({ value }) => {
|
|
5004
|
+
if (value !== undefined) {
|
|
5005
|
+
setInputValue(value);
|
|
5006
|
+
}
|
|
5007
|
+
}} />
|
|
5008
|
+
);
|
|
5009
|
+
};`},{id:"core-forms-combobox--with-custom-filter",name:"With Custom Filter",snippet:`const WithCustomFilter = () => <ComboBox
|
|
4969
5010
|
items={[
|
|
4970
5011
|
{ id: "pear", label: "Pear" },
|
|
4971
5012
|
{ id: "apple", label: "Apple" },
|
|
@@ -4996,6 +5037,8 @@ import { ComboBox } from "..";
|
|
|
4996
5037
|
import { Box } from "../../Box";
|
|
4997
5038
|
|
|
4998
5039
|
import type { ListItem, ListOption } from "../../shared/types/List";
|
|
5040
|
+
import type { ComboBoxProps } from "../ComboBox.types";
|
|
5041
|
+
import type { Key } from "react-aria";
|
|
4999
5042
|
|
|
5000
5043
|
export const items = [
|
|
5001
5044
|
{ id: "pears", label: "Pears" },
|
|
@@ -5076,6 +5119,114 @@ export const NumberComboBoxExample: React.FC<
|
|
|
5076
5119
|
);
|
|
5077
5120
|
};
|
|
5078
5121
|
|
|
5122
|
+
export const DynamicLabelComboBoxExample: React.FC<{
|
|
5123
|
+
onValueChange?: ComboBoxProps["onValueChange"];
|
|
5124
|
+
allowsCustomValue?: boolean;
|
|
5125
|
+
inputValue?: string;
|
|
5126
|
+
/** Relabels the selected item from "(selected)" to "(renamed)" when this exact text is typed. */
|
|
5127
|
+
relabelOnInput?: string;
|
|
5128
|
+
}> = ({ onValueChange, allowsCustomValue, inputValue, relabelOnInput }) => {
|
|
5129
|
+
const [value, setValue] = React.useState<Key | null>(null);
|
|
5130
|
+
// One-way: relabelling on every keystroke would feed the sync back into onInputChange and loop.
|
|
5131
|
+
const [isRelabelled, setIsRelabelled] = React.useState(false);
|
|
5132
|
+
|
|
5133
|
+
const suffix = isRelabelled ? "(renamed)" : "(selected)";
|
|
5134
|
+
const dynamicItems = items.map((item) =>
|
|
5135
|
+
item.id === value ? { ...item, label: \`\${item.label} \${suffix}\` } : item,
|
|
5136
|
+
);
|
|
5137
|
+
|
|
5138
|
+
return (
|
|
5139
|
+
<Box style={{ width: "100%", height: 200 }}>
|
|
5140
|
+
<ComboBox
|
|
5141
|
+
items={dynamicItems}
|
|
5142
|
+
aria-label="Combo box"
|
|
5143
|
+
value={value}
|
|
5144
|
+
onChange={setValue}
|
|
5145
|
+
onValueChange={onValueChange}
|
|
5146
|
+
allowsCustomValue={allowsCustomValue}
|
|
5147
|
+
inputValue={inputValue}
|
|
5148
|
+
onInputChange={(text) => {
|
|
5149
|
+
if (text === relabelOnInput) {
|
|
5150
|
+
setIsRelabelled(true);
|
|
5151
|
+
}
|
|
5152
|
+
}}
|
|
5153
|
+
/>
|
|
5154
|
+
<span data-testid="relabel-probe">
|
|
5155
|
+
{dynamicItems.find((item) => item.id === value)?.label ?? ""}
|
|
5156
|
+
</span>
|
|
5157
|
+
</Box>
|
|
5158
|
+
);
|
|
5159
|
+
};
|
|
5160
|
+
|
|
5161
|
+
export const AsyncItemsComboBoxExample: React.FC<{
|
|
5162
|
+
initiallyLoaded?: boolean;
|
|
5163
|
+
onValueChange?: ComboBoxProps["onValueChange"];
|
|
5164
|
+
allowsCustomValue?: boolean;
|
|
5165
|
+
/** Unloads and reloads the items when this exact text is typed, without moving focus. */
|
|
5166
|
+
refreshOnInput?: string;
|
|
5167
|
+
}> = ({
|
|
5168
|
+
initiallyLoaded = true,
|
|
5169
|
+
onValueChange,
|
|
5170
|
+
allowsCustomValue,
|
|
5171
|
+
refreshOnInput,
|
|
5172
|
+
}) => {
|
|
5173
|
+
const [loadState, setLoadState] = React.useState<
|
|
5174
|
+
"loaded" | "unloaded" | "refreshing"
|
|
5175
|
+
>(initiallyLoaded ? "loaded" : "unloaded");
|
|
5176
|
+
const [refreshCount, setRefreshCount] = React.useState(0);
|
|
5177
|
+
const [value, setValue] = React.useState<Key | null>(
|
|
5178
|
+
initiallyLoaded ? null : "pears",
|
|
5179
|
+
);
|
|
5180
|
+
const isLoaded = loadState === "loaded";
|
|
5181
|
+
|
|
5182
|
+
// The unloaded collection must reach the DOM for a render before the items come back,
|
|
5183
|
+
// otherwise there is no transient for the refresh to be mistaken for a new selection.
|
|
5184
|
+
React.useEffect(() => {
|
|
5185
|
+
if (loadState === "refreshing") {
|
|
5186
|
+
setLoadState("loaded");
|
|
5187
|
+
setRefreshCount((count) => count + 1);
|
|
5188
|
+
}
|
|
5189
|
+
}, [loadState]);
|
|
5190
|
+
|
|
5191
|
+
return (
|
|
5192
|
+
<Box style={{ width: "100%", height: 200 }}>
|
|
5193
|
+
<ComboBox
|
|
5194
|
+
items={isLoaded ? items : []}
|
|
5195
|
+
aria-label="Combo box"
|
|
5196
|
+
value={value}
|
|
5197
|
+
onChange={setValue}
|
|
5198
|
+
onValueChange={onValueChange}
|
|
5199
|
+
allowsCustomValue={allowsCustomValue}
|
|
5200
|
+
onInputChange={(text) => {
|
|
5201
|
+
if (text === refreshOnInput) {
|
|
5202
|
+
setLoadState("refreshing");
|
|
5203
|
+
}
|
|
5204
|
+
}}
|
|
5205
|
+
/>
|
|
5206
|
+
<button
|
|
5207
|
+
type="button"
|
|
5208
|
+
onClick={() => {
|
|
5209
|
+
setLoadState((state) => (state === "loaded" ? "unloaded" : "loaded"));
|
|
5210
|
+
}}
|
|
5211
|
+
>
|
|
5212
|
+
{isLoaded ? "Unload items" : "Load items"}
|
|
5213
|
+
</button>
|
|
5214
|
+
<span data-testid="refresh-probe">{refreshCount}</span>
|
|
5215
|
+
</Box>
|
|
5216
|
+
);
|
|
5217
|
+
};
|
|
5218
|
+
|
|
5219
|
+
export const LabelledByComboBoxExample: React.FC<
|
|
5220
|
+
Omit<React.ComponentProps<typeof ComboBox>, "items" | "aria-labelledby">
|
|
5221
|
+
> = (args) => {
|
|
5222
|
+
return (
|
|
5223
|
+
<Box style={{ width: "100%", height: 200 }}>
|
|
5224
|
+
<span id="external-label">External</span>
|
|
5225
|
+
<ComboBox items={items} {...args} aria-labelledby="external-label" />
|
|
5226
|
+
</Box>
|
|
5227
|
+
);
|
|
5228
|
+
};
|
|
5229
|
+
|
|
5079
5230
|
export const SectionComboBoxExample: React.FC = () => {
|
|
5080
5231
|
return (
|
|
5081
5232
|
<Box style={{ width: "100%", height: 300 }}>
|
|
@@ -7710,6 +7861,10 @@ children?: ReactNode
|
|
|
7710
7861
|
* Enables the selection of directories instead of individual files.
|
|
7711
7862
|
*/
|
|
7712
7863
|
acceptDirectory?: boolean
|
|
7864
|
+
/**
|
|
7865
|
+
* The id applied to the root element of the component.
|
|
7866
|
+
*/
|
|
7867
|
+
id?: string
|
|
7713
7868
|
/**
|
|
7714
7869
|
* The className applied to the root element of the component.
|
|
7715
7870
|
*/
|
|
@@ -8005,6 +8160,7 @@ disabledKeys?: Iterable<string> | "all"
|
|
|
8005
8160
|
);
|
|
8006
8161
|
};`}],implementation:`import React from "react";
|
|
8007
8162
|
|
|
8163
|
+
import { ActionButton } from "../../ActionButton";
|
|
8008
8164
|
import { FileList } from "../FileList";
|
|
8009
8165
|
|
|
8010
8166
|
import type { FileListItem } from "../FileList.types";
|
|
@@ -8059,6 +8215,32 @@ export const manyItems: FileListItem[] = Array.from({ length: 12 }, (_, i) => ({
|
|
|
8059
8215
|
name: \`attachment-\${i + 1}.pdf\`,
|
|
8060
8216
|
}));
|
|
8061
8217
|
|
|
8218
|
+
// Swaps in a new array whose items carry new content, which is the only way a caller can
|
|
8219
|
+
// legitimately invalidate the memoised options.
|
|
8220
|
+
export const UploadingFileList: React.FC = () => {
|
|
8221
|
+
const [items, setItems] = React.useState<FileListItem[]>(loadingItems);
|
|
8222
|
+
|
|
8223
|
+
return (
|
|
8224
|
+
<>
|
|
8225
|
+
<ActionButton
|
|
8226
|
+
label="Finish upload"
|
|
8227
|
+
onPress={() => {
|
|
8228
|
+
setItems((prev) =>
|
|
8229
|
+
prev.map((item) => ({ ...item, isLoading: false })),
|
|
8230
|
+
);
|
|
8231
|
+
}}
|
|
8232
|
+
/>
|
|
8233
|
+
<FileList
|
|
8234
|
+
aria-label="Uploaded files"
|
|
8235
|
+
items={items}
|
|
8236
|
+
onRemove={(id) => {
|
|
8237
|
+
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
8238
|
+
}}
|
|
8239
|
+
/>
|
|
8240
|
+
</>
|
|
8241
|
+
);
|
|
8242
|
+
};
|
|
8243
|
+
|
|
8062
8244
|
interface BasicProps {
|
|
8063
8245
|
onRemove?: (id: string) => void;
|
|
8064
8246
|
disabledKeys?: Iterable<string> | "all";
|
|
@@ -9847,7 +10029,12 @@ children: React.ReactNode
|
|
|
9847
10029
|
locale?: string
|
|
9848
10030
|
messages?: LocalizedStrings
|
|
9849
10031
|
/**
|
|
9850
|
-
*
|
|
10032
|
+
* Whether to \`console.warn\` about message ids that resolve through the
|
|
10033
|
+
* deprecated bare-id fallback or fall all the way through to their
|
|
10034
|
+
* \`defaultMessage\`. These warnings are development guidance, so they are off
|
|
10035
|
+
* in production builds \u2014 pass \`true\` to opt back in.
|
|
10036
|
+
*
|
|
10037
|
+
* @default process.env.NODE_ENV !== "production"
|
|
9851
10038
|
*/
|
|
9852
10039
|
shouldLogMissingMessages?: boolean
|
|
9853
10040
|
}`,stories:{usage:[{id:"core-utilities-i18nprovider--string-format",name:"String Format",snippet:`const StringFormat = ({ children }) => {
|
|
@@ -9987,7 +10174,6 @@ The following strings are used by the \`ImageDropZone\` component and can be ove
|
|
|
9987
10174
|
| Key | Default (en) |
|
|
9988
10175
|
| ------------------------------- | ------------ |
|
|
9989
10176
|
| \`bui.imageDropZone.selectImage\` | Select Image |
|
|
9990
|
-
| \`bui.imageDropZone.delete\` | Delete |
|
|
9991
10177
|
|
|
9992
10178
|
\`\`\`jsx
|
|
9993
10179
|
import { I18nProvider, ImageDropZone } from "@baseline-ui/core";
|
|
@@ -9997,7 +10183,6 @@ import { I18nProvider, ImageDropZone } from "@baseline-ui/core";
|
|
|
9997
10183
|
messages={{
|
|
9998
10184
|
en: {
|
|
9999
10185
|
"bui.imageDropZone.selectImage": "Choose Image",
|
|
10000
|
-
"bui.imageDropZone.delete": "Remove",
|
|
10001
10186
|
},
|
|
10002
10187
|
}}
|
|
10003
10188
|
>
|
|
@@ -10420,6 +10605,8 @@ renderImage?: (
|
|
|
10420
10605
|
imageContainerStyle?: React.CSSProperties
|
|
10421
10606
|
/**
|
|
10422
10607
|
* The dimensions of the image.
|
|
10608
|
+
*
|
|
10609
|
+
* @default { width: imageWidth, aspectRatio }
|
|
10423
10610
|
*/
|
|
10424
10611
|
imageDimensions?: | Dimension
|
|
10425
10612
|
| ((
|
|
@@ -10878,6 +11065,35 @@ export function ScrollIntoViewImageGalleryExample() {
|
|
|
10878
11065
|
);
|
|
10879
11066
|
}
|
|
10880
11067
|
|
|
11068
|
+
// Counts \`renderImage\` calls so a spec can prove that a re-render which changes nothing
|
|
11069
|
+
// the gallery reads does not throw away the list box's cached options. \`Report\` publishes
|
|
11070
|
+
// the tally taken *before* its own render, so two clicks bracket exactly one re-render.
|
|
11071
|
+
export function RenderCountingImageGalleryExample() {
|
|
11072
|
+
const calls = React.useRef(0);
|
|
11073
|
+
const [reported, setReported] = React.useState(0);
|
|
11074
|
+
|
|
11075
|
+
const renderImage = React.useCallback<
|
|
11076
|
+
Exclude<React.ComponentProps<typeof ImageGallery>["renderImage"], undefined>
|
|
11077
|
+
>((item) => {
|
|
11078
|
+
calls.current += 1;
|
|
11079
|
+
|
|
11080
|
+
return <img src={item.data?.src} alt={item.data?.alt} />;
|
|
11081
|
+
}, []);
|
|
11082
|
+
|
|
11083
|
+
return (
|
|
11084
|
+
<Box display="flex" flexDirection="column" gap="lg">
|
|
11085
|
+
<ActionButton
|
|
11086
|
+
label="Report"
|
|
11087
|
+
onPress={() => {
|
|
11088
|
+
setReported(calls.current);
|
|
11089
|
+
}}
|
|
11090
|
+
/>
|
|
11091
|
+
<Text data-testid="render-count">{reported.toString()}</Text>
|
|
11092
|
+
<ImageGallery defaultItems={items} renderImage={renderImage} />
|
|
11093
|
+
</Box>
|
|
11094
|
+
);
|
|
11095
|
+
}
|
|
11096
|
+
|
|
10881
11097
|
export function RTLImageGalleryExample(
|
|
10882
11098
|
props: Omit<React.ComponentProps<typeof ImageGallery>, "onDelete">,
|
|
10883
11099
|
) {
|
|
@@ -12183,10 +12399,13 @@ renderDragPreview?: (items: DragItem[]) => React.JSX.Element
|
|
|
12183
12399
|
*
|
|
12184
12400
|
* @param section ListSection
|
|
12185
12401
|
* @param ref React.RefObject<HTMLDivElement>
|
|
12402
|
+
* @param headingProps ARIA props for the heading element \u2014 spread these onto the header's
|
|
12403
|
+
* root (and attach \`ref\`) so the section group's \`aria-labelledby\` resolves to it.
|
|
12186
12404
|
*/
|
|
12187
12405
|
renderSectionHeader?: (
|
|
12188
12406
|
section: Node<ListItem>,
|
|
12189
12407
|
ref: React.Ref<HTMLSpanElement>,
|
|
12408
|
+
headingProps?: React.HTMLAttributes<HTMLElement>,
|
|
12190
12409
|
) => React.ReactNode
|
|
12191
12410
|
/**
|
|
12192
12411
|
* Whether to show the selected checkmark icon.
|
|
@@ -12879,27 +13098,45 @@ console.log(greet('Markdown Maverick'));
|
|
|
12879
13098
|
2. Selection options: The component can be configured to allow single, multiple, or no selection.
|
|
12880
13099
|
3. Disabled items support: Certain menu items can be disabled, preventing user interaction.
|
|
12881
13100
|
4. Sections support: Related items can be grouped into sections for better organization and navigation.
|
|
12882
|
-
5.
|
|
12883
|
-
6.
|
|
12884
|
-
7.
|
|
12885
|
-
8.
|
|
12886
|
-
9.
|
|
13101
|
+
5. Submenus: Any option can nest an \`items\` array to open a cascading submenu of arbitrary depth.
|
|
13102
|
+
6. Keyboard navigation: Users can navigate through the menu using their keyboard, including arrow keys, home/end, and page up/down.
|
|
13103
|
+
7. Auto-scroll: The menu automatically scrolls as the user navigates through it with their keyboard.
|
|
13104
|
+
8. Keyboard menu opening: The menu can be opened using the keyboard, and automatically focuses on the first or last item.
|
|
13105
|
+
9. Typeahead: Users can quickly navigate to a menu item by typing the first few letters of the item's label.
|
|
13106
|
+
10. Virtualized scrolling: For long lists, performance is improved by only rendering the visible items.
|
|
13107
|
+
|
|
13108
|
+
Pass the list of options via \`items\` and a \`triggerLabel\` for the default
|
|
13109
|
+
\`ActionButton\` trigger. \`Menu\` renders its own trigger and popover \u2014 it does not
|
|
13110
|
+
take children.
|
|
12887
13111
|
|
|
12888
13112
|
\`\`\`jsx
|
|
12889
|
-
import {
|
|
12890
|
-
import { Menu } from "@storybook/addon-docs/blocks";
|
|
13113
|
+
import { Menu } from "@baseline-ui/core";
|
|
12891
13114
|
|
|
12892
13115
|
const items = [
|
|
12893
|
-
{
|
|
12894
|
-
label: "
|
|
12895
|
-
id: "
|
|
12896
|
-
keyboardShortcut: "\u2318X",
|
|
12897
|
-
},
|
|
13116
|
+
{ id: "cut", label: "Cut", keyboardShortcut: "\u2318X" },
|
|
13117
|
+
{ id: "copy", label: "Copy", keyboardShortcut: "\u2318C" },
|
|
13118
|
+
{ id: "paste", label: "Paste", keyboardShortcut: "\u2318V" },
|
|
12898
13119
|
];
|
|
12899
13120
|
|
|
12900
|
-
|
|
12901
|
-
<
|
|
12902
|
-
|
|
13121
|
+
export default function App() {
|
|
13122
|
+
return <Menu items={items} triggerLabel="Edit" onAction={(id) => {}} />;
|
|
13123
|
+
}
|
|
13124
|
+
\`\`\`
|
|
13125
|
+
|
|
13126
|
+
To render a custom trigger, pass \`renderTrigger\` instead of \`triggerLabel\`. If
|
|
13127
|
+
you need on/off state rather than a command list, use \`ToggleButton\`; to pick a
|
|
13128
|
+
value from a set with an always-visible field, use \`Select\`.
|
|
13129
|
+
|
|
13130
|
+
Each option accepts an optional leading \`icon\` (a \`@baseline-ui/icons\` component)
|
|
13131
|
+
and a \`keyboardShortcut\` string rendered at the trailing edge of the item.
|
|
13132
|
+
|
|
13133
|
+
\`\`\`jsx
|
|
13134
|
+
import { CopyIcon, TrashIcon } from "@baseline-ui/icons/16";
|
|
13135
|
+
|
|
13136
|
+
const items = [
|
|
13137
|
+
{ id: "copy", label: "Copy", keyboardShortcut: "\u2318C", icon: CopyIcon },
|
|
13138
|
+
{ id: "delete", label: "Delete", keyboardShortcut: "\u232B", icon: TrashIcon },
|
|
13139
|
+
];
|
|
12903
13140
|
\`\`\`
|
|
12904
13141
|
|
|
12905
13142
|
The \`Menu\` component can be configured to allow single, multiple, or no selection. The default is no selection. To allow single selection, set the \`selectionMode\` prop to \`single\`. To allow multiple selection, set the \`selectionMode\` prop to \`multiple\`.
|
|
@@ -12927,9 +13164,93 @@ const items = [
|
|
|
12927
13164
|
];
|
|
12928
13165
|
\`\`\`
|
|
12929
13166
|
|
|
12930
|
-
|
|
13167
|
+
Pass the object form of \`selectionMode\` to make individual sections independent
|
|
13168
|
+
selection groups. \`selectedKeys\` and \`defaultSelectedKeys\` are then keyed by
|
|
13169
|
+
section id, and \`onSelectionChange\` receives the changed section's selection
|
|
13170
|
+
plus its \`sectionId\`.
|
|
13171
|
+
|
|
13172
|
+
\`\`\`tsx
|
|
13173
|
+
<Menu
|
|
13174
|
+
items={itemsWithSections}
|
|
13175
|
+
selectionMode={{ edit: "single", theme: "multiple" }}
|
|
13176
|
+
selectedKeys={{ edit: editKeys, theme: themeKeys }}
|
|
13177
|
+
onSelectionChange={(keys, meta) => {
|
|
13178
|
+
if (meta) setSelection((prev) => ({ ...prev, [meta.sectionId]: keys }));
|
|
13179
|
+
}}
|
|
13180
|
+
/>
|
|
13181
|
+
\`\`\`
|
|
13182
|
+
|
|
13183
|
+
Menu-wide selection (a string \`selectionMode\`) and per-section selection are
|
|
13184
|
+
mutually exclusive within one menu. Enter activation closes the menu. Pointer
|
|
13185
|
+
activation closes single-select menus and keeps multi-select menus open, while
|
|
13186
|
+
Space activation keeps both selection modes open.
|
|
13187
|
+
|
|
13188
|
+
Give any option an \`items\` array to turn it into a submenu trigger. The option
|
|
13189
|
+
renders with a trailing chevron and opens a nested menu on hover or when
|
|
13190
|
+
activated with \`ArrowRight\` / \`Enter\`. Submenus nest arbitrarily and may
|
|
13191
|
+
themselves contain leaf options, sections, or deeper submenus.
|
|
13192
|
+
|
|
13193
|
+
\`\`\`jsx
|
|
13194
|
+
const items = [
|
|
13195
|
+
{ id: "new", label: "New" },
|
|
13196
|
+
{
|
|
13197
|
+
id: "share",
|
|
13198
|
+
label: "Share",
|
|
13199
|
+
items: [
|
|
13200
|
+
{ id: "email", label: "Email link" },
|
|
13201
|
+
{ id: "sms", label: "SMS" },
|
|
13202
|
+
{
|
|
13203
|
+
id: "more",
|
|
13204
|
+
label: "More services",
|
|
13205
|
+
items: [
|
|
13206
|
+
{ id: "slack", label: "Slack" },
|
|
13207
|
+
{ id: "teams", label: "Teams" },
|
|
13208
|
+
],
|
|
13209
|
+
},
|
|
13210
|
+
],
|
|
13211
|
+
},
|
|
13212
|
+
];
|
|
13213
|
+
\`\`\`
|
|
13214
|
+
|
|
13215
|
+
\`onAction\` fires for the activated leaf at any depth (with that leaf's \`id\`);
|
|
13216
|
+
activating a submenu trigger does not fire \`onAction\`. Selecting a leaf closes
|
|
13217
|
+
the whole cascade. A single flat \`disabledKeys\` array disables triggers and
|
|
13218
|
+
nested items at any level. In RTL locales the chevron and the submenu's opening
|
|
13219
|
+
direction flip automatically.
|
|
13220
|
+
|
|
13221
|
+
Selection can be controlled or uncontrolled. When uncontrolled, the component manages its own state internally via \`defaultSelectedKeys\`. To control it, pass \`selectedKeys\` and handle \`onSelectionChange\`. The keys must match the \`id\` of the items. See the [Single Selection](#single-selection) example above.
|
|
13222
|
+
|
|
13223
|
+
The open state can likewise be controlled or uncontrolled. When uncontrolled, use \`defaultOpen\`; to control it, pass \`isOpen\` and handle \`onOpenChange\`.
|
|
13224
|
+
|
|
13225
|
+
Each menu item exposes the standard React Aria interaction-state attributes, and Baseline UI adds class hooks on the trigger, popover, and item subparts.
|
|
12931
13226
|
|
|
12932
|
-
|
|
13227
|
+
| Selector | Description |
|
|
13228
|
+
| ---------------------------------- | ------------------------------------------------------- |
|
|
13229
|
+
| \\[data-focused] | Whether the item is focused. |
|
|
13230
|
+
| \\[data-focus-visible] | Whether the item is keyboard focused. |
|
|
13231
|
+
| \\[data-hovered] | Whether the item is currently hovered with a mouse. |
|
|
13232
|
+
| \\[data-pressed] | Whether the item is currently pressed. |
|
|
13233
|
+
| \\[data-selected] | Whether the item is selected (selection modes). |
|
|
13234
|
+
| \\[data-disabled] | Whether the item is disabled. |
|
|
13235
|
+
| \\[data-has-submenu] | Whether the item opens a submenu. |
|
|
13236
|
+
| \\[data-open] | Whether the item's submenu is open. |
|
|
13237
|
+
| .BaselineUI-Menu-Trigger | The trigger button. |
|
|
13238
|
+
| .BaselineUI-Menu-Popover | The root popover container. |
|
|
13239
|
+
| .BaselineUI-Menu-SubmenuPopover | A nested submenu popover container. |
|
|
13240
|
+
| .BaselineUI-Menu-SubmenuChevron | The trailing chevron on a submenu trigger. |
|
|
13241
|
+
| .BaselineUI-Menu-OptionDescription | The trailing text of an item (e.g. \`keyboardShortcut\`). |
|
|
13242
|
+
|
|
13243
|
+
| Key | Function |
|
|
13244
|
+
| --------------------- | ---------------------------------------------------------------------------------- |
|
|
13245
|
+
| \`Enter\` / \`Space\` | Opens the menu from the trigger; activates the focused item. |
|
|
13246
|
+
| \`ArrowDown\` | Opens the menu focusing the first item; moves focus down. |
|
|
13247
|
+
| \`ArrowUp\` | Opens the menu focusing the last item; moves focus up. |
|
|
13248
|
+
| \`Home\` / \`End\` | Moves focus to the first / last item. |
|
|
13249
|
+
| \`PageUp\` / \`PageDown\` | Moves focus up / down by a page. |
|
|
13250
|
+
| \`A\`\u2013\`Z\` | Typeahead \u2014 focuses the next item starting with the typed letters. |
|
|
13251
|
+
| \`ArrowRight\` | Opens the focused submenu (\`ArrowLeft\` in RTL). |
|
|
13252
|
+
| \`ArrowLeft\` | Closes the current submenu and returns focus to its trigger (\`ArrowRight\` in RTL). |
|
|
13253
|
+
| \`Escape\` | Closes the menu (or the current submenu level). |`,props:`interface MenuProps {
|
|
12933
13254
|
/**
|
|
12934
13255
|
* Whether the overlay is open by default (controlled).
|
|
12935
13256
|
*/
|
|
@@ -12961,39 +13282,18 @@ contentClassName?: string
|
|
|
12961
13282
|
*/
|
|
12962
13283
|
itemClassName?: string
|
|
12963
13284
|
/**
|
|
12964
|
-
* A list of items to render in the menu.
|
|
12965
|
-
*
|
|
12966
|
-
* \`\`\`ts
|
|
12967
|
-
* export type MenuOption = {
|
|
12968
|
-
* id: string;
|
|
12969
|
-
* label: string;
|
|
12970
|
-
* keyboardShortcut?: string;
|
|
12971
|
-
* icon?: React.FC<IconProps>;
|
|
12972
|
-
* };
|
|
12973
|
-
*
|
|
12974
|
-
* export type MenuSection = {
|
|
12975
|
-
* id: string;
|
|
12976
|
-
* title?: string;
|
|
12977
|
-
* type: "section";
|
|
12978
|
-
* children: MenuOption[];
|
|
12979
|
-
* };
|
|
13285
|
+
* A list of items to render in the menu. See \`MenuItem\`.
|
|
12980
13286
|
*
|
|
12981
|
-
*
|
|
12982
|
-
*
|
|
13287
|
+
* A \`MenuSection\` may opt into independent selection by listing its id in the
|
|
13288
|
+
* object form of \`selectionMode\` (e.g. \`selectionMode={{ view: "single" }}\`).
|
|
12983
13289
|
*/
|
|
12984
13290
|
items: MenuItem[]
|
|
12985
13291
|
/**
|
|
12986
13292
|
* A function that renders the trigger element of the component. The default
|
|
12987
13293
|
* implementation renders an \`ActionButton\` component.
|
|
12988
|
-
*
|
|
12989
|
-
* \`\`\`tsx
|
|
12990
|
-
* <Menu renderTrigger={({ buttonProps, ref }) => <ActionButton {...buttonProps} label="Label" ref={ref} />
|
|
12991
|
-
* \`\`\`
|
|
12992
13294
|
*/
|
|
12993
13295
|
renderTrigger?: (options: {
|
|
12994
|
-
buttonProps: ActionButtonProps & {
|
|
12995
|
-
isOpen: boolean;
|
|
12996
|
-
};
|
|
13296
|
+
buttonProps: ActionButtonProps & { isOpen: boolean };
|
|
12997
13297
|
ref: React.RefObject<HTMLButtonElement>;
|
|
12998
13298
|
}) => React.ReactNode
|
|
12999
13299
|
/**
|
|
@@ -13001,6 +13301,33 @@ renderTrigger?: (options: {
|
|
|
13001
13301
|
* function that accepts a boolean indicating whether the menu is open.
|
|
13002
13302
|
*/
|
|
13003
13303
|
triggerLabel?: React.ReactNode | ((isOpen: boolean) => React.ReactNode)
|
|
13304
|
+
/**
|
|
13305
|
+
* \`"single"\`/\`"multiple"\` select the whole menu. A record keyed by section id
|
|
13306
|
+
* makes each listed section an independent selection group.
|
|
13307
|
+
*/
|
|
13308
|
+
selectionMode?: | "none"
|
|
13309
|
+
| "single"
|
|
13310
|
+
| "multiple"
|
|
13311
|
+
| Record<string, "single" | "multiple">
|
|
13312
|
+
/**
|
|
13313
|
+
* A menu-wide selection (\`"all"\` or an iterable of keys) or a per-section
|
|
13314
|
+
* record of \`Selection\`. The iterable form preserves the pre-existing
|
|
13315
|
+
* \`AriaMenuProps.selectedKeys\` shape (arrays stay assignable).
|
|
13316
|
+
*/
|
|
13317
|
+
selectedKeys?: "all" | Iterable<Key> | Record<string, Selection>
|
|
13318
|
+
/**
|
|
13319
|
+
* Initial selection, in the same flat-or-per-section shape as \`selectedKeys\`.
|
|
13320
|
+
*/
|
|
13321
|
+
defaultSelectedKeys?: | "all"
|
|
13322
|
+
| Iterable<Key>
|
|
13323
|
+
| Record<string, "all" | Iterable<Key>>
|
|
13324
|
+
/**
|
|
13325
|
+
* Fires on user selection. In per-section mode, the second argument carries
|
|
13326
|
+
* the \`sectionId\` of the section whose selection changed; it is \`undefined\`
|
|
13327
|
+
* in menu-wide mode. Typed optional so existing one-arg handlers stay
|
|
13328
|
+
* assignable.
|
|
13329
|
+
*/
|
|
13330
|
+
onSelectionChange?: (keys: Selection, meta?: { sectionId: string }) => void
|
|
13004
13331
|
placement?: any
|
|
13005
13332
|
}`,stories:{usage:[{id:"core-collections-menu--basic",name:"Basic",snippet:'const Basic = () => <Menu triggerLabel="Menu Trigger" items={items} />;'},{id:"core-collections-menu--with-sections",name:"With Sections",snippet:'const WithSections = () => <Menu triggerLabel="Menu Trigger" items={itemsWithSections} />;'},{id:"core-collections-menu--controlled-open",name:"Controlled Open",snippet:'const ControlledOpen = () => <Menu triggerLabel="Menu Trigger" items={items} isOpen />;'},{id:"core-collections-menu--disabled",name:"Disabled",snippet:'const Disabled = () => <Menu triggerLabel="Menu Trigger" items={items} isDisabled />;'},{id:"core-collections-menu--with-disabled-keys",name:"With Disabled Keys",snippet:'const WithDisabledKeys = () => <Menu triggerLabel="Menu Trigger" items={items} disabledKeys={["paste"]} />;'},{id:"core-collections-menu--single-selection",name:"Single Selection",snippet:`const SingleSelection = () => {
|
|
13006
13333
|
const [selectedKey, setSelectedKey] = React.useState(
|
|
@@ -13034,13 +13361,17 @@ placement?: any
|
|
|
13034
13361
|
};`},{id:"core-collections-menu--with-selected-keys-controlled",name:"With Selected Keys Controlled",snippet:`const WithSelectedKeysControlled = () => <Menu
|
|
13035
13362
|
triggerLabel="Menu Trigger"
|
|
13036
13363
|
items={items}
|
|
13037
|
-
selectedKeys={["light"]}
|
|
13364
|
+
selectedKeys={new Set(["light"])}
|
|
13038
13365
|
selectionMode="single" />;`},{id:"core-collections-menu--long-menu",name:"Long Menu",snippet:`const LongMenu = () => <Menu
|
|
13039
13366
|
triggerLabel="Menu Trigger"
|
|
13040
13367
|
items={longListItems}
|
|
13041
13368
|
selectionMode="single"
|
|
13042
13369
|
defaultOpen
|
|
13043
|
-
autoFocus="first" />;`},{id:"core-collections-menu--with-
|
|
13370
|
+
autoFocus="first" />;`},{id:"core-collections-menu--with-submenu",name:"With Submenu",snippet:'const WithSubmenu = () => <Menu triggerLabel="Menu Trigger" items={itemsWithSubmenu} defaultOpen />;'},{id:"core-collections-menu--with-icons",name:"With Icons",snippet:'const WithIcons = () => <Menu triggerLabel="Menu Trigger" items={itemsWithIcons} defaultOpen />;'},{id:"core-collections-menu--with-disabled-submenu",name:"With Disabled Submenu",snippet:`const WithDisabledSubmenu = () => <Menu
|
|
13371
|
+
triggerLabel="Menu Trigger"
|
|
13372
|
+
items={itemsWithSubmenu}
|
|
13373
|
+
disabledKeys={["share"]}
|
|
13374
|
+
defaultOpen />;`},{id:"core-collections-menu--with-long-labels",name:"With Long Labels",snippet:'const WithLongLabels = () => <Menu triggerLabel="Menu Trigger" items={longLabelItems} defaultOpen />;'},{id:"core-collections-menu--with-custom-trigger",name:"With Custom Trigger",snippet:`const WithCustomTrigger = () => <Menu
|
|
13044
13375
|
triggerLabel="Menu Trigger"
|
|
13045
13376
|
renderTrigger={({ buttonProps, ref }) => (
|
|
13046
13377
|
<ActionButton
|
|
@@ -13049,12 +13380,32 @@ placement?: any
|
|
|
13049
13380
|
size="sm"
|
|
13050
13381
|
ref={ref}
|
|
13051
13382
|
/>
|
|
13052
|
-
)} />;`}
|
|
13383
|
+
)} />;`},{id:"core-collections-menu--section-level-selection",name:"Section Level Selection",snippet:`const SectionLevelSelection = () => {
|
|
13384
|
+
const [sel, setSel] = React.useState<Record<string, Selection>>({
|
|
13385
|
+
edit: new Set<Key>(["copy"]),
|
|
13386
|
+
theme: new Set<Key>(["light", "dark"]),
|
|
13387
|
+
});
|
|
13388
|
+
|
|
13389
|
+
return (
|
|
13390
|
+
<Menu
|
|
13391
|
+
triggerLabel="Menu Trigger"
|
|
13392
|
+
items={itemsWithSections}
|
|
13393
|
+
isOpen
|
|
13394
|
+
selectionMode={{ edit: "single", theme: "multiple" }}
|
|
13395
|
+
selectedKeys={{ edit: sel.edit, theme: sel.theme }}
|
|
13396
|
+
onSelectionChange={(keys, meta) => {
|
|
13397
|
+
if (meta) setSel((prev) => ({ ...prev, [meta.sectionId]: keys }));
|
|
13398
|
+
}} />
|
|
13399
|
+
);
|
|
13400
|
+
};`}],implementation:`import React from "react";
|
|
13053
13401
|
|
|
13402
|
+
import { I18nProvider } from "../../I18nProvider/I18nProvider";
|
|
13054
13403
|
import { Menu } from "../Menu";
|
|
13055
|
-
import { items } from "./data";
|
|
13404
|
+
import { items, itemsWithSections, itemsWithSubmenu } from "./data";
|
|
13056
13405
|
|
|
13057
13406
|
import type { MenuProps } from "../Menu.types";
|
|
13407
|
+
import type { Key } from "react-aria";
|
|
13408
|
+
import type { Selection } from "react-stately";
|
|
13058
13409
|
|
|
13059
13410
|
export const MenuExample: React.FC<
|
|
13060
13411
|
MenuProps & {
|
|
@@ -13084,63 +13435,218 @@ export const MenuActionValueExample: React.FC<{ label: string }> = ({
|
|
|
13084
13435
|
<div data-testid="menu-action-value">{received}</div>
|
|
13085
13436
|
</>
|
|
13086
13437
|
);
|
|
13087
|
-
}
|
|
13438
|
+
};
|
|
13088
13439
|
|
|
13089
|
-
|
|
13090
|
-
|
|
13440
|
+
export const MenuSelectionExample: React.FC<{
|
|
13441
|
+
label: string;
|
|
13442
|
+
selectionMode: "single" | "multiple";
|
|
13443
|
+
}> = ({ label, selectionMode }) => {
|
|
13444
|
+
const [selected, setSelected] = React.useState<Selection>(new Set());
|
|
13445
|
+
return (
|
|
13446
|
+
<>
|
|
13447
|
+
<Menu
|
|
13448
|
+
items={items}
|
|
13449
|
+
triggerLabel={label}
|
|
13450
|
+
selectionMode={selectionMode}
|
|
13451
|
+
selectedKeys={selected}
|
|
13452
|
+
onSelectionChange={setSelected}
|
|
13453
|
+
/>
|
|
13454
|
+
<div data-testid="menu-selection">
|
|
13455
|
+
{selected === "all" ? "all" : [...selected].map(String).join(",")}
|
|
13456
|
+
</div>
|
|
13457
|
+
</>
|
|
13458
|
+
);
|
|
13459
|
+
};
|
|
13091
13460
|
|
|
13092
|
-
const
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13461
|
+
export const MenuOpenChangeExample: React.FC<{ label: string }> = ({
|
|
13462
|
+
label,
|
|
13463
|
+
}) => {
|
|
13464
|
+
const [log, setLog] = React.useState<string[]>([]);
|
|
13465
|
+
return (
|
|
13466
|
+
<>
|
|
13467
|
+
<Menu
|
|
13468
|
+
items={items}
|
|
13469
|
+
triggerLabel={label}
|
|
13470
|
+
onOpenChange={(isOpen) => {
|
|
13471
|
+
setLog((prev) => [...prev, String(isOpen)]);
|
|
13472
|
+
}}
|
|
13473
|
+
/>
|
|
13474
|
+
<div data-testid="menu-open-log">{log.join(",")}</div>
|
|
13475
|
+
</>
|
|
13476
|
+
);
|
|
13099
13477
|
};
|
|
13100
13478
|
|
|
13101
|
-
const
|
|
13102
|
-
|
|
13103
|
-
|
|
13479
|
+
export const MenuRtlSubmenuExample: React.FC<{ label: string }> = ({
|
|
13480
|
+
label,
|
|
13481
|
+
}) => (
|
|
13482
|
+
<I18nProvider locale="ar">
|
|
13483
|
+
<Menu items={itemsWithSubmenu} triggerLabel={label} />
|
|
13104
13484
|
</I18nProvider>
|
|
13105
13485
|
);
|
|
13106
|
-
\`\`\``,props:`interface MessageFormatProps {
|
|
13107
|
-
/**
|
|
13108
|
-
* By default \`<MessageFormat>\` will render the formatted string into a
|
|
13109
|
-
* \`<React.Fragment>\`. If you need to customize rendering, you can either wrap
|
|
13110
|
-
* it with another React element (recommended), specify a different tagName
|
|
13111
|
-
* (e.g., 'div')
|
|
13112
|
-
*/
|
|
13113
|
-
elementType?: React.ElementType | "div" | "span"
|
|
13114
|
-
/**
|
|
13115
|
-
* The id of the message to format.
|
|
13116
|
-
*/
|
|
13117
|
-
id: string
|
|
13118
|
-
/**
|
|
13119
|
-
* The default message to use if the message id is not found.
|
|
13120
|
-
*/
|
|
13121
|
-
defaultMessage?: string
|
|
13122
|
-
}`,stories:{usage:[{id:"core-utilities-messageformat--basic",name:"Basic",snippet:'const Basic = () => <MessageFormat id="addSignature" elementType={Text} />;'}],implementation:""},similarTo:[],figmaUrl:null},Modal:{id:"core-overlays-modal",breadcrumb:"Core/Overlays/Modal",importStatement:'import { DialogExample, Modal } from "@baseline-ui/core";',description:"`Modal` renders content in an overlay above the page, trapping focus and blocking interaction with the background. Use it when a task or message must be addressed before the user can return to the underlying view.",documentation:`\`Modal\` renders content in an overlay above the page, trapping focus and blocking interaction with the background. Use it when a task or message must be addressed before the user can return to the underlying view.
|
|
13123
13486
|
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13487
|
+
export const MenuFunctionLabelExample: React.FC = () => (
|
|
13488
|
+
<Menu
|
|
13489
|
+
items={items}
|
|
13490
|
+
triggerLabel={(isOpen) => (isOpen ? "Opened" : "Closed")}
|
|
13491
|
+
/>
|
|
13492
|
+
);
|
|
13130
13493
|
|
|
13131
|
-
|
|
13494
|
+
export const MenuPerSectionTypeCheck: React.FC = () => (
|
|
13495
|
+
<Menu
|
|
13496
|
+
items={items}
|
|
13497
|
+
triggerLabel="types"
|
|
13498
|
+
selectionMode={{ a: "single", b: "multiple" }}
|
|
13499
|
+
selectedKeys={{ a: new Set<Key>(["x"]), b: new Set<Key>() }}
|
|
13500
|
+
onSelectionChange={(keys, meta) => {
|
|
13501
|
+
void keys;
|
|
13502
|
+
void meta?.sectionId;
|
|
13503
|
+
}}
|
|
13504
|
+
/>
|
|
13505
|
+
);
|
|
13132
13506
|
|
|
13133
|
-
|
|
13507
|
+
const fmtSelection = (sel: Selection): string =>
|
|
13508
|
+
sel === "all" ? "all" : [...sel].map(String).join(",");
|
|
13134
13509
|
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13510
|
+
export const MenuSectionSelectionExample: React.FC<{
|
|
13511
|
+
label: string;
|
|
13512
|
+
disallowEmptySelection?: boolean;
|
|
13513
|
+
}> = ({ label, disallowEmptySelection }) => {
|
|
13514
|
+
const [sel, setSel] = React.useState<Record<string, Selection>>({
|
|
13515
|
+
edit: new Set<Key>(),
|
|
13516
|
+
theme: new Set<Key>(["light"]),
|
|
13517
|
+
});
|
|
13518
|
+
const [lastSection, setLastSection] = React.useState("");
|
|
13519
|
+
return (
|
|
13520
|
+
<>
|
|
13521
|
+
<Menu
|
|
13522
|
+
items={itemsWithSections}
|
|
13523
|
+
triggerLabel={label}
|
|
13524
|
+
selectionMode={{ edit: "single", theme: "multiple" }}
|
|
13525
|
+
selectedKeys={{ edit: sel.edit, theme: sel.theme }}
|
|
13526
|
+
disallowEmptySelection={disallowEmptySelection}
|
|
13527
|
+
onSelectionChange={(keys, meta) => {
|
|
13528
|
+
if (!meta) return;
|
|
13529
|
+
setSel((prev) => ({ ...prev, [meta.sectionId]: keys }));
|
|
13530
|
+
setLastSection(meta.sectionId);
|
|
13531
|
+
}}
|
|
13532
|
+
/>
|
|
13533
|
+
<div data-testid="menu-section-selection-edit">
|
|
13534
|
+
{fmtSelection(sel.edit)}
|
|
13535
|
+
</div>
|
|
13536
|
+
<div data-testid="menu-section-selection-theme">
|
|
13537
|
+
{fmtSelection(sel.theme)}
|
|
13538
|
+
</div>
|
|
13539
|
+
<div data-testid="menu-section-selection-lastsection">{lastSection}</div>
|
|
13540
|
+
</>
|
|
13541
|
+
);
|
|
13542
|
+
};
|
|
13543
|
+
|
|
13544
|
+
export const MenuDisabledSectionSelectionExample: React.FC = () => (
|
|
13545
|
+
<Menu
|
|
13546
|
+
items={itemsWithSections}
|
|
13547
|
+
triggerLabel="Menu"
|
|
13548
|
+
selectionMode={{ edit: "single" }}
|
|
13549
|
+
disabledKeys={["copy"]}
|
|
13550
|
+
/>
|
|
13551
|
+
);
|
|
13552
|
+
|
|
13553
|
+
export const MenuOneShotDisabledKeysSectionSelectionExample: React.FC = () => {
|
|
13554
|
+
const disabledKeys = ["copy"][Symbol.iterator]();
|
|
13555
|
+
|
|
13556
|
+
return (
|
|
13557
|
+
<Menu
|
|
13558
|
+
items={itemsWithSections}
|
|
13559
|
+
triggerLabel="Menu"
|
|
13560
|
+
selectionMode={{ edit: "single" }}
|
|
13561
|
+
disabledKeys={disabledKeys}
|
|
13562
|
+
/>
|
|
13563
|
+
);
|
|
13564
|
+
};
|
|
13565
|
+
|
|
13566
|
+
export function MenuUncontrolledSectionSelectionExample() {
|
|
13567
|
+
const [lastSection, setLastSection] = React.useState("");
|
|
13568
|
+
const [themeKeys, setThemeKeys] = React.useState("");
|
|
13569
|
+
return (
|
|
13570
|
+
<>
|
|
13571
|
+
<Menu
|
|
13572
|
+
triggerLabel="Options"
|
|
13573
|
+
items={itemsWithSections}
|
|
13574
|
+
selectionMode={{ theme: "multiple" }}
|
|
13575
|
+
defaultSelectedKeys={{ theme: new Set<Key>(["light"]) }}
|
|
13576
|
+
onSelectionChange={(keys, meta) => {
|
|
13577
|
+
if (!meta) return;
|
|
13578
|
+
setLastSection(meta.sectionId);
|
|
13579
|
+
setThemeKeys(fmtSelection(keys));
|
|
13580
|
+
}}
|
|
13581
|
+
/>
|
|
13582
|
+
<div data-testid="menu-uncontrolled-lastsection">{lastSection}</div>
|
|
13583
|
+
<div data-testid="menu-uncontrolled-keys">{themeKeys}</div>
|
|
13584
|
+
</>
|
|
13585
|
+
);
|
|
13586
|
+
}
|
|
13587
|
+
|
|
13588
|
+
export const MenuPartialSectionSelectionExample: React.FC<{
|
|
13589
|
+
label: string;
|
|
13590
|
+
}> = ({ label }) => {
|
|
13591
|
+
const [sel, setSel] = React.useState<Record<string, Selection>>({
|
|
13592
|
+
edit: new Set<Key>(),
|
|
13593
|
+
});
|
|
13594
|
+
const [action, setAction] = React.useState("");
|
|
13595
|
+
return (
|
|
13596
|
+
<>
|
|
13597
|
+
<Menu
|
|
13598
|
+
items={itemsWithSections}
|
|
13599
|
+
triggerLabel={label}
|
|
13600
|
+
selectionMode={{ edit: "single" }}
|
|
13601
|
+
selectedKeys={{ edit: sel.edit }}
|
|
13602
|
+
onSelectionChange={(keys, meta) => {
|
|
13603
|
+
if (meta) setSel((prev) => ({ ...prev, [meta.sectionId]: keys }));
|
|
13604
|
+
}}
|
|
13605
|
+
onAction={(key) => {
|
|
13606
|
+
setAction(String(key));
|
|
13607
|
+
}}
|
|
13608
|
+
/>
|
|
13609
|
+
<div data-testid="menu-partial-action">{action}</div>
|
|
13610
|
+
</>
|
|
13611
|
+
);
|
|
13612
|
+
};`},similarTo:[],figmaUrl:null},MessageFormat:{id:"core-utilities-messageformat",breadcrumb:"Core/Utilities/MessageFormat",importStatement:'import { MessageFormat } from "@baseline-ui/core";',description:"`MessageFormat` renders a single message from the catalog supplied to `I18nProvider`. When the catalog has no entry for `id`, it renders `defaultMessage`.",documentation:'`MessageFormat` renders a single message from the catalog supplied to `I18nProvider`. When the catalog has no entry for `id`, it renders `defaultMessage`.\n\n```jsx\nimport { I18nProvider, MessageFormat } from "@baseline-ui/core";\nimport en from "@baseline-ui/core/intl/en.json";\nimport fr from "@baseline-ui/core/intl/fr.json";\n\nconst App = () => (\n <I18nProvider locale="en" messages={{ en, fr }}>\n <MessageFormat id="bui.calendar.previousMonth" />\n <MessageFormat id="myApp.hello" defaultMessage="Hello!" />\n </I18nProvider>\n);\n```',props:`interface MessageFormatProps {
|
|
13613
|
+
/**
|
|
13614
|
+
* By default \`<MessageFormat>\` will render the formatted string into a
|
|
13615
|
+
* \`<React.Fragment>\`. If you need to customize rendering, you can either wrap
|
|
13616
|
+
* it with another React element (recommended), specify a different tagName
|
|
13617
|
+
* (e.g., 'div')
|
|
13618
|
+
*/
|
|
13619
|
+
elementType?: React.ElementType | "div" | "span"
|
|
13620
|
+
/**
|
|
13621
|
+
* The id of the message to format.
|
|
13622
|
+
*/
|
|
13623
|
+
id: string
|
|
13624
|
+
/**
|
|
13625
|
+
* The default message to use if the message id is not found.
|
|
13626
|
+
*/
|
|
13627
|
+
defaultMessage?: string
|
|
13628
|
+
}`,stories:{usage:[{id:"core-utilities-messageformat--basic",name:"Basic",snippet:'const Basic = () => <MessageFormat id="myApp.addSignature" defaultMessage="Add signature" elementType={Text} />;'}],implementation:""},similarTo:[],figmaUrl:null},Modal:{id:"core-overlays-modal",breadcrumb:"Core/Overlays/Modal",importStatement:'import { DialogExample, Modal } from "@baseline-ui/core";',description:"`Modal` renders content in an overlay above the page, trapping focus and blocking interaction with the background. Use it when a task or message must be addressed before the user can return to the underlying view.",documentation:`\`Modal\` renders content in an overlay above the page, trapping focus and blocking interaction with the background. Use it when a task or message must be addressed before the user can return to the underlying view.
|
|
13629
|
+
|
|
13630
|
+
* The content outside the modal is hidden from screen readers.
|
|
13631
|
+
* The modal can optionally be closed by clicking outside the modal or by pressing the <kbd>Esc</kbd> key.
|
|
13632
|
+
* Focus is trapped within the modal when it is open. It is automatically returned to the element that triggered the modal when it is closed.
|
|
13633
|
+
* Scrolling of the page is disabled when the modal is open.
|
|
13634
|
+
|
|
13635
|
+
When your SDK or component library is embedded inside a host application you don't control, the host page may have its own interactive UI (inputs, buttons, etc.) that users need to access even while a modal is open. By default, the modal traps focus and hides outside elements from assistive technologies, which would block interaction with the host app's UI.
|
|
13636
|
+
|
|
13637
|
+
Use the \`disableFocusManagement\` prop on \`ModalContent\` to prevent focus trapping and restoration, allowing users to interact with elements outside the modal's container.
|
|
13638
|
+
|
|
13639
|
+
Combine this with \`UNSAFE_enableInert\` to ensure that background elements behind the modal (inside the \`FrameProvider\` container) remain truly non-interactive while the host page's UI stays accessible.
|
|
13640
|
+
|
|
13641
|
+
\`\`\`jsx
|
|
13642
|
+
import {
|
|
13643
|
+
Dialog,
|
|
13644
|
+
Modal,
|
|
13645
|
+
ModalTrigger,
|
|
13646
|
+
ModalContent,
|
|
13647
|
+
ModalClose,
|
|
13648
|
+
DialogTitle,
|
|
13649
|
+
} from "../../utils";
|
|
13144
13650
|
|
|
13145
13651
|
<Modal>
|
|
13146
13652
|
<ModalTrigger>
|
|
@@ -16204,25 +16710,13 @@ export const PopoverDefaultOpenWithArrowExample = () => {
|
|
|
16204
16710
|
);
|
|
16205
16711
|
};
|
|
16206
16712
|
|
|
16207
|
-
export const PopoverContainedFocusExample = (
|
|
16208
|
-
|
|
16209
|
-
|
|
16210
|
-
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
|
|
16214
|
-
<Dialog
|
|
16215
|
-
size="content"
|
|
16216
|
-
className={sprinkles({
|
|
16217
|
-
padding: "md",
|
|
16218
|
-
display: "flex",
|
|
16219
|
-
gap: "xl",
|
|
16220
|
-
flexDirection: "column",
|
|
16221
|
-
})}
|
|
16222
|
-
style={{
|
|
16223
|
-
width: 200,
|
|
16224
|
-
}}
|
|
16225
|
-
>
|
|
16713
|
+
export const PopoverContainedFocusExample = ({
|
|
16714
|
+
shouldContainFocus = true,
|
|
16715
|
+
}: {
|
|
16716
|
+
shouldContainFocus?: boolean;
|
|
16717
|
+
}) => {
|
|
16718
|
+
const content = (
|
|
16719
|
+
<>
|
|
16226
16720
|
<Text type="label">The focus is contained within the popover.</Text>
|
|
16227
16721
|
|
|
16228
16722
|
<TextInput
|
|
@@ -16234,10 +16728,55 @@ export const PopoverContainedFocusExample = () => {
|
|
|
16234
16728
|
label="Button"
|
|
16235
16729
|
style={{ width: "100%", justifyContent: "center" }}
|
|
16236
16730
|
/>
|
|
16731
|
+
</>
|
|
16732
|
+
);
|
|
16733
|
+
const contentClassName = sprinkles({
|
|
16734
|
+
padding: "md",
|
|
16735
|
+
display: "flex",
|
|
16736
|
+
gap: "xl",
|
|
16737
|
+
flexDirection: "column",
|
|
16738
|
+
});
|
|
16739
|
+
|
|
16740
|
+
const popover = (
|
|
16741
|
+
<Popover type="dialog">
|
|
16742
|
+
<PopoverTrigger>
|
|
16743
|
+
<ActionButton label="Open" />
|
|
16744
|
+
</PopoverTrigger>
|
|
16745
|
+
<PopoverContent
|
|
16746
|
+
shouldContainFocus={shouldContainFocus}
|
|
16747
|
+
isNonModal={!shouldContainFocus}
|
|
16748
|
+
>
|
|
16749
|
+
{shouldContainFocus ? (
|
|
16750
|
+
<Dialog
|
|
16751
|
+
size="content"
|
|
16752
|
+
className={contentClassName}
|
|
16753
|
+
style={{ width: 200 }}
|
|
16754
|
+
>
|
|
16755
|
+
{content}
|
|
16237
16756
|
</Dialog>
|
|
16757
|
+
) : (
|
|
16758
|
+
// No Dialog: useDialog opts the overlay into focus containment,
|
|
16759
|
+
// which disables the Tab-out restore path.
|
|
16760
|
+
<Box className={contentClassName} style={{ width: 200 }}>
|
|
16761
|
+
{content}
|
|
16762
|
+
</Box>
|
|
16763
|
+
)}
|
|
16238
16764
|
</PopoverContent>
|
|
16239
16765
|
</Popover>
|
|
16240
16766
|
);
|
|
16767
|
+
|
|
16768
|
+
// The contained variant is the \`ContainedFocus\` story: a wrapper or sibling
|
|
16769
|
+
// here rebaselines its visual snapshot.
|
|
16770
|
+
if (shouldContainFocus) {
|
|
16771
|
+
return popover;
|
|
16772
|
+
}
|
|
16773
|
+
|
|
16774
|
+
return (
|
|
16775
|
+
<Box display="flex" flexDirection="column" gap="lg" alignItems="flex-start">
|
|
16776
|
+
{popover}
|
|
16777
|
+
<ActionButton label="After" />
|
|
16778
|
+
</Box>
|
|
16779
|
+
);
|
|
16241
16780
|
};
|
|
16242
16781
|
|
|
16243
16782
|
export const PopoverWithScrollableViewportExample: React.FC<{
|
|
@@ -18315,18 +18854,20 @@ function App() {
|
|
|
18315
18854
|
}
|
|
18316
18855
|
\`\`\`
|
|
18317
18856
|
|
|
18318
|
-
We can group items into sections by passing the \`items\` prop an array of objects
|
|
18857
|
+
We can group items into sections by passing the \`items\` prop an array of section objects. A section is any item with both a \`title\` and a \`children\` array of options \u2014 items missing either one are treated as plain options. The \`id\` of each section must be unique.
|
|
18858
|
+
|
|
18859
|
+
Sections are visually separated by a divider above every section but the first.
|
|
18319
18860
|
|
|
18320
18861
|
\`\`\`jsx
|
|
18321
18862
|
const itemsWithSections = [
|
|
18322
18863
|
{
|
|
18323
18864
|
id: "solid",
|
|
18324
|
-
|
|
18865
|
+
title: "Solid",
|
|
18325
18866
|
children: items,
|
|
18326
18867
|
},
|
|
18327
18868
|
{
|
|
18328
18869
|
id: "dashed",
|
|
18329
|
-
|
|
18870
|
+
title: "Dashed",
|
|
18330
18871
|
children: [
|
|
18331
18872
|
{
|
|
18332
18873
|
id: "ellipse-dashed",
|
|
@@ -18350,6 +18891,18 @@ const itemsWithSections = [
|
|
|
18350
18891
|
<Select items={itemsWithSections} label="Label" />;
|
|
18351
18892
|
\`\`\`
|
|
18352
18893
|
|
|
18894
|
+
By default each section's \`title\` is used only as the group's accessible name. Set \`showSectionHeader\` to render it as a visible heading above the section's options. This works the same way when the list is virtualized with \`Virtualizer\`.
|
|
18895
|
+
|
|
18896
|
+
<a href="?path=/story/core-forms-select--with-section-headers">View story</a>
|
|
18897
|
+
|
|
18898
|
+
\`\`\`jsx
|
|
18899
|
+
<Select
|
|
18900
|
+
items={itemsWithSections}
|
|
18901
|
+
showSectionHeader={true}
|
|
18902
|
+
aria-label="Choose an item"
|
|
18903
|
+
/>
|
|
18904
|
+
\`\`\`
|
|
18905
|
+
|
|
18353
18906
|
The \`Select\` component supports selecting multiple options by setting the \`selectionMode\` prop to \`"multiple"\`. When in multiselect mode, selected items are displayed as removable tags in the button, the popover stays open after selection, and checkboxes are shown instead of checkmarks.
|
|
18354
18907
|
|
|
18355
18908
|
\`\`\`jsx
|
|
@@ -18553,14 +19106,16 @@ import { Virtualizer, ListLayout } from "@baseline-ui/core";
|
|
|
18553
19106
|
\`\`\`
|
|
18554
19107
|
|
|
18555
19108
|
| Key | Function |
|
|
18556
|
-
|
|
|
19109
|
+
| -------------------- | ------------------------------------------------------------------------------------ |
|
|
19110
|
+
| \`Tab\` | Moves focus to and from the trigger. The popup itself is not a tab stop |
|
|
18557
19111
|
| \`Space\` | Opens the listbox popup or toggles selection of the focused item in multiselect mode |
|
|
18558
19112
|
| \`Enter\` | Opens the listbox popup or selects the focused item if the popup is open |
|
|
18559
19113
|
| \`Escape\` | Closes the listbox popup |
|
|
18560
19114
|
| \`ArrowDown\` | Opens the listbox popup and focuses the first item if no item is focused |
|
|
18561
19115
|
| \`ArrowUp\` | Opens the listbox popup and focuses the last item if no item is focused |
|
|
18562
|
-
| \`Home\` |
|
|
18563
|
-
| \`End\` |
|
|
19116
|
+
| \`Home\` | Focuses the first item |
|
|
19117
|
+
| \`End\` | Focuses the last item |
|
|
19118
|
+
| Printable characters | Focuses the first item matching the typed characters |
|
|
18564
19119
|
|
|
18565
19120
|
**Note:** In multiselect mode (\`selectionMode="multiple"\`), the \`Space\` key toggles selection of the focused item, and the popover remains open after selection.
|
|
18566
19121
|
|
|
@@ -18590,6 +19145,8 @@ The \`renderTrigger\` prop allows you to completely replace the default trigger
|
|
|
18590
19145
|
| \`.BaselineUI-Select-Label\` | Label element |
|
|
18591
19146
|
| \`.BaselineUI-Select-Popover\` | Popover container |
|
|
18592
19147
|
| \`.BaselineUI-Select-SearchInput\` | Search input (when wrapped with \`Autocomplete\`) |
|
|
19148
|
+
| \`.BaselineUI-ListBox\` | Listbox inside the popover |
|
|
19149
|
+
| \`.BaselineUI-ListBox-Section\` | A section within the listbox |
|
|
18593
19150
|
| \`[data-disabled]\` | Applied when \`isDisabled\` is true |
|
|
18594
19151
|
| \`[data-readonly]\` | Applied when \`isReadOnly\` is true |
|
|
18595
19152
|
| \`[data-focused]\` | Applied when the trigger is focused |
|
|
@@ -18598,6 +19155,7 @@ The \`renderTrigger\` prop allows you to completely replace the default trigger
|
|
|
18598
19155
|
| \`[data-pressed]\` | Applied when the trigger is pressed |
|
|
18599
19156
|
| \`[data-open]\` | Applied when the popover is open |
|
|
18600
19157
|
|
|
19158
|
+
* **ComboBox** \u2014 Use this instead when users should be able to type directly into the trigger to filter or enter a value
|
|
18601
19159
|
* **IconSelect** \u2014 Select variant with an icon trigger instead of a text button
|
|
18602
19160
|
* **ButtonSelect** \u2014 Select variant styled as a button
|
|
18603
19161
|
* **ListBox** \u2014 Standalone listbox without the trigger/popover wrapper
|
|
@@ -18740,125 +19298,125 @@ hideSelectAll?: boolean
|
|
|
18740
19298
|
*/
|
|
18741
19299
|
hideClear?: boolean
|
|
18742
19300
|
}`,stories:{usage:[{id:"core-forms-select-multiselect--basic",name:"Basic",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
18743
|
-
|
|
18744
|
-
|
|
18745
|
-
>
|
|
19301
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19302
|
+
33 |
|
|
19303
|
+
> 34 | export {
|
|
18746
19304
|
| ^
|
|
18747
|
-
|
|
18748
|
-
|
|
18749
|
-
|
|
18750
|
-
|
|
18751
|
-
|
|
18752
|
-
>
|
|
19305
|
+
35 | Basic,
|
|
19306
|
+
36 | WithLabel,
|
|
19307
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-label",name:"WithLabel",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19308
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19309
|
+
33 |
|
|
19310
|
+
> 34 | export {
|
|
18753
19311
|
| ^
|
|
18754
|
-
|
|
18755
|
-
|
|
18756
|
-
|
|
18757
|
-
|
|
18758
|
-
|
|
18759
|
-
>
|
|
19312
|
+
35 | Basic,
|
|
19313
|
+
36 | WithLabel,
|
|
19314
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-description",name:"WithDescription",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19315
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19316
|
+
33 |
|
|
19317
|
+
> 34 | export {
|
|
18760
19318
|
| ^
|
|
18761
|
-
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
>
|
|
19319
|
+
35 | Basic,
|
|
19320
|
+
36 | WithLabel,
|
|
19321
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-error",name:"WithError",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19322
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19323
|
+
33 |
|
|
19324
|
+
> 34 | export {
|
|
18767
19325
|
| ^
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
>
|
|
19326
|
+
35 | Basic,
|
|
19327
|
+
36 | WithLabel,
|
|
19328
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-error-and-error-message",name:"WithErrorAndErrorMessage",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19329
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19330
|
+
33 |
|
|
19331
|
+
> 34 | export {
|
|
18774
19332
|
| ^
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
>
|
|
19333
|
+
35 | Basic,
|
|
19334
|
+
36 | WithLabel,
|
|
19335
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-warning",name:"WithWarning",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19336
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19337
|
+
33 |
|
|
19338
|
+
> 34 | export {
|
|
18781
19339
|
| ^
|
|
18782
|
-
|
|
18783
|
-
|
|
18784
|
-
|
|
18785
|
-
|
|
18786
|
-
|
|
18787
|
-
>
|
|
19340
|
+
35 | Basic,
|
|
19341
|
+
36 | WithLabel,
|
|
19342
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-warning-and-warning-message",name:"WithWarningAndWarningMessage",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19343
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19344
|
+
33 |
|
|
19345
|
+
> 34 | export {
|
|
18788
19346
|
| ^
|
|
18789
|
-
|
|
18790
|
-
|
|
18791
|
-
|
|
18792
|
-
|
|
18793
|
-
|
|
18794
|
-
>
|
|
19347
|
+
35 | Basic,
|
|
19348
|
+
36 | WithLabel,
|
|
19349
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--ghost",name:"Ghost",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19350
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19351
|
+
33 |
|
|
19352
|
+
> 34 | export {
|
|
18795
19353
|
| ^
|
|
18796
|
-
|
|
18797
|
-
|
|
18798
|
-
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
>
|
|
19354
|
+
35 | Basic,
|
|
19355
|
+
36 | WithLabel,
|
|
19356
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-disabled",name:"WithDisabled",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19357
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19358
|
+
33 |
|
|
19359
|
+
> 34 | export {
|
|
18802
19360
|
| ^
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
|
|
18806
|
-
|
|
18807
|
-
|
|
18808
|
-
>
|
|
19361
|
+
35 | Basic,
|
|
19362
|
+
36 | WithLabel,
|
|
19363
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-disabled-items",name:"WithDisabledItems",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19364
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19365
|
+
33 |
|
|
19366
|
+
> 34 | export {
|
|
18809
19367
|
| ^
|
|
18810
|
-
|
|
18811
|
-
|
|
18812
|
-
|
|
18813
|
-
|
|
18814
|
-
|
|
18815
|
-
>
|
|
19368
|
+
35 | Basic,
|
|
19369
|
+
36 | WithLabel,
|
|
19370
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-sections",name:"WithSections",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19371
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19372
|
+
33 |
|
|
19373
|
+
> 34 | export {
|
|
18816
19374
|
| ^
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
>
|
|
19375
|
+
35 | Basic,
|
|
19376
|
+
36 | WithLabel,
|
|
19377
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-default-open",name:"WithDefaultOpen",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19378
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19379
|
+
33 |
|
|
19380
|
+
> 34 | export {
|
|
18823
19381
|
| ^
|
|
18824
|
-
|
|
18825
|
-
|
|
18826
|
-
|
|
18827
|
-
|
|
18828
|
-
|
|
18829
|
-
>
|
|
19382
|
+
35 | Basic,
|
|
19383
|
+
36 | WithLabel,
|
|
19384
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-controlled-open",name:"WithControlledOpen",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19385
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19386
|
+
33 |
|
|
19387
|
+
> 34 | export {
|
|
18830
19388
|
| ^
|
|
18831
|
-
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
>
|
|
19389
|
+
35 | Basic,
|
|
19390
|
+
36 | WithLabel,
|
|
19391
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-label-at-start",name:"WithLabelAtStart",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19392
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19393
|
+
33 |
|
|
19394
|
+
> 34 | export {
|
|
18837
19395
|
| ^
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
>
|
|
19396
|
+
35 | Basic,
|
|
19397
|
+
36 | WithLabel,
|
|
19398
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--scrollable",name:"Scrollable",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19399
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19400
|
+
33 |
|
|
19401
|
+
> 34 | export {
|
|
18844
19402
|
| ^
|
|
18845
|
-
|
|
18846
|
-
|
|
18847
|
-
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
>
|
|
19403
|
+
35 | Basic,
|
|
19404
|
+
36 | WithLabel,
|
|
19405
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--long-list",name:"LongList",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19406
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19407
|
+
33 |
|
|
19408
|
+
> 34 | export {
|
|
18851
19409
|
| ^
|
|
18852
|
-
|
|
18853
|
-
|
|
18854
|
-
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
>
|
|
19410
|
+
35 | Basic,
|
|
19411
|
+
36 | WithLabel,
|
|
19412
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--with-custom-trigger",name:"WithCustomTrigger",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
19413
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19414
|
+
33 |
|
|
19415
|
+
> 34 | export {
|
|
18858
19416
|
| ^
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
|
|
19417
|
+
35 | Basic,
|
|
19418
|
+
36 | WithLabel,
|
|
19419
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--read-only",name:"Read Only",snippet:`const ReadOnly = () => <Select
|
|
18862
19420
|
aria-label="Choose Stroke Style"
|
|
18863
19421
|
items={items}
|
|
18864
19422
|
placeholder="Choose Stroke Style"
|
|
@@ -18917,7 +19475,29 @@ hideClear?: boolean
|
|
|
18917
19475
|
aria-label="Choose Stroke Style"
|
|
18918
19476
|
items={items}
|
|
18919
19477
|
placeholder="Choose Stroke Style"
|
|
18920
|
-
selectionMode="multiple" />;`}
|
|
19478
|
+
selectionMode="multiple" />;`},{id:"core-forms-select-multiselect--with-error-and-tags",name:"With Error And Tags",snippet:`const WithErrorAndTags = () => <Select
|
|
19479
|
+
aria-label="Choose Stroke Style"
|
|
19480
|
+
items={items}
|
|
19481
|
+
placeholder="Choose Stroke Style"
|
|
19482
|
+
selectionMode="multiple"
|
|
19483
|
+
label="Label"
|
|
19484
|
+
validationState="error"
|
|
19485
|
+
errorMessage="Pick fewer shapes"
|
|
19486
|
+
defaultValue={["ellipse", "square", "polygon"]}
|
|
19487
|
+
maxCount={3} />;`,description:"Tags competing with the status icon for trigger width."},{id:"core-forms-select-multiselect--long-labels-as-tags",name:"Long Labels As Tags",snippet:`const LongLabelsAsTags = () => <Select
|
|
19488
|
+
aria-label="Choose Stroke Style"
|
|
19489
|
+
items={items}
|
|
19490
|
+
placeholder="Choose Stroke Style"
|
|
19491
|
+
selectionMode="multiple"
|
|
19492
|
+
defaultValue={["long1", "long2"]} />;`},{id:"core-forms-select-multiselect--read-only-with-tags-open",name:"Read Only With Tags Open",snippet:`const ReadOnlyWithTagsOpen = () => <Select
|
|
19493
|
+
aria-label="Choose Stroke Style"
|
|
19494
|
+
items={items}
|
|
19495
|
+
placeholder="Choose Stroke Style"
|
|
19496
|
+
selectionMode="multiple"
|
|
19497
|
+
label="Label"
|
|
19498
|
+
isReadOnly
|
|
19499
|
+
value={["ellipse", "square"]}
|
|
19500
|
+
defaultOpen />;`}],implementation:`import { EllipseIcon } from "@baseline-ui/icons/24";
|
|
18921
19501
|
import React from "react";
|
|
18922
19502
|
import { useFilter } from "react-aria";
|
|
18923
19503
|
import { Autocomplete, Virtualizer } from "react-aria-components";
|
|
@@ -18926,11 +19506,16 @@ import { useListData } from "react-stately";
|
|
|
18926
19506
|
import { ActionButton } from "../../ActionButton";
|
|
18927
19507
|
import { items } from "../../ListBox/__tests__/testComponents";
|
|
18928
19508
|
import { virtualizeAutocompleteItems } from "../../Menu/__tests__/data";
|
|
18929
|
-
import {
|
|
19509
|
+
import { itemsWithSectionTitles } from "../../UNSAFE_ListBox/__tests__/testComponents";
|
|
19510
|
+
import {
|
|
19511
|
+
ListLayout,
|
|
19512
|
+
VIRTUALIZER_LAYOUT_DEFAULT_OPTIONS,
|
|
19513
|
+
} from "../../Virtualizer";
|
|
18930
19514
|
import { IconSelect } from "../IconSelect";
|
|
18931
19515
|
import { Select } from "../Select";
|
|
18932
19516
|
|
|
18933
19517
|
import type { IconSelectProps } from "../Select.types";
|
|
19518
|
+
import type { Key } from "@react-types/shared";
|
|
18934
19519
|
|
|
18935
19520
|
export const SelectExample: React.FC<
|
|
18936
19521
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
@@ -18938,13 +19523,28 @@ export const SelectExample: React.FC<
|
|
|
18938
19523
|
return (
|
|
18939
19524
|
<Select
|
|
18940
19525
|
placeholder="Choose an item"
|
|
18941
|
-
{...args}
|
|
18942
19526
|
optionClassName={(item) => item.label}
|
|
19527
|
+
{...args}
|
|
18943
19528
|
items={items}
|
|
18944
19529
|
/>
|
|
18945
19530
|
);
|
|
18946
19531
|
};
|
|
18947
19532
|
|
|
19533
|
+
// "Apples" is a substring of "Pineapples" \u2014 exercises exact string matching
|
|
19534
|
+
// in the tester's option() locator.
|
|
19535
|
+
const substringItems = [
|
|
19536
|
+
{ id: "apples", label: "Apples" },
|
|
19537
|
+
{ id: "pineapples", label: "Pineapples" },
|
|
19538
|
+
];
|
|
19539
|
+
|
|
19540
|
+
export const SelectSubstringLabelsExample: React.FC<
|
|
19541
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19542
|
+
> = (args) => {
|
|
19543
|
+
return (
|
|
19544
|
+
<Select placeholder="Choose an item" {...args} items={substringItems} />
|
|
19545
|
+
);
|
|
19546
|
+
};
|
|
19547
|
+
|
|
18948
19548
|
export const SelectGetTargetRectExample: React.FC = () => {
|
|
18949
19549
|
const [called, setCalled] = React.useState(false);
|
|
18950
19550
|
|
|
@@ -19001,90 +19601,228 @@ export const SelectCustomTriggerExample: React.FC<
|
|
|
19001
19601
|
};
|
|
19002
19602
|
|
|
19003
19603
|
export const IconSelectExample: React.FC<
|
|
19004
|
-
Omit<IconSelectProps, "items" | "
|
|
19604
|
+
Omit<IconSelectProps, "items" | "aria-label">
|
|
19005
19605
|
> = (args) => {
|
|
19006
19606
|
return (
|
|
19007
19607
|
<IconSelect
|
|
19008
19608
|
placeholder="Choose an item"
|
|
19609
|
+
icon={EllipseIcon}
|
|
19009
19610
|
{...args}
|
|
19010
19611
|
items={items}
|
|
19011
|
-
icon={EllipseIcon}
|
|
19012
19612
|
aria-label="Aria Label"
|
|
19013
19613
|
/>
|
|
19014
19614
|
);
|
|
19015
19615
|
};
|
|
19016
19616
|
|
|
19017
|
-
export const
|
|
19617
|
+
export const VirtualSelectWithSectionHeadersExample: React.FC<
|
|
19018
19618
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19019
19619
|
> = (args) => {
|
|
19020
|
-
const list = useListData({
|
|
19021
|
-
initialItems: virtualizeAutocompleteItems,
|
|
19022
|
-
});
|
|
19023
|
-
const { contains } = useFilter({ sensitivity: "base" });
|
|
19024
|
-
const filter = (textValue, inputValue) => contains(textValue, inputValue);
|
|
19025
19620
|
return (
|
|
19026
|
-
<Virtualizer
|
|
19027
|
-
|
|
19621
|
+
<Virtualizer
|
|
19622
|
+
layout={ListLayout}
|
|
19623
|
+
layoutOptions={{
|
|
19624
|
+
rowHeight: 36,
|
|
19625
|
+
headingHeight: 40,
|
|
19626
|
+
}}
|
|
19627
|
+
>
|
|
19028
19628
|
<Select
|
|
19629
|
+
aria-label="Choose an item"
|
|
19630
|
+
placeholder="Choose an item"
|
|
19631
|
+
showSectionHeader={true}
|
|
19029
19632
|
{...args}
|
|
19030
|
-
items={
|
|
19031
|
-
|
|
19032
|
-
maxHeight={
|
|
19033
|
-
style={{
|
|
19034
|
-
width: 400,
|
|
19035
|
-
}}
|
|
19633
|
+
items={itemsWithSectionTitles}
|
|
19634
|
+
defaultOpen={true}
|
|
19635
|
+
maxHeight={400}
|
|
19036
19636
|
/>
|
|
19037
|
-
</Autocomplete>
|
|
19038
19637
|
</Virtualizer>
|
|
19039
19638
|
);
|
|
19040
|
-
}
|
|
19041
|
-
|
|
19042
|
-
\`\`\`jsx
|
|
19043
|
-
import { Separator } from "../../utils";
|
|
19044
|
-
|
|
19045
|
-
<Separator />;
|
|
19046
|
-
\`\`\`
|
|
19047
|
-
|
|
19048
|
-
By default, the separator is horizontal.
|
|
19049
|
-
|
|
19050
|
-
\`\`\`jsx
|
|
19051
|
-
import { Separator } from "../../utils";
|
|
19052
|
-
|
|
19053
|
-
<div>
|
|
19054
|
-
Section 1
|
|
19055
|
-
<Separator />
|
|
19056
|
-
Section 2
|
|
19057
|
-
</div>;
|
|
19058
|
-
\`\`\`
|
|
19059
|
-
|
|
19060
|
-
The \`orientation\` prop can be used to change the orientation of the separator.
|
|
19061
|
-
|
|
19062
|
-
\`\`\`jsx
|
|
19063
|
-
import { Separator } from "../../utils";
|
|
19639
|
+
};
|
|
19064
19640
|
|
|
19065
|
-
<
|
|
19066
|
-
|
|
19067
|
-
|
|
19068
|
-
|
|
19069
|
-
|
|
19070
|
-
|
|
19641
|
+
export const SelectWithSectionHeadersExample: React.FC<
|
|
19642
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19643
|
+
> = (args) => {
|
|
19644
|
+
return (
|
|
19645
|
+
<Select
|
|
19646
|
+
aria-label="Choose an item"
|
|
19647
|
+
placeholder="Choose an item"
|
|
19648
|
+
showSectionHeader={true}
|
|
19649
|
+
{...args}
|
|
19650
|
+
items={itemsWithSectionTitles}
|
|
19651
|
+
defaultOpen={true}
|
|
19652
|
+
/>
|
|
19653
|
+
);
|
|
19654
|
+
};
|
|
19071
19655
|
|
|
19072
|
-
| Selector | Description |
|
|
19073
|
-
| ------------------ | ----------------------------------------------------------------------- |
|
|
19074
|
-
| \\[data-orientation] | The orientation of the separator. It can be \`horizontal\` or \`vertical\`. |`,props:`interface SeparatorProps {
|
|
19075
|
-
/**
|
|
19076
|
-
* The orientation of the separator.
|
|
19077
|
-
*
|
|
19078
|
-
* @default 'horizontal'
|
|
19079
|
-
*/
|
|
19080
|
-
orientation?: "horizontal" | "vertical"
|
|
19081
19656
|
/**
|
|
19082
|
-
*
|
|
19657
|
+
* Owns \`isOpen\` so the controlled-open contract can be driven from outside the
|
|
19658
|
+
* Select, with a sibling readout of the current state.
|
|
19083
19659
|
*/
|
|
19084
|
-
|
|
19085
|
-
|
|
19086
|
-
|
|
19087
|
-
|
|
19660
|
+
export const ControlledOpenSelectExample: React.FC<
|
|
19661
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19662
|
+
> = (args) => {
|
|
19663
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
19664
|
+
|
|
19665
|
+
return (
|
|
19666
|
+
<>
|
|
19667
|
+
<Select
|
|
19668
|
+
aria-label="Choose an item"
|
|
19669
|
+
placeholder="Choose an item"
|
|
19670
|
+
{...args}
|
|
19671
|
+
items={items}
|
|
19672
|
+
isOpen={isOpen}
|
|
19673
|
+
onOpenChange={setIsOpen}
|
|
19674
|
+
/>
|
|
19675
|
+
<button
|
|
19676
|
+
data-testid="open-externally"
|
|
19677
|
+
onClick={() => {
|
|
19678
|
+
setIsOpen(true);
|
|
19679
|
+
}}
|
|
19680
|
+
>
|
|
19681
|
+
Open
|
|
19682
|
+
</button>
|
|
19683
|
+
<span data-testid="open-state">{String(isOpen)}</span>
|
|
19684
|
+
</>
|
|
19685
|
+
);
|
|
19686
|
+
};
|
|
19687
|
+
|
|
19688
|
+
/**
|
|
19689
|
+
* Custom trigger that renders the multi-select half of the \`renderTrigger\`
|
|
19690
|
+
* payload \u2014 \`selectionMode\`, \`maxCount\` and \`onRemove\` \u2014 which the default
|
|
19691
|
+
* \`SelectButton\` otherwise keeps to itself.
|
|
19692
|
+
*/
|
|
19693
|
+
export const MultiSelectCustomTriggerExample: React.FC<
|
|
19694
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19695
|
+
> = (args) => {
|
|
19696
|
+
return (
|
|
19697
|
+
<Select
|
|
19698
|
+
aria-label="Choose an item"
|
|
19699
|
+
selectionMode="multiple"
|
|
19700
|
+
{...args}
|
|
19701
|
+
items={items}
|
|
19702
|
+
renderTrigger={({
|
|
19703
|
+
buttonProps,
|
|
19704
|
+
ref,
|
|
19705
|
+
selectedValue,
|
|
19706
|
+
selectionMode,
|
|
19707
|
+
onRemove,
|
|
19708
|
+
maxCount,
|
|
19709
|
+
}) => (
|
|
19710
|
+
<div>
|
|
19711
|
+
<ActionButton
|
|
19712
|
+
{...buttonProps}
|
|
19713
|
+
ref={ref}
|
|
19714
|
+
label={\`\${selectionMode}|\${maxCount}|\${selectedValue?.length ?? 0}\`}
|
|
19715
|
+
variant="popover"
|
|
19716
|
+
/>
|
|
19717
|
+
<button
|
|
19718
|
+
data-testid="remove-first"
|
|
19719
|
+
onClick={() => {
|
|
19720
|
+
const first = selectedValue?.[0];
|
|
19721
|
+
if (first) {
|
|
19722
|
+
onRemove?.(new Set([first.id]));
|
|
19723
|
+
}
|
|
19724
|
+
}}
|
|
19725
|
+
>
|
|
19726
|
+
Remove first
|
|
19727
|
+
</button>
|
|
19728
|
+
</div>
|
|
19729
|
+
)}
|
|
19730
|
+
/>
|
|
19731
|
+
);
|
|
19732
|
+
};
|
|
19733
|
+
|
|
19734
|
+
export const SelectWithVirtualizeAutocompleteExample: React.FC<
|
|
19735
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19736
|
+
> = (args) => {
|
|
19737
|
+
const list = useListData({
|
|
19738
|
+
initialItems: virtualizeAutocompleteItems,
|
|
19739
|
+
});
|
|
19740
|
+
const { contains } = useFilter({ sensitivity: "base" });
|
|
19741
|
+
const filter = (textValue, inputValue) => contains(textValue, inputValue);
|
|
19742
|
+
return (
|
|
19743
|
+
<Virtualizer {...VIRTUALIZER_LAYOUT_DEFAULT_OPTIONS.LIST_BOX}>
|
|
19744
|
+
<Autocomplete filter={filter}>
|
|
19745
|
+
<Select
|
|
19746
|
+
{...args}
|
|
19747
|
+
items={list.items}
|
|
19748
|
+
placeholder="Select multiple options"
|
|
19749
|
+
maxHeight={300}
|
|
19750
|
+
style={{
|
|
19751
|
+
width: 400,
|
|
19752
|
+
}}
|
|
19753
|
+
/>
|
|
19754
|
+
</Autocomplete>
|
|
19755
|
+
</Virtualizer>
|
|
19756
|
+
);
|
|
19757
|
+
};
|
|
19758
|
+
|
|
19759
|
+
/**
|
|
19760
|
+
* \`optionClassName\` reads component state, and \`items\` is module-level so React Aria's
|
|
19761
|
+
* per-item element cache applies. Pinned open so the state change comes from selecting an
|
|
19762
|
+
* option rather than from an outside press the popover would swallow.
|
|
19763
|
+
*/
|
|
19764
|
+
export const CountingSelectExample: React.FC = () => {
|
|
19765
|
+
const [selected, setSelected] = React.useState<Key | null>(null);
|
|
19766
|
+
|
|
19767
|
+
return (
|
|
19768
|
+
<Select
|
|
19769
|
+
aria-label="Counting select"
|
|
19770
|
+
items={items}
|
|
19771
|
+
isOpen={true}
|
|
19772
|
+
optionClassName={(item) =>
|
|
19773
|
+
item.id === selected ? "option-picked" : "option-plain"
|
|
19774
|
+
}
|
|
19775
|
+
onSelectionChange={setSelected}
|
|
19776
|
+
/>
|
|
19777
|
+
);
|
|
19778
|
+
};`},similarTo:[],figmaUrl:null},Separator:{id:"core-content-separator",breadcrumb:"Core/Content/Separator",importStatement:'import { Separator } from "@baseline-ui/core";',description:"`Separator` is a thin horizontal or vertical rule that divides adjacent content. Use it to create a visual break between sections, groups of controls, or items in a list.",documentation:`\`Separator\` is a thin horizontal or vertical rule that divides adjacent content. Use it to create a visual break between sections, groups of controls, or items in a list.
|
|
19779
|
+
|
|
19780
|
+
\`\`\`jsx
|
|
19781
|
+
import { Separator } from "../../utils";
|
|
19782
|
+
|
|
19783
|
+
<Separator />;
|
|
19784
|
+
\`\`\`
|
|
19785
|
+
|
|
19786
|
+
By default, the separator is horizontal.
|
|
19787
|
+
|
|
19788
|
+
\`\`\`jsx
|
|
19789
|
+
import { Separator } from "../../utils";
|
|
19790
|
+
|
|
19791
|
+
<div>
|
|
19792
|
+
Section 1
|
|
19793
|
+
<Separator />
|
|
19794
|
+
Section 2
|
|
19795
|
+
</div>;
|
|
19796
|
+
\`\`\`
|
|
19797
|
+
|
|
19798
|
+
The \`orientation\` prop can be used to change the orientation of the separator.
|
|
19799
|
+
|
|
19800
|
+
\`\`\`jsx
|
|
19801
|
+
import { Separator } from "../../utils";
|
|
19802
|
+
|
|
19803
|
+
<div>
|
|
19804
|
+
Section 1
|
|
19805
|
+
<Separator orientation="vertical" variant="secondary" />
|
|
19806
|
+
Section 2
|
|
19807
|
+
</div>;
|
|
19808
|
+
\`\`\`
|
|
19809
|
+
|
|
19810
|
+
| Selector | Description |
|
|
19811
|
+
| ------------------ | ----------------------------------------------------------------------- |
|
|
19812
|
+
| \\[data-orientation] | The orientation of the separator. It can be \`horizontal\` or \`vertical\`. |`,props:`interface SeparatorProps {
|
|
19813
|
+
/**
|
|
19814
|
+
* The orientation of the separator.
|
|
19815
|
+
*
|
|
19816
|
+
* @default 'horizontal'
|
|
19817
|
+
*/
|
|
19818
|
+
orientation?: "horizontal" | "vertical"
|
|
19819
|
+
/**
|
|
19820
|
+
* The HTML element type that will be used to render the separator.
|
|
19821
|
+
*/
|
|
19822
|
+
elementType?: string
|
|
19823
|
+
/**
|
|
19824
|
+
* @deprecated Do not use in new components. This is a legacy block
|
|
19825
|
+
* identifier; new components should exclude it via
|
|
19088
19826
|
* \`Omit<StylingProps, keyof BlockProps>\` (see \`StatusCard\` / \`Code\`).
|
|
19089
19827
|
* Retained on existing components for backward compatibility.
|
|
19090
19828
|
*
|
|
@@ -23293,7 +24031,7 @@ export const TaggedPaginationExample: React.FC<
|
|
|
23293
24031
|
{...props}
|
|
23294
24032
|
/>
|
|
23295
24033
|
);
|
|
23296
|
-
};`},similarTo:[],figmaUrl:null},Text:{id:"core-content-text",breadcrumb:"Core/Content/Text",importStatement:'import { Text, VariantViewer } from "@baseline-ui/core";',description:"`Text` is a typography primitive that renders strings with consistent type, size, and weight from the design system. Use it whenever you need to display textual content so that headings, body copy, values, and helper text stay visually aligned.",documentation:'`Text` is a typography primitive that renders strings with consistent type, size, and weight from the design system. Use it whenever you need to display textual content so that headings, body copy, values, and helper text stay visually aligned.\n\n```jsx\nimport { Text } from "@
|
|
24034
|
+
};`},similarTo:[],figmaUrl:null},Text:{id:"core-content-text",breadcrumb:"Core/Content/Text",importStatement:'import { Input, Label, Text, TextField, VariantViewer } from "@baseline-ui/core";',description:"`Text` is a typography primitive that renders strings with consistent type, size, and weight from the design system. Use it whenever you need to display textual content so that headings, body copy, values, and helper text stay visually aligned.",documentation:'`Text` is a typography primitive that renders strings with consistent type, size, and weight from the design system. Use it whenever you need to display textual content so that headings, body copy, values, and helper text stay visually aligned.\n\n* Consistent type, size, and weight pulled from the design system\n* Renders as any HTML element via the `elementType` prop\n* Opt-in integration with a container\'s context through the `slot` prop for automatic `aria-describedby` / `aria-labelledby` wiring\n\n```jsx\nimport { Text } from "@baseline-ui/core";\n\n<Text type="subtitle" size="sm">\n Text\n</Text>;\n```\n\nThe `Text` component supports the following types: `title`, `subtitle`, `body`, `label`, `value`, and `helper`. It\nalso supports the following sizes: `sm`, `md`, and `lg`.\n\n`Text` can integrate with a container component\'s context. Pass a `slot` name\nand the text picks up the `id` the container provides for that slot, so it gets\nassociated via `aria-describedby` / `aria-labelledby` without manually wiring an\n`id`.\n\n```jsx\n<Text slot="description">\n This description is linked to its field automatically.\n</Text>\n```\n\nSlot integration is **opt-in**: a `Text` without a `slot` never inherits an\nambient context, so it renders identically whether or not a container is\npresent. Naming a `slot` the surrounding container does not define will throw \u2014\nonly pass slots you know the container exposes.\n\nNo Baseline container currently provides a slotted `TextContext`, so this is\ngroundwork today: the mechanism is exercisable against raw React Aria containers\n(`TextField`, `Select`, `TagGroup`, etc.) but no Baseline component wires it up yet.\n\n`Text` always emits a stable class name you can target for styling.\n\n| Selector | Description |\n| ------------------ | ------------------------------------- |\n| `.BaselineUI-Text` | Applied to the rendered text element. |',props:`interface TextProps {
|
|
23297
24035
|
/**
|
|
23298
24036
|
* @deprecated Do not use in new components. This is a legacy block
|
|
23299
24037
|
* identifier; new components should exclude it via
|
|
@@ -23349,6 +24087,13 @@ children: React.ReactNode
|
|
|
23349
24087
|
* @default "span"
|
|
23350
24088
|
*/
|
|
23351
24089
|
elementType?: React.ElementType
|
|
24090
|
+
/**
|
|
24091
|
+
* A slot name that wires this text into a parent container's context \u2014
|
|
24092
|
+
* e.g. \`slot="description"\` or \`slot="label"\` \u2014 so the container can
|
|
24093
|
+
* associate it via \`aria-describedby\` / \`aria-labelledby\` without manually
|
|
24094
|
+
* threading an \`id\`. Pass \`null\` to opt out of an ambient slot.
|
|
24095
|
+
*/
|
|
24096
|
+
slot?: string | null
|
|
23352
24097
|
}`,stories:{usage:[{id:"core-content-text--basic",name:"Basic",snippet:"const Basic = () => <Text>Sample Text</Text>;"},{id:"core-content-text--variants",name:"Variants",snippet:`const Variants = (args) => (
|
|
23353
24098
|
<VariantViewer<React.ComponentProps<typeof Text>>
|
|
23354
24099
|
header={["Small", "Medium", "Large"]}
|
|
@@ -23383,8 +24128,24 @@ elementType?: React.ElementType
|
|
|
23383
24128
|
}}
|
|
23384
24129
|
defaultProps={args}
|
|
23385
24130
|
/>
|
|
23386
|
-
);`}
|
|
24131
|
+
);`},{id:"core-content-text--slots",name:"Slots",snippet:`const Slots = () => (
|
|
24132
|
+
<TextField>
|
|
24133
|
+
{/* The raw React Aria Label carries no Baseline styling, so it inherits
|
|
24134
|
+
the storybook default (black) text and fails contrast against the dark
|
|
24135
|
+
theme background. Give it the themed foreground; the slot wiring below
|
|
24136
|
+
is the point of this story. */}
|
|
24137
|
+
<Label style={{ color: themeVars.color.text.primary }}>
|
|
24138
|
+
Display name
|
|
24139
|
+
</Label>
|
|
24140
|
+
<Input />
|
|
24141
|
+
<Text slot="description" type="helper" size="sm">
|
|
24142
|
+
This is shown to other members of your workspace.
|
|
24143
|
+
</Text>
|
|
24144
|
+
</TextField>
|
|
24145
|
+
);`,description:"`Text` opts into a container's context when given a `slot`. Here a raw React Aria `TextField` provides a `TextContext`, and `<Text slot=\"description\">` picks up the id the field exposes for that slot \u2014 wiring itself as the field's `aria-describedby` without a manually threaded `id`."}],implementation:`import React from "react";
|
|
24146
|
+
import { TextContext } from "react-aria-components";
|
|
23387
24147
|
|
|
24148
|
+
import { UNSAFE_ListBox } from "../../UNSAFE_ListBox";
|
|
23388
24149
|
import { Text } from "../Text";
|
|
23389
24150
|
|
|
23390
24151
|
export function TextWithRef() {
|
|
@@ -23405,65 +24166,61 @@ export function TextWithRef() {
|
|
|
23405
24166
|
<span data-testid="tag-name">{tag}</span>
|
|
23406
24167
|
</>
|
|
23407
24168
|
);
|
|
24169
|
+
}
|
|
24170
|
+
|
|
24171
|
+
const SLOTTED_TEXT_CONTEXT = {
|
|
24172
|
+
slots: {
|
|
24173
|
+
description: { id: "provided-description-id" },
|
|
24174
|
+
},
|
|
24175
|
+
};
|
|
24176
|
+
|
|
24177
|
+
export function TextInSlotContext() {
|
|
24178
|
+
return (
|
|
24179
|
+
<TextContext.Provider value={SLOTTED_TEXT_CONTEXT}>
|
|
24180
|
+
<Text slot="description" data-block-id="slotted">
|
|
24181
|
+
Description
|
|
24182
|
+
</Text>
|
|
24183
|
+
</TextContext.Provider>
|
|
24184
|
+
);
|
|
24185
|
+
}
|
|
24186
|
+
|
|
24187
|
+
export function TextBareInSlotContext() {
|
|
24188
|
+
// A slotless <Text> inside a slotted context that has no default slot must
|
|
24189
|
+
// render (opt out) rather than throw "A slot prop is required".
|
|
24190
|
+
return (
|
|
24191
|
+
<TextContext.Provider value={SLOTTED_TEXT_CONTEXT}>
|
|
24192
|
+
<Text id="bare-id" data-testid="bare">
|
|
24193
|
+
Description
|
|
24194
|
+
</Text>
|
|
24195
|
+
</TextContext.Provider>
|
|
24196
|
+
);
|
|
24197
|
+
}
|
|
24198
|
+
|
|
24199
|
+
export function TextInListBoxRenderOption() {
|
|
24200
|
+
// A bare <Text> in renderOption lands inside RAC's ListBoxItem, which provides
|
|
24201
|
+
// a TextContext whose default slot maps to the option's generated label id.
|
|
24202
|
+
// A slotless <Text> must opt out (no inherited id) rather than silently adopt
|
|
24203
|
+
// that label id \u2014 otherwise two Texts in one option collide on the same id.
|
|
24204
|
+
return (
|
|
24205
|
+
<UNSAFE_ListBox
|
|
24206
|
+
aria-label="Options"
|
|
24207
|
+
items={[{ id: "opt-1", label: "Option 1" }]}
|
|
24208
|
+
renderOption={(item) => (
|
|
24209
|
+
<Text data-testid="render-option">{item.label}</Text>
|
|
24210
|
+
)}
|
|
24211
|
+
/>
|
|
24212
|
+
);
|
|
24213
|
+
}
|
|
24214
|
+
|
|
24215
|
+
export function TextOptOutOfSlotContext() {
|
|
24216
|
+
return (
|
|
24217
|
+
<TextContext.Provider value={SLOTTED_TEXT_CONTEXT}>
|
|
24218
|
+
<Text slot={null} id="own-id" data-block-id="opt-out">
|
|
24219
|
+
Description
|
|
24220
|
+
</Text>
|
|
24221
|
+
</TextContext.Provider>
|
|
24222
|
+
);
|
|
23408
24223
|
}`},similarTo:[],figmaUrl:null},TextInput:{id:"core-forms-textinput",breadcrumb:"Core/Forms/TextInput",importStatement:'import { TextInput, VariantViewer } from "@baseline-ui/core";',description:"`TextInput` is a field for capturing free-form text \u2014 a single-line `<input>` by default, or a resizable multi-line `<textarea>` when `isMultiLine` is set. Use it for values such as names, emails, or longer notes.",documentation:'`TextInput` is a field for capturing free-form text \u2014 a single-line `<input>` by default, or a resizable multi-line `<textarea>` when `isMultiLine` is set. Use it for values such as names, emails, or longer notes.\n\n* This component is built on top of the `input` element (or `textarea` in multi-line mode).\n* It provides visual and ARIA labels to the input element to make it more accessible.\n* It supports events for change, clipboard, composition, focus, and keyboard.\n* It exposes invalid states to assistive technology via ARIA.\n* It supports description and other state messages which are linked to the input element via ARIA.\n\n```jsx\nimport { TextInput } from "@baseline-ui/core";\n\n<TextInput placeholder="Enter Text" />;\n```\n\nFor numeric entry use `NumberInput`, for search fields use `SearchInput`, and for color values use `ColorInput`.\n\n`TextInput` supports two variants: `primary` (default) and `ghost`. Set the variant with the `variant` prop.\n\n```jsx\n<TextInput placeholder="Placeholder" variant="primary" />\n<TextInput placeholder="Placeholder" variant="ghost" />\n```\n\nYou can add a label to the `TextInput` by passing a `label` prop.\n\n```jsx\n<TextInput label="Label" placeholder="Placeholder" />\n```\n\nBy default, the label is positioned above the `TextInput`. You can change the\nposition of the label by passing a `labelPosition` prop.\n\n```jsx\n<TextInput\n label="Label"\n labelPosition="start"\n description="Description"\n placeholder="Placeholder"\n/>\n```\n\nYou can add a description to the `TextInput` by passing a `description` prop. A\ndescription is used to provide additional information about the `TextInput`.\n\n```jsx\n<TextInput label="Label" description="Description" placeholder="Placeholder" />\n```\n\nYou can put the `TextInput` into an error state by setting `validationState` to\n`"error"`. You can also pass `errorMessage` to provide additional information\nabout the error; passing `errorMessage` on its own is enough to render the error\nstate. When `description` is also present, it takes precedence and the error\nmessage is not shown.\n\n```jsx\n<TextInput\n label="Label"\n validationState="error"\n errorMessage="Error message"\n placeholder="Placeholder"\n/>\n```\n\nYou can put the `TextInput` into a warning state by setting `validationState` to\n`"warning"`. You can also pass `warningMessage` to provide additional\ninformation about the warning.\n\n```jsx\n<TextInput\n label="Label"\n validationState="warning"\n warningMessage="Warning message"\n placeholder="Placeholder"\n/>\n```\n\nYou can make the `TextInput` read only by passing an `isReadOnly` prop.\n\n```jsx\n<TextInput label="Label" isReadOnly defaultValue="Read-only value" />\n```\n\nYou can disable the `TextInput` by passing an `isDisabled` prop.\n\n```jsx\n<TextInput\n label="Label"\n isDisabled\n defaultValue="Disabled value"\n description="Description"\n placeholder="Placeholder"\n/>\n```\n\nYou can control the `TextInput` by passing a `value` prop together with an\n`onChange` prop. `onChange` is called with the new string value (not a DOM\nevent).\n\n```jsx\nconst [value, setValue] = useState("Controlled value");\n\n<TextInput\n label="Label"\n value={value}\n onChange={(value) => setValue(value)}\n placeholder="Placeholder"\n/>;\n```\n\nSet `isMultiLine` to render the field as a resizable `<textarea>` instead of a\nsingle-line `<input>`. The field starts at a minimum height and can be dragged\nto resize in both directions, except when it is read only or disabled. All\nstates (error, warning, disabled, read only, ghost) are supported, just like the\nsingle-line input.\n\n```jsx\n<TextInput\n label="Label"\n isMultiLine\n defaultValue="Lorem ipsum"\n description="Helper text"\n/>\n```\n\nUse the `rows` prop to set the initial number of visible text rows.\n\n```jsx\n<TextInput label="Label" isMultiLine rows={5} placeholder="Placeholder" />\n```\n\nYou can use the `TextInput` in a HTML form by passing a `name` prop. In addition, attributes such as `type`, `pattern`, `inputMode`, and others are passed through to the underlying input element.\n\n```jsx\n<form>\n <TextInput\n name="text-input"\n type="text"\n placeholder="Placeholder"\n description="Description"\n />\n</form>\n```\n\nThese selectors are applied to the underlying `<input>` / `<textarea>` element. The root wrapper is also exposed via the `BaselineUI-TextInput` class and the field element via the `BaselineUI-TextInput-Input` class.\n\n| Selector | Description |\n| ------------------------- | ------------------------------------------------------------------- |\n| `[data-readonly]` | Whether the input is read only. |\n| `[data-disabled]` | Whether the input is disabled. |\n| `[data-validation-state]` | The validation state of the input (`error`, `warning`, or `valid`). |\n| `[data-focused]` | Whether the input is focused, either via a mouse or keyboard. |\n| `[data-focus-visible]` | Whether the input is keyboard focused. |\n\n| Key | Function |\n| ---------------- | ---------------------------------------------------------------------------- |\n| <kbd>Enter</kbd> | Submits the form in single-line mode; inserts a new line in multi-line mode. |',props:`interface TextInputProps {
|
|
23409
|
-
/**
|
|
23410
|
-
* @deprecated Do not use in new components. This is a legacy block
|
|
23411
|
-
* identifier; new components should exclude it via
|
|
23412
|
-
* \`Omit<StylingProps, keyof BlockProps>\` (see \`StatusCard\` / \`Code\`).
|
|
23413
|
-
* Retained on existing components for backward compatibility.
|
|
23414
|
-
*
|
|
23415
|
-
* The unique identifier for the block. This is used to identify the block in
|
|
23416
|
-
* the DOM and in the block map. It is added as a data attribute
|
|
23417
|
-
* \`data-block-id\` to the root element of the block if a DOM node is
|
|
23418
|
-
* rendered.
|
|
23419
|
-
*/
|
|
23420
|
-
data-block-id?: string
|
|
23421
|
-
/**
|
|
23422
|
-
* @deprecated Do not use in new components. This is a legacy block group
|
|
23423
|
-
* marker; new components should exclude it via
|
|
23424
|
-
* \`Omit<StylingProps, keyof BlockProps>\` (see \`StatusCard\` / \`Code\`).
|
|
23425
|
-
* Retained on existing components for backward compatibility.
|
|
23426
|
-
*
|
|
23427
|
-
* Represents a data block group. This is similar to \`data-block-id\` but it
|
|
23428
|
-
* doesn't have to be unique just like \`class\`. This is used to group blocks
|
|
23429
|
-
* together in the DOM and in the block map. It is added as a data attribute
|
|
23430
|
-
* \`data-block-class\` to the root element of the block if a DOM node is
|
|
23431
|
-
* rendered.
|
|
23432
|
-
*/
|
|
23433
|
-
data-block-class?: string
|
|
23434
|
-
/**
|
|
23435
|
-
* The className applied to the root element of the component.
|
|
23436
|
-
*/
|
|
23437
|
-
className?: string
|
|
23438
|
-
/**
|
|
23439
|
-
* The style applied to the root element of the component.
|
|
23440
|
-
*/
|
|
23441
|
-
style?: React.CSSProperties
|
|
23442
|
-
/**
|
|
23443
|
-
* The description to display below the input.
|
|
23444
|
-
*/
|
|
23445
|
-
description?: string
|
|
23446
|
-
/**
|
|
23447
|
-
* The error message to display when the input is in an error state.
|
|
23448
|
-
*/
|
|
23449
|
-
errorMessage?: string
|
|
23450
|
-
/**
|
|
23451
|
-
* The warning message to display when the input is in a warning state.
|
|
23452
|
-
*/
|
|
23453
|
-
warningMessage?: string
|
|
23454
|
-
/**
|
|
23455
|
-
* The style object to apply to the input element
|
|
23456
|
-
*/
|
|
23457
|
-
inputStyle?: React.CSSProperties
|
|
23458
|
-
/**
|
|
23459
|
-
* The class name to apply to the input element
|
|
23460
|
-
*/
|
|
23461
|
-
inputClassName?: string
|
|
23462
|
-
/**
|
|
23463
|
-
* The number of visible text rows for the multi-line input. Only applies when
|
|
23464
|
-
* \`isMultiLine\` is set.
|
|
23465
|
-
*/
|
|
23466
|
-
rows?: number
|
|
23467
24224
|
variant?: any
|
|
23468
24225
|
labelPosition?: any
|
|
23469
24226
|
isMultiLine?: any
|
|
@@ -26806,6 +27563,7 @@ export const VirtualizedTreeViewWithRenameExample: React.FC<
|
|
|
26806
27563
|
VirtualizedScrollIntoViewExample,
|
|
26807
27564
|
VirtualListBoxGridLayoutExample,
|
|
26808
27565
|
VirtualListBoxListLayoutExample,
|
|
27566
|
+
VirtualListBoxWithSectionHeadersExample,
|
|
26809
27567
|
VirtualListBoxWithSectionsExample,
|
|
26810
27568
|
} from "@baseline-ui/core";`,description:"`UNSAFE_ListBox` is a low-level selectable list with custom option rendering, grouped sections, drag-and-drop reordering, and virtualization. Use it to build bespoke list UIs \u2014 such as font pickers, layer panels, or large catalogs \u2014 where the standard list components are too constrained.",documentation:`\`UNSAFE_ListBox\` is a low-level selectable list with custom option rendering, grouped sections, drag-and-drop reordering, and virtualization. Use it to build bespoke list UIs \u2014 such as font pickers, layer panels, or large catalogs \u2014 where the standard list components are too constrained.
|
|
26811
27569
|
|
|
@@ -26902,6 +27660,34 @@ const fonts = [
|
|
|
26902
27660
|
/>;
|
|
26903
27661
|
\`\`\`
|
|
26904
27662
|
|
|
27663
|
+
Rendered options and sections are cached per item object. Reading component state from
|
|
27664
|
+
\`renderOption\`, \`optionClassName\`, \`optionStyle\`, \`renderSectionHeader\`, \`sectionClassName\`
|
|
27665
|
+
or \`sectionStyle\` works \u2014 the options re-render when the state changes \u2014 and toggling
|
|
27666
|
+
\`showSectionHeader\` or \`withSectionHeaderPadding\` does too.
|
|
27667
|
+
|
|
27668
|
+
The cost only applies when \`items\` is memoized, since an inline \`items={data.map(...)}\`
|
|
27669
|
+
produces new item objects every render and the cache never applies in the first place. With
|
|
27670
|
+
stable items, any of these props changing identity rebuilds every option and section, so
|
|
27671
|
+
memoize the ones that don't depend on state \u2014 including object literals passed to
|
|
27672
|
+
\`optionStyle\`, which are new on every render.
|
|
27673
|
+
|
|
27674
|
+
\`\`\`jsx
|
|
27675
|
+
const [highlighted, setHighlighted] = useState(null);
|
|
27676
|
+
|
|
27677
|
+
// Rebuilds only when the highlight moves; \`fonts\` is module-level, so the cache applies.
|
|
27678
|
+
const optionStyle = useCallback(
|
|
27679
|
+
(item) => ({ fontWeight: item.id === highlighted ? "bold" : "normal" }),
|
|
27680
|
+
[highlighted],
|
|
27681
|
+
);
|
|
27682
|
+
|
|
27683
|
+
<UNSAFE_ListBox
|
|
27684
|
+
items={fonts}
|
|
27685
|
+
aria-label="Fonts"
|
|
27686
|
+
optionStyle={optionStyle}
|
|
27687
|
+
onAction={setHighlighted}
|
|
27688
|
+
/>;
|
|
27689
|
+
\`\`\`
|
|
27690
|
+
|
|
26905
27691
|
\`\`\`jsx
|
|
26906
27692
|
<UNSAFE_ListBox
|
|
26907
27693
|
items={items}
|
|
@@ -26999,6 +27785,10 @@ style?: React.CSSProperties
|
|
|
26999
27785
|
/**
|
|
27000
27786
|
* The custom render function for the listbox options.
|
|
27001
27787
|
*
|
|
27788
|
+
* Reading component state here works, at the cost of rebuilding every cached option and
|
|
27789
|
+
* section whenever the function's identity changes \u2014 see {@link UNSAFE_ListBoxProps.items}
|
|
27790
|
+
* for when that cost applies.
|
|
27791
|
+
*
|
|
27002
27792
|
* @param item ListOption
|
|
27003
27793
|
* @param options ListBoxItemRenderProps
|
|
27004
27794
|
*/
|
|
@@ -27008,6 +27798,9 @@ renderOption?: (
|
|
|
27008
27798
|
) => React.ReactNode
|
|
27009
27799
|
/**
|
|
27010
27800
|
* The CSS class name for the option.
|
|
27801
|
+
*
|
|
27802
|
+
* Compared by identity, so an inline function or an unmemoized value rebuilds every
|
|
27803
|
+
* cached option and section on each render. A plain string is compared by value.
|
|
27011
27804
|
*/
|
|
27012
27805
|
optionClassName?: | string
|
|
27013
27806
|
| ((
|
|
@@ -27016,6 +27809,9 @@ optionClassName?: | string
|
|
|
27016
27809
|
) => string | undefined)
|
|
27017
27810
|
/**
|
|
27018
27811
|
* The style of the option.
|
|
27812
|
+
*
|
|
27813
|
+
* Compared by identity, so an inline function or object literal rebuilds every cached
|
|
27814
|
+
* option and section on each render \u2014 memoize it to avoid that.
|
|
27019
27815
|
*/
|
|
27020
27816
|
optionStyle?: | React.CSSProperties
|
|
27021
27817
|
| ((
|
|
@@ -27025,15 +27821,25 @@ optionStyle?: | React.CSSProperties
|
|
|
27025
27821
|
/**
|
|
27026
27822
|
* The custom render function for the listbox sections.
|
|
27027
27823
|
*
|
|
27824
|
+
* Reading component state here works, at the cost of rebuilding every cached option and
|
|
27825
|
+
* section whenever the function's identity changes \u2014 see {@link UNSAFE_ListBoxProps.items}
|
|
27826
|
+
* for when that cost applies.
|
|
27827
|
+
*
|
|
27028
27828
|
* @param section ListSection
|
|
27029
27829
|
*/
|
|
27030
27830
|
renderSectionHeader?: (section: ListSection) => React.ReactNode
|
|
27031
27831
|
/**
|
|
27032
27832
|
* The CSS class name for the section.
|
|
27833
|
+
*
|
|
27834
|
+
* Compared by identity, so an inline function or an unmemoized value rebuilds every
|
|
27835
|
+
* cached option and section on each render. A plain string is compared by value.
|
|
27033
27836
|
*/
|
|
27034
27837
|
sectionClassName?: string | ((section: ListSection) => string | undefined)
|
|
27035
27838
|
/**
|
|
27036
27839
|
* The style of the section.
|
|
27840
|
+
*
|
|
27841
|
+
* Compared by identity, so an inline function or object literal rebuilds every cached
|
|
27842
|
+
* option and section on each render \u2014 memoize it to avoid that.
|
|
27037
27843
|
*/
|
|
27038
27844
|
sectionStyle?: | React.CSSProperties
|
|
27039
27845
|
| ((section: ListSection) => React.CSSProperties | undefined)
|
|
@@ -27069,6 +27875,11 @@ withSectionHeaderPadding?: boolean
|
|
|
27069
27875
|
*
|
|
27070
27876
|
* type ListItem = ListOption | ListSection;
|
|
27071
27877
|
* \`\`\`
|
|
27878
|
+
*
|
|
27879
|
+
* Rendered options and sections are cached per item object. Building this array inline
|
|
27880
|
+
* (\`items={data.map(...)}\`) produces new item objects every render, so nothing is ever
|
|
27881
|
+
* reused and the customisation props cost nothing; memoize it and the cache applies,
|
|
27882
|
+
* which is when their identity starts to matter.
|
|
27072
27883
|
*/
|
|
27073
27884
|
items?: ListItem[]
|
|
27074
27885
|
/**
|
|
@@ -27155,7 +27966,7 @@ listBoxHandle?: React.RefObject<ListHandle>
|
|
|
27155
27966
|
items={items}
|
|
27156
27967
|
aria-label="List box"
|
|
27157
27968
|
selectionMode="multiple"
|
|
27158
|
-
defaultSelectedKeys={["item-0"]} />;`},{id:"core-collections-unsafe-listbox--virtualized-horizontal",name:"Virtualized Horizontal",snippet:'const VirtualizedHorizontal = () => <VirtualListBoxGridLayoutExample items={items} aria-label="List box" selectionMode="multiple" />;'},{id:"core-collections-unsafe-listbox--virtualized-with-sections",name:"Virtualized With Sections",snippet:'const VirtualizedWithSections = () => <VirtualListBoxWithSectionsExample items={items} aria-label="List box" selectionMode="single" />;'},{id:"core-collections-unsafe-listbox--virtualized-scroll-into-view",name:"Virtualized Scroll Into View",snippet:"const VirtualizedScrollIntoView = () => <VirtualizedScrollIntoViewExample />;"}],implementation:`import { XIcon } from "@baseline-ui/icons/16";
|
|
27969
|
+
defaultSelectedKeys={["item-0"]} />;`},{id:"core-collections-unsafe-listbox--virtualized-horizontal",name:"Virtualized Horizontal",snippet:'const VirtualizedHorizontal = () => <VirtualListBoxGridLayoutExample items={items} aria-label="List box" selectionMode="multiple" />;'},{id:"core-collections-unsafe-listbox--virtualized-with-sections",name:"Virtualized With Sections",snippet:'const VirtualizedWithSections = () => <VirtualListBoxWithSectionsExample items={items} aria-label="List box" selectionMode="single" />;'},{id:"core-collections-unsafe-listbox--virtualized-with-section-separators",name:"Virtualized With Section Separators",snippet:'const VirtualizedWithSectionSeparators = () => <VirtualListBoxWithSectionHeadersExample items={items} aria-label="List box" selectionMode="single" />;'},{id:"core-collections-unsafe-listbox--virtualized-scroll-into-view",name:"Virtualized Scroll Into View",snippet:"const VirtualizedScrollIntoView = () => <VirtualizedScrollIntoViewExample />;"}],implementation:`import { XIcon } from "@baseline-ui/icons/16";
|
|
27159
27970
|
import {
|
|
27160
27971
|
EllipseDashedIcon,
|
|
27161
27972
|
EllipseIcon,
|
|
@@ -27185,7 +27996,10 @@ import {
|
|
|
27185
27996
|
import { useDragAndDrop } from "../hooks/useDragAndDrop";
|
|
27186
27997
|
import { UNSAFE_ListBox as ListBox } from "../ListBox";
|
|
27187
27998
|
|
|
27188
|
-
import type {
|
|
27999
|
+
import type {
|
|
28000
|
+
ListItem,
|
|
28001
|
+
ListOption as ListOptionType,
|
|
28002
|
+
} from "../../shared/types/List";
|
|
27189
28003
|
import type { ListHandle } from "../ListBox.types";
|
|
27190
28004
|
import type { DroppableCollectionReorderEvent } from "@react-types/shared";
|
|
27191
28005
|
|
|
@@ -27762,16 +28576,85 @@ export const VirtualListBoxWithSectionsExample: React.FC<
|
|
|
27762
28576
|
);
|
|
27763
28577
|
};
|
|
27764
28578
|
|
|
27765
|
-
export const
|
|
27766
|
-
|
|
27767
|
-
|
|
27768
|
-
id: \`item-\${i}\`,
|
|
27769
|
-
label: \`Item \${i}\`,
|
|
27770
|
-
}));
|
|
27771
|
-
|
|
28579
|
+
export const VirtualListBoxWithSectionHeadersExample: React.FC<
|
|
28580
|
+
Omit<React.ComponentProps<typeof ListBox>, "items">
|
|
28581
|
+
> = (args) => {
|
|
27772
28582
|
return (
|
|
27773
|
-
<
|
|
27774
|
-
|
|
28583
|
+
<Virtualizer
|
|
28584
|
+
layout={ListLayout}
|
|
28585
|
+
layoutOptions={{
|
|
28586
|
+
rowHeight: 36,
|
|
28587
|
+
headingHeight: 40,
|
|
28588
|
+
}}
|
|
28589
|
+
>
|
|
28590
|
+
<ListBox
|
|
28591
|
+
{...args}
|
|
28592
|
+
items={itemsWithSectionTitles}
|
|
28593
|
+
showSectionHeader={true}
|
|
28594
|
+
style={{
|
|
28595
|
+
height: 400,
|
|
28596
|
+
width: 300,
|
|
28597
|
+
overflow: "auto",
|
|
28598
|
+
}}
|
|
28599
|
+
aria-label="Virtualized list box with section headers"
|
|
28600
|
+
/>
|
|
28601
|
+
</Virtualizer>
|
|
28602
|
+
);
|
|
28603
|
+
};
|
|
28604
|
+
|
|
28605
|
+
const leadingSection = {
|
|
28606
|
+
id: "leading",
|
|
28607
|
+
title: "Leading",
|
|
28608
|
+
children: [{ id: "leading-item", label: "Leading item" }],
|
|
28609
|
+
} as ListItem;
|
|
28610
|
+
|
|
28611
|
+
export const VirtualListBoxWithPrependableSectionExample: React.FC = () => {
|
|
28612
|
+
const [showLeadingSection, setShowLeadingSection] = React.useState(false);
|
|
28613
|
+
|
|
28614
|
+
return (
|
|
28615
|
+
<>
|
|
28616
|
+
<ActionButton
|
|
28617
|
+
onPress={() => {
|
|
28618
|
+
setShowLeadingSection(true);
|
|
28619
|
+
}}
|
|
28620
|
+
label="Prepend section"
|
|
28621
|
+
/>
|
|
28622
|
+
<Virtualizer
|
|
28623
|
+
layout={ListLayout}
|
|
28624
|
+
layoutOptions={{
|
|
28625
|
+
rowHeight: 36,
|
|
28626
|
+
headingHeight: 40,
|
|
28627
|
+
}}
|
|
28628
|
+
>
|
|
28629
|
+
<ListBox
|
|
28630
|
+
items={
|
|
28631
|
+
showLeadingSection
|
|
28632
|
+
? [leadingSection, ...itemsWithSectionTitles]
|
|
28633
|
+
: itemsWithSectionTitles
|
|
28634
|
+
}
|
|
28635
|
+
showSectionHeader={true}
|
|
28636
|
+
style={{
|
|
28637
|
+
height: 400,
|
|
28638
|
+
width: 300,
|
|
28639
|
+
overflow: "auto",
|
|
28640
|
+
}}
|
|
28641
|
+
aria-label="Virtualized list box with a prependable section"
|
|
28642
|
+
/>
|
|
28643
|
+
</Virtualizer>
|
|
28644
|
+
</>
|
|
28645
|
+
);
|
|
28646
|
+
};
|
|
28647
|
+
|
|
28648
|
+
export const VirtualizedScrollIntoViewExample: React.FC = () => {
|
|
28649
|
+
const listBoxHandle = React.useRef<ListHandle>(null);
|
|
28650
|
+
const items = Array.from({ length: 10_000 }).map((_, i) => ({
|
|
28651
|
+
id: \`item-\${i}\`,
|
|
28652
|
+
label: \`Item \${i}\`,
|
|
28653
|
+
}));
|
|
28654
|
+
|
|
28655
|
+
return (
|
|
28656
|
+
<Box display="flex" flexDirection="column" gap="md" style={{ width: 300 }}>
|
|
28657
|
+
<Box display="flex" flexDirection="column" gap="sm">
|
|
27775
28658
|
<Text type="body" size="sm">
|
|
27776
28659
|
Scroll to items in a virtualized list (10,000 items). Items that
|
|
27777
28660
|
aren't currently rendered will be scrolled into view.
|
|
@@ -27819,7 +28702,110 @@ export const VirtualizedScrollIntoViewExample: React.FC = () => {
|
|
|
27819
28702
|
</Virtualizer>
|
|
27820
28703
|
</Box>
|
|
27821
28704
|
);
|
|
27822
|
-
}
|
|
28705
|
+
};
|
|
28706
|
+
|
|
28707
|
+
// Each example varies exactly one prop off \`count\` and keeps the rest at stable
|
|
28708
|
+
// module-level identity; varying several at once would let one invalidate the cache for
|
|
28709
|
+
// the others, hiding a missing \`dependencies\` entry.
|
|
28710
|
+
const stableRenderOption = (item: ListOptionType) => <span>{item.label}</span>;
|
|
28711
|
+
const stableOptionClassName = () => "option-stable";
|
|
28712
|
+
const stableOptionStyle = () => ({ marginBlockStart: "0px" });
|
|
28713
|
+
const stableSectionClassName = () => "section-stable";
|
|
28714
|
+
const stableSectionStyle = () => ({ marginBlockStart: "0px" });
|
|
28715
|
+
|
|
28716
|
+
// Offset off the \`0px\` browser default so the pre-click assertion also proves the prop
|
|
28717
|
+
// reached the DOM, not just that it refreshed.
|
|
28718
|
+
const varyingMargin = (count: number) => ({
|
|
28719
|
+
marginBlockStart: \`\${count + 2}px\`,
|
|
28720
|
+
});
|
|
28721
|
+
|
|
28722
|
+
const CountingExample: React.FC<{
|
|
28723
|
+
children: (count: number) => React.ReactNode;
|
|
28724
|
+
}> = ({ children }) => {
|
|
28725
|
+
const [count, setCount] = React.useState(0);
|
|
28726
|
+
|
|
28727
|
+
return (
|
|
28728
|
+
<>
|
|
28729
|
+
<ActionButton
|
|
28730
|
+
label="Increment"
|
|
28731
|
+
onPress={() => {
|
|
28732
|
+
setCount(count + 1);
|
|
28733
|
+
}}
|
|
28734
|
+
/>
|
|
28735
|
+
{children(count)}
|
|
28736
|
+
</>
|
|
28737
|
+
);
|
|
28738
|
+
};
|
|
28739
|
+
|
|
28740
|
+
export const CountingOptionListBoxExample: React.FC<{
|
|
28741
|
+
vary: "renderOption" | "optionClassName" | "optionStyle";
|
|
28742
|
+
// Options inside a section render through a second, nested collection that inherits the
|
|
28743
|
+
// root \`dependencies\` only via React Aria's collection context.
|
|
28744
|
+
sectioned?: boolean;
|
|
28745
|
+
}> = ({ vary, sectioned = false }) => (
|
|
28746
|
+
<CountingExample>
|
|
28747
|
+
{(count) => (
|
|
28748
|
+
<ListBox
|
|
28749
|
+
items={sectioned ? itemsWithSectionTitles : items}
|
|
28750
|
+
aria-label="Counting option list box"
|
|
28751
|
+
renderOption={
|
|
28752
|
+
vary === "renderOption"
|
|
28753
|
+
? (item) => <span>{\`\${item.label} count-\${count}\`}</span>
|
|
28754
|
+
: stableRenderOption
|
|
28755
|
+
}
|
|
28756
|
+
optionClassName={
|
|
28757
|
+
vary === "optionClassName"
|
|
28758
|
+
? () => \`option-count-\${count}\`
|
|
28759
|
+
: stableOptionClassName
|
|
28760
|
+
}
|
|
28761
|
+
optionStyle={
|
|
28762
|
+
vary === "optionStyle"
|
|
28763
|
+
? () => varyingMargin(count)
|
|
28764
|
+
: stableOptionStyle
|
|
28765
|
+
}
|
|
28766
|
+
/>
|
|
28767
|
+
)}
|
|
28768
|
+
</CountingExample>
|
|
28769
|
+
);
|
|
28770
|
+
|
|
28771
|
+
export const CountingSectionListBoxExample: React.FC<{
|
|
28772
|
+
vary:
|
|
28773
|
+
| "renderSectionHeader"
|
|
28774
|
+
| "sectionClassName"
|
|
28775
|
+
| "sectionStyle"
|
|
28776
|
+
| "showSectionHeader"
|
|
28777
|
+
| "withSectionHeaderPadding";
|
|
28778
|
+
}> = ({ vary }) => (
|
|
28779
|
+
<CountingExample>
|
|
28780
|
+
{(count) => (
|
|
28781
|
+
<ListBox
|
|
28782
|
+
items={itemsWithSectionTitles}
|
|
28783
|
+
aria-label="Counting section list box"
|
|
28784
|
+
// \`withSectionHeaderPadding\` only reaches the DOM through the default header, so
|
|
28785
|
+
// that variant must not supply a custom one.
|
|
28786
|
+
showSectionHeader={vary === "showSectionHeader" ? count > 0 : true}
|
|
28787
|
+
withSectionHeaderPadding={
|
|
28788
|
+
vary === "withSectionHeaderPadding" ? count > 0 : false
|
|
28789
|
+
}
|
|
28790
|
+
renderSectionHeader={
|
|
28791
|
+
vary === "renderSectionHeader"
|
|
28792
|
+
? (section) => \`\${section.title} count-\${count}\`
|
|
28793
|
+
: undefined
|
|
28794
|
+
}
|
|
28795
|
+
sectionClassName={
|
|
28796
|
+
vary === "sectionClassName"
|
|
28797
|
+
? () => \`section-count-\${count}\`
|
|
28798
|
+
: stableSectionClassName
|
|
28799
|
+
}
|
|
28800
|
+
sectionStyle={
|
|
28801
|
+
vary === "sectionStyle"
|
|
28802
|
+
? () => varyingMargin(count)
|
|
28803
|
+
: stableSectionStyle
|
|
28804
|
+
}
|
|
28805
|
+
/>
|
|
28806
|
+
)}
|
|
28807
|
+
</CountingExample>
|
|
28808
|
+
);`},similarTo:[],figmaUrl:null},Virtualizer:{id:"core-collections-virtualizer",breadcrumb:"Core/Collections/Virtualizer",importStatement:'import { Virtualizer } from "react-aria-components";',description:"`Virtualizer` renders large collections efficiently by keeping only the visible portion of the collection in the DOM. In baseline-ui it is typically paired with collection components such as `UNSAFE_ListBox`, `TreeView`, and `ImageGallery`.",documentation:`\`Virtualizer\` renders large collections efficiently by keeping only the visible portion of the collection in the DOM. In baseline-ui it is typically paired with collection components such as \`UNSAFE_ListBox\`, \`TreeView\`, and \`ImageGallery\`.
|
|
27823
28809
|
|
|
27824
28810
|
* Efficient rendering for very large collections
|
|
27825
28811
|
* Preset layout options for list boxes, tree views, and image galleries
|
|
@@ -30797,25 +31783,13 @@ export const PopoverDefaultOpenWithArrowExample = () => {
|
|
|
30797
31783
|
);
|
|
30798
31784
|
};
|
|
30799
31785
|
|
|
30800
|
-
export const PopoverContainedFocusExample = (
|
|
30801
|
-
|
|
30802
|
-
|
|
30803
|
-
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
<Dialog
|
|
30808
|
-
size="content"
|
|
30809
|
-
className={sprinkles({
|
|
30810
|
-
padding: "md",
|
|
30811
|
-
display: "flex",
|
|
30812
|
-
gap: "xl",
|
|
30813
|
-
flexDirection: "column",
|
|
30814
|
-
})}
|
|
30815
|
-
style={{
|
|
30816
|
-
width: 200,
|
|
30817
|
-
}}
|
|
30818
|
-
>
|
|
31786
|
+
export const PopoverContainedFocusExample = ({
|
|
31787
|
+
shouldContainFocus = true,
|
|
31788
|
+
}: {
|
|
31789
|
+
shouldContainFocus?: boolean;
|
|
31790
|
+
}) => {
|
|
31791
|
+
const content = (
|
|
31792
|
+
<>
|
|
30819
31793
|
<Text type="label">The focus is contained within the popover.</Text>
|
|
30820
31794
|
|
|
30821
31795
|
<TextInput
|
|
@@ -30827,10 +31801,55 @@ export const PopoverContainedFocusExample = () => {
|
|
|
30827
31801
|
label="Button"
|
|
30828
31802
|
style={{ width: "100%", justifyContent: "center" }}
|
|
30829
31803
|
/>
|
|
31804
|
+
</>
|
|
31805
|
+
);
|
|
31806
|
+
const contentClassName = sprinkles({
|
|
31807
|
+
padding: "md",
|
|
31808
|
+
display: "flex",
|
|
31809
|
+
gap: "xl",
|
|
31810
|
+
flexDirection: "column",
|
|
31811
|
+
});
|
|
31812
|
+
|
|
31813
|
+
const popover = (
|
|
31814
|
+
<Popover type="dialog">
|
|
31815
|
+
<PopoverTrigger>
|
|
31816
|
+
<ActionButton label="Open" />
|
|
31817
|
+
</PopoverTrigger>
|
|
31818
|
+
<PopoverContent
|
|
31819
|
+
shouldContainFocus={shouldContainFocus}
|
|
31820
|
+
isNonModal={!shouldContainFocus}
|
|
31821
|
+
>
|
|
31822
|
+
{shouldContainFocus ? (
|
|
31823
|
+
<Dialog
|
|
31824
|
+
size="content"
|
|
31825
|
+
className={contentClassName}
|
|
31826
|
+
style={{ width: 200 }}
|
|
31827
|
+
>
|
|
31828
|
+
{content}
|
|
30830
31829
|
</Dialog>
|
|
31830
|
+
) : (
|
|
31831
|
+
// No Dialog: useDialog opts the overlay into focus containment,
|
|
31832
|
+
// which disables the Tab-out restore path.
|
|
31833
|
+
<Box className={contentClassName} style={{ width: 200 }}>
|
|
31834
|
+
{content}
|
|
31835
|
+
</Box>
|
|
31836
|
+
)}
|
|
30831
31837
|
</PopoverContent>
|
|
30832
31838
|
</Popover>
|
|
30833
31839
|
);
|
|
31840
|
+
|
|
31841
|
+
// The contained variant is the \`ContainedFocus\` story: a wrapper or sibling
|
|
31842
|
+
// here rebaselines its visual snapshot.
|
|
31843
|
+
if (shouldContainFocus) {
|
|
31844
|
+
return popover;
|
|
31845
|
+
}
|
|
31846
|
+
|
|
31847
|
+
return (
|
|
31848
|
+
<Box display="flex" flexDirection="column" gap="lg" alignItems="flex-start">
|
|
31849
|
+
{popover}
|
|
31850
|
+
<ActionButton label="After" />
|
|
31851
|
+
</Box>
|
|
31852
|
+
);
|
|
30834
31853
|
};
|
|
30835
31854
|
|
|
30836
31855
|
export const PopoverWithScrollableViewportExample: React.FC<{
|
|
@@ -31957,25 +32976,13 @@ export const PopoverDefaultOpenWithArrowExample = () => {
|
|
|
31957
32976
|
);
|
|
31958
32977
|
};
|
|
31959
32978
|
|
|
31960
|
-
export const PopoverContainedFocusExample = (
|
|
31961
|
-
|
|
31962
|
-
|
|
31963
|
-
|
|
31964
|
-
|
|
31965
|
-
|
|
31966
|
-
|
|
31967
|
-
<Dialog
|
|
31968
|
-
size="content"
|
|
31969
|
-
className={sprinkles({
|
|
31970
|
-
padding: "md",
|
|
31971
|
-
display: "flex",
|
|
31972
|
-
gap: "xl",
|
|
31973
|
-
flexDirection: "column",
|
|
31974
|
-
})}
|
|
31975
|
-
style={{
|
|
31976
|
-
width: 200,
|
|
31977
|
-
}}
|
|
31978
|
-
>
|
|
32979
|
+
export const PopoverContainedFocusExample = ({
|
|
32980
|
+
shouldContainFocus = true,
|
|
32981
|
+
}: {
|
|
32982
|
+
shouldContainFocus?: boolean;
|
|
32983
|
+
}) => {
|
|
32984
|
+
const content = (
|
|
32985
|
+
<>
|
|
31979
32986
|
<Text type="label">The focus is contained within the popover.</Text>
|
|
31980
32987
|
|
|
31981
32988
|
<TextInput
|
|
@@ -31987,10 +32994,55 @@ export const PopoverContainedFocusExample = () => {
|
|
|
31987
32994
|
label="Button"
|
|
31988
32995
|
style={{ width: "100%", justifyContent: "center" }}
|
|
31989
32996
|
/>
|
|
32997
|
+
</>
|
|
32998
|
+
);
|
|
32999
|
+
const contentClassName = sprinkles({
|
|
33000
|
+
padding: "md",
|
|
33001
|
+
display: "flex",
|
|
33002
|
+
gap: "xl",
|
|
33003
|
+
flexDirection: "column",
|
|
33004
|
+
});
|
|
33005
|
+
|
|
33006
|
+
const popover = (
|
|
33007
|
+
<Popover type="dialog">
|
|
33008
|
+
<PopoverTrigger>
|
|
33009
|
+
<ActionButton label="Open" />
|
|
33010
|
+
</PopoverTrigger>
|
|
33011
|
+
<PopoverContent
|
|
33012
|
+
shouldContainFocus={shouldContainFocus}
|
|
33013
|
+
isNonModal={!shouldContainFocus}
|
|
33014
|
+
>
|
|
33015
|
+
{shouldContainFocus ? (
|
|
33016
|
+
<Dialog
|
|
33017
|
+
size="content"
|
|
33018
|
+
className={contentClassName}
|
|
33019
|
+
style={{ width: 200 }}
|
|
33020
|
+
>
|
|
33021
|
+
{content}
|
|
31990
33022
|
</Dialog>
|
|
33023
|
+
) : (
|
|
33024
|
+
// No Dialog: useDialog opts the overlay into focus containment,
|
|
33025
|
+
// which disables the Tab-out restore path.
|
|
33026
|
+
<Box className={contentClassName} style={{ width: 200 }}>
|
|
33027
|
+
{content}
|
|
33028
|
+
</Box>
|
|
33029
|
+
)}
|
|
31991
33030
|
</PopoverContent>
|
|
31992
33031
|
</Popover>
|
|
31993
33032
|
);
|
|
33033
|
+
|
|
33034
|
+
// The contained variant is the \`ContainedFocus\` story: a wrapper or sibling
|
|
33035
|
+
// here rebaselines its visual snapshot.
|
|
33036
|
+
if (shouldContainFocus) {
|
|
33037
|
+
return popover;
|
|
33038
|
+
}
|
|
33039
|
+
|
|
33040
|
+
return (
|
|
33041
|
+
<Box display="flex" flexDirection="column" gap="lg" alignItems="flex-start">
|
|
33042
|
+
{popover}
|
|
33043
|
+
<ActionButton label="After" />
|
|
33044
|
+
</Box>
|
|
33045
|
+
);
|
|
31994
33046
|
};
|
|
31995
33047
|
|
|
31996
33048
|
export const PopoverWithScrollableViewportExample: React.FC<{
|
|
@@ -32756,7 +33808,15 @@ iconTooltip?: ActionIconButtonProps["tooltip"]
|
|
|
32756
33808
|
placeholder="Select"
|
|
32757
33809
|
items={items}
|
|
32758
33810
|
isReadOnly
|
|
32759
|
-
value="square" />;`}
|
|
33811
|
+
value="square" />;`},{id:"core-forms-select-iconselect--without-icon",name:"Without Icon",snippet:`const WithoutIcon = () => <IconSelect
|
|
33812
|
+
aria-label="Choose Stroke Style"
|
|
33813
|
+
placeholder="Select"
|
|
33814
|
+
items={items}
|
|
33815
|
+
icon={undefined} />;`},{id:"core-forms-select-iconselect--with-default-open",name:"With Default Open",snippet:`const WithDefaultOpen = () => <IconSelect
|
|
33816
|
+
aria-label="Choose Stroke Style"
|
|
33817
|
+
placeholder="Select"
|
|
33818
|
+
items={items}
|
|
33819
|
+
defaultOpen />;`}],implementation:`import { EllipseIcon } from "@baseline-ui/icons/24";
|
|
32760
33820
|
import React from "react";
|
|
32761
33821
|
import { useFilter } from "react-aria";
|
|
32762
33822
|
import { Autocomplete, Virtualizer } from "react-aria-components";
|
|
@@ -32765,11 +33825,16 @@ import { useListData } from "react-stately";
|
|
|
32765
33825
|
import { ActionButton } from "../../ActionButton";
|
|
32766
33826
|
import { items } from "../../ListBox/__tests__/testComponents";
|
|
32767
33827
|
import { virtualizeAutocompleteItems } from "../../Menu/__tests__/data";
|
|
32768
|
-
import {
|
|
33828
|
+
import { itemsWithSectionTitles } from "../../UNSAFE_ListBox/__tests__/testComponents";
|
|
33829
|
+
import {
|
|
33830
|
+
ListLayout,
|
|
33831
|
+
VIRTUALIZER_LAYOUT_DEFAULT_OPTIONS,
|
|
33832
|
+
} from "../../Virtualizer";
|
|
32769
33833
|
import { IconSelect } from "../IconSelect";
|
|
32770
33834
|
import { Select } from "../Select";
|
|
32771
33835
|
|
|
32772
33836
|
import type { IconSelectProps } from "../Select.types";
|
|
33837
|
+
import type { Key } from "@react-types/shared";
|
|
32773
33838
|
|
|
32774
33839
|
export const SelectExample: React.FC<
|
|
32775
33840
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
@@ -32777,13 +33842,28 @@ export const SelectExample: React.FC<
|
|
|
32777
33842
|
return (
|
|
32778
33843
|
<Select
|
|
32779
33844
|
placeholder="Choose an item"
|
|
32780
|
-
{...args}
|
|
32781
33845
|
optionClassName={(item) => item.label}
|
|
33846
|
+
{...args}
|
|
32782
33847
|
items={items}
|
|
32783
33848
|
/>
|
|
32784
33849
|
);
|
|
32785
33850
|
};
|
|
32786
33851
|
|
|
33852
|
+
// "Apples" is a substring of "Pineapples" \u2014 exercises exact string matching
|
|
33853
|
+
// in the tester's option() locator.
|
|
33854
|
+
const substringItems = [
|
|
33855
|
+
{ id: "apples", label: "Apples" },
|
|
33856
|
+
{ id: "pineapples", label: "Pineapples" },
|
|
33857
|
+
];
|
|
33858
|
+
|
|
33859
|
+
export const SelectSubstringLabelsExample: React.FC<
|
|
33860
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
33861
|
+
> = (args) => {
|
|
33862
|
+
return (
|
|
33863
|
+
<Select placeholder="Choose an item" {...args} items={substringItems} />
|
|
33864
|
+
);
|
|
33865
|
+
};
|
|
33866
|
+
|
|
32787
33867
|
export const SelectGetTargetRectExample: React.FC = () => {
|
|
32788
33868
|
const [called, setCalled] = React.useState(false);
|
|
32789
33869
|
|
|
@@ -32840,19 +33920,136 @@ export const SelectCustomTriggerExample: React.FC<
|
|
|
32840
33920
|
};
|
|
32841
33921
|
|
|
32842
33922
|
export const IconSelectExample: React.FC<
|
|
32843
|
-
Omit<IconSelectProps, "items" | "
|
|
33923
|
+
Omit<IconSelectProps, "items" | "aria-label">
|
|
32844
33924
|
> = (args) => {
|
|
32845
33925
|
return (
|
|
32846
33926
|
<IconSelect
|
|
32847
33927
|
placeholder="Choose an item"
|
|
33928
|
+
icon={EllipseIcon}
|
|
32848
33929
|
{...args}
|
|
32849
33930
|
items={items}
|
|
32850
|
-
icon={EllipseIcon}
|
|
32851
33931
|
aria-label="Aria Label"
|
|
32852
33932
|
/>
|
|
32853
33933
|
);
|
|
32854
33934
|
};
|
|
32855
33935
|
|
|
33936
|
+
export const VirtualSelectWithSectionHeadersExample: React.FC<
|
|
33937
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
33938
|
+
> = (args) => {
|
|
33939
|
+
return (
|
|
33940
|
+
<Virtualizer
|
|
33941
|
+
layout={ListLayout}
|
|
33942
|
+
layoutOptions={{
|
|
33943
|
+
rowHeight: 36,
|
|
33944
|
+
headingHeight: 40,
|
|
33945
|
+
}}
|
|
33946
|
+
>
|
|
33947
|
+
<Select
|
|
33948
|
+
aria-label="Choose an item"
|
|
33949
|
+
placeholder="Choose an item"
|
|
33950
|
+
showSectionHeader={true}
|
|
33951
|
+
{...args}
|
|
33952
|
+
items={itemsWithSectionTitles}
|
|
33953
|
+
defaultOpen={true}
|
|
33954
|
+
maxHeight={400}
|
|
33955
|
+
/>
|
|
33956
|
+
</Virtualizer>
|
|
33957
|
+
);
|
|
33958
|
+
};
|
|
33959
|
+
|
|
33960
|
+
export const SelectWithSectionHeadersExample: React.FC<
|
|
33961
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
33962
|
+
> = (args) => {
|
|
33963
|
+
return (
|
|
33964
|
+
<Select
|
|
33965
|
+
aria-label="Choose an item"
|
|
33966
|
+
placeholder="Choose an item"
|
|
33967
|
+
showSectionHeader={true}
|
|
33968
|
+
{...args}
|
|
33969
|
+
items={itemsWithSectionTitles}
|
|
33970
|
+
defaultOpen={true}
|
|
33971
|
+
/>
|
|
33972
|
+
);
|
|
33973
|
+
};
|
|
33974
|
+
|
|
33975
|
+
/**
|
|
33976
|
+
* Owns \`isOpen\` so the controlled-open contract can be driven from outside the
|
|
33977
|
+
* Select, with a sibling readout of the current state.
|
|
33978
|
+
*/
|
|
33979
|
+
export const ControlledOpenSelectExample: React.FC<
|
|
33980
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
33981
|
+
> = (args) => {
|
|
33982
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
33983
|
+
|
|
33984
|
+
return (
|
|
33985
|
+
<>
|
|
33986
|
+
<Select
|
|
33987
|
+
aria-label="Choose an item"
|
|
33988
|
+
placeholder="Choose an item"
|
|
33989
|
+
{...args}
|
|
33990
|
+
items={items}
|
|
33991
|
+
isOpen={isOpen}
|
|
33992
|
+
onOpenChange={setIsOpen}
|
|
33993
|
+
/>
|
|
33994
|
+
<button
|
|
33995
|
+
data-testid="open-externally"
|
|
33996
|
+
onClick={() => {
|
|
33997
|
+
setIsOpen(true);
|
|
33998
|
+
}}
|
|
33999
|
+
>
|
|
34000
|
+
Open
|
|
34001
|
+
</button>
|
|
34002
|
+
<span data-testid="open-state">{String(isOpen)}</span>
|
|
34003
|
+
</>
|
|
34004
|
+
);
|
|
34005
|
+
};
|
|
34006
|
+
|
|
34007
|
+
/**
|
|
34008
|
+
* Custom trigger that renders the multi-select half of the \`renderTrigger\`
|
|
34009
|
+
* payload \u2014 \`selectionMode\`, \`maxCount\` and \`onRemove\` \u2014 which the default
|
|
34010
|
+
* \`SelectButton\` otherwise keeps to itself.
|
|
34011
|
+
*/
|
|
34012
|
+
export const MultiSelectCustomTriggerExample: React.FC<
|
|
34013
|
+
Omit<React.ComponentProps<typeof Select>, "items">
|
|
34014
|
+
> = (args) => {
|
|
34015
|
+
return (
|
|
34016
|
+
<Select
|
|
34017
|
+
aria-label="Choose an item"
|
|
34018
|
+
selectionMode="multiple"
|
|
34019
|
+
{...args}
|
|
34020
|
+
items={items}
|
|
34021
|
+
renderTrigger={({
|
|
34022
|
+
buttonProps,
|
|
34023
|
+
ref,
|
|
34024
|
+
selectedValue,
|
|
34025
|
+
selectionMode,
|
|
34026
|
+
onRemove,
|
|
34027
|
+
maxCount,
|
|
34028
|
+
}) => (
|
|
34029
|
+
<div>
|
|
34030
|
+
<ActionButton
|
|
34031
|
+
{...buttonProps}
|
|
34032
|
+
ref={ref}
|
|
34033
|
+
label={\`\${selectionMode}|\${maxCount}|\${selectedValue?.length ?? 0}\`}
|
|
34034
|
+
variant="popover"
|
|
34035
|
+
/>
|
|
34036
|
+
<button
|
|
34037
|
+
data-testid="remove-first"
|
|
34038
|
+
onClick={() => {
|
|
34039
|
+
const first = selectedValue?.[0];
|
|
34040
|
+
if (first) {
|
|
34041
|
+
onRemove?.(new Set([first.id]));
|
|
34042
|
+
}
|
|
34043
|
+
}}
|
|
34044
|
+
>
|
|
34045
|
+
Remove first
|
|
34046
|
+
</button>
|
|
34047
|
+
</div>
|
|
34048
|
+
)}
|
|
34049
|
+
/>
|
|
34050
|
+
);
|
|
34051
|
+
};
|
|
34052
|
+
|
|
32856
34053
|
export const SelectWithVirtualizeAutocompleteExample: React.FC<
|
|
32857
34054
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
32858
34055
|
> = (args) => {
|
|
@@ -32876,6 +34073,27 @@ export const SelectWithVirtualizeAutocompleteExample: React.FC<
|
|
|
32876
34073
|
</Autocomplete>
|
|
32877
34074
|
</Virtualizer>
|
|
32878
34075
|
);
|
|
34076
|
+
};
|
|
34077
|
+
|
|
34078
|
+
/**
|
|
34079
|
+
* \`optionClassName\` reads component state, and \`items\` is module-level so React Aria's
|
|
34080
|
+
* per-item element cache applies. Pinned open so the state change comes from selecting an
|
|
34081
|
+
* option rather than from an outside press the popover would swallow.
|
|
34082
|
+
*/
|
|
34083
|
+
export const CountingSelectExample: React.FC = () => {
|
|
34084
|
+
const [selected, setSelected] = React.useState<Key | null>(null);
|
|
34085
|
+
|
|
34086
|
+
return (
|
|
34087
|
+
<Select
|
|
34088
|
+
aria-label="Counting select"
|
|
34089
|
+
items={items}
|
|
34090
|
+
isOpen={true}
|
|
34091
|
+
optionClassName={(item) =>
|
|
34092
|
+
item.id === selected ? "option-picked" : "option-plain"
|
|
34093
|
+
}
|
|
34094
|
+
onSelectionChange={setSelected}
|
|
34095
|
+
/>
|
|
34096
|
+
);
|
|
32879
34097
|
};`},similarTo:[],figmaUrl:null},IconSlider:{id:"core-forms-slider-iconslider",importStatement:'import { IconSlider } from "@baseline-ui/core";',description:"",documentation:null,props:`interface IconSliderProps {
|
|
32880
34098
|
/**
|
|
32881
34099
|
* @deprecated Do not use in new components. This is a legacy block
|
|
@@ -32986,6 +34204,21 @@ import { ActionButton, I18nProvider, ThemeProvider } from "@baseline-ui/core";
|
|
|
32986
34204
|
|
|
32987
34205
|
It\u2019s important to wrap your application with the \`ThemeProvider\` and \`I18nProvider\` components. The \`ThemeProvider\` component provides the theme to all the components in the tree, and the \`I18nProvider\` component provides the locale to all the components in the tree.
|
|
32988
34206
|
|
|
34207
|
+
### Translations
|
|
34208
|
+
|
|
34209
|
+
Components render English out of the box. Translations ship as one JSON file per locale so projects that only need English don\u2019t pay for the other 32 \u2014 import the ones you need and pass them to \`I18nProvider\`:
|
|
34210
|
+
|
|
34211
|
+
\`\`\`jsx
|
|
34212
|
+
import { I18nProvider } from "@baseline-ui/core";
|
|
34213
|
+
import de from "@baseline-ui/core/intl/de.json";
|
|
34214
|
+
|
|
34215
|
+
<I18nProvider locale="de-DE" messages={{ de }}>
|
|
34216
|
+
<YourApp />
|
|
34217
|
+
</I18nProvider>;
|
|
34218
|
+
\`\`\`
|
|
34219
|
+
|
|
34220
|
+
Any string a catalog omits falls back to English. See [Internationalization](?path=/docs/internationalization--docs) for the full list of locales and message IDs, lazy loading, and overriding individual strings.
|
|
34221
|
+
|
|
32989
34222
|
### Styling
|
|
32990
34223
|
|
|
32991
34224
|
Import the following files at the top of your stylesheet to use the Baseline UI styles:
|
|
@@ -33254,22 +34487,24 @@ function App() {
|
|
|
33254
34487
|
}
|
|
33255
34488
|
\`\`\``,internationalization:`# Internationalization
|
|
33256
34489
|
|
|
33257
|
-
It\u2019s important the content of your website is accessible to as many people as possible. This includes people who speak different languages and people who use screen readers. Internationalization (i18n) is the process of making your website accessible to people who speak different languages. Baseline UI supports internationalization for many of the components out of the box
|
|
34490
|
+
It\u2019s important the content of your website is accessible to as many people as possible. This includes people who speak different languages and people who use screen readers. Internationalization (i18n) is the process of making your website accessible to people who speak different languages. Baseline UI supports internationalization for many of the components out of the box: localization of dates and times, number formatting, currency formatting, collation, and text direction all follow the active locale with no setup.
|
|
34491
|
+
|
|
34492
|
+
Translated strings are the one part you opt into. Components render English until you import a catalog and pass it to \`I18nProvider\`, so an application that ships in English carries none of the other locales in its bundle. See [Loading a translation catalog](#loading-a-translation-catalog).
|
|
33258
34493
|
|
|
33259
34494
|
## Localization
|
|
33260
34495
|
|
|
33261
|
-
Localization is the process of translating your website into different languages. Baseline UI supports localization of the built-in strings, dates and times, number/currency formatting, collating and sorting, text search, and more. It\u2019s built on top of [react-aria](https://react-spectrum.adobe.com/react-aria),
|
|
34496
|
+
Localization is the process of translating your website into different languages. Baseline UI supports localization of the built-in strings, dates and times, number/currency formatting, collating and sorting, text search, and more. It\u2019s built on top of [react-aria](https://react-spectrum.adobe.com/react-aria), whose own strings \u2014 the announcements a date picker or a drag handle makes to a screen reader \u2014 are bundled and translated for you. Baseline UI\u2019s strings are the ones you load a catalog for, and you can add your own on top.
|
|
33262
34497
|
|
|
33263
|
-
Baseline UI automatically detects a user\u2019s preferred language from the browser, and it uses that language for all localization. It\u2019s possible to override the language used for localization by providing a \`locale\` prop to the \`
|
|
34498
|
+
Baseline UI automatically detects a user\u2019s preferred language from the browser, and it uses that language for all localization. It\u2019s possible to override the language used for localization by providing a \`locale\` prop to the \`I18nProvider\` component.
|
|
33264
34499
|
|
|
33265
34500
|
See [\`useMessageFormatter\`](https://react-spectrum.adobe.com/react-aria/useMessageFormatter.html), [\`DateFormat\`](/?path=/docs/utilities-dateformat--docs), [\`NumberFormat\`](/?path=/docs/utilities-numberformat--docs), and [\`useCollator\`](https://react-spectrum.adobe.com/react-aria/useCollator.html) for more information about using our internationalization hooks.
|
|
33266
34501
|
|
|
33267
34502
|
### Example
|
|
33268
34503
|
|
|
33269
|
-
The rootmost element of your application should define the [\`lang\`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and [\`dir\`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) attributes so that the browser knows which language and direction the user interface should be rendered in. This can be done with the \`useLocale\` hook
|
|
34504
|
+
The rootmost element of your application should define the [\`lang\`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and [\`dir\`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) attributes so that the browser knows which language and direction the user interface should be rendered in. This can be done with the \`useLocale\` hook:
|
|
33270
34505
|
|
|
33271
34506
|
\`\`\`jsx
|
|
33272
|
-
import { useLocale } from "
|
|
34507
|
+
import { useLocale } from "@baseline-ui/core";
|
|
33273
34508
|
|
|
33274
34509
|
function YourApp() {
|
|
33275
34510
|
let { locale, direction } = useLocale();
|
|
@@ -33285,27 +34520,128 @@ function YourApp() {
|
|
|
33285
34520
|
You can also override the language used for localization with the [\`I18nProvider\`](/?path=/docs/utilities-i18nprovider--docs) component:
|
|
33286
34521
|
|
|
33287
34522
|
\`\`\`jsx
|
|
33288
|
-
import { I18nProvider } from "
|
|
34523
|
+
import { I18nProvider } from "@baseline-ui/core";
|
|
33289
34524
|
|
|
33290
34525
|
<I18nProvider locale="fr-FR">
|
|
33291
34526
|
<YourApp />
|
|
33292
34527
|
</I18nProvider>;
|
|
33293
34528
|
\`\`\`
|
|
33294
34529
|
|
|
34530
|
+
Setting \`locale\` alone switches date, number and collation formatting, and flips text direction for RTL languages. It does not translate Baseline UI\u2019s own strings \u2014 for that, load a catalog.
|
|
34531
|
+
|
|
34532
|
+
### Loading a translation catalog
|
|
34533
|
+
|
|
34534
|
+
Import the catalogs for the languages you ship and hand them to \`I18nProvider\`:
|
|
34535
|
+
|
|
34536
|
+
\`\`\`jsx
|
|
34537
|
+
import { I18nProvider } from "@baseline-ui/core";
|
|
34538
|
+
import de from "@baseline-ui/core/intl/de.json";
|
|
34539
|
+
import fr from "@baseline-ui/core/intl/fr.json";
|
|
34540
|
+
|
|
34541
|
+
// Hoisted out of render: a fresh object each render rebuilds the message
|
|
34542
|
+
// formatter, so every string reformats on every pass.
|
|
34543
|
+
const messages = { de, fr };
|
|
34544
|
+
|
|
34545
|
+
<I18nProvider locale="de-DE" messages={messages}>
|
|
34546
|
+
<YourApp />
|
|
34547
|
+
</I18nProvider>;
|
|
34548
|
+
\`\`\`
|
|
34549
|
+
|
|
34550
|
+
Each file is a flat map of \`bui.*\` ID to translated string, so your bundler includes only
|
|
34551
|
+
the locales you actually import. The key you file a catalog under is matched against the
|
|
34552
|
+
active locale exactly first, then by language, then by any other region of that language \u2014
|
|
34553
|
+
so \`{ de }\` answers for \`de\`, \`de-DE\` and \`de-AT\` alike, and \`{ de, "de-AT" }\` under
|
|
34554
|
+
\`de-AT\` uses the Austrian entry.
|
|
34555
|
+
|
|
34556
|
+
TypeScript needs \`resolveJsonModule\` enabled to import the files, and Node ESM needs a
|
|
34557
|
+
\`with { type: "json" }\` import attribute.
|
|
34558
|
+
|
|
34559
|
+
To avoid shipping every language up front, put each catalog behind a dynamic \`import()\`
|
|
34560
|
+
and load one when the user picks a language. Write the specifiers out in full \u2014 a
|
|
34561
|
+
template literal over a bare package subpath is not statically analyzable, so bundlers
|
|
34562
|
+
cannot split on it:
|
|
34563
|
+
|
|
34564
|
+
\`\`\`jsx
|
|
34565
|
+
const catalogs = {
|
|
34566
|
+
de: () => import("@baseline-ui/core/intl/de.json"),
|
|
34567
|
+
fr: () => import("@baseline-ui/core/intl/fr.json"),
|
|
34568
|
+
};
|
|
34569
|
+
|
|
34570
|
+
const [messages, setMessages] = useState({});
|
|
34571
|
+
|
|
34572
|
+
async function selectLocale(locale) {
|
|
34573
|
+
const catalog = await catalogs[locale]();
|
|
34574
|
+
|
|
34575
|
+
setMessages({ [locale]: catalog.default });
|
|
34576
|
+
}
|
|
34577
|
+
\`\`\`
|
|
34578
|
+
|
|
34579
|
+
An ID your catalog omits falls back to that component's English \`defaultMessage\`, so a
|
|
34580
|
+
partial catalog is a valid one \u2014 you are never forced to translate a string before you
|
|
34581
|
+
ship it. Outside production, each such ID is reported once in the console.
|
|
34582
|
+
|
|
34583
|
+
If you supply catalogs but none of them matches the active locale \u2014 \`{ de }\` while the
|
|
34584
|
+
locale is \`ja-JP\`, say \u2014 every string falls back to English and that is reported once for
|
|
34585
|
+
the locale rather than once per ID. It means the catalog keys and the locale disagree,
|
|
34586
|
+
which no per-ID warning can tell you. Supplying no catalogs at all is the supported
|
|
34587
|
+
English-only mode and stays silent.
|
|
34588
|
+
|
|
33295
34589
|
### Supported locales
|
|
33296
34590
|
|
|
33297
|
-
|
|
34591
|
+
A catalog ships for each of these locales, with an entry for every message ID:
|
|
34592
|
+
|
|
34593
|
+
### Message IDs
|
|
34594
|
+
|
|
34595
|
+
Every string Baseline UI can render is keyed by a \`bui.<component>.<key>\` ID. The same
|
|
34596
|
+
list is exported as a value, so you can derive translation coverage in a test instead of
|
|
34597
|
+
committing a copy that goes stale on the next upgrade:
|
|
34598
|
+
|
|
34599
|
+
\`\`\`ts
|
|
34600
|
+
import { messageIds } from "@baseline-ui/core";
|
|
34601
|
+
|
|
34602
|
+
const uncovered = messageIds.filter((id) => !(id in ourCatalog.en));
|
|
34603
|
+
\`\`\`
|
|
34604
|
+
|
|
34605
|
+
For the English string behind each ID \u2014 and the translator context that goes with it \u2014
|
|
34606
|
+
read \`@baseline-ui/core/messages.json\`, the extracted source messages keyed by ID.
|
|
33298
34607
|
|
|
33299
|
-
###
|
|
34608
|
+
### Translating them yourself
|
|
33300
34609
|
|
|
33301
|
-
|
|
34610
|
+
If you localize the \`bui.*\` strings in your own pipeline rather than shipping our catalogs,
|
|
34611
|
+
hand your translators \`@baseline-ui/core/messages.json\` \u2014 the extracted source messages,
|
|
34612
|
+
keyed by ID and shaped the way a TMS expects:
|
|
34613
|
+
|
|
34614
|
+
\`\`\`json
|
|
34615
|
+
{
|
|
34616
|
+
"bui.select.more": {
|
|
34617
|
+
"defaultMessage": "+{count} more",
|
|
34618
|
+
"description": "Tag shown on the select trigger standing in for the selected options that did not fit \u2014 renders as '+3 more'. ..."
|
|
34619
|
+
}
|
|
34620
|
+
}
|
|
34621
|
+
\`\`\`
|
|
34622
|
+
|
|
34623
|
+
The \`description\` is the context a translator needs and cannot infer from the string
|
|
34624
|
+
alone \u2014 part of speech, sense, and where it renders. Translating \`bui.editor.mention\`
|
|
34625
|
+
without it yields the verb "to mention" where the noun label belongs, and
|
|
34626
|
+
\`bui.editor.shortcut\` becomes a desktop shortcut file rather than a key combination.
|
|
33302
34627
|
|
|
33303
34628
|
## Overriding Component Translations
|
|
33304
34629
|
|
|
33305
34630
|
You can override any built-in component string by passing its \`bui.*\`-namespaced key to
|
|
33306
34631
|
\`I18nProvider.messages\`. Only the keys you provide are overridden \u2014 all other strings
|
|
33307
|
-
fall back to each component's
|
|
33308
|
-
|
|
34632
|
+
fall back to each component's English \`defaultMessage\`. Spread a shipped catalog and
|
|
34633
|
+
override on top of it to change a single string:
|
|
34634
|
+
|
|
34635
|
+
\`\`\`jsx
|
|
34636
|
+
import de from "@baseline-ui/core/intl/de.json";
|
|
34637
|
+
|
|
34638
|
+
<I18nProvider
|
|
34639
|
+
locale="de-DE"
|
|
34640
|
+
messages={{ de: { ...de, "bui.imageDropZone.selectImage": "Bild w\xE4hlen" } }}
|
|
34641
|
+
>
|
|
34642
|
+
<YourApp />
|
|
34643
|
+
</I18nProvider>;
|
|
34644
|
+
\`\`\`
|
|
33309
34645
|
|
|
33310
34646
|
Each component's documentation lists its overridable keys and shows an example. See:
|
|
33311
34647
|
|
|
@@ -33313,7 +34649,43 @@ Each component's documentation lists its overridable keys and shows an example.
|
|
|
33313
34649
|
* [ColorInput](?path=/docs/components-colorinput--docs#translations)
|
|
33314
34650
|
* [ImageDropZone](?path=/docs/components-imagedropzone--docs#translations)
|
|
33315
34651
|
* [FreehandCanvas](?path=/docs/components-freehandcanvas--docs#translations)
|
|
33316
|
-
* [InlineAlert](?path=/docs/components-inlinealert--docs#translations)
|
|
34652
|
+
* [InlineAlert](?path=/docs/components-inlinealert--docs#translations)
|
|
34653
|
+
|
|
34654
|
+
### Migrating from bare IDs
|
|
34655
|
+
|
|
34656
|
+
Older catalogs key off the bare tail of an ID (\`close\` rather than \`bui.drawer.close\`).
|
|
34657
|
+
That still resolves, with a deprecation warning, but it will be removed in a future
|
|
34658
|
+
major \u2014 and it is ambiguous: several bare IDs are claimed by more than one component,
|
|
34659
|
+
so a single entry silently translates all of them. That happens to work in English, but
|
|
34660
|
+
it forecloses any language where the word inflects differently per context.
|
|
34661
|
+
|
|
34662
|
+
\`legacyMessageIdMap\` maps each bare ID to every namespaced ID that claims it, so a catalog
|
|
34663
|
+
can be re-keyed mechanically. Keep each original key alongside the IDs it maps to \u2014 a bare
|
|
34664
|
+
key may also be one your own app looks up, and Baseline UI resolves the namespaced entry
|
|
34665
|
+
either way:
|
|
34666
|
+
|
|
34667
|
+
\`\`\`ts
|
|
34668
|
+
import { legacyMessageIdMap } from "@baseline-ui/core";
|
|
34669
|
+
|
|
34670
|
+
const migrated = Object.fromEntries(
|
|
34671
|
+
Object.entries(oldCatalog).flatMap(([key, value]) => [
|
|
34672
|
+
[key, value],
|
|
34673
|
+
...(legacyMessageIdMap[key] ?? []).map((id) => [id, value]),
|
|
34674
|
+
]),
|
|
34675
|
+
);
|
|
34676
|
+
\`\`\`
|
|
34677
|
+
|
|
34678
|
+
Review the ambiguous ones by hand \u2014 each deserves its own translation:
|
|
34679
|
+
|
|
34680
|
+
| Bare ID | Also translates |
|
|
34681
|
+
| ----------- | ---------------------------------------------------------------------------------------- |
|
|
34682
|
+
| \`close\` | \`bui.alertDialog.close\`, \`bui.drawer.close\`, \`bui.editor.close\`, \`bui.inlineAlert.close\` |
|
|
34683
|
+
| \`more\` | \`bui.buttonSelect.more\`, \`bui.select.more\`, \`bui.toolbar.more\` |
|
|
34684
|
+
| \`cancel\` | \`bui.colorInput.cancel\`, \`bui.editor.cancel\`, \`bui.imageGallery.cancel\` |
|
|
34685
|
+
| \`redo\` | \`bui.editor.redo\`, \`bui.freehandCanvas.redo\` |
|
|
34686
|
+
| \`selectAll\` | \`bui.editor.selectAll\`, \`bui.select.selectAll\` |
|
|
34687
|
+
| \`undo\` | \`bui.editor.undo\`, \`bui.freehandCanvas.undo\` |
|
|
34688
|
+
| \`loading\` | \`bui.fileList.loading\`, \`bui.imageGallery.loading\`, \`bui.table.loading\` |`,styling:`# Styling with Sprinkles
|
|
33317
34689
|
|
|
33318
34690
|
Baseline UI provides a powerful, type-safe styling system built on top of [vanilla-extract sprinkles](https://vanilla-extract.style/documentation/packages/sprinkles/).
|
|
33319
34691
|
|
|
@@ -34223,7 +35595,7 @@ padding={[null, "lg", "xl"]}
|
|
|
34223
35595
|
|
|
34224
35596
|
* [vanilla-extract sprinkles documentation](https://vanilla-extract.style/documentation/packages/sprinkles/) - Learn about the underlying sprinkles framework
|
|
34225
35597
|
* [Box component documentation](/docs/core-utilities-box--docs) - Detailed information about the Box component
|
|
34226
|
-
* [Theme documentation](/docs/theming--docs) - Learn about Baseline UI's theming system`};var c={"8":["CaretDownIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","ChevronRightFilledIcon","ChevronRightIcon","EllipseIcon","MinusIcon","PlusIcon","XIcon"],"12":["CaretDownIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","CheckmarkIcon","DragIndicatorIcon","DragIndicatorVerticalIcon","EditIcon","EllipseIcon","EnterKeyIcon","LockFilledIcon","LockIcon","MinusIcon","MoreVIcon","MoreIcon","PlaceholderIcon","PlusIcon","SearchIcon","SizeIcon","TrashIcon","XIcon","ZoomIcon"],"16":["AlignBottomIcon","AlignMiddleIcon","AlignTopIcon","AnonymousIcon","ArrowDiagonalTopLeftBottomRightIcon","ArrowDownCircleFilledIcon","ArrowDownIcon","ArrowIcon","ArrowLeftRightIcon","ArrowRightIcon","ArrowUpArrowDownIcon","ArrowUpIcon","AtIcon","AttachmentsIcon","AvatarIcon","BoldIcon","BookmarkFilledIcon","BookmarkIcon","BulletListIcon","CalendarIcon","CaretLeftIcon","CaretRightIcon","CheckmarkCircleFilledIcon","CheckmarkCircleIcon","CheckmarkIcon","CircleFilledIcon","ClockIcon","CopyIcon","CustomizeIcon","DocumentEditIcon","DownloadIcon","DuplicateIcon","EditIcon","ElipseAreaIcon","EllipseCloudyIcon","EllipseDashedIcon","EllipseIcon","EmbedIcon","EmojiSmileIcon","ErrorAltCircleFilledIcon","ErrorCircleFilledIcon","ErrorCircleIcon","ExpandIcon","FilterAltIcon","FolderIcon","FormButtonIcon","FormChoiceIcon","FormComboboxIcon","FormDateIcon","FormListboxIcon","FormRadioButtonIcon","FormSignatureIcon","FormTextFieldIcon","FullScreenIcon","HelpCircleIcon","HelpIcon","HereIcon","HideIcon","HighlightTextAltIcon","HighlightTextIcon","HorizontalScrollIcon","ImageIcon","InfoCircleFilledIcon","InsertIcon","ItalicIcon","LightBulbIcon","LineIcon","LinkIcon","ListIcon","LockIcon","MagicIcon","MeasureIcon","MinusIcon","MoreIcon","MoreVerticalIcon","NoteArrowRightIcon","NoteCheckIcon","NoteCircleIcon","NoteCloudIcon","NoteCrossIcon","NoteHelpIcon","NoteInsetIcon","NoteKeyIcon","NoteNewParagraphAltIcon","NoteNewParagraphIcon","NoteNoteIcon","NotePointerRightIcon","NoteSpeechBubbleIcon","NoteStarIcon","NumberedListIcon","OpenIcon","PageFittingFillIcon","PageFittingFitIcon","PageHorizontalScrollIcon","PageLayoutDoubleIcon","PageLayoutSingleIcon","PageVerticalScrollIcon","PauseIcon","PenHighlighterIcon","PenIcon","PerimeterIcon","PlaceholderIcon","PlayIcon","PlusIcon","PolygonAreaIcon","PolygonCloudyIcon","PolygonDashedIcon","PolygonIcon","PolylineIcon","ReadOnlyIcon","RectangleAreaIcon","RectangleCloudyIcon","RectangleDashedIcon","RectangleIcon","RedoIcon","RemoveFormattingIcon","ReorderIcon","RotateClockwiseIcon","RotateCounterClockwiseIcon","RulerIcon","SearchIcon","SettingsIcon","ShowIcon","SlashCommandsIcon","SoundRecordIcon","StampIcon","StarFilledIcon","StarIcon","StrikeoutTextAltIcon","TableCellIcon","TableColumnIcon","TableHeaderIcon","TableIcon","TableRowIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextCalloutIcon","TextDecreaseIndentIcon","TextIcon","TextIncreaseIndentIcon","TextMarkIcon","ThumbnailsIcon","ThumbsDownIcon","ThumbsUpIcon","TrashIcon","TypeTextIcon","UnderlineIcon","UndoIcon","UnlockIcon","VerticalScrollIcon","VideoIcon","WarningFilledIcon","WarningIcon","WindowedIcon","WorkflowIcon","XCircleFilledIcon","XIcon"],"20":["AddPageIcon","AnonymousIcon","ArrowLeftIcon","ArrowRightIcon","ArrowUpCircleFilledIcon","AtIcon","AvatarFilledIcon","BoldIcon","CalloutIcon","CaretDownIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","CheckCircleFilledIcon","CheckmarkCircleIcon","CheckmarkIcon","ClockIcon","CollapseIcon","CommentIcon","CopyIcon","CutIcon","DistanceIcon","DownloadIcon","DuplicateIcon","EditIcon","EllipseIcon","EmojiSmileIcon","ErrorAltCircleFilledIcon","ErrorAlternativeCircleIcon","ErrorCircleFilledIcon","ErrorCircleIcon","ExpandIcon","FormDateIcon","FormSignatureIcon","FormTextFieldIcon","HelpCircleIcon","HighlightTextIcon","HomeIcon","ImageIcon","InfoCircleFilledIcon","InfoCircleIcon","ItalicIcon","LinkIcon","ListIcon","LockIcon","MagicIcon","MinusIcon","MoreIcon","MoreVerticalIcon","MoveIcon","NoteArrowRightIcon","NoteCheckIcon","NoteCircleIcon","NoteCrossIcon","NoteHelpIcon","NoteInsetIcon","NoteKeyIcon","NoteNewParagraphAltIcon","NoteNewParagraphIcon","NoteNoteIcon","NotePointerRightIcon","NoteSpeechBubbleIcon","NoteStarIcon","OpenIcon","PageMoveLeftIcon","PageMoveRightIcon","PagesInsertIcon","PasteIcon","PipetteIcon","PlusIcon","PrintIcon","RotateClockwiseIcon","SearchIcon","SettingsIcon","ShapeIcon","ShareIcon","SoundIcon","SoundRecordIcon","StarFilledIcon","StarIcon","StyleIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextIcon","ThumbnailsIcon","ThumbsDownIcon","ThumbsUpIcon","TrashIcon","TypeTextIcon","UnderlineIcon","UploadIcon","WarningFilledIcon","WarningIcon","XCircleFilledIcon","XCircleIcon","XIcon"],"24":["AddNoteCloudIcon","AddNoteIcon","AddTextSerifIcon","AiIcon","AirplaneIcon","AlignBottomIcon","AlignHorizontalCenterIcon","AlignMiddleIcon","AlignTopIcon","AnonymousIcon","ArrowDownIcon","ArrowIcon","ArrowLeftIcon","ArrowRightIcon","ArrowUpIcon","AtIcon","AttachmentIcon","AvatarFilledIcon","AvatarIcon","BlendModeIcon","BoldIcon","BookmarkFilledIcon","BookmarkIcon","BorderColorIcon","BottomBorderIcon","BulletListIcon","CalibrateIcon","CaptureAddIcon","CaretDownIcon","CaretIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","CheckmarkCircleFilledIcon","CheckmarkCircleIcon","CheckmarkIcon","ChevronListIcon","ClockIcon","CloudyBorderIcon","CollapseIcon","ColorPaletteIcon","ColorSwatchIcon","CommentIcon","CommentInSidebarIcon","CommentOnPageIcon","CompareDocumentsIcon","CopyIcon","CopyPageIcon","CropIcon","CustomizeIcon","CutIcon","DateModifiedIcon","DatePlusIcon","DebugIcon","DocumentArrowDownCircleIcon","DocumentArrowDownIcon","DocumentArrowRightIcon","DocumentFilledIcon","DocumentLockIcon","DocumentPdfIcon","DownloadIcon","DragIndicatorIcon","DragIndicatorVerticalIcon","DuplicateIcon","EditAnnotationsIcon","EditContentIcon","EditDocumentIcon","EditIcon","EditThumbnailsIcon","EllipseAreaIcon","EllipseCloudyIcon","EllipseDashedIcon","EllipseIcon","EmbedIcon","EmojiSmileIcon","EndCapArrowFilledIcon","EndCapArrowIcon","EndCapChevronFilledIcon","EndCapChevronIcon","EndCapCircleIcon","EndCapDiamondIcon","EndCapNoneIcon","EndCapSlantedIcon","EndCapSquareIcon","EndCapStraightIcon","EraserIcon","ErrorAltCircleFilledIcon","ErrorAltIcon","ErrorCircleFilledIcon","ErrorCircleIcon","ExpandIcon","ExpandVerticalIcon","FillColorIcon","FilterIcon","FitToHeightIcon","FivePagesHorizontalFilledIcon","FivePagesVerticalFilledIcon","FolderAddIcon","FolderIcon","FontListIcon","FontSizeIcon","FormButtonIcon","FormChoiceIcon","FormComboboxIcon","FormDateIcon","FormListboxIcon","FormPageIcon","FormRadioButtonIcon","FormSignatureIcon","FormTextFieldIcon","FormTwoRadioButtonsIcon","FourPagesGridFilledIcon","FourPagesHorizontalFilledIcon","FourPagesStackedFilledIcon","FourPagesVerticalFilledIcon","GroupIcon","HamburgerMenuIcon","HandIcon","HeartIcon","HideIcon","HideRevealIcon","HighlightTextIcon","HomeIcon","HorizontalScollIcon","ImageIcon","InfoCircleFilledIcon","InfoCircleIcon","InitialsIcon","InnerHorizontalBorderIcon","InnerVerticalBorderIcon","InsertIcon","ItalicIcon","LayerBottomIcon","LayerDownIcon","LayerTopIcon","LayerUpIcon","LayersIcon","LeftBindingIcon","LeftBorderIcon","LineCapsIcon","LineIcon","LineSpacingIcon","LineStyleCloudyIcon","LineStyleDashedDoubleDashIcon","LineStyleDashedDoubleGapIcon","LineStyleDashedQuadrupleDashIcon","LineStyleDashedSingleGapIcon","LineStyleIcon","LineStyleSolidIcon","LineWidthIcon","LinkIcon","LockFilledIcon","LockIcon","MagicIcon","MagicPenIcon","MailIcon","MarkupIcon","MarqueeZoomIcon","MeasureIcon","MergeIcon","MessageCloudIcon","MinusIcon","MoonIcon","MoreCircleIcon","MoreIcon","MoreVerticalIcon","MoveAllDirectionsIcon","MoveLeftIcon","MoveLeftRightIcon","MoveRightIcon","MultiplePagesIcon","NonEditableIcon","NoteArrowRightIcon","NoteCheckIcon","NoteCircleIcon","NoteCloudIcon","NoteCrossIcon","NoteHelpIcon","NoteIcon","NoteInsetIcon","NoteKeyIcon","NoteNewParagraphAltIcon","NoteNewParagraphIcon","NoteNoteIcon","NotePointerRightIcon","NoteSpeechBubbleIcon","NoteStarIcon","OcrIcon","OpacityIcon","PageAddIcon","PageCurlIcon","PageDuplicateIcon","PageFittingFillIcon","PageFittingFitIcon","PageHorizontalScrollIcon","PageLandscapeIcon","PageLayoutDoubleIcon","PageLayoutSingleIcon","PageMoveLeftIcon","PageMoveRightIcon","PageNumberCircleIcon","PageNumberIcon","PagePortraitIcon","PageRemoveIcon","PageVerticalScrollIcon","PagesInsertAltIcon","PagesInsertIcon","PagesNewFromSelectionAltIcon","PagesNewFromSelectionIcon","PagesSelectAllIcon","PagesSelectNoneIcon","PasteBoardIcon","PastePageIcon","PauseIcon","PenHighlighterIcon","PenIcon","PerimeterIcon","PinDropFilledIcon","PinDropIcon","PipetteIcon","PlayIcon","PlusCircleFilledIcon","PlusCircleIcon","PlusIcon","PointerIcon","PolygonAreaIcon","PolygonCloudyIcon","PolygonDashedIcon","PolygonIcon","PolylineIcon","PrecisionIcon","PrintIcon","PrivateModeIcon","PushPinIcon","QuestionmarkCircleIcon","ReaderViewIcon","RectangleAreaIcon","RectangleCloudyIcon","RectangleDashedIcon","RectangleIcon","RedactIcon","RedactRectangleIcon","RedactTextHighlighterIcon","RedactionTextRepeatingIcon","RedactionTextSingleIcon","RedoAllIcon","RedoIcon","RegexIcon","ReplaceIcon","RightBindingIcon","RightBorderIcon","RotateClockwiseIcon","RotateCounterClockwiseIcon","RotateObjectClockwiseIcon","RotateObjectCounterClockwiseIcon","RulerIcon","ScaleIcon","SearchCircleIcon","SearchIcon","SearchSelectionIcon","SelectAllIcon","SelectionToolIcon","SettingsIcon","ShapesIcon","ShareAltIcon","ShareIcon","ShieldAddIcon","ShieldCheckmarkIcon","ShieldWarningIcon","ShieldXIcon","ShowIcon","SidebarIcon","SignOutIcon","SignatureDigitalIcon","SignatureIcon","SinglePageFilledIcon","SoundIcon","SquigglyTextIcon","StampAddIcon","StampIcon","StarFilledIcon","StarIcon","StartCapArrowFilledIcon","StartCapArrowIcon","StartCapChevronFilledIcon","StartCapChevronIcon","StartCapCircleIcon","StartCapDiamondIcon","StartCapNoneIcon","StartCapSlantedIcon","StartCapSquareIcon","StartCapStraightIcon","StrikeoutTextIcon","StyleFilledIcon","StyleIcon","StylusFilledIcon","StylusIcon","SunIcon","TableCellIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextCalloutIcon","TextColorIcon","TextIcon","TextPropertiesHideIcon","TextPropertiesShowIcon","TextSerifIcon","TextSmallerIcon","ThreePagesHorizontalFilledIcon","ThreePagesStackedFilledIcon","ThreePagesVerticalFilledIcon","ThumbnailsIcon","ThumbsDownIcon","ThumbsUpIcon","TopBorderIcon","TrashIcon","TwoPagesHorizontalFilledIcon","TwoPagesVerticalFilledIcon","TypeTextIcon","UnderlineIcon","UnderlineTextIcon","UndoAllIcon","UndoIcon","UndoRedoIcon","UngroupIcon","UnlockIcon","UploadIcon","UserIcon","VerticalScrollIcon","VideoIcon","WarningFilledIcon","WarningIcon","WidgetIcon","WorkflowIcon","XCircleFilledIcon","XCircleIcon","XIcon","ZoomInIcon","ZoomOutIcon"],"36":["ArrowRight","Check","Circle","Cross","Help","Inset","Key","NewParagraphAlt","NewParagraph","Note","PointerRight","SpeechBubble","Star"]};var p={version:"1.1.0"};var u=`
|
|
35598
|
+
* [Theme documentation](/docs/theming--docs) - Learn about Baseline UI's theming system`};var c={"8":["CaretDownIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","ChevronRightFilledIcon","ChevronRightIcon","EllipseIcon","MinusIcon","PlusIcon","XIcon"],"12":["CaretDownIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","CheckmarkIcon","DragIndicatorIcon","DragIndicatorVerticalIcon","EditIcon","EllipseIcon","EnterKeyIcon","LockFilledIcon","LockIcon","MinusIcon","MoreVIcon","MoreIcon","PlaceholderIcon","PlusIcon","SearchIcon","SizeIcon","TrashIcon","XIcon","ZoomIcon"],"16":["AlignBottomIcon","AlignMiddleIcon","AlignTopIcon","AnonymousIcon","ArrowDiagonalTopLeftBottomRightIcon","ArrowDownCircleFilledIcon","ArrowDownIcon","ArrowIcon","ArrowLeftRightIcon","ArrowRightIcon","ArrowUpArrowDownIcon","ArrowUpIcon","AtIcon","AttachmentsIcon","AvatarIcon","BoldIcon","BookmarkFilledIcon","BookmarkIcon","BulletListIcon","CalendarIcon","CaretLeftIcon","CaretRightIcon","CheckmarkCircleFilledIcon","CheckmarkCircleIcon","CheckmarkIcon","CircleFilledIcon","ClockIcon","CopyIcon","CustomizeIcon","DocumentEditIcon","DownloadIcon","DuplicateIcon","EditIcon","ElipseAreaIcon","EllipseCloudyIcon","EllipseDashedIcon","EllipseIcon","EmbedIcon","EmojiSmileIcon","ErrorAltCircleFilledIcon","ErrorCircleFilledIcon","ErrorCircleIcon","ExpandIcon","FilterAltIcon","FolderIcon","FormButtonIcon","FormChoiceIcon","FormComboboxIcon","FormDateIcon","FormListboxIcon","FormRadioButtonIcon","FormSignatureIcon","FormTextFieldIcon","FullScreenIcon","HelpCircleIcon","HelpIcon","HereIcon","HideIcon","HighlightTextAltIcon","HighlightTextIcon","HorizontalScrollIcon","ImageIcon","InfoCircleFilledIcon","InsertIcon","ItalicIcon","LightBulbIcon","LineIcon","LinkIcon","ListIcon","LockIcon","MagicIcon","MeasureIcon","MinusIcon","MoreIcon","MoreVerticalIcon","NoteArrowRightIcon","NoteCheckIcon","NoteCircleIcon","NoteCloudIcon","NoteCrossIcon","NoteHelpIcon","NoteInsetIcon","NoteKeyIcon","NoteNewParagraphAltIcon","NoteNewParagraphIcon","NoteNoteIcon","NotePointerRightIcon","NoteSpeechBubbleIcon","NoteStarIcon","NumberedListIcon","OpenIcon","PageFittingFillIcon","PageFittingFitIcon","PageHorizontalScrollIcon","PageLayoutDoubleIcon","PageLayoutSingleIcon","PageVerticalScrollIcon","PauseIcon","PenHighlighterIcon","PenIcon","PerimeterIcon","PlaceholderIcon","PlayIcon","PlusIcon","PolygonAreaIcon","PolygonCloudyIcon","PolygonDashedIcon","PolygonIcon","PolylineIcon","ReadOnlyIcon","RectangleAreaIcon","RectangleCloudyIcon","RectangleDashedIcon","RectangleIcon","RedoIcon","RemoveFormattingIcon","ReorderIcon","RotateClockwiseIcon","RotateCounterClockwiseIcon","RulerIcon","SearchIcon","SettingsIcon","ShowIcon","SlashCommandsIcon","SoundRecordIcon","StampIcon","StarFilledIcon","StarIcon","StrikeoutTextAltIcon","TableCellIcon","TableColumnIcon","TableHeaderIcon","TableIcon","TableRowIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextCalloutIcon","TextDecreaseIndentIcon","TextIcon","TextIncreaseIndentIcon","TextMarkIcon","ThumbnailsIcon","ThumbsDownIcon","ThumbsUpIcon","TrashIcon","TypeTextIcon","UnderlineIcon","UndoIcon","UnlockIcon","VerticalScrollIcon","VideoIcon","WarningFilledIcon","WarningIcon","WindowedIcon","WorkflowIcon","XCircleFilledIcon","XIcon"],"20":["AddPageIcon","AnonymousIcon","ArrowLeftIcon","ArrowRightIcon","ArrowUpCircleFilledIcon","AtIcon","AvatarFilledIcon","BoldIcon","CalloutIcon","CaretDownIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","CheckCircleFilledIcon","CheckmarkCircleIcon","CheckmarkIcon","ClockIcon","CollapseIcon","CommentIcon","CopyIcon","CutIcon","DistanceIcon","DownloadIcon","DuplicateIcon","EditIcon","EllipseIcon","EmojiSmileIcon","ErrorAltCircleFilledIcon","ErrorAlternativeCircleIcon","ErrorCircleFilledIcon","ErrorCircleIcon","ExpandIcon","FormDateIcon","FormSignatureIcon","FormTextFieldIcon","HelpCircleIcon","HighlightTextIcon","HomeIcon","ImageIcon","InfoCircleFilledIcon","InfoCircleIcon","ItalicIcon","LinkIcon","ListIcon","LockIcon","MagicIcon","MinusIcon","MoreIcon","MoreVerticalIcon","MoveIcon","NoteArrowRightIcon","NoteCheckIcon","NoteCircleIcon","NoteCrossIcon","NoteHelpIcon","NoteInsetIcon","NoteKeyIcon","NoteNewParagraphAltIcon","NoteNewParagraphIcon","NoteNoteIcon","NotePointerRightIcon","NoteSpeechBubbleIcon","NoteStarIcon","OpenIcon","PageMoveLeftIcon","PageMoveRightIcon","PagesInsertIcon","PasteIcon","PipetteIcon","PlusIcon","PrintIcon","RotateClockwiseIcon","SearchIcon","SettingsIcon","ShapeIcon","ShareIcon","SoundIcon","SoundRecordIcon","StarFilledIcon","StarIcon","StyleIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextIcon","ThumbnailsIcon","ThumbsDownIcon","ThumbsUpIcon","TrashIcon","TypeTextIcon","UnderlineIcon","UploadIcon","WarningFilledIcon","WarningIcon","XCircleFilledIcon","XCircleIcon","XIcon"],"24":["AddNoteCloudIcon","AddNoteIcon","AddTextSerifIcon","AiIcon","AirplaneIcon","AlignBottomIcon","AlignHorizontalCenterIcon","AlignMiddleIcon","AlignTopIcon","AnonymousIcon","ArrowDownIcon","ArrowIcon","ArrowLeftIcon","ArrowRightIcon","ArrowUpIcon","AtIcon","AttachmentIcon","AvatarFilledIcon","AvatarIcon","BlendModeIcon","BoldIcon","BookmarkFilledIcon","BookmarkIcon","BorderColorIcon","BottomBorderIcon","BulletListIcon","CalibrateIcon","CaptureAddIcon","CaretDownIcon","CaretIcon","CaretLeftIcon","CaretRightIcon","CaretUpIcon","CheckmarkCircleFilledIcon","CheckmarkCircleIcon","CheckmarkIcon","ChevronListIcon","ClockIcon","CloudyBorderIcon","CollapseIcon","ColorPaletteIcon","ColorSwatchIcon","CommentIcon","CommentInSidebarIcon","CommentOnPageIcon","CompareDocumentsIcon","CopyIcon","CopyPageIcon","CropIcon","CustomizeIcon","CutIcon","DateModifiedIcon","DatePlusIcon","DebugIcon","DocumentArrowDownCircleIcon","DocumentArrowDownIcon","DocumentArrowRightIcon","DocumentFilledIcon","DocumentLockIcon","DocumentPdfIcon","DownloadIcon","DragIndicatorIcon","DragIndicatorVerticalIcon","DuplicateIcon","EditAnnotationsIcon","EditContentIcon","EditDocumentIcon","EditIcon","EditThumbnailsIcon","EllipseAreaIcon","EllipseCloudyIcon","EllipseDashedIcon","EllipseIcon","EmbedIcon","EmojiSmileIcon","EndCapArrowFilledIcon","EndCapArrowIcon","EndCapChevronFilledIcon","EndCapChevronIcon","EndCapCircleIcon","EndCapDiamondIcon","EndCapNoneIcon","EndCapSlantedIcon","EndCapSquareIcon","EndCapStraightIcon","EraserIcon","ErrorAltCircleFilledIcon","ErrorAltIcon","ErrorCircleFilledIcon","ErrorCircleIcon","ExpandIcon","ExpandVerticalIcon","FillColorIcon","FilterIcon","FitToHeightIcon","FivePagesHorizontalFilledIcon","FivePagesVerticalFilledIcon","FolderAddIcon","FolderIcon","FontListIcon","FontSizeIcon","FormButtonIcon","FormChoiceIcon","FormComboboxIcon","FormDateIcon","FormListboxIcon","FormPageIcon","FormRadioButtonIcon","FormSignatureIcon","FormTextFieldIcon","FormTwoRadioButtonsIcon","FourPagesGridFilledIcon","FourPagesHorizontalFilledIcon","FourPagesStackedFilledIcon","FourPagesVerticalFilledIcon","GroupIcon","HamburgerMenuIcon","HandIcon","HeartIcon","HideIcon","HideRevealIcon","HighlightTextIcon","HomeIcon","HorizontalScollIcon","ImageIcon","InfoCircleFilledIcon","InfoCircleIcon","InitialsIcon","InnerHorizontalBorderIcon","InnerVerticalBorderIcon","InsertIcon","ItalicIcon","LayerBottomIcon","LayerDownIcon","LayerTopIcon","LayerUpIcon","LayersIcon","LeftBindingIcon","LeftBorderIcon","LineCapsIcon","LineIcon","LineSpacingIcon","LineStyleCloudyIcon","LineStyleDashedDoubleDashIcon","LineStyleDashedDoubleGapIcon","LineStyleDashedQuadrupleDashIcon","LineStyleDashedSingleGapIcon","LineStyleIcon","LineStyleSolidIcon","LineWidthIcon","LinkIcon","LockFilledIcon","LockIcon","MagicIcon","MagicPenIcon","MailIcon","MarkupIcon","MarqueeZoomIcon","MeasureIcon","MergeIcon","MessageCloudIcon","MinusIcon","MoonIcon","MoreCircleIcon","MoreIcon","MoreVerticalIcon","MoveAllDirectionsIcon","MoveLeftIcon","MoveLeftRightIcon","MoveRightIcon","MultiplePagesIcon","NonEditableIcon","NoteArrowRightIcon","NoteCheckIcon","NoteCircleIcon","NoteCloudIcon","NoteCrossIcon","NoteHelpIcon","NoteIcon","NoteInsetIcon","NoteKeyIcon","NoteNewParagraphAltIcon","NoteNewParagraphIcon","NoteNoteIcon","NotePointerRightIcon","NoteSpeechBubbleIcon","NoteStarIcon","OcrIcon","OpacityIcon","PageAddIcon","PageCurlIcon","PageDuplicateIcon","PageFittingFillIcon","PageFittingFitIcon","PageHorizontalScrollIcon","PageLandscapeIcon","PageLayoutDoubleIcon","PageLayoutSingleIcon","PageMoveLeftIcon","PageMoveRightIcon","PageNumberCircleIcon","PageNumberIcon","PagePortraitIcon","PageRemoveIcon","PageVerticalScrollIcon","PagesInsertAltIcon","PagesInsertIcon","PagesNewFromSelectionAltIcon","PagesNewFromSelectionIcon","PagesSelectAllIcon","PagesSelectNoneIcon","PasteBoardIcon","PastePageIcon","PauseIcon","PenHighlighterIcon","PenIcon","PerimeterIcon","PinDropFilledIcon","PinDropIcon","PipetteIcon","PlayIcon","PlusCircleFilledIcon","PlusCircleIcon","PlusIcon","PointerIcon","PolygonAreaIcon","PolygonCloudyIcon","PolygonDashedIcon","PolygonIcon","PolylineIcon","PrecisionIcon","PrintIcon","PrivateModeIcon","PushPinIcon","QuestionmarkCircleIcon","ReaderViewIcon","RectangleAreaIcon","RectangleCloudyIcon","RectangleDashedIcon","RectangleIcon","RedactIcon","RedactRectangleIcon","RedactTextHighlighterIcon","RedactionTextRepeatingIcon","RedactionTextSingleIcon","RedoAllIcon","RedoIcon","RegexIcon","ReplaceIcon","RightBindingIcon","RightBorderIcon","RotateClockwiseIcon","RotateCounterClockwiseIcon","RotateObjectClockwiseIcon","RotateObjectCounterClockwiseIcon","RulerIcon","ScaleIcon","SearchCircleIcon","SearchIcon","SearchSelectionIcon","SelectAllIcon","SelectionToolIcon","SettingsIcon","ShapesIcon","ShareAltIcon","ShareIcon","ShieldAddIcon","ShieldCheckmarkIcon","ShieldWarningIcon","ShieldXIcon","ShowIcon","SidebarIcon","SignOutIcon","SignatureDigitalIcon","SignatureIcon","SinglePageFilledIcon","SoundIcon","SquigglyTextIcon","StampAddIcon","StampIcon","StarFilledIcon","StarIcon","StartCapArrowFilledIcon","StartCapArrowIcon","StartCapChevronFilledIcon","StartCapChevronIcon","StartCapCircleIcon","StartCapDiamondIcon","StartCapNoneIcon","StartCapSlantedIcon","StartCapSquareIcon","StartCapStraightIcon","StrikeoutTextIcon","StyleFilledIcon","StyleIcon","StylusFilledIcon","StylusIcon","SunIcon","TableCellIcon","TextAlignCenterIcon","TextAlignJustifyIcon","TextAlignLeftIcon","TextAlignRightIcon","TextCalloutIcon","TextColorIcon","TextIcon","TextPropertiesHideIcon","TextPropertiesShowIcon","TextSerifIcon","TextSmallerIcon","ThreePagesHorizontalFilledIcon","ThreePagesStackedFilledIcon","ThreePagesVerticalFilledIcon","ThumbnailsIcon","ThumbsDownIcon","ThumbsUpIcon","TopBorderIcon","TrashIcon","TwoPagesHorizontalFilledIcon","TwoPagesVerticalFilledIcon","TypeTextIcon","UnderlineIcon","UnderlineTextIcon","UndoAllIcon","UndoIcon","UndoRedoIcon","UngroupIcon","UnlockIcon","UploadIcon","UserIcon","VerticalScrollIcon","VideoIcon","WarningFilledIcon","WarningIcon","WidgetIcon","WorkflowIcon","XCircleFilledIcon","XCircleIcon","XIcon","ZoomInIcon","ZoomOutIcon"],"36":["ArrowRight","Check","Circle","Cross","Help","Inset","Key","NewParagraphAlt","NewParagraph","Note","PointerRight","SpeechBubble","Star"]};var p={version:"2.0.0"};var u=`
|
|
34227
35599
|
# Baseline UI MCP Server Guidelines
|
|
34228
35600
|
|
|
34229
35601
|
This MCP server provides AI assistants with structured access to Baseline UI's comprehensive component documentation, icon library, theming resources, and design guidelines.
|