@baseline-ui/mcp 1.2.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 +2 -0
- package/dist/index.cjs +1796 -427
- package/dist/index.js +1796 -427
- package/package.json +1 -1
- package/sbom.json +65 -65
package/dist/index.cjs
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
|
) {
|
|
@@ -12882,27 +13098,45 @@ console.log(greet('Markdown Maverick'));
|
|
|
12882
13098
|
2. Selection options: The component can be configured to allow single, multiple, or no selection.
|
|
12883
13099
|
3. Disabled items support: Certain menu items can be disabled, preventing user interaction.
|
|
12884
13100
|
4. Sections support: Related items can be grouped into sections for better organization and navigation.
|
|
12885
|
-
5.
|
|
12886
|
-
6.
|
|
12887
|
-
7.
|
|
12888
|
-
8.
|
|
12889
|
-
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.
|
|
12890
13111
|
|
|
12891
13112
|
\`\`\`jsx
|
|
12892
|
-
import {
|
|
12893
|
-
import { Menu } from "@storybook/addon-docs/blocks";
|
|
13113
|
+
import { Menu } from "@baseline-ui/core";
|
|
12894
13114
|
|
|
12895
13115
|
const items = [
|
|
12896
|
-
{
|
|
12897
|
-
label: "
|
|
12898
|
-
id: "
|
|
12899
|
-
keyboardShortcut: "\u2318X",
|
|
12900
|
-
},
|
|
13116
|
+
{ id: "cut", label: "Cut", keyboardShortcut: "\u2318X" },
|
|
13117
|
+
{ id: "copy", label: "Copy", keyboardShortcut: "\u2318C" },
|
|
13118
|
+
{ id: "paste", label: "Paste", keyboardShortcut: "\u2318V" },
|
|
12901
13119
|
];
|
|
12902
13120
|
|
|
12903
|
-
|
|
12904
|
-
<
|
|
12905
|
-
|
|
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
|
+
];
|
|
12906
13140
|
\`\`\`
|
|
12907
13141
|
|
|
12908
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\`.
|
|
@@ -12930,9 +13164,93 @@ const items = [
|
|
|
12930
13164
|
];
|
|
12931
13165
|
\`\`\`
|
|
12932
13166
|
|
|
12933
|
-
|
|
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.
|
|
12934
13226
|
|
|
12935
|
-
|
|
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 {
|
|
12936
13254
|
/**
|
|
12937
13255
|
* Whether the overlay is open by default (controlled).
|
|
12938
13256
|
*/
|
|
@@ -12964,39 +13282,18 @@ contentClassName?: string
|
|
|
12964
13282
|
*/
|
|
12965
13283
|
itemClassName?: string
|
|
12966
13284
|
/**
|
|
12967
|
-
* A list of items to render in the menu.
|
|
12968
|
-
*
|
|
12969
|
-
* \`\`\`ts
|
|
12970
|
-
* export type MenuOption = {
|
|
12971
|
-
* id: string;
|
|
12972
|
-
* label: string;
|
|
12973
|
-
* keyboardShortcut?: string;
|
|
12974
|
-
* icon?: React.FC<IconProps>;
|
|
12975
|
-
* };
|
|
12976
|
-
*
|
|
12977
|
-
* export type MenuSection = {
|
|
12978
|
-
* id: string;
|
|
12979
|
-
* title?: string;
|
|
12980
|
-
* type: "section";
|
|
12981
|
-
* children: MenuOption[];
|
|
12982
|
-
* };
|
|
13285
|
+
* A list of items to render in the menu. See \`MenuItem\`.
|
|
12983
13286
|
*
|
|
12984
|
-
*
|
|
12985
|
-
*
|
|
13287
|
+
* A \`MenuSection\` may opt into independent selection by listing its id in the
|
|
13288
|
+
* object form of \`selectionMode\` (e.g. \`selectionMode={{ view: "single" }}\`).
|
|
12986
13289
|
*/
|
|
12987
13290
|
items: MenuItem[]
|
|
12988
13291
|
/**
|
|
12989
13292
|
* A function that renders the trigger element of the component. The default
|
|
12990
13293
|
* implementation renders an \`ActionButton\` component.
|
|
12991
|
-
*
|
|
12992
|
-
* \`\`\`tsx
|
|
12993
|
-
* <Menu renderTrigger={({ buttonProps, ref }) => <ActionButton {...buttonProps} label="Label" ref={ref} />
|
|
12994
|
-
* \`\`\`
|
|
12995
13294
|
*/
|
|
12996
13295
|
renderTrigger?: (options: {
|
|
12997
|
-
buttonProps: ActionButtonProps & {
|
|
12998
|
-
isOpen: boolean;
|
|
12999
|
-
};
|
|
13296
|
+
buttonProps: ActionButtonProps & { isOpen: boolean };
|
|
13000
13297
|
ref: React.RefObject<HTMLButtonElement>;
|
|
13001
13298
|
}) => React.ReactNode
|
|
13002
13299
|
/**
|
|
@@ -13004,6 +13301,33 @@ renderTrigger?: (options: {
|
|
|
13004
13301
|
* function that accepts a boolean indicating whether the menu is open.
|
|
13005
13302
|
*/
|
|
13006
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
|
|
13007
13331
|
placement?: any
|
|
13008
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 = () => {
|
|
13009
13333
|
const [selectedKey, setSelectedKey] = React.useState(
|
|
@@ -13037,13 +13361,17 @@ placement?: any
|
|
|
13037
13361
|
};`},{id:"core-collections-menu--with-selected-keys-controlled",name:"With Selected Keys Controlled",snippet:`const WithSelectedKeysControlled = () => <Menu
|
|
13038
13362
|
triggerLabel="Menu Trigger"
|
|
13039
13363
|
items={items}
|
|
13040
|
-
selectedKeys={["light"]}
|
|
13364
|
+
selectedKeys={new Set(["light"])}
|
|
13041
13365
|
selectionMode="single" />;`},{id:"core-collections-menu--long-menu",name:"Long Menu",snippet:`const LongMenu = () => <Menu
|
|
13042
13366
|
triggerLabel="Menu Trigger"
|
|
13043
13367
|
items={longListItems}
|
|
13044
13368
|
selectionMode="single"
|
|
13045
13369
|
defaultOpen
|
|
13046
|
-
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
|
|
13047
13375
|
triggerLabel="Menu Trigger"
|
|
13048
13376
|
renderTrigger={({ buttonProps, ref }) => (
|
|
13049
13377
|
<ActionButton
|
|
@@ -13052,12 +13380,32 @@ placement?: any
|
|
|
13052
13380
|
size="sm"
|
|
13053
13381
|
ref={ref}
|
|
13054
13382
|
/>
|
|
13055
|
-
)} />;`}
|
|
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";
|
|
13056
13401
|
|
|
13402
|
+
import { I18nProvider } from "../../I18nProvider/I18nProvider";
|
|
13057
13403
|
import { Menu } from "../Menu";
|
|
13058
|
-
import { items } from "./data";
|
|
13404
|
+
import { items, itemsWithSections, itemsWithSubmenu } from "./data";
|
|
13059
13405
|
|
|
13060
13406
|
import type { MenuProps } from "../Menu.types";
|
|
13407
|
+
import type { Key } from "react-aria";
|
|
13408
|
+
import type { Selection } from "react-stately";
|
|
13061
13409
|
|
|
13062
13410
|
export const MenuExample: React.FC<
|
|
13063
13411
|
MenuProps & {
|
|
@@ -13087,63 +13435,218 @@ export const MenuActionValueExample: React.FC<{ label: string }> = ({
|
|
|
13087
13435
|
<div data-testid="menu-action-value">{received}</div>
|
|
13088
13436
|
</>
|
|
13089
13437
|
);
|
|
13090
|
-
}
|
|
13438
|
+
};
|
|
13091
13439
|
|
|
13092
|
-
|
|
13093
|
-
|
|
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
|
+
};
|
|
13094
13460
|
|
|
13095
|
-
const
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
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
|
+
);
|
|
13102
13477
|
};
|
|
13103
13478
|
|
|
13104
|
-
const
|
|
13105
|
-
|
|
13106
|
-
|
|
13479
|
+
export const MenuRtlSubmenuExample: React.FC<{ label: string }> = ({
|
|
13480
|
+
label,
|
|
13481
|
+
}) => (
|
|
13482
|
+
<I18nProvider locale="ar">
|
|
13483
|
+
<Menu items={itemsWithSubmenu} triggerLabel={label} />
|
|
13107
13484
|
</I18nProvider>
|
|
13108
13485
|
);
|
|
13109
|
-
\`\`\``,props:`interface MessageFormatProps {
|
|
13110
|
-
/**
|
|
13111
|
-
* By default \`<MessageFormat>\` will render the formatted string into a
|
|
13112
|
-
* \`<React.Fragment>\`. If you need to customize rendering, you can either wrap
|
|
13113
|
-
* it with another React element (recommended), specify a different tagName
|
|
13114
|
-
* (e.g., 'div')
|
|
13115
|
-
*/
|
|
13116
|
-
elementType?: React.ElementType | "div" | "span"
|
|
13117
|
-
/**
|
|
13118
|
-
* The id of the message to format.
|
|
13119
|
-
*/
|
|
13120
|
-
id: string
|
|
13121
|
-
/**
|
|
13122
|
-
* The default message to use if the message id is not found.
|
|
13123
|
-
*/
|
|
13124
|
-
defaultMessage?: string
|
|
13125
|
-
}`,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.
|
|
13126
13486
|
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13487
|
+
export const MenuFunctionLabelExample: React.FC = () => (
|
|
13488
|
+
<Menu
|
|
13489
|
+
items={items}
|
|
13490
|
+
triggerLabel={(isOpen) => (isOpen ? "Opened" : "Closed")}
|
|
13491
|
+
/>
|
|
13492
|
+
);
|
|
13133
13493
|
|
|
13134
|
-
|
|
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
|
+
);
|
|
13135
13506
|
|
|
13136
|
-
|
|
13507
|
+
const fmtSelection = (sel: Selection): string =>
|
|
13508
|
+
sel === "all" ? "all" : [...sel].map(String).join(",");
|
|
13137
13509
|
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
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";
|
|
13147
13650
|
|
|
13148
13651
|
<Modal>
|
|
13149
13652
|
<ModalTrigger>
|
|
@@ -16207,25 +16710,13 @@ export const PopoverDefaultOpenWithArrowExample = () => {
|
|
|
16207
16710
|
);
|
|
16208
16711
|
};
|
|
16209
16712
|
|
|
16210
|
-
export const PopoverContainedFocusExample = (
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
<Dialog
|
|
16218
|
-
size="content"
|
|
16219
|
-
className={sprinkles({
|
|
16220
|
-
padding: "md",
|
|
16221
|
-
display: "flex",
|
|
16222
|
-
gap: "xl",
|
|
16223
|
-
flexDirection: "column",
|
|
16224
|
-
})}
|
|
16225
|
-
style={{
|
|
16226
|
-
width: 200,
|
|
16227
|
-
}}
|
|
16228
|
-
>
|
|
16713
|
+
export const PopoverContainedFocusExample = ({
|
|
16714
|
+
shouldContainFocus = true,
|
|
16715
|
+
}: {
|
|
16716
|
+
shouldContainFocus?: boolean;
|
|
16717
|
+
}) => {
|
|
16718
|
+
const content = (
|
|
16719
|
+
<>
|
|
16229
16720
|
<Text type="label">The focus is contained within the popover.</Text>
|
|
16230
16721
|
|
|
16231
16722
|
<TextInput
|
|
@@ -16237,10 +16728,55 @@ export const PopoverContainedFocusExample = () => {
|
|
|
16237
16728
|
label="Button"
|
|
16238
16729
|
style={{ width: "100%", justifyContent: "center" }}
|
|
16239
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}
|
|
16240
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
|
+
)}
|
|
16241
16764
|
</PopoverContent>
|
|
16242
16765
|
</Popover>
|
|
16243
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
|
+
);
|
|
16244
16780
|
};
|
|
16245
16781
|
|
|
16246
16782
|
export const PopoverWithScrollableViewportExample: React.FC<{
|
|
@@ -18318,18 +18854,20 @@ function App() {
|
|
|
18318
18854
|
}
|
|
18319
18855
|
\`\`\`
|
|
18320
18856
|
|
|
18321
|
-
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.
|
|
18322
18860
|
|
|
18323
18861
|
\`\`\`jsx
|
|
18324
18862
|
const itemsWithSections = [
|
|
18325
18863
|
{
|
|
18326
18864
|
id: "solid",
|
|
18327
|
-
|
|
18865
|
+
title: "Solid",
|
|
18328
18866
|
children: items,
|
|
18329
18867
|
},
|
|
18330
18868
|
{
|
|
18331
18869
|
id: "dashed",
|
|
18332
|
-
|
|
18870
|
+
title: "Dashed",
|
|
18333
18871
|
children: [
|
|
18334
18872
|
{
|
|
18335
18873
|
id: "ellipse-dashed",
|
|
@@ -18353,6 +18891,18 @@ const itemsWithSections = [
|
|
|
18353
18891
|
<Select items={itemsWithSections} label="Label" />;
|
|
18354
18892
|
\`\`\`
|
|
18355
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
|
+
|
|
18356
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.
|
|
18357
18907
|
|
|
18358
18908
|
\`\`\`jsx
|
|
@@ -18556,14 +19106,16 @@ import { Virtualizer, ListLayout } from "@baseline-ui/core";
|
|
|
18556
19106
|
\`\`\`
|
|
18557
19107
|
|
|
18558
19108
|
| Key | Function |
|
|
18559
|
-
|
|
|
19109
|
+
| -------------------- | ------------------------------------------------------------------------------------ |
|
|
19110
|
+
| \`Tab\` | Moves focus to and from the trigger. The popup itself is not a tab stop |
|
|
18560
19111
|
| \`Space\` | Opens the listbox popup or toggles selection of the focused item in multiselect mode |
|
|
18561
19112
|
| \`Enter\` | Opens the listbox popup or selects the focused item if the popup is open |
|
|
18562
19113
|
| \`Escape\` | Closes the listbox popup |
|
|
18563
19114
|
| \`ArrowDown\` | Opens the listbox popup and focuses the first item if no item is focused |
|
|
18564
19115
|
| \`ArrowUp\` | Opens the listbox popup and focuses the last item if no item is focused |
|
|
18565
|
-
| \`Home\` |
|
|
18566
|
-
| \`End\` |
|
|
19116
|
+
| \`Home\` | Focuses the first item |
|
|
19117
|
+
| \`End\` | Focuses the last item |
|
|
19118
|
+
| Printable characters | Focuses the first item matching the typed characters |
|
|
18567
19119
|
|
|
18568
19120
|
**Note:** In multiselect mode (\`selectionMode="multiple"\`), the \`Space\` key toggles selection of the focused item, and the popover remains open after selection.
|
|
18569
19121
|
|
|
@@ -18593,6 +19145,8 @@ The \`renderTrigger\` prop allows you to completely replace the default trigger
|
|
|
18593
19145
|
| \`.BaselineUI-Select-Label\` | Label element |
|
|
18594
19146
|
| \`.BaselineUI-Select-Popover\` | Popover container |
|
|
18595
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 |
|
|
18596
19150
|
| \`[data-disabled]\` | Applied when \`isDisabled\` is true |
|
|
18597
19151
|
| \`[data-readonly]\` | Applied when \`isReadOnly\` is true |
|
|
18598
19152
|
| \`[data-focused]\` | Applied when the trigger is focused |
|
|
@@ -18601,6 +19155,7 @@ The \`renderTrigger\` prop allows you to completely replace the default trigger
|
|
|
18601
19155
|
| \`[data-pressed]\` | Applied when the trigger is pressed |
|
|
18602
19156
|
| \`[data-open]\` | Applied when the popover is open |
|
|
18603
19157
|
|
|
19158
|
+
* **ComboBox** \u2014 Use this instead when users should be able to type directly into the trigger to filter or enter a value
|
|
18604
19159
|
* **IconSelect** \u2014 Select variant with an icon trigger instead of a text button
|
|
18605
19160
|
* **ButtonSelect** \u2014 Select variant styled as a button
|
|
18606
19161
|
* **ListBox** \u2014 Standalone listbox without the trigger/popover wrapper
|
|
@@ -18743,125 +19298,125 @@ hideSelectAll?: boolean
|
|
|
18743
19298
|
*/
|
|
18744
19299
|
hideClear?: boolean
|
|
18745
19300
|
}`,stories:{usage:[{id:"core-forms-select-multiselect--basic",name:"Basic",error:{name:"SyntaxError",message:`Expected story to be a function or variable declaration
|
|
18746
|
-
|
|
18747
|
-
|
|
18748
|
-
>
|
|
19301
|
+
32 | type Story = StoryObj<typeof meta>;
|
|
19302
|
+
33 |
|
|
19303
|
+
> 34 | export {
|
|
18749
19304
|
| ^
|
|
18750
|
-
|
|
18751
|
-
|
|
18752
|
-
|
|
18753
|
-
|
|
18754
|
-
|
|
18755
|
-
>
|
|
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 {
|
|
18756
19311
|
| ^
|
|
18757
|
-
|
|
18758
|
-
|
|
18759
|
-
|
|
18760
|
-
|
|
18761
|
-
|
|
18762
|
-
>
|
|
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 {
|
|
18763
19318
|
| ^
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
|
|
18769
|
-
>
|
|
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 {
|
|
18770
19325
|
| ^
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
|
|
18774
|
-
|
|
18775
|
-
|
|
18776
|
-
>
|
|
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 {
|
|
18777
19332
|
| ^
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
|
|
18782
|
-
|
|
18783
|
-
>
|
|
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 {
|
|
18784
19339
|
| ^
|
|
18785
|
-
|
|
18786
|
-
|
|
18787
|
-
|
|
18788
|
-
|
|
18789
|
-
|
|
18790
|
-
>
|
|
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 {
|
|
18791
19346
|
| ^
|
|
18792
|
-
|
|
18793
|
-
|
|
18794
|
-
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
>
|
|
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 {
|
|
18798
19353
|
| ^
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
>
|
|
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 {
|
|
18805
19360
|
| ^
|
|
18806
|
-
|
|
18807
|
-
|
|
18808
|
-
|
|
18809
|
-
|
|
18810
|
-
|
|
18811
|
-
>
|
|
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 {
|
|
18812
19367
|
| ^
|
|
18813
|
-
|
|
18814
|
-
|
|
18815
|
-
|
|
18816
|
-
|
|
18817
|
-
|
|
18818
|
-
>
|
|
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 {
|
|
18819
19374
|
| ^
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
|
|
18824
|
-
|
|
18825
|
-
>
|
|
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 {
|
|
18826
19381
|
| ^
|
|
18827
|
-
|
|
18828
|
-
|
|
18829
|
-
|
|
18830
|
-
|
|
18831
|
-
|
|
18832
|
-
>
|
|
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 {
|
|
18833
19388
|
| ^
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
>
|
|
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 {
|
|
18840
19395
|
| ^
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
|
|
18845
|
-
|
|
18846
|
-
>
|
|
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 {
|
|
18847
19402
|
| ^
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
|
|
18852
|
-
|
|
18853
|
-
>
|
|
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 {
|
|
18854
19409
|
| ^
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18860
|
-
>
|
|
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 {
|
|
18861
19416
|
| ^
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
|
|
19417
|
+
35 | Basic,
|
|
19418
|
+
36 | WithLabel,
|
|
19419
|
+
37 | WithDescription,`}},{id:"core-forms-select-multiselect--read-only",name:"Read Only",snippet:`const ReadOnly = () => <Select
|
|
18865
19420
|
aria-label="Choose Stroke Style"
|
|
18866
19421
|
items={items}
|
|
18867
19422
|
placeholder="Choose Stroke Style"
|
|
@@ -18920,7 +19475,29 @@ hideClear?: boolean
|
|
|
18920
19475
|
aria-label="Choose Stroke Style"
|
|
18921
19476
|
items={items}
|
|
18922
19477
|
placeholder="Choose Stroke Style"
|
|
18923
|
-
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";
|
|
18924
19501
|
import React from "react";
|
|
18925
19502
|
import { useFilter } from "react-aria";
|
|
18926
19503
|
import { Autocomplete, Virtualizer } from "react-aria-components";
|
|
@@ -18929,11 +19506,16 @@ import { useListData } from "react-stately";
|
|
|
18929
19506
|
import { ActionButton } from "../../ActionButton";
|
|
18930
19507
|
import { items } from "../../ListBox/__tests__/testComponents";
|
|
18931
19508
|
import { virtualizeAutocompleteItems } from "../../Menu/__tests__/data";
|
|
18932
|
-
import {
|
|
19509
|
+
import { itemsWithSectionTitles } from "../../UNSAFE_ListBox/__tests__/testComponents";
|
|
19510
|
+
import {
|
|
19511
|
+
ListLayout,
|
|
19512
|
+
VIRTUALIZER_LAYOUT_DEFAULT_OPTIONS,
|
|
19513
|
+
} from "../../Virtualizer";
|
|
18933
19514
|
import { IconSelect } from "../IconSelect";
|
|
18934
19515
|
import { Select } from "../Select";
|
|
18935
19516
|
|
|
18936
19517
|
import type { IconSelectProps } from "../Select.types";
|
|
19518
|
+
import type { Key } from "@react-types/shared";
|
|
18937
19519
|
|
|
18938
19520
|
export const SelectExample: React.FC<
|
|
18939
19521
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
@@ -18941,13 +19523,28 @@ export const SelectExample: React.FC<
|
|
|
18941
19523
|
return (
|
|
18942
19524
|
<Select
|
|
18943
19525
|
placeholder="Choose an item"
|
|
18944
|
-
{...args}
|
|
18945
19526
|
optionClassName={(item) => item.label}
|
|
19527
|
+
{...args}
|
|
18946
19528
|
items={items}
|
|
18947
19529
|
/>
|
|
18948
19530
|
);
|
|
18949
19531
|
};
|
|
18950
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
|
+
|
|
18951
19548
|
export const SelectGetTargetRectExample: React.FC = () => {
|
|
18952
19549
|
const [called, setCalled] = React.useState(false);
|
|
18953
19550
|
|
|
@@ -19004,90 +19601,228 @@ export const SelectCustomTriggerExample: React.FC<
|
|
|
19004
19601
|
};
|
|
19005
19602
|
|
|
19006
19603
|
export const IconSelectExample: React.FC<
|
|
19007
|
-
Omit<IconSelectProps, "items" | "
|
|
19604
|
+
Omit<IconSelectProps, "items" | "aria-label">
|
|
19008
19605
|
> = (args) => {
|
|
19009
19606
|
return (
|
|
19010
19607
|
<IconSelect
|
|
19011
19608
|
placeholder="Choose an item"
|
|
19609
|
+
icon={EllipseIcon}
|
|
19012
19610
|
{...args}
|
|
19013
19611
|
items={items}
|
|
19014
|
-
icon={EllipseIcon}
|
|
19015
19612
|
aria-label="Aria Label"
|
|
19016
19613
|
/>
|
|
19017
19614
|
);
|
|
19018
19615
|
};
|
|
19019
19616
|
|
|
19020
|
-
export const
|
|
19617
|
+
export const VirtualSelectWithSectionHeadersExample: React.FC<
|
|
19021
19618
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
19022
19619
|
> = (args) => {
|
|
19023
|
-
const list = useListData({
|
|
19024
|
-
initialItems: virtualizeAutocompleteItems,
|
|
19025
|
-
});
|
|
19026
|
-
const { contains } = useFilter({ sensitivity: "base" });
|
|
19027
|
-
const filter = (textValue, inputValue) => contains(textValue, inputValue);
|
|
19028
19620
|
return (
|
|
19029
|
-
<Virtualizer
|
|
19030
|
-
|
|
19621
|
+
<Virtualizer
|
|
19622
|
+
layout={ListLayout}
|
|
19623
|
+
layoutOptions={{
|
|
19624
|
+
rowHeight: 36,
|
|
19625
|
+
headingHeight: 40,
|
|
19626
|
+
}}
|
|
19627
|
+
>
|
|
19031
19628
|
<Select
|
|
19629
|
+
aria-label="Choose an item"
|
|
19630
|
+
placeholder="Choose an item"
|
|
19631
|
+
showSectionHeader={true}
|
|
19032
19632
|
{...args}
|
|
19033
|
-
items={
|
|
19034
|
-
|
|
19035
|
-
maxHeight={
|
|
19036
|
-
style={{
|
|
19037
|
-
width: 400,
|
|
19038
|
-
}}
|
|
19633
|
+
items={itemsWithSectionTitles}
|
|
19634
|
+
defaultOpen={true}
|
|
19635
|
+
maxHeight={400}
|
|
19039
19636
|
/>
|
|
19040
|
-
</Autocomplete>
|
|
19041
19637
|
</Virtualizer>
|
|
19042
19638
|
);
|
|
19043
|
-
}
|
|
19044
|
-
|
|
19045
|
-
\`\`\`jsx
|
|
19046
|
-
import { Separator } from "../../utils";
|
|
19047
|
-
|
|
19048
|
-
<Separator />;
|
|
19049
|
-
\`\`\`
|
|
19050
|
-
|
|
19051
|
-
By default, the separator is horizontal.
|
|
19052
|
-
|
|
19053
|
-
\`\`\`jsx
|
|
19054
|
-
import { Separator } from "../../utils";
|
|
19055
|
-
|
|
19056
|
-
<div>
|
|
19057
|
-
Section 1
|
|
19058
|
-
<Separator />
|
|
19059
|
-
Section 2
|
|
19060
|
-
</div>;
|
|
19061
|
-
\`\`\`
|
|
19062
|
-
|
|
19063
|
-
The \`orientation\` prop can be used to change the orientation of the separator.
|
|
19064
|
-
|
|
19065
|
-
\`\`\`jsx
|
|
19066
|
-
import { Separator } from "../../utils";
|
|
19639
|
+
};
|
|
19067
19640
|
|
|
19068
|
-
<
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
|
|
19073
|
-
|
|
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
|
+
};
|
|
19074
19655
|
|
|
19075
|
-
| Selector | Description |
|
|
19076
|
-
| ------------------ | ----------------------------------------------------------------------- |
|
|
19077
|
-
| \\[data-orientation] | The orientation of the separator. It can be \`horizontal\` or \`vertical\`. |`,props:`interface SeparatorProps {
|
|
19078
|
-
/**
|
|
19079
|
-
* The orientation of the separator.
|
|
19080
|
-
*
|
|
19081
|
-
* @default 'horizontal'
|
|
19082
|
-
*/
|
|
19083
|
-
orientation?: "horizontal" | "vertical"
|
|
19084
19656
|
/**
|
|
19085
|
-
*
|
|
19657
|
+
* Owns \`isOpen\` so the controlled-open contract can be driven from outside the
|
|
19658
|
+
* Select, with a sibling readout of the current state.
|
|
19086
19659
|
*/
|
|
19087
|
-
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
|
|
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
|
|
19091
19826
|
* \`Omit<StylingProps, keyof BlockProps>\` (see \`StatusCard\` / \`Code\`).
|
|
19092
19827
|
* Retained on existing components for backward compatibility.
|
|
19093
19828
|
*
|
|
@@ -23296,7 +24031,7 @@ export const TaggedPaginationExample: React.FC<
|
|
|
23296
24031
|
{...props}
|
|
23297
24032
|
/>
|
|
23298
24033
|
);
|
|
23299
|
-
};`},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 {
|
|
23300
24035
|
/**
|
|
23301
24036
|
* @deprecated Do not use in new components. This is a legacy block
|
|
23302
24037
|
* identifier; new components should exclude it via
|
|
@@ -23352,6 +24087,13 @@ children: React.ReactNode
|
|
|
23352
24087
|
* @default "span"
|
|
23353
24088
|
*/
|
|
23354
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
|
|
23355
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) => (
|
|
23356
24098
|
<VariantViewer<React.ComponentProps<typeof Text>>
|
|
23357
24099
|
header={["Small", "Medium", "Large"]}
|
|
@@ -23386,8 +24128,24 @@ elementType?: React.ElementType
|
|
|
23386
24128
|
}}
|
|
23387
24129
|
defaultProps={args}
|
|
23388
24130
|
/>
|
|
23389
|
-
);`}
|
|
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";
|
|
23390
24147
|
|
|
24148
|
+
import { UNSAFE_ListBox } from "../../UNSAFE_ListBox";
|
|
23391
24149
|
import { Text } from "../Text";
|
|
23392
24150
|
|
|
23393
24151
|
export function TextWithRef() {
|
|
@@ -23408,65 +24166,61 @@ export function TextWithRef() {
|
|
|
23408
24166
|
<span data-testid="tag-name">{tag}</span>
|
|
23409
24167
|
</>
|
|
23410
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
|
+
);
|
|
23411
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 {
|
|
23412
|
-
/**
|
|
23413
|
-
* @deprecated Do not use in new components. This is a legacy block
|
|
23414
|
-
* identifier; new components should exclude it via
|
|
23415
|
-
* \`Omit<StylingProps, keyof BlockProps>\` (see \`StatusCard\` / \`Code\`).
|
|
23416
|
-
* Retained on existing components for backward compatibility.
|
|
23417
|
-
*
|
|
23418
|
-
* The unique identifier for the block. This is used to identify the block in
|
|
23419
|
-
* the DOM and in the block map. It is added as a data attribute
|
|
23420
|
-
* \`data-block-id\` to the root element of the block if a DOM node is
|
|
23421
|
-
* rendered.
|
|
23422
|
-
*/
|
|
23423
|
-
data-block-id?: string
|
|
23424
|
-
/**
|
|
23425
|
-
* @deprecated Do not use in new components. This is a legacy block group
|
|
23426
|
-
* marker; new components should exclude it via
|
|
23427
|
-
* \`Omit<StylingProps, keyof BlockProps>\` (see \`StatusCard\` / \`Code\`).
|
|
23428
|
-
* Retained on existing components for backward compatibility.
|
|
23429
|
-
*
|
|
23430
|
-
* Represents a data block group. This is similar to \`data-block-id\` but it
|
|
23431
|
-
* doesn't have to be unique just like \`class\`. This is used to group blocks
|
|
23432
|
-
* together in the DOM and in the block map. It is added as a data attribute
|
|
23433
|
-
* \`data-block-class\` to the root element of the block if a DOM node is
|
|
23434
|
-
* rendered.
|
|
23435
|
-
*/
|
|
23436
|
-
data-block-class?: string
|
|
23437
|
-
/**
|
|
23438
|
-
* The className applied to the root element of the component.
|
|
23439
|
-
*/
|
|
23440
|
-
className?: string
|
|
23441
|
-
/**
|
|
23442
|
-
* The style applied to the root element of the component.
|
|
23443
|
-
*/
|
|
23444
|
-
style?: React.CSSProperties
|
|
23445
|
-
/**
|
|
23446
|
-
* The description to display below the input.
|
|
23447
|
-
*/
|
|
23448
|
-
description?: string
|
|
23449
|
-
/**
|
|
23450
|
-
* The error message to display when the input is in an error state.
|
|
23451
|
-
*/
|
|
23452
|
-
errorMessage?: string
|
|
23453
|
-
/**
|
|
23454
|
-
* The warning message to display when the input is in a warning state.
|
|
23455
|
-
*/
|
|
23456
|
-
warningMessage?: string
|
|
23457
|
-
/**
|
|
23458
|
-
* The style object to apply to the input element
|
|
23459
|
-
*/
|
|
23460
|
-
inputStyle?: React.CSSProperties
|
|
23461
|
-
/**
|
|
23462
|
-
* The class name to apply to the input element
|
|
23463
|
-
*/
|
|
23464
|
-
inputClassName?: string
|
|
23465
|
-
/**
|
|
23466
|
-
* The number of visible text rows for the multi-line input. Only applies when
|
|
23467
|
-
* \`isMultiLine\` is set.
|
|
23468
|
-
*/
|
|
23469
|
-
rows?: number
|
|
23470
24224
|
variant?: any
|
|
23471
24225
|
labelPosition?: any
|
|
23472
24226
|
isMultiLine?: any
|
|
@@ -26809,6 +27563,7 @@ export const VirtualizedTreeViewWithRenameExample: React.FC<
|
|
|
26809
27563
|
VirtualizedScrollIntoViewExample,
|
|
26810
27564
|
VirtualListBoxGridLayoutExample,
|
|
26811
27565
|
VirtualListBoxListLayoutExample,
|
|
27566
|
+
VirtualListBoxWithSectionHeadersExample,
|
|
26812
27567
|
VirtualListBoxWithSectionsExample,
|
|
26813
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.
|
|
26814
27569
|
|
|
@@ -26905,6 +27660,34 @@ const fonts = [
|
|
|
26905
27660
|
/>;
|
|
26906
27661
|
\`\`\`
|
|
26907
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
|
+
|
|
26908
27691
|
\`\`\`jsx
|
|
26909
27692
|
<UNSAFE_ListBox
|
|
26910
27693
|
items={items}
|
|
@@ -27002,6 +27785,10 @@ style?: React.CSSProperties
|
|
|
27002
27785
|
/**
|
|
27003
27786
|
* The custom render function for the listbox options.
|
|
27004
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
|
+
*
|
|
27005
27792
|
* @param item ListOption
|
|
27006
27793
|
* @param options ListBoxItemRenderProps
|
|
27007
27794
|
*/
|
|
@@ -27011,6 +27798,9 @@ renderOption?: (
|
|
|
27011
27798
|
) => React.ReactNode
|
|
27012
27799
|
/**
|
|
27013
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.
|
|
27014
27804
|
*/
|
|
27015
27805
|
optionClassName?: | string
|
|
27016
27806
|
| ((
|
|
@@ -27019,6 +27809,9 @@ optionClassName?: | string
|
|
|
27019
27809
|
) => string | undefined)
|
|
27020
27810
|
/**
|
|
27021
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.
|
|
27022
27815
|
*/
|
|
27023
27816
|
optionStyle?: | React.CSSProperties
|
|
27024
27817
|
| ((
|
|
@@ -27028,15 +27821,25 @@ optionStyle?: | React.CSSProperties
|
|
|
27028
27821
|
/**
|
|
27029
27822
|
* The custom render function for the listbox sections.
|
|
27030
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
|
+
*
|
|
27031
27828
|
* @param section ListSection
|
|
27032
27829
|
*/
|
|
27033
27830
|
renderSectionHeader?: (section: ListSection) => React.ReactNode
|
|
27034
27831
|
/**
|
|
27035
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.
|
|
27036
27836
|
*/
|
|
27037
27837
|
sectionClassName?: string | ((section: ListSection) => string | undefined)
|
|
27038
27838
|
/**
|
|
27039
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.
|
|
27040
27843
|
*/
|
|
27041
27844
|
sectionStyle?: | React.CSSProperties
|
|
27042
27845
|
| ((section: ListSection) => React.CSSProperties | undefined)
|
|
@@ -27072,6 +27875,11 @@ withSectionHeaderPadding?: boolean
|
|
|
27072
27875
|
*
|
|
27073
27876
|
* type ListItem = ListOption | ListSection;
|
|
27074
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.
|
|
27075
27883
|
*/
|
|
27076
27884
|
items?: ListItem[]
|
|
27077
27885
|
/**
|
|
@@ -27158,7 +27966,7 @@ listBoxHandle?: React.RefObject<ListHandle>
|
|
|
27158
27966
|
items={items}
|
|
27159
27967
|
aria-label="List box"
|
|
27160
27968
|
selectionMode="multiple"
|
|
27161
|
-
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";
|
|
27162
27970
|
import {
|
|
27163
27971
|
EllipseDashedIcon,
|
|
27164
27972
|
EllipseIcon,
|
|
@@ -27188,7 +27996,10 @@ import {
|
|
|
27188
27996
|
import { useDragAndDrop } from "../hooks/useDragAndDrop";
|
|
27189
27997
|
import { UNSAFE_ListBox as ListBox } from "../ListBox";
|
|
27190
27998
|
|
|
27191
|
-
import type {
|
|
27999
|
+
import type {
|
|
28000
|
+
ListItem,
|
|
28001
|
+
ListOption as ListOptionType,
|
|
28002
|
+
} from "../../shared/types/List";
|
|
27192
28003
|
import type { ListHandle } from "../ListBox.types";
|
|
27193
28004
|
import type { DroppableCollectionReorderEvent } from "@react-types/shared";
|
|
27194
28005
|
|
|
@@ -27765,16 +28576,85 @@ export const VirtualListBoxWithSectionsExample: React.FC<
|
|
|
27765
28576
|
);
|
|
27766
28577
|
};
|
|
27767
28578
|
|
|
27768
|
-
export const
|
|
27769
|
-
|
|
27770
|
-
|
|
27771
|
-
id: \`item-\${i}\`,
|
|
27772
|
-
label: \`Item \${i}\`,
|
|
27773
|
-
}));
|
|
27774
|
-
|
|
28579
|
+
export const VirtualListBoxWithSectionHeadersExample: React.FC<
|
|
28580
|
+
Omit<React.ComponentProps<typeof ListBox>, "items">
|
|
28581
|
+
> = (args) => {
|
|
27775
28582
|
return (
|
|
27776
|
-
<
|
|
27777
|
-
|
|
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">
|
|
27778
28658
|
<Text type="body" size="sm">
|
|
27779
28659
|
Scroll to items in a virtualized list (10,000 items). Items that
|
|
27780
28660
|
aren't currently rendered will be scrolled into view.
|
|
@@ -27822,7 +28702,110 @@ export const VirtualizedScrollIntoViewExample: React.FC = () => {
|
|
|
27822
28702
|
</Virtualizer>
|
|
27823
28703
|
</Box>
|
|
27824
28704
|
);
|
|
27825
|
-
}
|
|
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\`.
|
|
27826
28809
|
|
|
27827
28810
|
* Efficient rendering for very large collections
|
|
27828
28811
|
* Preset layout options for list boxes, tree views, and image galleries
|
|
@@ -30800,25 +31783,13 @@ export const PopoverDefaultOpenWithArrowExample = () => {
|
|
|
30800
31783
|
);
|
|
30801
31784
|
};
|
|
30802
31785
|
|
|
30803
|
-
export const PopoverContainedFocusExample = (
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
|
|
30808
|
-
|
|
30809
|
-
|
|
30810
|
-
<Dialog
|
|
30811
|
-
size="content"
|
|
30812
|
-
className={sprinkles({
|
|
30813
|
-
padding: "md",
|
|
30814
|
-
display: "flex",
|
|
30815
|
-
gap: "xl",
|
|
30816
|
-
flexDirection: "column",
|
|
30817
|
-
})}
|
|
30818
|
-
style={{
|
|
30819
|
-
width: 200,
|
|
30820
|
-
}}
|
|
30821
|
-
>
|
|
31786
|
+
export const PopoverContainedFocusExample = ({
|
|
31787
|
+
shouldContainFocus = true,
|
|
31788
|
+
}: {
|
|
31789
|
+
shouldContainFocus?: boolean;
|
|
31790
|
+
}) => {
|
|
31791
|
+
const content = (
|
|
31792
|
+
<>
|
|
30822
31793
|
<Text type="label">The focus is contained within the popover.</Text>
|
|
30823
31794
|
|
|
30824
31795
|
<TextInput
|
|
@@ -30830,10 +31801,55 @@ export const PopoverContainedFocusExample = () => {
|
|
|
30830
31801
|
label="Button"
|
|
30831
31802
|
style={{ width: "100%", justifyContent: "center" }}
|
|
30832
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}
|
|
30833
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
|
+
)}
|
|
30834
31837
|
</PopoverContent>
|
|
30835
31838
|
</Popover>
|
|
30836
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
|
+
);
|
|
30837
31853
|
};
|
|
30838
31854
|
|
|
30839
31855
|
export const PopoverWithScrollableViewportExample: React.FC<{
|
|
@@ -31960,25 +32976,13 @@ export const PopoverDefaultOpenWithArrowExample = () => {
|
|
|
31960
32976
|
);
|
|
31961
32977
|
};
|
|
31962
32978
|
|
|
31963
|
-
export const PopoverContainedFocusExample = (
|
|
31964
|
-
|
|
31965
|
-
|
|
31966
|
-
|
|
31967
|
-
|
|
31968
|
-
|
|
31969
|
-
|
|
31970
|
-
<Dialog
|
|
31971
|
-
size="content"
|
|
31972
|
-
className={sprinkles({
|
|
31973
|
-
padding: "md",
|
|
31974
|
-
display: "flex",
|
|
31975
|
-
gap: "xl",
|
|
31976
|
-
flexDirection: "column",
|
|
31977
|
-
})}
|
|
31978
|
-
style={{
|
|
31979
|
-
width: 200,
|
|
31980
|
-
}}
|
|
31981
|
-
>
|
|
32979
|
+
export const PopoverContainedFocusExample = ({
|
|
32980
|
+
shouldContainFocus = true,
|
|
32981
|
+
}: {
|
|
32982
|
+
shouldContainFocus?: boolean;
|
|
32983
|
+
}) => {
|
|
32984
|
+
const content = (
|
|
32985
|
+
<>
|
|
31982
32986
|
<Text type="label">The focus is contained within the popover.</Text>
|
|
31983
32987
|
|
|
31984
32988
|
<TextInput
|
|
@@ -31990,10 +32994,55 @@ export const PopoverContainedFocusExample = () => {
|
|
|
31990
32994
|
label="Button"
|
|
31991
32995
|
style={{ width: "100%", justifyContent: "center" }}
|
|
31992
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}
|
|
31993
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
|
+
)}
|
|
31994
33030
|
</PopoverContent>
|
|
31995
33031
|
</Popover>
|
|
31996
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
|
+
);
|
|
31997
33046
|
};
|
|
31998
33047
|
|
|
31999
33048
|
export const PopoverWithScrollableViewportExample: React.FC<{
|
|
@@ -32759,7 +33808,15 @@ iconTooltip?: ActionIconButtonProps["tooltip"]
|
|
|
32759
33808
|
placeholder="Select"
|
|
32760
33809
|
items={items}
|
|
32761
33810
|
isReadOnly
|
|
32762
|
-
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";
|
|
32763
33820
|
import React from "react";
|
|
32764
33821
|
import { useFilter } from "react-aria";
|
|
32765
33822
|
import { Autocomplete, Virtualizer } from "react-aria-components";
|
|
@@ -32768,11 +33825,16 @@ import { useListData } from "react-stately";
|
|
|
32768
33825
|
import { ActionButton } from "../../ActionButton";
|
|
32769
33826
|
import { items } from "../../ListBox/__tests__/testComponents";
|
|
32770
33827
|
import { virtualizeAutocompleteItems } from "../../Menu/__tests__/data";
|
|
32771
|
-
import {
|
|
33828
|
+
import { itemsWithSectionTitles } from "../../UNSAFE_ListBox/__tests__/testComponents";
|
|
33829
|
+
import {
|
|
33830
|
+
ListLayout,
|
|
33831
|
+
VIRTUALIZER_LAYOUT_DEFAULT_OPTIONS,
|
|
33832
|
+
} from "../../Virtualizer";
|
|
32772
33833
|
import { IconSelect } from "../IconSelect";
|
|
32773
33834
|
import { Select } from "../Select";
|
|
32774
33835
|
|
|
32775
33836
|
import type { IconSelectProps } from "../Select.types";
|
|
33837
|
+
import type { Key } from "@react-types/shared";
|
|
32776
33838
|
|
|
32777
33839
|
export const SelectExample: React.FC<
|
|
32778
33840
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
@@ -32780,13 +33842,28 @@ export const SelectExample: React.FC<
|
|
|
32780
33842
|
return (
|
|
32781
33843
|
<Select
|
|
32782
33844
|
placeholder="Choose an item"
|
|
32783
|
-
{...args}
|
|
32784
33845
|
optionClassName={(item) => item.label}
|
|
33846
|
+
{...args}
|
|
32785
33847
|
items={items}
|
|
32786
33848
|
/>
|
|
32787
33849
|
);
|
|
32788
33850
|
};
|
|
32789
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
|
+
|
|
32790
33867
|
export const SelectGetTargetRectExample: React.FC = () => {
|
|
32791
33868
|
const [called, setCalled] = React.useState(false);
|
|
32792
33869
|
|
|
@@ -32843,19 +33920,136 @@ export const SelectCustomTriggerExample: React.FC<
|
|
|
32843
33920
|
};
|
|
32844
33921
|
|
|
32845
33922
|
export const IconSelectExample: React.FC<
|
|
32846
|
-
Omit<IconSelectProps, "items" | "
|
|
33923
|
+
Omit<IconSelectProps, "items" | "aria-label">
|
|
32847
33924
|
> = (args) => {
|
|
32848
33925
|
return (
|
|
32849
33926
|
<IconSelect
|
|
32850
33927
|
placeholder="Choose an item"
|
|
33928
|
+
icon={EllipseIcon}
|
|
32851
33929
|
{...args}
|
|
32852
33930
|
items={items}
|
|
32853
|
-
icon={EllipseIcon}
|
|
32854
33931
|
aria-label="Aria Label"
|
|
32855
33932
|
/>
|
|
32856
33933
|
);
|
|
32857
33934
|
};
|
|
32858
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
|
+
|
|
32859
34053
|
export const SelectWithVirtualizeAutocompleteExample: React.FC<
|
|
32860
34054
|
Omit<React.ComponentProps<typeof Select>, "items">
|
|
32861
34055
|
> = (args) => {
|
|
@@ -32879,6 +34073,27 @@ export const SelectWithVirtualizeAutocompleteExample: React.FC<
|
|
|
32879
34073
|
</Autocomplete>
|
|
32880
34074
|
</Virtualizer>
|
|
32881
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
|
+
);
|
|
32882
34097
|
};`},similarTo:[],figmaUrl:null},IconSlider:{id:"core-forms-slider-iconslider",importStatement:'import { IconSlider } from "@baseline-ui/core";',description:"",documentation:null,props:`interface IconSliderProps {
|
|
32883
34098
|
/**
|
|
32884
34099
|
* @deprecated Do not use in new components. This is a legacy block
|
|
@@ -32989,6 +34204,21 @@ import { ActionButton, I18nProvider, ThemeProvider } from "@baseline-ui/core";
|
|
|
32989
34204
|
|
|
32990
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.
|
|
32991
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
|
+
|
|
32992
34222
|
### Styling
|
|
32993
34223
|
|
|
32994
34224
|
Import the following files at the top of your stylesheet to use the Baseline UI styles:
|
|
@@ -33257,22 +34487,24 @@ function App() {
|
|
|
33257
34487
|
}
|
|
33258
34488
|
\`\`\``,internationalization:`# Internationalization
|
|
33259
34489
|
|
|
33260
|
-
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).
|
|
33261
34493
|
|
|
33262
34494
|
## Localization
|
|
33263
34495
|
|
|
33264
|
-
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.
|
|
33265
34497
|
|
|
33266
|
-
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.
|
|
33267
34499
|
|
|
33268
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.
|
|
33269
34501
|
|
|
33270
34502
|
### Example
|
|
33271
34503
|
|
|
33272
|
-
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:
|
|
33273
34505
|
|
|
33274
34506
|
\`\`\`jsx
|
|
33275
|
-
import { useLocale } from "
|
|
34507
|
+
import { useLocale } from "@baseline-ui/core";
|
|
33276
34508
|
|
|
33277
34509
|
function YourApp() {
|
|
33278
34510
|
let { locale, direction } = useLocale();
|
|
@@ -33288,27 +34520,128 @@ function YourApp() {
|
|
|
33288
34520
|
You can also override the language used for localization with the [\`I18nProvider\`](/?path=/docs/utilities-i18nprovider--docs) component:
|
|
33289
34521
|
|
|
33290
34522
|
\`\`\`jsx
|
|
33291
|
-
import { I18nProvider } from "
|
|
34523
|
+
import { I18nProvider } from "@baseline-ui/core";
|
|
33292
34524
|
|
|
33293
34525
|
<I18nProvider locale="fr-FR">
|
|
33294
34526
|
<YourApp />
|
|
33295
34527
|
</I18nProvider>;
|
|
33296
34528
|
\`\`\`
|
|
33297
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
|
+
|
|
33298
34589
|
### Supported locales
|
|
33299
34590
|
|
|
33300
|
-
|
|
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.
|
|
33301
34607
|
|
|
33302
|
-
###
|
|
34608
|
+
### Translating them yourself
|
|
33303
34609
|
|
|
33304
|
-
|
|
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.
|
|
33305
34627
|
|
|
33306
34628
|
## Overriding Component Translations
|
|
33307
34629
|
|
|
33308
34630
|
You can override any built-in component string by passing its \`bui.*\`-namespaced key to
|
|
33309
34631
|
\`I18nProvider.messages\`. Only the keys you provide are overridden \u2014 all other strings
|
|
33310
|
-
fall back to each component's
|
|
33311
|
-
|
|
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
|
+
\`\`\`
|
|
33312
34645
|
|
|
33313
34646
|
Each component's documentation lists its overridable keys and shows an example. See:
|
|
33314
34647
|
|
|
@@ -33316,7 +34649,43 @@ Each component's documentation lists its overridable keys and shows an example.
|
|
|
33316
34649
|
* [ColorInput](?path=/docs/components-colorinput--docs#translations)
|
|
33317
34650
|
* [ImageDropZone](?path=/docs/components-imagedropzone--docs#translations)
|
|
33318
34651
|
* [FreehandCanvas](?path=/docs/components-freehandcanvas--docs#translations)
|
|
33319
|
-
* [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
|
|
33320
34689
|
|
|
33321
34690
|
Baseline UI provides a powerful, type-safe styling system built on top of [vanilla-extract sprinkles](https://vanilla-extract.style/documentation/packages/sprinkles/).
|
|
33322
34691
|
|
|
@@ -34226,7 +35595,7 @@ padding={[null, "lg", "xl"]}
|
|
|
34226
35595
|
|
|
34227
35596
|
* [vanilla-extract sprinkles documentation](https://vanilla-extract.style/documentation/packages/sprinkles/) - Learn about the underlying sprinkles framework
|
|
34228
35597
|
* [Box component documentation](/docs/core-utilities-box--docs) - Detailed information about the Box component
|
|
34229
|
-
* [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.2.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=`
|
|
34230
35599
|
# Baseline UI MCP Server Guidelines
|
|
34231
35600
|
|
|
34232
35601
|
This MCP server provides AI assistants with structured access to Baseline UI's comprehensive component documentation, icon library, theming resources, and design guidelines.
|