Rewrite to vanilla Web Components
Complete rewrite from SolidJS to browser-native Custom Elements. 8 components: Dialog, Select, Tabs, Accordion, Form, Toast, DropdownMenu, Popover Infrastructure: signals (~30 lines), router (Navigation API + View Transitions) Theme: optional default CSS with custom properties Zero framework deps. No Shadow DOM. Built on Popover API, <dialog>, Invoker Commands, Navigation API, View Transitions.
This commit is contained in:
parent
8cfa75fe3e
commit
3768af1369
@ -1,73 +0,0 @@
|
|||||||
# Animation
|
|
||||||
|
|
||||||
Kobalte components can be animated with CSS keyframes or your JavaScript animation library of choice. However, there are some caveats noted here in regard to exiting animations with JavaScript animation libraries.
|
|
||||||
|
|
||||||
## Animating with CSS animation
|
|
||||||
|
|
||||||
The simplest way to animate Kobalte components is with CSS.
|
|
||||||
|
|
||||||
You can use CSS animation to animate both mount and unmount phases of several Kobalte components. The latter is possible because this components will suspend unmount while your animation plays out.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
.popover__content {
|
|
||||||
animation: fadeOut 300ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popover__content[data-expanded] {
|
|
||||||
animation: fadeIn 300ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOut {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
.popover__content {
|
|
||||||
animation: fadeOut 300ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popover__content[data-expanded] {
|
|
||||||
animation: fadeIn 300ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeOut {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Delegating unmounting for JavaScript animation
|
|
||||||
|
|
||||||
When many stateful Kobalte components are hidden from view, they are actually removed from the DOM. JavaScript animation libraries need control of the unmounting phase, so we provide the `forceMount` prop on many components to allow consumers to delegate the mounting and unmounting of children based on the animation state determined by those libraries.
|
|
||||||
|
|
||||||
Previous[←Styling](https://kobalte.dev/docs/core/overview/styling)Next[Polymorphism→](https://kobalte.dev/docs/core/overview/polymorphism)
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
# v0.13.x
|
|
||||||
|
|
||||||
## v0.13.11 (July 27, 2025)
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- Update createInteractOutside to work with other Element types ( [#612](https://github.com/kobaltedev/kobalte/pull/612))
|
|
||||||
- Meter, Progress: remove rounding from fill width ( [#602](https://github.com/kobaltedev/kobalte/pull/602))
|
|
||||||
- Image: handle crossOrigin and referrerPolicy ( [#598](https://github.com/kobaltedev/kobalte/pull/598))
|
|
||||||
- ToggleGroup: reactive disabled state ( [#595](https://github.com/kobaltedev/kobalte/pull/595))
|
|
||||||
- ColorArea: double onChange trigger ( [#593](https://github.com/kobaltedev/kobalte/pull/593))
|
|
||||||
- ColorChannelField: fix handling of alpha values ( [#590](https://github.com/kobaltedev/kobalte/pull/590))
|
|
||||||
- Colors: color parsing and rgb(a)/hsl(a) format ( [#587](https://github.com/kobaltedev/kobalte/pull/587))
|
|
||||||
|
|
||||||
## v0.13.10 (May 30, 2025)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- [New `SegmentedControl` component](https://kobalte.dev/docs/core/components/segmented-control) ( [#531](https://github.com/kobaltedev/kobalte/pull/531))
|
|
||||||
|
|
||||||
## v0.13.9 (February 21, 2025)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- [New `ColorWheel` component](https://kobalte.dev/docs/core/components/color-wheel) ( [#510](https://github.com/kobaltedev/kobalte/pull/510))
|
|
||||||
- [New `ColorField` component](https://kobalte.dev/docs/core/components/color-field) ( [#510](https://github.com/kobaltedev/kobalte/pull/510))
|
|
||||||
- [New `ColorChannelField` component](https://kobalte.dev/docs/core/components/color-channel-field) ( [#508](https://github.com/kobaltedev/kobalte/pull/508))
|
|
||||||
- [New `ColorArea` component](https://kobalte.dev/docs/core/components/color-area) ( [#508](https://github.com/kobaltedev/kobalte/pull/508))
|
|
||||||
- [New `ColorSlider` component](https://kobalte.dev/docs/core/components/color-slider) ( [#508](https://github.com/kobaltedev/kobalte/pull/508))
|
|
||||||
- [New `ColorSwatch` component](https://kobalte.dev/docs/core/components/color-swatch) ( [#508](https://github.com/kobaltedev/kobalte/pull/508))
|
|
||||||
- [New `Search` component](https://kobalte.dev/docs/core/components/search) ( [#506](https://github.com/kobaltedev/kobalte/pull/506))
|
|
||||||
|
|
||||||
## v0.13.8 (February 7, 2025)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- [New `FileField` component](https://kobalte.dev/docs/core/components/file-field) ( [#512](https://github.com/kobaltedev/kobalte/pull/512))
|
|
||||||
- [New `Badge` component](https://kobalte.dev/docs/core/components/badge) ( [#503](https://github.com/kobaltedev/kobalte/pull/503))
|
|
||||||
- [New `Meter` component](https://kobalte.dev/docs/core/components/meter) ( [#500](https://github.com/kobaltedev/kobalte/pull/500))
|
|
||||||
|
|
||||||
## v0.13.7 (October 7, 2024)
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- ToggleGroup: root value type definition ( [#479](https://github.com/kobaltedev/kobalte/pull/479))
|
|
||||||
- Collapsible: close animation on default open ( [#483](https://github.com/kobaltedev/kobalte/pull/483))
|
|
||||||
- Toast: filter dismissed toasts in region ( [#489](https://github.com/kobaltedev/kobalte/pull/489))
|
|
||||||
|
|
||||||
## v0.13.6 (August 27, 2024)
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- Update missing export from `@kobalte/utils` ( [#477](https://github.com/kobaltedev/kobalte/pull/477))
|
|
||||||
|
|
||||||
## v0.13.5 (August 27, 2024)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- Tooltip: add skipDelayDuration prop ( [#467](https://github.com/kobaltedev/kobalte/pull/467))
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- NumberField: only format when enabled ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- NumberField: don't trigger `onRawValueChange` on mount when NaN ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- Select: correct type definition & empty value for multiselect ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- TextField: clear input when controlled value set to undefined ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- Combobox: correct type definition & empty value for multiselect ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- Skeleton: correct data-animate & data-visible attribute value ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- Combobox: close list on outside click ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- NavigationMenu: incorrect animation after closed ( [#456](https://github.com/kobaltedev/kobalte/pull/456))
|
|
||||||
- Tabs: recalculate indicator styles on resize ( [#458](https://github.com/kobaltedev/kobalte/pull/458))
|
|
||||||
- Pagination: correctly render fixedItems with low page count ( [#464](https://github.com/kobaltedev/kobalte/pull/464))
|
|
||||||
- Combobox: prevent opening on input with triggerMode="manual" ( [#465](https://github.com/kobaltedev/kobalte/pull/465))
|
|
||||||
- NumberField: precision handling with floating point offsets and value snapping ( [#468](https://github.com/kobaltedev/kobalte/pull/468))
|
|
||||||
|
|
||||||
## v0.13.4 (June 22, 2024)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- Add source exports ( [#408](https://github.com/kobaltedev/kobalte/pull/408))
|
|
||||||
- Support string style prop ( [#432](https://github.com/kobaltedev/kobalte/pull/432))
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- Combobox: convert textValue with optionTextValue ( [#436](https://github.com/kobaltedev/kobalte/pull/436))
|
|
||||||
- Polymorphic: override the `component` prop of `<Dynamic />` ( [#437](https://github.com/kobaltedev/kobalte/pull/437))
|
|
||||||
- Slider: inverted slider thumb in the wrong position ( [#441](https://github.com/kobaltedev/kobalte/pull/441))
|
|
||||||
- Wait for presence to finish before enabling scroll ( [#447](https://github.com/kobaltedev/kobalte/pull/447))
|
|
||||||
|
|
||||||
## v0.13.3 (June 3, 2024)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- [New `NavigationMenu` component](https://kobalte.dev/docs/core/components/navigation-menu) ( [#409](https://github.com/kobaltedev/kobalte/pull/409))
|
|
||||||
|
|
||||||
## v0.13.2 (May 29, 2024)
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- Refactored polymorphic element type in CommonProps ( [#420](https://github.com/kobaltedev/kobalte/pull/420))
|
|
||||||
|
|
||||||
## v0.13.1 (May 3, 2024)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- NumberField: improve input handling ( [#379](https://github.com/kobaltedev/kobalte/pull/379)) ( [#395](https://github.com/kobaltedev/kobalte/pull/395))
|
|
||||||
|
|
||||||
**Bug fixes**
|
|
||||||
|
|
||||||
- Slider: call `onChangeEnd` on blur after changing value ( [#402](https://github.com/kobaltedev/kobalte/pull/402))
|
|
||||||
- Select: `options` non reactive inside suspense ( [#401](https://github.com/kobaltedev/kobalte/pull/401))
|
|
||||||
- Combobox: close on select with `focus` trigger mode ( [#400](https://github.com/kobaltedev/kobalte/pull/400))
|
|
||||||
- Menu: open link menu items ( [#397](https://github.com/kobaltedev/kobalte/pull/397))
|
|
||||||
|
|
||||||
## v0.13.0 (May 1, 2024)
|
|
||||||
|
|
||||||
**Breaking changes**
|
|
||||||
|
|
||||||
- [#381](https://github.com/kobaltedev/kobalte/pull/381)
|
|
||||||
- Removed `asChild` and `<As/>`: [Polymorphism documentation](https://kobalte.dev/docs/core/overview/polymorphism)
|
|
||||||
- Refactored `as` prop: [Polymorphism documentation](https://kobalte.dev/docs/core/overview/polymorphism)
|
|
||||||
- [New component types](https://kobalte.dev/docs/core/overview/polymorphism#types)
|
|
||||||
|
|
||||||
**New features**
|
|
||||||
|
|
||||||
- Allow importing individual components ( [#391](https://github.com/kobaltedev/kobalte/pull/391))
|
|
||||||
- [New `ToggleGroup` component](https://kobalte.dev/docs/core/components/toggle-group) ( [#378](https://github.com/kobaltedev/kobalte/pull/378))
|
|
||||||
|
|
||||||
Next[v0.12.x→](https://kobalte.dev/docs/changelog/0-12-x)
|
|
||||||
@ -1,349 +0,0 @@
|
|||||||
# Color Area
|
|
||||||
|
|
||||||
Allows users to adjust two channels of an RGB, HSL, or HSB color value against a two-dimensional gradient background.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorArea } from "@kobalte/core/color-area";
|
|
||||||
// or
|
|
||||||
import { Root, Background, ... } from "@kobalte/core/color-area";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorArea } from "@kobalte/core/color-area";
|
|
||||||
// or
|
|
||||||
import { Root, Background, ... } from "@kobalte/core/color-area";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Support for adjusting two-channel values of an RGB, HSL or HSB color value.
|
|
||||||
- Pressing on the color area background moves the thumb to that position.
|
|
||||||
- Supports using the arrow keys, for changing value by step, as well as shift + arrow key, page up/down, home, and end keys, for changing the value by page step.
|
|
||||||
- Support for disabling the color area.
|
|
||||||
- Prevents text selection while dragging.
|
|
||||||
- Exposed to assistive technology as a 2D slider element via ARIA.
|
|
||||||
- Uses two hidden native input elements within a group to support touch screen readers.
|
|
||||||
- Automatic ARIA labeling using the localized channel names by default.
|
|
||||||
- Support for mirroring in RTL locales.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The color area consists of:
|
|
||||||
|
|
||||||
- **ColorArea:** The root container for the color area.
|
|
||||||
- **ColorArea.Background:** The component that visually represents the range of colors from which a user can select.
|
|
||||||
- **ColorArea.Thumb:** The thumb that is used to visually indicate a value in the color area background.
|
|
||||||
- **ColorArea.HiddenInputX:** The horizontal native html input that is visually hidden in the color area thumb.
|
|
||||||
- **ColorArea.HiddenInputY:** The vertical native html input that is visually hidden in the color area thumb.
|
|
||||||
- **ColorArea.Label:** The label that gives the user information on the color area.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorArea>
|
|
||||||
<ColorArea.Label />
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Track>
|
|
||||||
</ColorArea>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorArea>
|
|
||||||
<ColorArea.Label />
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Track>
|
|
||||||
</ColorArea>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorArea } from "@kobalte/core/color-area";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorArea class="ColorAreaRoot">
|
|
||||||
<ColorArea.Label class="ColorAreaLabel">Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background class="ColorAreaBackground">
|
|
||||||
<ColorArea.Thumb class="ColorAreaThumb">
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorArea } from "@kobalte/core/color-area";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorArea class="ColorAreaRoot">
|
|
||||||
<ColorArea.Label class="ColorAreaLabel">Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background class="ColorAreaBackground">
|
|
||||||
<ColorArea.Thumb class="ColorAreaThumb">
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The value provided to `defaultValue` or `value` should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string.
|
|
||||||
The `xChannel` and `yChannel` must be one of the channels included in the color value, for example, for RGB colors, the "red", "green", and "blue" channels are available.
|
|
||||||
If no `xChannel` or `yChannel` is provided, for the RGB color space, the red color channel maps to the horizontal axis or xChannel, and the green color channel maps to the vertical axis or yChannel. Similarly, for the HSL and HSB color spaces, the hue color channel maps to the horizontal axis or xChannel, and the saturation color channel maps to the vertical axis or yChannel.
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorArea defaultValue={parseColor("rgb(2, 132, 197)")}>
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorArea defaultValue={parseColor("rgb(2, 132, 197)")}>
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
Current color value: hsl(0 100% 50%)
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)"));
|
|
||||||
<>
|
|
||||||
<ColorArea value={value()} onChange={setValue}>
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
<p>Current color value: {value().toString("hsl")}</p>
|
|
||||||
</>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)"));
|
|
||||||
<>
|
|
||||||
<ColorArea value={value()} onChange={setValue}>
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
<p>Current color value: {value().toString("hsl")}</p>
|
|
||||||
</>;
|
|
||||||
```
|
|
||||||
|
|
||||||
### xChannel and yChannel
|
|
||||||
|
|
||||||
The color channel for each axis of a color area can be specified using the `xChannel` and `yChannel` props. An array of channel names for a color can be returned using the color.getColorChannels method.
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
const [value, setValue] = createSignal(parseColor("rgb(100, 149, 237)"));
|
|
||||||
const [rChannel, gChannel, bChannel] = value().getColorChannels();
|
|
||||||
|
|
||||||
<ColorArea value={value()} onChange={setValue} xChannel={gChannel} yChannel={bChannel}>
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
const [value, setValue] = createSignal(parseColor("rgb(100, 149, 237)"));
|
|
||||||
const [rChannel, gChannel, bChannel] = value().getColorChannels();
|
|
||||||
|
|
||||||
<ColorArea value={value()} onChange={setValue} xChannel={gChannel} yChannel={bChannel}>
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>;
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
ColorArea supports the `xName` and `yName` props for integration with HTML forms.
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorArea defaultValue={parseColor("rgb(100, 149, 237)")} xName="red" yName="green">
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorArea defaultValue={parseColor("rgb(100, 149, 237)")} xName="red" yName="green">
|
|
||||||
<ColorArea.Label>Label</ColorArea.Label>
|
|
||||||
<ColorArea.Background>
|
|
||||||
<ColorArea.Thumb>
|
|
||||||
<ColorArea.HiddenInputX />
|
|
||||||
<ColorArea.HiddenInputY />
|
|
||||||
</ColorArea.Thumb>
|
|
||||||
</ColorArea.Background>
|
|
||||||
</ColorArea>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ColorArea
|
|
||||||
|
|
||||||
`ColorArea` is equivalent to the `Root` import from `@kobalte/core/color-area`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `Color`<br> The controlled value of the color area.. |
|
|
||||||
| defaultValue | `Color`<br> The value of the color area when initially rendered. |
|
|
||||||
| colorSpace | `ColorSpace`<br> The color space that the color area operates in. The `xChannel` and `yChannel` must be in this color space. |
|
|
||||||
| onChange | `(value: Color) => void`<br> Event handler called when the value changes. |
|
|
||||||
| onChangeEnd | `(value: Color) => void`<br> Event handler called when the value changes at the end of an interaction. |
|
|
||||||
| xChannel | `ColorChannel`<br> Color channel for the horizontal axis. |
|
|
||||||
| yChannel | `ColorChannel`<br> Color channel for the vertical axis. |
|
|
||||||
| xName | `string`<br> The name of the x channel input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| yName | `string`<br> The name of the y channel input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| name | `string`<br> The name of the color area, used when submitting an HTML form. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the color area should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check a radio group item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the radio group items can be selected but not changed by the user. |
|
|
||||||
| translations | `ColorAreaIntlTranslations`<br> Localization strings. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the slider is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the slider is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must slider an item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the slider is disabled. |
|
|
||||||
| data-readonly | Present when the slider is read only. |
|
|
||||||
|
|
||||||
`ColorArea.Background`, `ColorArea.Thumb`, `ColorArea.HiddenInputX`, `ColorArea.HiddenInputY` and `ColorArea.Label` share the same data-attributes.
|
|
||||||
|
|
||||||
### ColorArea.Thumb
|
|
||||||
|
|
||||||
The current color is available on the thumb using the custom css property `--kb-color-current`.
|
|
||||||
|
|
||||||
### ColorArea.HiddenInputX
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Always presesnt |
|
|
||||||
|
|
||||||
### ColorArea.HiddenInputY
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='vertical' | Always presesnt |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ColorArea` | `div` |
|
|
||||||
| `ColorArea.Background` | `div` |
|
|
||||||
| `ColorArea.Thumb` | `span` |
|
|
||||||
| `ColorArea.HiddenInputX` | `input` |
|
|
||||||
| `ColorArea.HiddenInputY` | `input` |
|
|
||||||
| `ColorArea.Label` | `label` |
|
|
||||||
| `ColorArea.Description` | `div` |
|
|
||||||
| `ColorArea.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `PageUp` | Increments the value of the thumb in the vertical axis by a larger step. |
|
|
||||||
| `PageDown` | Decrements the value of the thumb in the vertical axis by a larger step. |
|
|
||||||
| `ArrowDown` | Decrements the value of the thumb in the vertical axis by the step amount. |
|
|
||||||
| `ArrowUp` | Increments the value of the thumb in the vertical axis by the step amount. |
|
|
||||||
| `ArrowRight` | Increments the value of the thumb in the horizontal axis by the step amount. |
|
|
||||||
| `ArrowLeft` | Decrements the value of the thumb in the vertical axis by the step amount. |
|
|
||||||
| `Home` | Decrements the value of the thumb in the horizontal axis by a larger step. |
|
|
||||||
| `End` | Increments the value of the thumb in the horizontal axis by a larger step. |
|
|
||||||
|
|
||||||
Previous[←Collapsible](https://kobalte.dev/docs/core/components/collapsible)Next[Color Channel Field→](https://kobalte.dev/docs/core/components/color-channel-field)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,263 +0,0 @@
|
|||||||
# Dialog
|
|
||||||
|
|
||||||
A window overlaid on either the primary window or another dialog window. Content behind a modal dialog is inert, meaning that users cannot interact with it.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Dialog } from "@kobalte/core/dialog";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/dialog";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Dialog } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Dialog } from "@kobalte/core/dialog";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/dialog";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Dialog } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follows the [WAI ARIA Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/) design pattern.
|
|
||||||
- Supports modal and non-modal modes.
|
|
||||||
- Provides screen reader announcements via rendered title and description.
|
|
||||||
- Focus is trapped and scrolling is blocked while it is open.
|
|
||||||
- Pressing `Esc` closes the dialog.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The dialog consists of:
|
|
||||||
|
|
||||||
- **Dialog:** Contains all the parts of a dialog.
|
|
||||||
- **Dialog.Trigger:** The button that opens the dialog.
|
|
||||||
- **Dialog.Portal:** Portals its children into the `body` when the dialog is open.
|
|
||||||
- **Dialog.Overlay:** The layer that covers the inert portion of the view when the dialog is open.
|
|
||||||
- **Dialog.Content:** Contains the content to be rendered when the dialog is open.
|
|
||||||
- **Dialog.CloseButton:** The button that closes the dialog.
|
|
||||||
- **Dialog.Title:** An accessible title to be announced when the dialog is opened.
|
|
||||||
- **Dialog.Description:** An optional accessible description to be announced when the dialog is opened.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Dialog>
|
|
||||||
<Dialog.Trigger />
|
|
||||||
<Dialog.Portal>
|
|
||||||
<Dialog.Overlay />
|
|
||||||
<Dialog.Content>
|
|
||||||
<Dialog.CloseButton />
|
|
||||||
<Dialog.Title />
|
|
||||||
<Dialog.Description />
|
|
||||||
</Dialog.Content>
|
|
||||||
</Dialog.Portal>
|
|
||||||
</Dialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Dialog>
|
|
||||||
<Dialog.Trigger />
|
|
||||||
<Dialog.Portal>
|
|
||||||
<Dialog.Overlay />
|
|
||||||
<Dialog.Content>
|
|
||||||
<Dialog.CloseButton />
|
|
||||||
<Dialog.Title />
|
|
||||||
<Dialog.Description />
|
|
||||||
</Dialog.Content>
|
|
||||||
</Dialog.Portal>
|
|
||||||
</Dialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Open
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Dialog } from "@kobalte/core/dialog";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Dialog>
|
|
||||||
<Dialog.Trigger class="dialog__trigger">Open</Dialog.Trigger>
|
|
||||||
<Dialog.Portal>
|
|
||||||
<Dialog.Overlay class="dialog__overlay" />
|
|
||||||
<div class="dialog__positioner">
|
|
||||||
<Dialog.Content class="dialog__content">
|
|
||||||
<div class="dialog__header">
|
|
||||||
<Dialog.Title class="dialog__title">About Kobalte</Dialog.Title>
|
|
||||||
<Dialog.CloseButton class="dialog__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Dialog.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Dialog.Description class="dialog__description">
|
|
||||||
Kobalte is a UI toolkit for building accessible web apps and design systems with
|
|
||||||
SolidJS. It provides a set of low-level UI components and primitives which can be the
|
|
||||||
foundation for your design system implementation.
|
|
||||||
</Dialog.Description>
|
|
||||||
</Dialog.Content>
|
|
||||||
</div>
|
|
||||||
</Dialog.Portal>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Dialog } from "@kobalte/core/dialog";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Dialog>
|
|
||||||
<Dialog.Trigger class="dialog__trigger">Open</Dialog.Trigger>
|
|
||||||
<Dialog.Portal>
|
|
||||||
<Dialog.Overlay class="dialog__overlay" />
|
|
||||||
<div class="dialog__positioner">
|
|
||||||
<Dialog.Content class="dialog__content">
|
|
||||||
<div class="dialog__header">
|
|
||||||
<Dialog.Title class="dialog__title">About Kobalte</Dialog.Title>
|
|
||||||
<Dialog.CloseButton class="dialog__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Dialog.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Dialog.Description class="dialog__description">
|
|
||||||
Kobalte is a UI toolkit for building accessible web apps and design systems with
|
|
||||||
SolidJS. It provides a set of low-level UI components and primitives which can be the
|
|
||||||
foundation for your design system implementation.
|
|
||||||
</Dialog.Description>
|
|
||||||
</Dialog.Content>
|
|
||||||
</div>
|
|
||||||
</Dialog.Portal>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default open
|
|
||||||
|
|
||||||
An initial, uncontrolled open value can be provided using the `defaultOpen` prop.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Dialog defaultOpen>...</Dialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Dialog defaultOpen>...</Dialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled open
|
|
||||||
|
|
||||||
The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, close button or overlay, and receives the new value.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog open={open()} onOpenChange={setOpen}>
|
|
||||||
...
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog open={open()} onOpenChange={setOpen}>
|
|
||||||
...
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Dialog
|
|
||||||
|
|
||||||
`Dialog` is equivalent to the `Root` import from `@kobalte/core/dialog` (and deprecated `Dialog.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the dialog. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the dialog changes. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| modal | `boolean`<br> Whether the dialog should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the dialog content. <br> \- elements outside the dialog content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the dialog is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the dialog (portal, overlay and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
| translations | [`DialogIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/dialog/dialog.intl.ts)<br> Localization strings. |
|
|
||||||
|
|
||||||
### Dialog.Trigger
|
|
||||||
|
|
||||||
`Dialog.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button).
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the dialog is open. |
|
|
||||||
| data-closed | Present when the dialog is close. |
|
|
||||||
|
|
||||||
`Dialog.Content` and `Dialog.Overlay` shares the same data-attributes.
|
|
||||||
|
|
||||||
### Dialog.Content
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Dialog` | none |
|
|
||||||
| `Dialog.Trigger` | `button` |
|
|
||||||
| `Dialog.Portal` | `Portal` |
|
|
||||||
| `Dialog.Overlay` | `div` |
|
|
||||||
| `Dialog.Content` | `div` |
|
|
||||||
| `Dialog.CloseButton` | `button` |
|
|
||||||
| `Dialog.Title` | `h2` |
|
|
||||||
| `Dialog.Description` | `p` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on the trigger, opens/closes the dialog. |
|
|
||||||
| `Enter` | When focus is on the trigger, opens/closes the dialog. |
|
|
||||||
| `Tab` | Moves focus to the next focusable element. |
|
|
||||||
| `Shift` \+ `Tab` | Moves focus to the previous focusable element. |
|
|
||||||
| `Esc` | Closes the dialog and moves focus to the trigger. |
|
|
||||||
|
|
||||||
Previous[←Context Menu](https://kobalte.dev/docs/core/components/context-menu)Next[Dropdown Menu→](https://kobalte.dev/docs/core/components/dropdown-menu)
|
|
||||||
@ -1,378 +0,0 @@
|
|||||||
# File Field
|
|
||||||
|
|
||||||
A file input to upload multiple files, with ability to drag and drop files.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { FileField } from "@kobalte/core/file-field";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/file-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { FileField } from "@kobalte/core/file-field";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/file-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Supports uploading multiple files at once.
|
|
||||||
- Supports drag and drop functionality for uploading files.
|
|
||||||
- Supports maximum file limits to restrict the number of files that can be uploaded.
|
|
||||||
- Supports file size validation to ensure that files are within the specified size limits.
|
|
||||||
- Supports custom validation rules for uploaded files.
|
|
||||||
- Supports restricting the types of files that can be uploaded (e.g., images, documents).
|
|
||||||
- Displays a list of files that have been selected for upload.
|
|
||||||
- Allows users to remove files from the upload list before uploading.
|
|
||||||
- Provides a preview of image files before they are uploaded.
|
|
||||||
- Displays the size of each file in the upload list.
|
|
||||||
- Supports customizing the components with custom styles and classes.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The File Field consists of:
|
|
||||||
|
|
||||||
- **FileField**: The root container for the File Field component.
|
|
||||||
- **FileField.Dropzone**: The dropzone area where files can be dragged and dropped.
|
|
||||||
- **FileField.Trigger**: The trigger element that opens the file selection dialog.
|
|
||||||
- **FileField.Label**: The label for the File Field component to toggle the file selection dialog.
|
|
||||||
- **FileField.HiddenInput**: The hidden input element that triggers the file selection dialog.
|
|
||||||
- **FileField.ItemList**: The container for the list of files that have been selected for upload.
|
|
||||||
- **FileField.Item**: The individual file item in the list of files that have been selected for upload.
|
|
||||||
- **FileField.ItemPreview**: The preview for matching file types that have been selected for upload.
|
|
||||||
- **FileField.ItemPreviewImage**: The preview image for image files that have been selected for upload.
|
|
||||||
- **FileField.ItemName**: The name of the file that has been selected for upload.
|
|
||||||
- **FileField.ItemSize**: The size of the file that has been selected for upload.
|
|
||||||
- **FileField.ItemDeleteTrigger**: The trigger element to remove a file from the list of files that have been selected for upload.
|
|
||||||
- **FileField.Description**: The description that gives the user more information on the file field.
|
|
||||||
- **FileField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the file field.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<FileField>
|
|
||||||
<FileField.Label />
|
|
||||||
<FileField.Dropzone>
|
|
||||||
<FileField.Trigger />
|
|
||||||
</FileField.Dropzone>
|
|
||||||
<FileField.HiddenInput />
|
|
||||||
<FileField.ItemList>
|
|
||||||
<FileField.Item>
|
|
||||||
<FileField.ItemPreview />
|
|
||||||
<FileField.ItemPreviewImage />
|
|
||||||
<FileField.ItemSize />
|
|
||||||
<FileField.ItemName />
|
|
||||||
<FileField.ItemDeleteTrigger />
|
|
||||||
</FileField.Item>
|
|
||||||
</FileField.ItemList>
|
|
||||||
<FileField.Description />
|
|
||||||
<FileField.ErrorMessage />
|
|
||||||
</FileField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<FileField>
|
|
||||||
<FileField.Label />
|
|
||||||
<FileField.Dropzone>
|
|
||||||
<FileField.Trigger />
|
|
||||||
</FileField.Dropzone>
|
|
||||||
<FileField.HiddenInput />
|
|
||||||
<FileField.ItemList>
|
|
||||||
<FileField.Item>
|
|
||||||
<FileField.ItemPreview />
|
|
||||||
<FileField.ItemPreviewImage />
|
|
||||||
<FileField.ItemSize />
|
|
||||||
<FileField.ItemName />
|
|
||||||
<FileField.ItemDeleteTrigger />
|
|
||||||
</FileField.Item>
|
|
||||||
</FileField.ItemList>
|
|
||||||
<FileField.Description />
|
|
||||||
<FileField.ErrorMessage />
|
|
||||||
</FileField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
File Upload
|
|
||||||
|
|
||||||
Drop your files here...Choose files!
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { FileField } from "@kobalte/core/file-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<FileField
|
|
||||||
class={style.FileField}
|
|
||||||
multiple
|
|
||||||
maxFiles={5}
|
|
||||||
onFileAccept={(data) => console.log("data", data)}
|
|
||||||
onFileReject={(data) => console.log("data", data)}
|
|
||||||
onFileChange={(data) => console.log("data", data)}
|
|
||||||
>
|
|
||||||
<FileField.Label class={style.FileField__label}>
|
|
||||||
File Field
|
|
||||||
</FileField.Label>
|
|
||||||
<FileField.Dropzone class={style.FileField__dropzone}>
|
|
||||||
Drop your files here...
|
|
||||||
<FileField.Trigger class={style.FileField__trigger}>
|
|
||||||
Choose files!
|
|
||||||
</FileField.Trigger>
|
|
||||||
</FileField.Dropzone>
|
|
||||||
<FileField.HiddenInput />
|
|
||||||
<FileField.ItemList class={style.FileField__itemList}>
|
|
||||||
{(file) => (
|
|
||||||
<FileField.Item class={style.FileField__item}>
|
|
||||||
<FileField.ItemPreviewImage
|
|
||||||
class={style.FileField__itemPreviewImage}
|
|
||||||
/>
|
|
||||||
<FileField.ItemName class={style.FileField__itemName} />
|
|
||||||
<FileField.ItemSize class={style.FileField__itemSize} />
|
|
||||||
<FileField.ItemDeleteTrigger
|
|
||||||
class={style.FileField__itemDeleteTrigger}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</FileField.ItemDeleteTrigger>
|
|
||||||
</FileField.Item>
|
|
||||||
)}
|
|
||||||
</FileField.ItemList>
|
|
||||||
</FileField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { FileField } from "@kobalte/core/file-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<FileField
|
|
||||||
class={style.FileField}
|
|
||||||
multiple
|
|
||||||
maxFiles={5}
|
|
||||||
onFileAccept={(data) => console.log("data", data)}
|
|
||||||
onFileReject={(data) => console.log("data", data)}
|
|
||||||
onFileChange={(data) => console.log("data", data)}
|
|
||||||
>
|
|
||||||
<FileField.Label class={style.FileField__label}>
|
|
||||||
File Field
|
|
||||||
</FileField.Label>
|
|
||||||
<FileField.Dropzone class={style.FileField__dropzone}>
|
|
||||||
Drop your files here...
|
|
||||||
<FileField.Trigger class={style.FileField__trigger}>
|
|
||||||
Choose files!
|
|
||||||
</FileField.Trigger>
|
|
||||||
</FileField.Dropzone>
|
|
||||||
<FileField.HiddenInput />
|
|
||||||
<FileField.ItemList class={style.FileField__itemList}>
|
|
||||||
{(file) => (
|
|
||||||
<FileField.Item class={style.FileField__item}>
|
|
||||||
<FileField.ItemPreviewImage
|
|
||||||
class={style.FileField__itemPreviewImage}
|
|
||||||
/>
|
|
||||||
<FileField.ItemName class={style.FileField__itemName} />
|
|
||||||
<FileField.ItemSize class={style.FileField__itemSize} />
|
|
||||||
<FileField.ItemDeleteTrigger
|
|
||||||
class={style.FileField__itemDeleteTrigger}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</FileField.ItemDeleteTrigger>
|
|
||||||
</FileField.Item>
|
|
||||||
)}
|
|
||||||
</FileField.ItemList>
|
|
||||||
</FileField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
By passing name prop to FileField.HiddenInput, you can use FileField in HTML forms.
|
|
||||||
|
|
||||||
File Upload
|
|
||||||
|
|
||||||
Drop your files here...Choose files!
|
|
||||||
|
|
||||||
Submit Files
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
let formRef: HTMLFormElement | undefined;
|
|
||||||
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
const formData = new FormData(formRef);
|
|
||||||
const uploadedFiles = formData.getAll("uploaded-files");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form ref={formRef} onSubmit={onSubmit}>
|
|
||||||
<FileField
|
|
||||||
multiple
|
|
||||||
maxFiles={5}
|
|
||||||
onFileAccept={data => console.log("data", data)}
|
|
||||||
onFileReject={data => console.log("data", data)}
|
|
||||||
onFileChange={data => console.log("data", data)}
|
|
||||||
>
|
|
||||||
<FileField.Label>File Field</FileField.Label>
|
|
||||||
<FileField.Dropzone>
|
|
||||||
Drop your files here...
|
|
||||||
<FileField.Trigger>Choose files!</FileField.Trigger>
|
|
||||||
</FileField.Dropzone>
|
|
||||||
<FileField.HiddenInput name="uploaded-files" />
|
|
||||||
<FileField.ItemList>
|
|
||||||
{file => (
|
|
||||||
<FileField.Item>
|
|
||||||
<FileField.ItemPreviewImage class={"FileField__itemPreviewImage"} />
|
|
||||||
<FileField.ItemName />
|
|
||||||
<FileField.ItemSize />
|
|
||||||
<FileField.ItemDeleteTrigger>Delete</FileField.ItemDeleteTrigger>
|
|
||||||
</FileField.Item>
|
|
||||||
)}
|
|
||||||
</FileField.ItemList>
|
|
||||||
</FileField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
let formRef: HTMLFormElement | undefined;
|
|
||||||
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
const formData = new FormData(formRef);
|
|
||||||
const uploadedFiles = formData.getAll("uploaded-files");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form ref={formRef} onSubmit={onSubmit}>
|
|
||||||
<FileField
|
|
||||||
multiple
|
|
||||||
maxFiles={5}
|
|
||||||
onFileAccept={data => console.log("data", data)}
|
|
||||||
onFileReject={data => console.log("data", data)}
|
|
||||||
onFileChange={data => console.log("data", data)}
|
|
||||||
>
|
|
||||||
<FileField.Label>File Field</FileField.Label>
|
|
||||||
<FileField.Dropzone>
|
|
||||||
Drop your files here...
|
|
||||||
<FileField.Trigger>Choose files!</FileField.Trigger>
|
|
||||||
</FileField.Dropzone>
|
|
||||||
<FileField.HiddenInput name="uploaded-files" />
|
|
||||||
<FileField.ItemList>
|
|
||||||
{file => (
|
|
||||||
<FileField.Item>
|
|
||||||
<FileField.ItemPreviewImage class={"FileField__itemPreviewImage"} />
|
|
||||||
<FileField.ItemName />
|
|
||||||
<FileField.ItemSize />
|
|
||||||
<FileField.ItemDeleteTrigger>Delete</FileField.ItemDeleteTrigger>
|
|
||||||
</FileField.Item>
|
|
||||||
)}
|
|
||||||
</FileField.ItemList>
|
|
||||||
</FileField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### FileField
|
|
||||||
|
|
||||||
`FileField` is equivalent to the `Root` import from `@kobalte/core/file-field`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `multiple` | `boolean`<br> Allows multiple files to be uploaded |
|
|
||||||
| `maxFiles` | `number`<br> The maximum number of files that can be uploaded |
|
|
||||||
| `disabled` | `boolean`<br> Disables the file upload component |
|
|
||||||
| `accept` | `string | string[] | undefined`<br> The types of files that can be uploaded. |
|
|
||||||
| `allowDragAndDrop` | `boolean`<br> Allows files to be dragged and dropped into the component. |
|
|
||||||
| `maxFileSize` | `number`<br> The maximum size of the file that can be uploaded in bytes. |
|
|
||||||
| `minFileSize` | `number`<br> The minimum size of the file that can be uploaded in bytes. |
|
|
||||||
| `onFileAccept` | `(files: File[]) => void`<br> Callback function that is called when file(s) is(are) accepted. |
|
|
||||||
| `onFileReject` | `(files: FileRejection[]) => void`<br> Callback function that is called when a file(s) is(are) rejected. |
|
|
||||||
| `onFileChange` | `(details: Details) => void`<br> Callback function that is called when the list of files changes. |
|
|
||||||
| `validateFile` | `(file: File) => FileError[] | null`<br> Custom validation function for files. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the slider is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the slider is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must slider an item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the slider is disabled. |
|
|
||||||
| data-readonly | Present when the slider is read only. |
|
|
||||||
|
|
||||||
`Slider.Trigger` shares the same data-attributes.
|
|
||||||
|
|
||||||
### FileField.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `file` | `File`<br> Selected file object |
|
|
||||||
|
|
||||||
### FileField.ItemSize
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `precision` | `number`<br> The number of decimal places to round the file size to. |
|
|
||||||
|
|
||||||
### FileField.ItemPreview
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `type` | `string`<br> The type of file to preview, only applicable for Images. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `FileField` | `div` |
|
|
||||||
| `FileField.Dropzone` | `div` |
|
|
||||||
| `FileField.Trigger` | `button` |
|
|
||||||
| `FileField.Label` | `label` |
|
|
||||||
| `FileField.HiddenInput` | `input` |
|
|
||||||
| `FileField.ItemList` | `ul` |
|
|
||||||
| `FileField.Item` | `li` |
|
|
||||||
| `FileField.ItemPreview` | `div` |
|
|
||||||
| `FileField.ItemPreviewImage` | `img` |
|
|
||||||
| `FileField.ItemName` | `span` |
|
|
||||||
| `FileField.ItemSize` | `span` |
|
|
||||||
| `FileField.ItemDeleteTrigger` | `button` |
|
|
||||||
| `FileField.Description` | `div` |
|
|
||||||
| `FileField.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on dropzone, opens the file dialog.<br> When focus is on trigger, opens the file dialog. |
|
|
||||||
| `Enter` | When focus is on dropzone, opens the file dialog.<br> When focus is on trigger, opens the file dialog. |
|
|
||||||
|
|
||||||
Previous[←Dropdown Menu](https://kobalte.dev/docs/core/components/dropdown-menu)Next[Hover Card→](https://kobalte.dev/docs/core/components/hover-card)
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
# Getting started
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Install Kobalte by running either of the following:
|
|
||||||
|
|
||||||
npmyarnpnpm
|
|
||||||
|
|
||||||
```
|
|
||||||
Copybash
|
|
||||||
npm install @kobalte/core
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copybash
|
|
||||||
npm install @kobalte/core
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using the components
|
|
||||||
|
|
||||||
The example below demonstrate how to create a Popover component with Kobalte.
|
|
||||||
|
|
||||||
Learn more
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover } from "@kobalte/core/popover";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
<Popover>
|
|
||||||
<Popover.Trigger class="popover__trigger">Learn more</Popover.Trigger>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content class="popover__content">
|
|
||||||
<Popover.Arrow />
|
|
||||||
<div class="popover__header">
|
|
||||||
<Popover.Title class="popover__title">About Kobalte</Popover.Title>
|
|
||||||
<Popover.CloseButton class="popover__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Popover.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Popover.Description class="popover__description">
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</Popover.Description>
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover } from "@kobalte/core/popover";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
<Popover>
|
|
||||||
<Popover.Trigger class="popover__trigger">Learn more</Popover.Trigger>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content class="popover__content">
|
|
||||||
<Popover.Arrow />
|
|
||||||
<div class="popover__header">
|
|
||||||
<Popover.Title class="popover__title">About Kobalte</Popover.Title>
|
|
||||||
<Popover.CloseButton class="popover__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Popover.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Popover.Description class="popover__description">
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</Popover.Description>
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In a few lines of code, we've implemented a fully accessible Popover component that :
|
|
||||||
|
|
||||||
- Adheres to [WAI-ARIA Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/) design pattern.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Optionally render a pointing arrow.
|
|
||||||
- Has focus fully managed and customizable.
|
|
||||||
|
|
||||||
Previous[←Introduction](https://kobalte.dev/docs/core/overview/introduction)Next[Styling→](https://kobalte.dev/docs/core/overview/styling)
|
|
||||||
@ -1,140 +0,0 @@
|
|||||||
[Skip to content](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src#start-of-content)
|
|
||||||
|
|
||||||
You signed in with another tab or window. [Reload](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src) to refresh your session.You signed out in another tab or window. [Reload](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src) to refresh your session.You switched accounts on another tab or window. [Reload](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src) to refresh your session.Dismiss alert
|
|
||||||
|
|
||||||
{{ message }}
|
|
||||||
|
|
||||||
[kobaltedev](https://github.com/kobaltedev)/ **[kobalte](https://github.com/kobaltedev/kobalte)** Public
|
|
||||||
|
|
||||||
- [Sponsor](https://github.com/sponsors/jer3m01)
|
|
||||||
- [Notifications](https://github.com/login?return_to=%2Fkobaltedev%2Fkobalte) You must be signed in to change notification settings
|
|
||||||
- [Fork\\
|
|
||||||
105](https://github.com/login?return_to=%2Fkobaltedev%2Fkobalte)
|
|
||||||
- [Star\\
|
|
||||||
1.8k](https://github.com/login?return_to=%2Fkobaltedev%2Fkobalte)
|
|
||||||
|
|
||||||
|
|
||||||
## Collapse file tree
|
|
||||||
|
|
||||||
## Files
|
|
||||||
|
|
||||||
main
|
|
||||||
|
|
||||||
Search this repository(forward slash)` forward slash/`
|
|
||||||
|
|
||||||
/
|
|
||||||
|
|
||||||
# src
|
|
||||||
|
|
||||||
/
|
|
||||||
|
|
||||||
Copy path
|
|
||||||
|
|
||||||
## Directory actions
|
|
||||||
|
|
||||||
## More options
|
|
||||||
|
|
||||||
More options
|
|
||||||
|
|
||||||
## Directory actions
|
|
||||||
|
|
||||||
## More options
|
|
||||||
|
|
||||||
More options
|
|
||||||
|
|
||||||
## Latest commit
|
|
||||||
|
|
||||||
[](https://github.com/teidesu)[teidesu](https://github.com/kobaltedev/kobalte/commits?author=teidesu)
|
|
||||||
|
|
||||||
[feat(tooltip): expose onCurrentPlacementChange (](https://github.com/kobaltedev/kobalte/commit/8a2d219b442fb5febb7221ef3e685545076b544e) [#637](https://github.com/kobaltedev/kobalte/pull/637) [)](https://github.com/kobaltedev/kobalte/commit/8a2d219b442fb5febb7221ef3e685545076b544e)
|
|
||||||
|
|
||||||
failure
|
|
||||||
|
|
||||||
3 months agoDec 16, 2025
|
|
||||||
|
|
||||||
[8a2d219](https://github.com/kobaltedev/kobalte/commit/8a2d219b442fb5febb7221ef3e685545076b544e) · 3 months agoDec 16, 2025
|
|
||||||
|
|
||||||
## History
|
|
||||||
|
|
||||||
[History](https://github.com/kobaltedev/kobalte/commits/main/packages/core/src)
|
|
||||||
|
|
||||||
Open commit details
|
|
||||||
|
|
||||||
[View commit history for this file.](https://github.com/kobaltedev/kobalte/commits/main/packages/core/src) History
|
|
||||||
|
|
||||||
/
|
|
||||||
|
|
||||||
# src
|
|
||||||
|
|
||||||
/
|
|
||||||
|
|
||||||
Top
|
|
||||||
|
|
||||||
## Folders and files
|
|
||||||
|
|
||||||
| Name | Name | Last commit message | Last commit date |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| ### parent directory<br> [..](https://github.com/kobaltedev/kobalte/tree/main/packages/core) |
|
|
||||||
| [accordion](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/accordion "accordion") | [accordion](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/accordion "accordion") | [chore: prepare release](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)")`0.13.11` [(](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)") [#614](https://github.com/kobaltedev/kobalte/pull/614) [)](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [alert-dialog](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/alert-dialog "alert-dialog") | [alert-dialog](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/alert-dialog "alert-dialog") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [alert](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/alert "alert") | [alert](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/alert "alert") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [badge](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/badge "badge") | [badge](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/badge "badge") | [refactor(FileField): rename from FileUpload and change types (](https://github.com/kobaltedev/kobalte/commit/34bd063d55bef45fb1eca87b2b801db367f7fb93 "refactor(FileField): rename from FileUpload and change types (#552)") [#552](https://github.com/kobaltedev/kobalte/pull/552) [)](https://github.com/kobaltedev/kobalte/commit/34bd063d55bef45fb1eca87b2b801db367f7fb93 "refactor(FileField): rename from FileUpload and change types (#552)") | last yearFeb 6, 2025 |
|
|
||||||
| [breadcrumbs](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/breadcrumbs "breadcrumbs") | [breadcrumbs](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/breadcrumbs "breadcrumbs") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [button](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/button "button") | [button](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/button "button") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [checkbox](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/checkbox "checkbox") | [checkbox](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/checkbox "checkbox") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [collapsible](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/collapsible "collapsible") | [collapsible](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/collapsible "collapsible") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [color-area](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-area "color-area") | [color-area](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-area "color-area") | [fix(color-area): double onChange trigger (](https://github.com/kobaltedev/kobalte/commit/e1c3385acf3321acdc0c9e57af9d182455c5dcb0 "fix(color-area): double onChange trigger (#593)") [#593](https://github.com/kobaltedev/kobalte/pull/593) [)](https://github.com/kobaltedev/kobalte/commit/e1c3385acf3321acdc0c9e57af9d182455c5dcb0 "fix(color-area): double onChange trigger (#593)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [color-channel-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-channel-field "color-channel-field") | [color-channel-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-channel-field "color-channel-field") | [chore: prepare release](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)")`0.13.11` [(](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)") [#614](https://github.com/kobaltedev/kobalte/pull/614) [)](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [color-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-field "color-field") | [color-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-field "color-field") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [color-mode](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-mode "color-mode") | [color-mode](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-mode "color-mode") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [color-slider](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-slider "color-slider") | [color-slider](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-slider "color-slider") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [color-swatch](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-swatch "color-swatch") | [color-swatch](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-swatch "color-swatch") | [refactor: move new component files (](https://github.com/kobaltedev/kobalte/commit/5312ce79d82e4a4b4723050c9712eb23169b9ad3 "refactor: move new component files (#513)") [#513](https://github.com/kobaltedev/kobalte/pull/513) [)](https://github.com/kobaltedev/kobalte/commit/5312ce79d82e4a4b4723050c9712eb23169b9ad3 "refactor: move new component files (#513)") | 2 years agoNov 2, 2024 |
|
|
||||||
| [color-wheel](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-wheel "color-wheel") | [color-wheel](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/color-wheel "color-wheel") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [colors](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/colors "colors") | [colors](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/colors "colors") | [chore: prepare release](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)")`0.13.11` [(](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)") [#614](https://github.com/kobaltedev/kobalte/pull/614) [)](https://github.com/kobaltedev/kobalte/commit/91a41e91f45bc5c57bd942ac641137e7745d22a5 "chore: prepare release `0.13.11` (#614)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [combobox](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/combobox "combobox") | [combobox](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/combobox "combobox") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [context-menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/context-menu "context-menu") | [context-menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/context-menu "context-menu") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [dialog](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/dialog "dialog") | [dialog](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/dialog "dialog") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [dismissable-layer](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/dismissable-layer "dismissable-layer") | [dismissable-layer](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/dismissable-layer "dismissable-layer") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [dropdown-menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/dropdown-menu "dropdown-menu") | [dropdown-menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/dropdown-menu "dropdown-menu") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [file-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/file-field "file-field") | [file-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/file-field "file-field") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [form-control](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/form-control "form-control") | [form-control](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/form-control "form-control") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [hover-card](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/hover-card "hover-card") | [hover-card](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/hover-card "hover-card") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [i18n](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/i18n "i18n") | [i18n](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/i18n "i18n") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [image](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/image "image") | [image](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/image "image") | [fix(image): handle crossOrigin and referrerPolicy (](https://github.com/kobaltedev/kobalte/commit/53a39a8cf11d0ed57743ee8c77e8d52372045b94 "fix(image): handle crossOrigin and referrerPolicy (#598)") [#598](https://github.com/kobaltedev/kobalte/pull/598) [)](https://github.com/kobaltedev/kobalte/commit/53a39a8cf11d0ed57743ee8c77e8d52372045b94 "fix(image): handle crossOrigin and referrerPolicy (#598)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [link](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/link "link") | [link](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/link "link") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [list](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/list "list") | [list](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/list "list") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [listbox](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/listbox "listbox") | [listbox](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/listbox "listbox") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [live-announcer](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/live-announcer "live-announcer") | [live-announcer](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/live-announcer "live-announcer") | [chore: strip license headers from build (](https://github.com/kobaltedev/kobalte/commit/f191fe728cf17df414d0fb2bd433a34c5b3a659c "chore: strip license headers from build (#403)") [#403](https://github.com/kobaltedev/kobalte/pull/403) [)](https://github.com/kobaltedev/kobalte/commit/f191fe728cf17df414d0fb2bd433a34c5b3a659c "chore: strip license headers from build (#403)") | 2 years agoMay 3, 2024 |
|
|
||||||
| [menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/menu "menu") | [menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/menu "menu") | [fix(menu): fix navigationmenu operation on mobile (](https://github.com/kobaltedev/kobalte/commit/0f5b98e14a9cbbeb4e66db90560282b667dd4a32 "fix(menu): fix navigationmenu operation on mobile (#634)") [#634](https://github.com/kobaltedev/kobalte/pull/634) [)](https://github.com/kobaltedev/kobalte/commit/0f5b98e14a9cbbeb4e66db90560282b667dd4a32 "fix(menu): fix navigationmenu operation on mobile (#634)") | 5 months agoOct 1, 2025 |
|
|
||||||
| [menubar](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/menubar "menubar") | [menubar](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/menubar "menubar") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [meter](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/meter "meter") | [meter](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/meter "meter") | [fix(meter, progress): remove rounding from fill width (](https://github.com/kobaltedev/kobalte/commit/82923280705eaa16943824080424537c9770e358 "fix(meter, progress): remove rounding from fill width (#602)") [#602](https://github.com/kobaltedev/kobalte/pull/602) [)](https://github.com/kobaltedev/kobalte/commit/82923280705eaa16943824080424537c9770e358 "fix(meter, progress): remove rounding from fill width (#602)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [navigation-menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/navigation-menu "navigation-menu") | [navigation-menu](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/navigation-menu "navigation-menu") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [number-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/number-field "number-field") | [number-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/number-field "number-field") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [pagination](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/pagination "pagination") | [pagination](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/pagination "pagination") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [polymorphic](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/polymorphic "polymorphic") | [polymorphic](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/polymorphic "polymorphic") | [fix(polymorphic): override the "component" prop of](https://github.com/kobaltedev/kobalte/commit/5ef35cfbd77ea462035cc56353ebeec2e60ca995 "fix(polymorphic): override the \"component\" prop of `<Dynamic />` (#437)")`<Dynamic />` [(](https://github.com/kobaltedev/kobalte/commit/5ef35cfbd77ea462035cc56353ebeec2e60ca995 "fix(polymorphic): override the \"component\" prop of `<Dynamic />` (#437)") [#437](https://github.com/kobaltedev/kobalte/pull/437) [)](https://github.com/kobaltedev/kobalte/commit/5ef35cfbd77ea462035cc56353ebeec2e60ca995 "fix(polymorphic): override the \"component\" prop of `<Dynamic />` (#437)") | 2 years agoJun 28, 2024 |
|
|
||||||
| [popover](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/popover "popover") | [popover](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/popover "popover") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [popper](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/popper "popper") | [popper](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/popper "popper") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [primitives](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/primitives "primitives") | [primitives](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/primitives "primitives") | [chore: removed unused imports (](https://github.com/kobaltedev/kobalte/commit/2d05356cecf7e189034f1f94f9f92f63cce216de "chore: removed unused imports (#629)") [#629](https://github.com/kobaltedev/kobalte/pull/629) [)](https://github.com/kobaltedev/kobalte/commit/2d05356cecf7e189034f1f94f9f92f63cce216de "chore: removed unused imports (#629)") | 5 months agoOct 1, 2025 |
|
|
||||||
| [progress](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/progress "progress") | [progress](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/progress "progress") | [fix(meter, progress): remove rounding from fill width (](https://github.com/kobaltedev/kobalte/commit/82923280705eaa16943824080424537c9770e358 "fix(meter, progress): remove rounding from fill width (#602)") [#602](https://github.com/kobaltedev/kobalte/pull/602) [)](https://github.com/kobaltedev/kobalte/commit/82923280705eaa16943824080424537c9770e358 "fix(meter, progress): remove rounding from fill width (#602)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [radio-group](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/radio-group "radio-group") | [radio-group](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/radio-group "radio-group") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [rating-group](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/rating-group "rating-group") | [rating-group](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/rating-group "rating-group") | [feat: RatingGroup component (](https://github.com/kobaltedev/kobalte/commit/0e7656715057106aa594d20d7f614325e63a658c "feat: RatingGroup component (#516) Co-authored-by: HBS999 <mrbirb007@gmail.com> Co-authored-by: jer3m01 <jer3m01@jer3m01.com>") [#516](https://github.com/kobaltedev/kobalte/pull/516) [)](https://github.com/kobaltedev/kobalte/commit/0e7656715057106aa594d20d7f614325e63a658c "feat: RatingGroup component (#516) Co-authored-by: HBS999 <mrbirb007@gmail.com> Co-authored-by: jer3m01 <jer3m01@jer3m01.com>") | 8 months agoJul 26, 2025 |
|
|
||||||
| [search](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/search "search") | [search](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/search "search") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [segmented-control](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/segmented-control "segmented-control") | [segmented-control](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/segmented-control "segmented-control") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [select](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/select "select") | [select](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/select "select") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [selection](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/selection "selection") | [selection](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/selection "selection") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [separator](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/separator "separator") | [separator](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/separator "separator") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [skeleton](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/skeleton "skeleton") | [skeleton](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/skeleton "skeleton") | [fix: various bug fixes (](https://github.com/kobaltedev/kobalte/commit/24c5ef85a93b66b634c87c5a971ebe4cd72d662b "fix: various bug fixes (#456) * fix(number-field): only format when enabled * fix(number-field): don't trigger `onRawValueChange` on mount when NaN * fix(select): correct type definition & empty value for multiselect * fix(text-field): clear input when controlled value set to undefined * fix(combobox): correct type definition & empty value for multiselect * fix(skeleton): correct data-animate & data-visible attribute value * fix(combobox): close list on outside click * fix(navigation-menu): incorrect animation after closed") [#456](https://github.com/kobaltedev/kobalte/pull/456) [)](https://github.com/kobaltedev/kobalte/commit/24c5ef85a93b66b634c87c5a971ebe4cd72d662b "fix: various bug fixes (#456) * fix(number-field): only format when enabled * fix(number-field): don't trigger `onRawValueChange` on mount when NaN * fix(select): correct type definition & empty value for multiselect * fix(text-field): clear input when controlled value set to undefined * fix(combobox): correct type definition & empty value for multiselect * fix(skeleton): correct data-animate & data-visible attribute value * fix(combobox): close list on outside click * fix(navigation-menu): incorrect animation after closed") | 2 years agoAug 26, 2024 |
|
|
||||||
| [slider](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/slider "slider") | [slider](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/slider "slider") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [spin-button](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/spin-button "spin-button") | [spin-button](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/spin-button "spin-button") | [refactor: Search and Color components (](https://github.com/kobaltedev/kobalte/commit/19a0181639d4628f7827dd8a68289ea9aa01ee6e "refactor: Search and Color components (#557)") [#557](https://github.com/kobaltedev/kobalte/pull/557) [)](https://github.com/kobaltedev/kobalte/commit/19a0181639d4628f7827dd8a68289ea9aa01ee6e "refactor: Search and Color components (#557)") | last yearFeb 21, 2025 |
|
|
||||||
| [switch](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/switch "switch") | [switch](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/switch "switch") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [tabs](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/tabs "tabs") | [tabs](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/tabs "tabs") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [text-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/text-field "text-field") | [text-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/text-field "text-field") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [time-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/time-field "time-field") | [time-field](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/time-field "time-field") | [feat: TimeField component (](https://github.com/kobaltedev/kobalte/commit/5a48be9b665e9a6afe0c655407e95b2fadc72882 "feat: TimeField component (#529) Co-authored-by: HBS999 <mrbirb007@gmail.com> Co-authored-by: jer3m01 <jer3m01@jer3m01.com>") [#529](https://github.com/kobaltedev/kobalte/pull/529) [)](https://github.com/kobaltedev/kobalte/commit/5a48be9b665e9a6afe0c655407e95b2fadc72882 "feat: TimeField component (#529) Co-authored-by: HBS999 <mrbirb007@gmail.com> Co-authored-by: jer3m01 <jer3m01@jer3m01.com>") | 8 months agoJul 26, 2025 |
|
|
||||||
| [toast](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/toast "toast") | [toast](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/toast "toast") | [refactor: menu radio types and segmented control (](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") [#596](https://github.com/kobaltedev/kobalte/pull/596) [)](https://github.com/kobaltedev/kobalte/commit/6d1737b17f43994adbc56616408f2f8319d3c521 "refactor: menu radio types and segmented control (#596)") | 10 months agoMay 29, 2025 |
|
|
||||||
| [toggle-button](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/toggle-button "toggle-button") | [toggle-button](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/toggle-button "toggle-button") | [feat: support string style prop (](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") [#432](https://github.com/kobaltedev/kobalte/pull/432) [)](https://github.com/kobaltedev/kobalte/commit/4dc7f8df7167f0da8f6abd4c402a771d831cecb3 "feat: support string style prop (#432) * chore: update formatter") | 2 years agoJun 18, 2024 |
|
|
||||||
| [toggle-group](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/toggle-group "toggle-group") | [toggle-group](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/toggle-group "toggle-group") | [fix(toggle-group): reactive disabled state (](https://github.com/kobaltedev/kobalte/commit/631ea73ab2444a857a82889ee639e0c02833b234 "fix(toggle-group): reactive disabled state (#595)") [#595](https://github.com/kobaltedev/kobalte/pull/595) [)](https://github.com/kobaltedev/kobalte/commit/631ea73ab2444a857a82889ee639e0c02833b234 "fix(toggle-group): reactive disabled state (#595)") | 8 months agoJul 26, 2025 |
|
|
||||||
| [tooltip](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/tooltip "tooltip") | [tooltip](https://github.com/kobaltedev/kobalte/tree/main/packages/core/src/tooltip "tooltip") | [feat(tooltip): expose onCurrentPlacementChange (](https://github.com/kobaltedev/kobalte/commit/8a2d219b442fb5febb7221ef3e685545076b544e "feat(tooltip): expose onCurrentPlacementChange (#637)") [#637](https://github.com/kobaltedev/kobalte/pull/637) [)](https://github.com/kobaltedev/kobalte/commit/8a2d219b442fb5febb7221ef3e685545076b544e "feat(tooltip): expose onCurrentPlacementChange (#637)") | 3 months agoDec 16, 2025 |
|
|
||||||
| [index.tsx](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/index.tsx "index.tsx") | [index.tsx](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/index.tsx "index.tsx") | [feat: TimeField component (](https://github.com/kobaltedev/kobalte/commit/5a48be9b665e9a6afe0c655407e95b2fadc72882 "feat: TimeField component (#529) Co-authored-by: HBS999 <mrbirb007@gmail.com> Co-authored-by: jer3m01 <jer3m01@jer3m01.com>") [#529](https://github.com/kobaltedev/kobalte/pull/529) [)](https://github.com/kobaltedev/kobalte/commit/5a48be9b665e9a6afe0c655407e95b2fadc72882 "feat: TimeField component (#529) Co-authored-by: HBS999 <mrbirb007@gmail.com> Co-authored-by: jer3m01 <jer3m01@jer3m01.com>") | 8 months agoJul 26, 2025 |
|
|
||||||
| View all files |
|
|
||||||
|
|
||||||
You can’t perform that action at this time.
|
|
||||||
@ -1,936 +0,0 @@
|
|||||||
# Menubar
|
|
||||||
|
|
||||||
A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Menubar } from "@kobalte/core/menubar";
|
|
||||||
// or
|
|
||||||
import { Root, Menu, ... } from "@kobalte/core/menubar";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Menubar } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Menubar } from "@kobalte/core/menubar";
|
|
||||||
// or
|
|
||||||
import { Root, Menu, ... } from "@kobalte/core/menubar";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Menubar } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follows the [WAI ARIA Menubar](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/) design pattern.
|
|
||||||
- Supports modal and non-modal modes.
|
|
||||||
- Supports submenus.
|
|
||||||
- Supports items, labels, groups of items.
|
|
||||||
- Supports checkable items (single or multiple) with optional indeterminate state.
|
|
||||||
- Support disabled items.
|
|
||||||
- Complex item labeling support for accessibility.
|
|
||||||
- Keyboard opening and navigation support.
|
|
||||||
- Automatic scrolling support during keyboard navigation.
|
|
||||||
- Typeahead to allow focusing items by typing text.
|
|
||||||
- Optionally render a pointing arrow.
|
|
||||||
- Focus is fully managed.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The menubar consists of:
|
|
||||||
|
|
||||||
- **Menubar:** The root container for a menubar.
|
|
||||||
|
|
||||||
The menu consists of:
|
|
||||||
|
|
||||||
- **Menubar.Menu:** The container of each menu.
|
|
||||||
- **Menubar.Trigger:** The button that toggles the menu.
|
|
||||||
- **Menubar.Icon:** A small icon that can be displayed inside the menu trigger as a visual affordance for the fact it can be open.
|
|
||||||
- **Menubar.Portal:** Portals its children into the `body` when the menu is open.
|
|
||||||
- **Menubar.Content:** Contains the content to be rendered when the menu is open.
|
|
||||||
- **Menubar.Arrow:** An optional arrow element to render alongside the menu content.
|
|
||||||
- **Menubar.Separator:** Used to visually separate items in the menu.
|
|
||||||
- **Menubar.Group:** Used to group multiple items. Use in conjunction with `Menubar.GroupLabel` to ensure good accessibility via automatic labelling.
|
|
||||||
- **Menubar.GroupLabel:** Used to render the label of a group. It won't be focusable using arrow keys.
|
|
||||||
- **Menubar.Sub:** Contains all the parts of a submenu.
|
|
||||||
- **Menubar.SubTrigger:** An item that opens a submenu. Must be rendered inside `Menubar.Sub`.
|
|
||||||
- **Menubar.SubContent:** The component that pops out when a submenu is open. Must be rendered inside `Menubar.Sub`.
|
|
||||||
|
|
||||||
The menu item consists of:
|
|
||||||
|
|
||||||
- **Menubar.Item:** An item of the select.
|
|
||||||
- **Menubar.ItemLabel:** An accessible label to be announced for the item.
|
|
||||||
- **Menubar.ItemDescription:** An optional accessible description to be announced for the item.
|
|
||||||
- **Menubar.ItemIndicator:** The visual indicator rendered when the item is checked.
|
|
||||||
|
|
||||||
The checkable menu item consists of:
|
|
||||||
|
|
||||||
- **Menubar.RadioGroup:** Used to group multiple `Menubar.RadioItem`s and manage the selection.
|
|
||||||
- **Menubar.RadioItem:** An item that can be controlled and rendered like a radio.
|
|
||||||
- **Menubar.CheckboxItem:** An item that can be controlled and rendered like a checkbox.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Menubar>
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger>
|
|
||||||
<Menubar.Icon />
|
|
||||||
</Menubar.Trigger>
|
|
||||||
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content>
|
|
||||||
<Menubar.Arrow />
|
|
||||||
|
|
||||||
<Menubar.Item>
|
|
||||||
<Menubar.ItemLabel />
|
|
||||||
<Menubar.ItemDescription />
|
|
||||||
</Menubar.Item>
|
|
||||||
|
|
||||||
<Menubar.Group>
|
|
||||||
<Menubar.GroupLabel />
|
|
||||||
<Menubar.Item />
|
|
||||||
</Menubar.Group>
|
|
||||||
|
|
||||||
<Menubar.CheckboxItem>
|
|
||||||
<Menubar.ItemIndicator />
|
|
||||||
</Menubar.CheckboxItem>
|
|
||||||
|
|
||||||
<Menubar.RadioGroup>
|
|
||||||
<Menubar.RadioItem>
|
|
||||||
<Menubar.ItemIndicator />
|
|
||||||
</Menubar.RadioItem>
|
|
||||||
</Menubar.RadioGroup>
|
|
||||||
|
|
||||||
<Menubar.Sub>
|
|
||||||
<Menubar.SubTrigger />
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent />
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator />
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
</Menubar>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Menubar>
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger>
|
|
||||||
<Menubar.Icon />
|
|
||||||
</Menubar.Trigger>
|
|
||||||
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content>
|
|
||||||
<Menubar.Arrow />
|
|
||||||
|
|
||||||
<Menubar.Item>
|
|
||||||
<Menubar.ItemLabel />
|
|
||||||
<Menubar.ItemDescription />
|
|
||||||
</Menubar.Item>
|
|
||||||
|
|
||||||
<Menubar.Group>
|
|
||||||
<Menubar.GroupLabel />
|
|
||||||
<Menubar.Item />
|
|
||||||
</Menubar.Group>
|
|
||||||
|
|
||||||
<Menubar.CheckboxItem>
|
|
||||||
<Menubar.ItemIndicator />
|
|
||||||
</Menubar.CheckboxItem>
|
|
||||||
|
|
||||||
<Menubar.RadioGroup>
|
|
||||||
<Menubar.RadioItem>
|
|
||||||
<Menubar.ItemIndicator />
|
|
||||||
</Menubar.RadioItem>
|
|
||||||
</Menubar.RadioGroup>
|
|
||||||
|
|
||||||
<Menubar.Sub>
|
|
||||||
<Menubar.SubTrigger />
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent />
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator />
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
</Menubar>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
GitFileEdit
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Menubar } from "@kobalte/core/menubar";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [showGitLog, setShowGitLog] = createSignal(true);
|
|
||||||
const [showHistory, setShowHistory] = createSignal(false);
|
|
||||||
const [branch, setBranch] = createSignal("main");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Menubar class="menubar__root">
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger class="menubar__trigger">
|
|
||||||
Git
|
|
||||||
</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content class="menubar__content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Commit <div class="menubar__item-right-slot">⌘+K</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Push <div class="menubar__item-right-slot">⇧+⌘+K</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item" disabled>
|
|
||||||
Update Project <div class="menubar__item-right-slot">⌘+T</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<Menubar.SubTrigger class="menubar__sub-trigger">
|
|
||||||
GitHub
|
|
||||||
<div class="menubar__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</Menubar.SubTrigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent class="menubar__sub-content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Create Pull Request…
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
View Pull Requests
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">Sync Fork</Menubar.Item>
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Open on GitHub
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.SubContent>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.CheckboxItem
|
|
||||||
class="menubar__checkbox-item"
|
|
||||||
checked={showGitLog()}
|
|
||||||
onChange={setShowGitLog}
|
|
||||||
>
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
Show Git Log
|
|
||||||
</Menubar.CheckboxItem>
|
|
||||||
<Menubar.CheckboxItem
|
|
||||||
class="menubar__checkbox-item"
|
|
||||||
checked={showHistory()}
|
|
||||||
onChange={setShowHistory}
|
|
||||||
>
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
Show History
|
|
||||||
</Menubar.CheckboxItem>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.Group>
|
|
||||||
<Menubar.GroupLabel class="menubar__group-label">
|
|
||||||
Branches
|
|
||||||
</Menubar.GroupLabel>
|
|
||||||
<Menubar.RadioGroup value={branch()} onChange={setBranch}>
|
|
||||||
<Menubar.RadioItem class="menubar__radio-item" value="main">
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
main
|
|
||||||
</Menubar.RadioItem>
|
|
||||||
<Menubar.RadioItem class="menubar__radio-item" value="develop">
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
develop
|
|
||||||
</Menubar.RadioItem>
|
|
||||||
</Menubar.RadioGroup>
|
|
||||||
</Menubar.Group>
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger class="menubar__trigger">
|
|
||||||
File
|
|
||||||
</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content class="menubar__content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
New Tab <div class="menubar__item-right-slot">⌘+T</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
New Window <div class="menubar__item-right-slot">⌘+N</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item" disabled>
|
|
||||||
New Incognito Window
|
|
||||||
</Menubar.Item>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator"/>
|
|
||||||
|
|
||||||
<Menubar.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<Menubar.SubTrigger class="menubar__sub-trigger">
|
|
||||||
Share
|
|
||||||
<div class="menubar__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</Menubar.SubTrigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent class="menubar__sub-content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Email Link
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Messages
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Notes
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.SubContent>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Print... <div class="menubar__item-right-slot">⌘+P</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger class="menubar__trigger">
|
|
||||||
Edit
|
|
||||||
</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content class="menubar__content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Undo <div class="menubar__item-right-slot">⌘+Z</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Redo <div class="menubar__item-right-slot">⇧+⌘+Z</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator"/>
|
|
||||||
|
|
||||||
<Menubar.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<Menubar.SubTrigger class="menubar__sub-trigger">
|
|
||||||
Find
|
|
||||||
<div class="menubar__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</Menubar.SubTrigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent class="menubar__sub-content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Search The Web
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Separator class="menubar__separator"/>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Find...
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Find Next
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Find Previous
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.SubContent>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Cut
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Copy
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Paste
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
</Menubar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Menubar } from "@kobalte/core/menubar";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [showGitLog, setShowGitLog] = createSignal(true);
|
|
||||||
const [showHistory, setShowHistory] = createSignal(false);
|
|
||||||
const [branch, setBranch] = createSignal("main");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Menubar class="menubar__root">
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger class="menubar__trigger">
|
|
||||||
Git
|
|
||||||
</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content class="menubar__content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Commit <div class="menubar__item-right-slot">⌘+K</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Push <div class="menubar__item-right-slot">⇧+⌘+K</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item" disabled>
|
|
||||||
Update Project <div class="menubar__item-right-slot">⌘+T</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<Menubar.SubTrigger class="menubar__sub-trigger">
|
|
||||||
GitHub
|
|
||||||
<div class="menubar__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</Menubar.SubTrigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent class="menubar__sub-content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Create Pull Request…
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
View Pull Requests
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">Sync Fork</Menubar.Item>
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Open on GitHub
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.SubContent>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.CheckboxItem
|
|
||||||
class="menubar__checkbox-item"
|
|
||||||
checked={showGitLog()}
|
|
||||||
onChange={setShowGitLog}
|
|
||||||
>
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
Show Git Log
|
|
||||||
</Menubar.CheckboxItem>
|
|
||||||
<Menubar.CheckboxItem
|
|
||||||
class="menubar__checkbox-item"
|
|
||||||
checked={showHistory()}
|
|
||||||
onChange={setShowHistory}
|
|
||||||
>
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
Show History
|
|
||||||
</Menubar.CheckboxItem>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.Group>
|
|
||||||
<Menubar.GroupLabel class="menubar__group-label">
|
|
||||||
Branches
|
|
||||||
</Menubar.GroupLabel>
|
|
||||||
<Menubar.RadioGroup value={branch()} onChange={setBranch}>
|
|
||||||
<Menubar.RadioItem class="menubar__radio-item" value="main">
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
main
|
|
||||||
</Menubar.RadioItem>
|
|
||||||
<Menubar.RadioItem class="menubar__radio-item" value="develop">
|
|
||||||
<Menubar.ItemIndicator class="menubar__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</Menubar.ItemIndicator>
|
|
||||||
develop
|
|
||||||
</Menubar.RadioItem>
|
|
||||||
</Menubar.RadioGroup>
|
|
||||||
</Menubar.Group>
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger class="menubar__trigger">
|
|
||||||
File
|
|
||||||
</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content class="menubar__content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
New Tab <div class="menubar__item-right-slot">⌘+T</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
New Window <div class="menubar__item-right-slot">⌘+N</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item" disabled>
|
|
||||||
New Incognito Window
|
|
||||||
</Menubar.Item>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator"/>
|
|
||||||
|
|
||||||
<Menubar.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<Menubar.SubTrigger class="menubar__sub-trigger">
|
|
||||||
Share
|
|
||||||
<div class="menubar__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</Menubar.SubTrigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent class="menubar__sub-content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Email Link
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Messages
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Notes
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.SubContent>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Print... <div class="menubar__item-right-slot">⌘+P</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger class="menubar__trigger">
|
|
||||||
Edit
|
|
||||||
</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content class="menubar__content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Undo <div class="menubar__item-right-slot">⌘+Z</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Redo <div class="menubar__item-right-slot">⇧+⌘+Z</div>
|
|
||||||
</Menubar.Item>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator"/>
|
|
||||||
|
|
||||||
<Menubar.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<Menubar.SubTrigger class="menubar__sub-trigger">
|
|
||||||
Find
|
|
||||||
<div class="menubar__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</Menubar.SubTrigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.SubContent class="menubar__sub-content">
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Search The Web
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Separator class="menubar__separator"/>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Find...
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Find Next
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Find Previous
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.SubContent>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Sub>
|
|
||||||
|
|
||||||
<Menubar.Separator class="menubar__separator" />
|
|
||||||
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Cut
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Copy
|
|
||||||
</Menubar.Item>
|
|
||||||
<Menubar.Item class="menubar__item">
|
|
||||||
Paste
|
|
||||||
</Menubar.Item>
|
|
||||||
</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
</Menubar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Link Trigger
|
|
||||||
|
|
||||||
To make one of the menubar triggers a link instead of opening a menu, omit the `Menubar.Menu` and set `as="a"` on the `Menubar.Trigger`.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Menubar>
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger>Opens a regular menu</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content>...</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
|
|
||||||
<Menubar.Trigger as="a" href="https://kobalte.dev">
|
|
||||||
Opens a link on click and enter
|
|
||||||
</Menubar.Trigger>
|
|
||||||
</Menubar>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Menubar>
|
|
||||||
<Menubar.Menu>
|
|
||||||
<Menubar.Trigger>Opens a regular menu</Menubar.Trigger>
|
|
||||||
<Menubar.Portal>
|
|
||||||
<Menubar.Content>...</Menubar.Content>
|
|
||||||
</Menubar.Portal>
|
|
||||||
</Menubar.Menu>
|
|
||||||
|
|
||||||
<Menubar.Trigger as="a" href="https://kobalte.dev">
|
|
||||||
Opens a link on click and enter
|
|
||||||
</Menubar.Trigger>
|
|
||||||
</Menubar>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Origin-aware animations
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-menu-content-transform-origin` which can be used to animate the content from its computed origin.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.context-menu__content,
|
|
||||||
.context-menu__sub-content {
|
|
||||||
transform-origin: var(--kb-menu-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-menu__content[data-expanded],
|
|
||||||
.context-menu__sub-content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.context-menu__content,
|
|
||||||
.context-menu__sub-content {
|
|
||||||
transform-origin: var(--kb-menu-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-menu__content[data-expanded],
|
|
||||||
.context-menu__sub-content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Menubar
|
|
||||||
|
|
||||||
`Menubar` is equivalent to the `Root` import from `@kobalte/core/menubar` (and deprecated `Menubar.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| defaultValue | `string`<br> The value of the menu that should be open when initially rendered. Use when you do not need to control the value state. |
|
|
||||||
| value | `string`<br> The controlled value of the menu to open. Should be used in conjunction with onValueChange. |
|
|
||||||
| onValueChange | `(value: string | undefined | null) => void`<br> Event handler called when the value changes. |
|
|
||||||
| loop | `boolean`<br> When true, keyboard navigation will loop from last item to first, and vice versa. |
|
|
||||||
| focusOnAlt | `boolean`<br> When true, click on alt by itsef will focus this Menubar (some browsers interfere). |
|
|
||||||
|
|
||||||
### Menubar.Menu
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the menu changes. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| modal | `boolean`<br> Whether the menu should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the menu content. <br> \- elements outside the menu content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the menu is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the menu (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
| value | `string`<br> A unique value that associates the item with an active value when the navigation menu is controlled. This prop is managed automatically when uncontrolled. |
|
|
||||||
|
|
||||||
`Menubar.Menu` also accepts the following props to customize the placement of the `Menubar.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| placement | `Placement`<br> The placement of the menu content. |
|
|
||||||
| gutter | `number`<br> The distance between the menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the menu content along the trigger element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the menu content when it overflows the viewport:<br> \- If a `boolean`, specifies whether the menu content should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the menu content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the menu content can overlap the trigger element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the menu content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the menu content should fit the viewport. If this is set to true, the menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the menu content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the menu content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### Menubar.Trigger
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| disabled | `boolean`<br> Whether the context menu trigger is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the menu is open. |
|
|
||||||
| data-closed | Present when the menu is close. |
|
|
||||||
| data-disabled | Present when the trigger is disabled. |
|
|
||||||
|
|
||||||
`Menubar.Icon`, `Menubar.Content`, `Menubar.SubTrigger` and `Menubar.SubContent` share the same `data-expanded` attribute.
|
|
||||||
|
|
||||||
### Menubar.Content
|
|
||||||
|
|
||||||
The popper positioner will copy the same `z-index` as the `Menubar.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
### Menubar.Arrow
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| size | `number`<br> The size of the arrow. |
|
|
||||||
|
|
||||||
### Menubar.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `Menubar.ItemLabel` part if provided, or fallback to the .textContent of the `Menubar.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is activated. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
`Menubar.ItemLabel`, `Menubar.ItemDescription` and `Menubar.ItemIndicator` shares the same data-attributes.
|
|
||||||
|
|
||||||
### Menubar.ItemIndicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### Menubar.RadioGroup
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the menu radio item to check. |
|
|
||||||
| defaultValue | `string`<br> The value of the menu radio item that should be checked when initially rendered. Useful when you do not need to control the state of the radio group. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value changes. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled or not. |
|
|
||||||
|
|
||||||
### Menubar.RadioItem
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The value of the menu item radio. |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `Menubar.ItemLabel` part if provided, or fallback to the .textContent of the `Menubar.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is checked. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-checked | Present when the item is checked. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### Menubar.CheckboxItem
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `boolean`<br> The controlled checked state of the item. |
|
|
||||||
| defaultChecked | `boolean`<br> The default checked state when initially rendered. Useful when you do not need to control the checked state. |
|
|
||||||
| onChange | `(checked: boolean) => void`<br> Event handler called when the checked state of the item changes. |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `Menubar.ItemLabel` part if provided, or fallback to the .textContent of the `Menubar.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| indeterminate | `boolean`<br> Whether the item is in an indeterminate state. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is checked/unchecked. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-indeterminate | Present when the item is in an indeterminate state. |
|
|
||||||
| data-checked | Present when the item is checked. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### Menubar.Sub
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the sub menu. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the sub menu changes. |
|
|
||||||
|
|
||||||
`Menubar.Sub` also accepts the following props to customize the placement of the `Menubar.SubContent`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the trigger element's DOMRect. |
|
|
||||||
| gutter | `number`<br> The distance between the sub menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the sub menu content along the trigger element. |
|
|
||||||
| slide | `boolean`<br> Whether the sub menu content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the sub menu content can overlap the trigger element when it overflows. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the sub menu content should fit the viewport. If this is set to true, the sub menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the sub menu content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the sub menu content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the sub menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### Menubar.SubTrigger
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `Menubar.SubTrigger`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the sub menu trigger is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### Menubar.SubContent
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Menubar` | `div` |
|
|
||||||
| `Menubar.Menu` | none |
|
|
||||||
| `Menubar.Trigger` | `div` |
|
|
||||||
| `Menubar.Icon` | `div` |
|
|
||||||
| `Menubar.Portal` | `Portal` |
|
|
||||||
| `Menubar.Content` | `div` |
|
|
||||||
| `Menubar.Arrow` | `div` |
|
|
||||||
| `Menubar.Separator` | `hr` |
|
|
||||||
| `Menubar.Group` | `div` |
|
|
||||||
| `Menubar.GroupLabel` | `span` |
|
|
||||||
| `Menubar.Sub` | none |
|
|
||||||
| `Menubar.SubTrigger` | `div` |
|
|
||||||
| `Menubar.SubContent` | `div` |
|
|
||||||
| `Menubar.Item` | `div` |
|
|
||||||
| `Menubar.ItemLabel` | `div` |
|
|
||||||
| `Menubar.ItemDescription` | `div` |
|
|
||||||
| `Menubar.ItemIndicator` | `div` |
|
|
||||||
| `Menubar.RadioGroup` | `div` |
|
|
||||||
| `Menubar.RadioItem` | `div` |
|
|
||||||
| `Menubar.CheckboxItem` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on an item, activates the item. |
|
|
||||||
| `Enter` | When focus is on an item, activates the item. |
|
|
||||||
| `ArrowDown` | When focus is on an item, moves focus to the next item. |
|
|
||||||
| `ArrowUp` | When focus is on an item, moves focus to the previous item. |
|
|
||||||
| `ArrowRight` | When focus is on an item (not sub menu trigger), moves focus to the next menu. |
|
|
||||||
| `ArrowLeft` | When focus is on an item (not sub menu item), moves focus to the previous menu. |
|
|
||||||
| `ArrowRight` / `ArrowLeft` | When focus is on a sub menu trigger, opens or closes the submenu depending on reading direction. |
|
|
||||||
| `Home` | When focus is on an item, moves focus to first item. |
|
|
||||||
| `End` | When focus is on an item, moves focus to last item. |
|
|
||||||
| `Esc` | Closes the menu. |
|
|
||||||
|
|
||||||
Previous[←Link](https://kobalte.dev/docs/core/components/link)Next[Meter→](https://kobalte.dev/docs/core/components/meter)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,93 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@kobalte/core",
|
|
||||||
"version": "0.13.11",
|
|
||||||
"private": false,
|
|
||||||
"description": "Unstyled components and primitives for building accessible web apps and design systems with SolidJS.",
|
|
||||||
"keywords": \[\
|
|
||||||
"solid",\
|
|
||||||
"solidjs",\
|
|
||||||
"ui",\
|
|
||||||
"library",\
|
|
||||||
"design-system",\
|
|
||||||
"components",\
|
|
||||||
"headless",\
|
|
||||||
"unstyled",\
|
|
||||||
"aria"\
|
|
||||||
\],
|
|
||||||
"homepage": "https://github.com/kobaltedev/kobalte/tree/main/packages/core#readme",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/kobaltedev/kobalte/issues"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/kobaltedev/kobalte.git"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"author": "jer3m01 ",
|
|
||||||
"contributors": \[\
|
|
||||||
"Fabien Marie-Louise "\
|
|
||||||
\],
|
|
||||||
"sideEffects": false,
|
|
||||||
"type": "module",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"types": "./dist/index.d.ts",
|
|
||||||
"solid": "./dist/index.jsx",
|
|
||||||
"default": "./dist/index.js"
|
|
||||||
},
|
|
||||||
"./\*": {
|
|
||||||
"types": "./dist/\*/index.d.ts",
|
|
||||||
"solid": "./dist/\*/index.jsx",
|
|
||||||
"default": "./dist/\*/index.js"
|
|
||||||
},
|
|
||||||
"./src/\*": "./src/\*"
|
|
||||||
},
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"module": "dist/index.js",
|
|
||||||
"types": "dist/index.d.ts",
|
|
||||||
"typesVersions": {
|
|
||||||
"\*": {
|
|
||||||
"\*": \[\
|
|
||||||
"./dist/\*/index.d.ts",\
|
|
||||||
"./dist/index.d.ts"\
|
|
||||||
\]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"source": "src/index.tsx",
|
|
||||||
"files": \[\
|
|
||||||
"dist",\
|
|
||||||
"src",\
|
|
||||||
"NOTICE.txt"\
|
|
||||||
\],
|
|
||||||
"scripts": {
|
|
||||||
"build": "pnpm build:cp && pnpm build:tsup",
|
|
||||||
"build:cp": "cp ../../NOTICE.txt .",
|
|
||||||
"build:tsup": "NODE\_OPTIONS=\\"--max-old-space-size=8192\\" tsup",
|
|
||||||
"clean": "rm -rf .turbo && rm -rf node\_modules && rm -rf dist && rm NOTICE.txt",
|
|
||||||
"dev": "vite serve dev --host",
|
|
||||||
"test-old": "jest --passWithNoTests",
|
|
||||||
"test": "vitest run",
|
|
||||||
"typecheck": "tsc --noEmit"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@floating-ui/dom": "^1.5.1",
|
|
||||||
"@internationalized/date": "^3.4.0",
|
|
||||||
"@internationalized/number": "^3.2.1",
|
|
||||||
"@kobalte/utils": "^0.9.1",
|
|
||||||
"@solid-primitives/props": "^3.1.8",
|
|
||||||
"@solid-primitives/resize-observer": "^2.0.26",
|
|
||||||
"solid-presence": "^0.1.8",
|
|
||||||
"solid-prevent-scroll": "^0.1.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@kobalte/tests": "workspace:\*",
|
|
||||||
"esbuild-plugin-solid": "^0.5.0",
|
|
||||||
"tsup": "7.2.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"solid-js": "^1.8.15"
|
|
||||||
},
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,406 +0,0 @@
|
|||||||
# Popover
|
|
||||||
|
|
||||||
A popover positioned relative to an anchor element.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Popover } from "@kobalte/core/popover";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/popover";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Popover } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Popover } from "@kobalte/core/popover";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/popover";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Popover } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Popover](https://www.w3.org/WAI/ARIA/apg/patterns/popovermodal/) design pattern.
|
|
||||||
- Supports modal and non-modal modes.
|
|
||||||
- Provides screen reader announcements via rendered title and description.
|
|
||||||
- Focus is fully managed and customizable.
|
|
||||||
- Optionally render a pointing arrow.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The popover consists of:
|
|
||||||
|
|
||||||
- **Popover:** The root container for a popover.
|
|
||||||
- **Popover.Trigger:** The button that opens the popover.
|
|
||||||
- **Popover.Anchor:** An optional element to position the `Popover.Content` against.
|
|
||||||
- **Popover.Portal:** Portals its children into the `body` when the popover is open.
|
|
||||||
- **Popover.Content:** Contains the content to be rendered when the popover is open.
|
|
||||||
- **Popover.Arrow:** An optional arrow element to render alongside the popover.
|
|
||||||
- **Popover.CloseButton:** The button that closes the popover.
|
|
||||||
- **Popover.Title:** An accessible title to be announced when the popover is open.
|
|
||||||
- **Popover.Description:** An optional accessible description to be announced when the popover is open.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Popover>
|
|
||||||
<Popover.Trigger />
|
|
||||||
<Popover.Anchor />
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content>
|
|
||||||
<Popover.Arrow />
|
|
||||||
<Popover.CloseButton />
|
|
||||||
<Popover.Title />
|
|
||||||
<Popover.Description />
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Popover>
|
|
||||||
<Popover.Trigger />
|
|
||||||
<Popover.Anchor />
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content>
|
|
||||||
<Popover.Arrow />
|
|
||||||
<Popover.CloseButton />
|
|
||||||
<Popover.Title />
|
|
||||||
<Popover.Description />
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Open
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover } from "@kobalte/core/popover";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Popover>
|
|
||||||
<Popover.Trigger class="popover__trigger">Open</Popover.Trigger>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content class="popover__content">
|
|
||||||
<Popover.Arrow />
|
|
||||||
<div class="popover__header">
|
|
||||||
<Popover.Title class="popover__title">About Kobalte</Popover.Title>
|
|
||||||
<Popover.CloseButton class="popover__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Popover.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Popover.Description class="popover__description">
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</Popover.Description>
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover } from "@kobalte/core/popover";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Popover>
|
|
||||||
<Popover.Trigger class="popover__trigger">Open</Popover.Trigger>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content class="popover__content">
|
|
||||||
<Popover.Arrow />
|
|
||||||
<div class="popover__header">
|
|
||||||
<Popover.Title class="popover__title">About Kobalte</Popover.Title>
|
|
||||||
<Popover.CloseButton class="popover__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Popover.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Popover.Description class="popover__description">
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</Popover.Description>
|
|
||||||
</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default open
|
|
||||||
|
|
||||||
An initial, uncontrolled open value can be provided using the `defaultOpen` prop.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Popover defaultOpen>...</Popover>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Popover defaultOpen>...</Popover>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled open
|
|
||||||
|
|
||||||
The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, close button or interact outside, and receives the new value.
|
|
||||||
|
|
||||||
Open
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover open={open()} onOpenChange={setOpen}>
|
|
||||||
<Popover.Trigger>{open() ? "Close" : "Open"}</Popover.Trigger>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content>...</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover open={open()} onOpenChange={setOpen}>
|
|
||||||
<Popover.Trigger>{open() ? "Close" : "Open"}</Popover.Trigger>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content>...</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### With custom anchor
|
|
||||||
|
|
||||||
Use the `Popover.Anchor` component to anchor the content to another element if you do not want to use the trigger as the anchor.
|
|
||||||
|
|
||||||
The popover opens when you click here.
|
|
||||||
|
|
||||||
But it's anchored to the whole div.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Popover>
|
|
||||||
<Popover.Anchor>
|
|
||||||
<p>
|
|
||||||
The popover opens when you click <Popover.Trigger>here</Popover.Trigger>.
|
|
||||||
</p>
|
|
||||||
<p>But it's anchored to the whole div.</p>
|
|
||||||
</Popover.Anchor>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content>...</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Popover>
|
|
||||||
<Popover.Anchor>
|
|
||||||
<p>
|
|
||||||
The popover opens when you click <Popover.Trigger>here</Popover.Trigger>.
|
|
||||||
</p>
|
|
||||||
<p>But it's anchored to the whole div.</p>
|
|
||||||
</Popover.Anchor>
|
|
||||||
<Popover.Portal>
|
|
||||||
<Popover.Content>...</Popover.Content>
|
|
||||||
</Popover.Portal>
|
|
||||||
</Popover>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Origin-aware animations
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-popover-content-transform-origin` which can be used to animate the content from its computed origin.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.popover__content {
|
|
||||||
transform-origin: var(--kb-popover-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popover__content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.popover__content {
|
|
||||||
transform-origin: var(--kb-popover-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popover__content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Popover
|
|
||||||
|
|
||||||
`Popover` is equivalent to the `Root` import from `@kobalte/core/popover` (and deprecated `Popover.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the popover. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the popover changes. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| modal | `boolean`<br> Whether the popover should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the popover content. <br> \- elements outside the popover content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the popover is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the popover (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
| translations | [`PopoverIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/popover/popover.intl.ts)<br> Localization strings. |
|
|
||||||
|
|
||||||
`Popover` also accepts the following props to customize the placement of the `Popover.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the anchor element's DOMRect. |
|
|
||||||
| anchorRef | `Accessor<HTMLElement | undefined>`<br> A ref for the anchor element. Useful if you want to use an element outside `Popover` as the popover anchor. |
|
|
||||||
| placement | `Placement`<br> The placement of the popover. |
|
|
||||||
| gutter | `number`<br> The distance between the popover and the trigger/anchor element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the popover along the anchor element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the popover when it overflows the viewport:<br> \- If a `boolean`, specifies whether the popover should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the popover should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the popover can overlap the anchor element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the popover should have the same width as the anchor element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the popover should fit the viewport. If this is set to true, the popover content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the popover when the anchor element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the anchor element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the popover corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the popover and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### Popover.Trigger
|
|
||||||
|
|
||||||
`Popover.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button).
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the popover is open. |
|
|
||||||
| data-closed | Present when the popover is close. |
|
|
||||||
|
|
||||||
`Popover.Anchor` , `Popover.Content` , `Popover.Arrow`, `Popover.Title`, `Popover.Description` and `Popover.CloseButton` share the same data-attributes.
|
|
||||||
|
|
||||||
### Popover.Content
|
|
||||||
|
|
||||||
The popper positioner will copy the same `z-index` as the `Popover.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
### Popover.Arrow
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| size | `number`<br> The size of the arrow. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Popover` | none |
|
|
||||||
| `Popover.Trigger` | `button` |
|
|
||||||
| `Popover.Anchor` | `div` |
|
|
||||||
| `Popover.Portal` | `Portal` |
|
|
||||||
| `Popover.Content` | `div` |
|
|
||||||
| `Popover.Arrow` | `div` |
|
|
||||||
| `Popover.CloseButton` | `button` |
|
|
||||||
| `Popover.Title` | `h2` |
|
|
||||||
| `Popover.Description` | `p` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on the trigger, opens/closes the popover. |
|
|
||||||
| `Enter` | When focus is on the trigger, opens/closes the popover. |
|
|
||||||
| `Tab` | Moves focus to the next focusable element. |
|
|
||||||
| `Shift` \+ `Tab` | Moves focus to the previous focusable element. |
|
|
||||||
| `Esc` | Closes the popover and moves focus to the trigger. |
|
|
||||||
|
|
||||||
Previous[←Pagination](https://kobalte.dev/docs/core/components/pagination)Next[Progress→](https://kobalte.dev/docs/core/components/progress)
|
|
||||||
@ -1,618 +0,0 @@
|
|||||||
# Rating Group
|
|
||||||
|
|
||||||
Allows users to rate items using a set of icons.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { RatingGroup } from "@kobalte/core/rating-group";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/rating-group";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { RatingGroup } from "@kobalte/core/rating-group";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/rating-group";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Precise ratings with half-value increments.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Group and rating labeling support for assistive technology.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The rating group consists of:
|
|
||||||
|
|
||||||
- **RatingGroup**: The root container for the rating group.
|
|
||||||
- **RatingGroup.Control**: The container for the rating items.
|
|
||||||
- **RatingGroup.Label**: The label that gives the user information on the rating group.
|
|
||||||
- **RatingGroup.HiddenInput**: The native html input that is visually hidden in the rating group.
|
|
||||||
- **RatingGroup.Description**: The description that gives the user more information on the rating group.
|
|
||||||
- **RatingGroup.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the rating group.
|
|
||||||
|
|
||||||
The rating item consists of:
|
|
||||||
|
|
||||||
- **RatingGroup.Item**: The root container for a rating item.
|
|
||||||
- **RatingGroup.ItemControl**: The element that visually represents a rating item.
|
|
||||||
- **RatingGroup.ItemLabel**: The label that gives the user information on the rating item.
|
|
||||||
- **RatingGroup.ItemDescription**: The description that gives the user more information on the rating item.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup>
|
|
||||||
<RatingGroup.Label />
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl />
|
|
||||||
<RatingGroup.ItemLabel />
|
|
||||||
<RatingGroup.ItemDescription />
|
|
||||||
</RatingGroup.Item>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<RatingGroup.HiddenInput />
|
|
||||||
<RatingGroup.Description />
|
|
||||||
<RatingGroup.ErrorMessage />
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup>
|
|
||||||
<RatingGroup.Label />
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl />
|
|
||||||
<RatingGroup.ItemLabel />
|
|
||||||
<RatingGroup.ItemDescription />
|
|
||||||
</RatingGroup.Item>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<RatingGroup.HiddenInput />
|
|
||||||
<RatingGroup.Description />
|
|
||||||
<RatingGroup.ErrorMessage />
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Rate Us:
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { RatingGroup } from "@kobalte/core/rating-group";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<RatingGroup class="rating-group">
|
|
||||||
<RatingGroup.Label class="rating-group__label">Rate Us:</RatingGroup.Label>
|
|
||||||
<RatingGroup.Control class="rating-group__control">
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item class="rating-group-item">
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { RatingGroup } from "@kobalte/core/rating-group";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<RatingGroup class="rating-group">
|
|
||||||
<RatingGroup.Label class="rating-group__label">Rate Us:</RatingGroup.Label>
|
|
||||||
<RatingGroup.Control class="rating-group__control">
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item class="rating-group-item">
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultValue` prop.
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup defaultValue={3}>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup defaultValue={3}>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `value` prop can be used to make the value controlled. The `onChange` event is fired when the user selects a rating, and receives the new value.
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Your rating is: 0/5
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal(0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<RatingGroup value={value()} onChange={setValue}>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
<p>Your rating is: {value()}/5</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal(0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<RatingGroup value={value()} onChange={setValue}>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
<p>Your rating is: {value()}/5</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Half Ratings
|
|
||||||
|
|
||||||
Allow 0.5 value steps by setting the `allowHalf` prop to true.
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup allowHalf>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
{(state) => (state.half() ? <StarHalfIcon /> : <StarIcon />)}
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup allowHalf>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
{(state) => (state.half() ? <StarHalfIcon /> : <StarIcon />)}
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `RatingGroup.Description` component can be used to associate additional help text with a rating group.
|
|
||||||
|
|
||||||
Rate Us:
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Rate your experience with us.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup>
|
|
||||||
<RatingGroup.Label>Rate Us:</RatingGroup.Label>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
<RatingGroup.Description>Rate your experience with us.</RatingGroup.Description>
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RatingGroup>
|
|
||||||
<RatingGroup.Label>Rate Us:</RatingGroup.Label>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
<RatingGroup.Description>Rate your experience with us.</RatingGroup.Description>
|
|
||||||
</RatingGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `RatingGroup.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the rating group as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Rate Us:
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Please select a rating between 1 and 5.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal(0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RatingGroup
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() === 0 ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<RatingGroup.Label>Rate Us:</RatingGroup.Label>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
<RatingGroup.ErrorMessage>Please select a rating between 1 and 5.</RatingGroup.ErrorMessage>
|
|
||||||
</RatingGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal(0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RatingGroup
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() === 0 ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<RatingGroup.Label>Rate Us:</RatingGroup.Label>
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
<RatingGroup.ErrorMessage>Please select a rating between 1 and 5.</RatingGroup.ErrorMessage>
|
|
||||||
</RatingGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The `name` prop can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
Star Icon
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<RatingGroup name="rate">
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
<RatingGroup.HiddenInput />
|
|
||||||
</RatingGroup>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<RatingGroup name="rate">
|
|
||||||
<RatingGroup.Control>
|
|
||||||
<Index each={Array(5)}>
|
|
||||||
{_ => (
|
|
||||||
<RatingGroup.Item>
|
|
||||||
<RatingGroup.ItemControl>
|
|
||||||
<StarIcon />
|
|
||||||
</RatingGroup.ItemControl>
|
|
||||||
</RatingGroup.Item>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</RatingGroup.Control>
|
|
||||||
<RatingGroup.HiddenInput />
|
|
||||||
</RatingGroup>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### RatingGroup
|
|
||||||
|
|
||||||
`RatingGroup` is equivalent to the `Root` import from `@kobalte/core/rating-group`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `number`<br> The current rating value. |
|
|
||||||
| defaultValue | `number`<br> The initial value of the rating group when it is first rendered. Use when you do not need to control the state of the rating group. |
|
|
||||||
| onChange | `(value: number) => void`<br> Event handler called when the value changes. |
|
|
||||||
| allowHalf | `boolean`<br> Whether to allow half ratings. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The axis the rating group items should align with. |
|
|
||||||
| name | `string`<br> The name of the rating group. Submitted with its owning form as part of a name/value pair. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the rating group should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must select an item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the rating group is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the rating group items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the rating group is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the rating group is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must select a rating group item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the rating group is disabled. |
|
|
||||||
| data-readonly | Present when the rating group is read only. |
|
|
||||||
|
|
||||||
`RatingGroup.Label`, `RatingGroup.Description` and `RatingGroup.ErrorMesssage` shares the same data-attributes.
|
|
||||||
|
|
||||||
### RatingGroup.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### RatingGroup.ItemControl
|
|
||||||
|
|
||||||
| Render Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| half | `Accessor<boolean>`<br> Whether the rating item is half. |
|
|
||||||
| highlighted | `Accessor<boolean>`<br> Whether the rating item is highlighted. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the parent rating group is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the parent rating group is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the parent rating group is required. |
|
|
||||||
| data-disabled | Present when the parent rating group is disabled. |
|
|
||||||
| data-readonly | Present when the parent rating group is read only. |
|
|
||||||
| data-checked | Present when the rating is checked. |
|
|
||||||
| data-half | Present when the rating is half. |
|
|
||||||
| data-highlighted | Present when the rating is highlighted. |
|
|
||||||
|
|
||||||
`RatingGroup.ItemLabel` and `RatingGroup.ItemDescription` share the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `RatingGroup` | `div` |
|
|
||||||
| `RatingGroup.Control` | `div` |
|
|
||||||
| `RatingGroup.Label` | `span` |
|
|
||||||
| `RatingGroup.HiddenInput` | `input` |
|
|
||||||
| `RatingGroup.Description` | `div` |
|
|
||||||
| `RatingGroup.ErrorMessage` | `div` |
|
|
||||||
| `RatingGroup.Item` | `div` |
|
|
||||||
| `RatingGroup.ItemControl` | `div` |
|
|
||||||
| `RatingGroup.ItemLabel` | `label` |
|
|
||||||
| `RatingGroup.ItemDescription` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `ArrowDown` | Moves focus to the next item, increasing the rating value based on the `allowHalf` property. |
|
|
||||||
| `ArrowRight` | Moves focus to the next item, increasing the rating value based on the `allowHalf` property. |
|
|
||||||
| `ArrowUp` | Moves focus to the previous item, decreasing the rating value based on the `allowHalf` property. |
|
|
||||||
| `ArrowLeft` | Moves focus to the previous item, decreasing the rating value based on the `allowHalf` property. |
|
|
||||||
| `Space` | Selects the focused item in the rating group. |
|
|
||||||
| `Home` | Sets the value of the rating group to 1. |
|
|
||||||
| `End` | Sets the value of the rating group to the maximum value. |
|
|
||||||
|
|
||||||
Previous[←Radio Group](https://kobalte.dev/docs/core/components/radio-group)Next[Search→](https://kobalte.dev/docs/core/components/search)
|
|
||||||
@ -1,562 +0,0 @@
|
|||||||
# Search
|
|
||||||
|
|
||||||
Search a searchbox text input with a menu.
|
|
||||||
Handle the case where dataset filtering needs to occur outside the combobox component.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Search } from "@kobalte/core/search";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/search";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Search } from "@kobalte/core/search";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/search";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Inherits all the features of [combobox](https://kobalte.dev/docs/core/components/combobox), except result filtering which should be managed externally.
|
|
||||||
- Debouncing text input to rate limit search suggestions calls.
|
|
||||||
- Optional indicator to show when suggestions are loading.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The search consists of:
|
|
||||||
|
|
||||||
- **Search:** The root container for a search component.
|
|
||||||
- **Search.Label:** The label that gives the user information on the search component.
|
|
||||||
- **Search.Description:** The description that gives the user more information on the component.
|
|
||||||
- **Search.Control:** Contains the search input and indicator.
|
|
||||||
- **Search.Indicator:** Wrapper for icon to indicate loading status.
|
|
||||||
- **Search.Icon:** A small icon often displayed next to the input as a visual affordance for the fact it can be open.
|
|
||||||
- **Search.Input:** The input used to search and reflects the selected suggestion values.
|
|
||||||
- **Search.Portal:** Portals its children into the `body` when the search is open.
|
|
||||||
- **Search.Content:** Contains the content to be rendered when the search is open.
|
|
||||||
- **Search.Arrow:** An optional arrow element to render alongside the search content.
|
|
||||||
- **Search.Listbox:** Contains a list of items and allows a user to search one or more of them.
|
|
||||||
- **Search.Section:** Used to render the label of an option group. It won't be focusable using arrow keys.
|
|
||||||
- **Search.Item:** An item of the search suggestion.
|
|
||||||
- **Search.ItemLabel:** An accessible label to be announced for the item.
|
|
||||||
- **Search.ItemDescription:** An optional accessible description to be announced for the item.
|
|
||||||
- **Search.NoResult:** Displayed when no suggestion options are given.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Search>
|
|
||||||
<Search.Label />
|
|
||||||
|
|
||||||
<Search.Control>
|
|
||||||
<Search.Indicator>
|
|
||||||
<Search.Icon />
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input />
|
|
||||||
</Search.Control>
|
|
||||||
|
|
||||||
<Search.Description />
|
|
||||||
|
|
||||||
<Search.Portal>
|
|
||||||
<Search.Content>
|
|
||||||
<Search.Arrow />
|
|
||||||
<Search.Listbox />
|
|
||||||
<Search.NoResult>
|
|
||||||
</Search.Content>
|
|
||||||
</Search.Portal>
|
|
||||||
</Search>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Search>
|
|
||||||
<Search.Label />
|
|
||||||
|
|
||||||
<Search.Control>
|
|
||||||
<Search.Indicator>
|
|
||||||
<Search.Icon />
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input />
|
|
||||||
</Search.Control>
|
|
||||||
|
|
||||||
<Search.Description />
|
|
||||||
|
|
||||||
<Search.Portal>
|
|
||||||
<Search.Content>
|
|
||||||
<Search.Arrow />
|
|
||||||
<Search.Listbox />
|
|
||||||
<Search.NoResult>
|
|
||||||
</Search.Content>
|
|
||||||
</Search.Portal>
|
|
||||||
</Search>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Magnifying Glass
|
|
||||||
|
|
||||||
Emoji selected:
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Search } from "@kobalte/core/search";
|
|
||||||
import { MagnifyingGlassIcon, ReloadIcon } from "some-icon-library";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
import { queryEmojiData } from "your-search-function";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [options, setOptions] = createSignal([]);
|
|
||||||
const [emoji, setEmoji] = createSignal();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Search
|
|
||||||
triggerMode="focus"
|
|
||||||
options={options()}
|
|
||||||
onInputChange={query => setOptions(queryEmojiData(query))}
|
|
||||||
onChange={result => setEmoji(result)}
|
|
||||||
optionValue="name"
|
|
||||||
optionLabel="name"
|
|
||||||
placeholder="Search an emoji…"
|
|
||||||
itemComponent={props => (
|
|
||||||
<Search.Item item={props.item} class="search__item">
|
|
||||||
<Search.ItemLabel>{props.item.rawValue.emoji}</Search.ItemLabel>
|
|
||||||
</Search.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Search.Control class="search__control" aria-label="Emoji">
|
|
||||||
<Search.Indicator
|
|
||||||
class="search__indicator"
|
|
||||||
loadingComponent={
|
|
||||||
<Search.Icon class="load__icon">
|
|
||||||
<ReloadIcon class="spin__icon" />
|
|
||||||
</Search.Icon>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Search.Icon class="search__icon">
|
|
||||||
<MagnifyingGlassIcon class="center__icon" />
|
|
||||||
</Search.Icon>
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input class="search__input" />
|
|
||||||
</Search.Control>
|
|
||||||
<Search.Portal>
|
|
||||||
<Search.Content class="search__content" onCloseAutoFocus={(e) => e.preventDefault()}>
|
|
||||||
<Search.Listbox class="search__listbox" />
|
|
||||||
<Search.NoResult class="search__no_result">
|
|
||||||
😬 No emoji found
|
|
||||||
</Search.NoResult>
|
|
||||||
</Search.Content>
|
|
||||||
</Search.Portal>
|
|
||||||
</Search>
|
|
||||||
<div class="result__content">
|
|
||||||
Emoji selected: {emoji()?.emoji} {emoji()?.name}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Search } from "@kobalte/core/search";
|
|
||||||
import { MagnifyingGlassIcon, ReloadIcon } from "some-icon-library";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
import { queryEmojiData } from "your-search-function";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [options, setOptions] = createSignal([]);
|
|
||||||
const [emoji, setEmoji] = createSignal();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Search
|
|
||||||
triggerMode="focus"
|
|
||||||
options={options()}
|
|
||||||
onInputChange={query => setOptions(queryEmojiData(query))}
|
|
||||||
onChange={result => setEmoji(result)}
|
|
||||||
optionValue="name"
|
|
||||||
optionLabel="name"
|
|
||||||
placeholder="Search an emoji…"
|
|
||||||
itemComponent={props => (
|
|
||||||
<Search.Item item={props.item} class="search__item">
|
|
||||||
<Search.ItemLabel>{props.item.rawValue.emoji}</Search.ItemLabel>
|
|
||||||
</Search.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Search.Control class="search__control" aria-label="Emoji">
|
|
||||||
<Search.Indicator
|
|
||||||
class="search__indicator"
|
|
||||||
loadingComponent={
|
|
||||||
<Search.Icon class="load__icon">
|
|
||||||
<ReloadIcon class="spin__icon" />
|
|
||||||
</Search.Icon>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Search.Icon class="search__icon">
|
|
||||||
<MagnifyingGlassIcon class="center__icon" />
|
|
||||||
</Search.Icon>
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input class="search__input" />
|
|
||||||
</Search.Control>
|
|
||||||
<Search.Portal>
|
|
||||||
<Search.Content class="search__content" onCloseAutoFocus={(e) => e.preventDefault()}>
|
|
||||||
<Search.Listbox class="search__listbox" />
|
|
||||||
<Search.NoResult class="search__no_result">
|
|
||||||
😬 No emoji found
|
|
||||||
</Search.NoResult>
|
|
||||||
</Search.Content>
|
|
||||||
</Search.Portal>
|
|
||||||
</Search>
|
|
||||||
<div class="result__content">
|
|
||||||
Emoji selected: {emoji()?.emoji} {emoji()?.name}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Debounce
|
|
||||||
|
|
||||||
Set `debounceOptionsMillisecond`, to prevent new search queries immediately on input change. Instead, search queries are requested once input is idle for a set time.
|
|
||||||
|
|
||||||
Show a debouncing icon by adding a `loadingComponent` to `Search.Indicator`.
|
|
||||||
|
|
||||||
Magnifying Glass
|
|
||||||
|
|
||||||
Emoji selected:
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Search
|
|
||||||
triggerMode="focus"
|
|
||||||
options={options()}
|
|
||||||
onInputChange={query => setOptions(queryEmojiData(query))}
|
|
||||||
onChange={result => setEmoji(result)}
|
|
||||||
debounceOptionsMillisecond={300}
|
|
||||||
optionValue="name"
|
|
||||||
optionLabel="name"
|
|
||||||
placeholder="Search an emoji…"
|
|
||||||
itemComponent={(props: any) => (
|
|
||||||
<Search.Item item={props.item}>
|
|
||||||
<Search.ItemLabel>{props.item.rawValue.emoji}</Search.ItemLabel>
|
|
||||||
</Search.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Search.Control aria-label="Emoji">
|
|
||||||
<Search.Indicator
|
|
||||||
loadingComponent={
|
|
||||||
<Search.Icon>
|
|
||||||
<ReloadIcon />
|
|
||||||
</Search.Icon>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Search.Icon>
|
|
||||||
<MagnifyingGlassIcon />
|
|
||||||
</Search.Icon>
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input />
|
|
||||||
</Search.Control>
|
|
||||||
<Search.Portal>
|
|
||||||
<Search.Content onCloseAutoFocus={(e) => e.preventDefault()}>
|
|
||||||
<Search.Listbox />
|
|
||||||
<Search.NoResult>
|
|
||||||
😬 No emoji found
|
|
||||||
</Search.NoResult>
|
|
||||||
</Search.Content>
|
|
||||||
</Search.Portal>
|
|
||||||
</Search>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Search
|
|
||||||
triggerMode="focus"
|
|
||||||
options={options()}
|
|
||||||
onInputChange={query => setOptions(queryEmojiData(query))}
|
|
||||||
onChange={result => setEmoji(result)}
|
|
||||||
debounceOptionsMillisecond={300}
|
|
||||||
optionValue="name"
|
|
||||||
optionLabel="name"
|
|
||||||
placeholder="Search an emoji…"
|
|
||||||
itemComponent={(props: any) => (
|
|
||||||
<Search.Item item={props.item}>
|
|
||||||
<Search.ItemLabel>{props.item.rawValue.emoji}</Search.ItemLabel>
|
|
||||||
</Search.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Search.Control aria-label="Emoji">
|
|
||||||
<Search.Indicator
|
|
||||||
loadingComponent={
|
|
||||||
<Search.Icon>
|
|
||||||
<ReloadIcon />
|
|
||||||
</Search.Icon>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Search.Icon>
|
|
||||||
<MagnifyingGlassIcon />
|
|
||||||
</Search.Icon>
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input />
|
|
||||||
</Search.Control>
|
|
||||||
<Search.Portal>
|
|
||||||
<Search.Content onCloseAutoFocus={(e) => e.preventDefault()}>
|
|
||||||
<Search.Listbox />
|
|
||||||
<Search.NoResult>
|
|
||||||
😬 No emoji found
|
|
||||||
</Search.NoResult>
|
|
||||||
</Search.Content>
|
|
||||||
</Search.Portal>
|
|
||||||
</Search>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Inline style
|
|
||||||
|
|
||||||
To achieve the command menu look, add the `open` prop to permanently open dropdown. Replace `Search.Portal` and `Search.Content` with a `div` to directly mount your content below the search input.
|
|
||||||
|
|
||||||
Magnifying Glass
|
|
||||||
|
|
||||||
😬 No emoji found
|
|
||||||
|
|
||||||
Emoji selected:
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Search
|
|
||||||
open
|
|
||||||
options={options()}
|
|
||||||
onInputChange={query => setOptions(queryEmojiData(query))}
|
|
||||||
onChange={result => setEmoji(result)}
|
|
||||||
debounceOptionsMillisecond={300}
|
|
||||||
optionValue="name"
|
|
||||||
optionLabel="name"
|
|
||||||
placeholder="Search an emoji…"
|
|
||||||
itemComponent={(props: any) => (
|
|
||||||
<Search.Item item={props.item}>
|
|
||||||
<Search.ItemLabel>{props.item.rawValue.emoji}</Search.ItemLabel>
|
|
||||||
</Search.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Search.Control aria-label="Emoji">
|
|
||||||
<Search.Indicator>
|
|
||||||
<Search.Icon>
|
|
||||||
<MagnifyingGlassIcon />
|
|
||||||
</Search.Icon>
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input />
|
|
||||||
</Search.Control>
|
|
||||||
<div>
|
|
||||||
<Search.Listbox />
|
|
||||||
<Search.NoResult>
|
|
||||||
😬 No emoji found
|
|
||||||
</Search.NoResult>
|
|
||||||
</div>
|
|
||||||
</Search>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Search
|
|
||||||
open
|
|
||||||
options={options()}
|
|
||||||
onInputChange={query => setOptions(queryEmojiData(query))}
|
|
||||||
onChange={result => setEmoji(result)}
|
|
||||||
debounceOptionsMillisecond={300}
|
|
||||||
optionValue="name"
|
|
||||||
optionLabel="name"
|
|
||||||
placeholder="Search an emoji…"
|
|
||||||
itemComponent={(props: any) => (
|
|
||||||
<Search.Item item={props.item}>
|
|
||||||
<Search.ItemLabel>{props.item.rawValue.emoji}</Search.ItemLabel>
|
|
||||||
</Search.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Search.Control aria-label="Emoji">
|
|
||||||
<Search.Indicator>
|
|
||||||
<Search.Icon>
|
|
||||||
<MagnifyingGlassIcon />
|
|
||||||
</Search.Icon>
|
|
||||||
</Search.Indicator>
|
|
||||||
<Search.Input />
|
|
||||||
</Search.Control>
|
|
||||||
<div>
|
|
||||||
<Search.Listbox />
|
|
||||||
<Search.NoResult>
|
|
||||||
😬 No emoji found
|
|
||||||
</Search.NoResult>
|
|
||||||
</div>
|
|
||||||
</Search>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Search
|
|
||||||
|
|
||||||
`Search` is equivalent to the `Root` import from `@kobalte/core/search`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| options | `Array<T | U>`<br> An array of options to display as the available options. |
|
|
||||||
| optionValue | `keyof T | ((option: T) => string | number)`<br> Property name or getter function to use as the value of an option. This is the value that will be submitted when the search component is part of a `<form>`. |
|
|
||||||
| optionTextValue | `keyof T | ((option: T) => string)`<br> Property name or getter function to use as the text value of an option for typeahead purpose. |
|
|
||||||
| optionLabel | `keyof T | ((option: T) => string)`<br> Property name or getter function to use as the label of an option. This is the string representation of the option to display in the `Search.Input`. |
|
|
||||||
| optionDisabled | `keyof T | ((option: T) => boolean)`<br> Property name or getter function to use as the disabled flag of an option. |
|
|
||||||
| optionGroupChildren | `keyof U`<br> Property name that refers to the children options of an option group. |
|
|
||||||
| itemComponent | `Component<SearchItemComponentProps<T>>`<br> When NOT virtualized, the component to render as an item in the `Search.Listbox`. |
|
|
||||||
| sectionComponent | `Component<SearchSectionComponentProps<U>>`<br> When NOT virtualized, the component to render as a section in the `Search.Listbox`. |
|
|
||||||
| multiple | `boolean`<br> Whether the search component allows multi-selection. |
|
|
||||||
| placeholder | `JSX.Element`<br> The content that will be rendered when no value or defaultValue is set. |
|
|
||||||
| value | `T | Array<T>`<br> The controlled value of the search input. |
|
|
||||||
| defaultValue | `T | Array<T>`<br> The value of the search input when initially rendered. Useful when you do not need to control the value. |
|
|
||||||
| onChange | `(value: T | Array<T>) => void`<br> Event handler called when the value changes. |
|
|
||||||
| open | `boolean`<br> The controlled open state of the search suggestion. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean, triggerMode?: SearchTriggerMode) => void`<br> Event handler called when the open state of the search component changes. Returns the new open state and the action that caused the opening of the menu. |
|
|
||||||
| onInputChange | `(value: string) => void`<br> Handler that is called when the search input value changes. |
|
|
||||||
| triggerMode | `SearchTriggerMode`<br> The interaction required to display search suggestion, it can be one of the following: <br> \- **input**: open search suggestion when the user is typing. <br> \- **focus**: open search suggestion when the input is focused. <br> \- **manual**: open search suggestion when pressing arrow down/up while focus is on the input or clicking on the trigger. |
|
|
||||||
| removeOnBackspace | `boolean`<br> When `multiple` is true, whether the last selected option should be removed when the user press the Backspace key and the input is empty. |
|
|
||||||
| allowDuplicateSelectionEvents | `boolean`<br> Whether `onChange` should fire even if the new value is the same as the last. |
|
|
||||||
| disallowEmptySelection | `boolean`<br> Whether the search component allows empty selection or not. |
|
|
||||||
| allowsEmptyCollection | `boolean`<br> Whether the search component allows the menu to be open when the collection is empty. |
|
|
||||||
| closeOnSelection | `boolean`<br> Whether the search component closes after selection. |
|
|
||||||
| selectionBehavior | `'toggle' | 'replace'`<br> How selection should behave in the search component. |
|
|
||||||
| virtualized | `boolean`<br> Whether the search suggestion uses virtual scrolling. |
|
|
||||||
| modal | `boolean`<br> Whether the search component should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the search component content. <br> \- elements outside the search component content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the search suggestion is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the search suggestion (portal, positioner and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
| name | `string`<br> The name of the search component. Submitted with its owning form as part of a name/value pair. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the search component should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must select an item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the search component is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the search component items can be selected but not changed by the user. |
|
|
||||||
| autoComplete | `string`<br> Describes the type of autocomplete functionality the input should provide if any. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete) |
|
|
||||||
| translations | [`SearchIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/combobox/combobox.intl.ts)<br> Localization strings. |
|
|
||||||
|
|
||||||
`Search` also accepts the following props to customize the placement of the `Search.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| placement | `Placement`<br> The placement of the search component content. |
|
|
||||||
| gutter | `number`<br> The distance between the search component content and the trigger element. |
|
|
||||||
| shift | `number`<br> The skidding of the search component content along the trigger element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the search component content when it overflows the viewport: <br> \- If a `boolean`, specifies whether the search component content should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the search component content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the search component content can overlap the trigger element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the search component content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the search component content should fit the viewport. If this is set to true, the search component content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the search component content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the search component content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the search component content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the search component is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the search component is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must select an item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the search component is disabled. |
|
|
||||||
| data-readonly | Present when the search component is read only. |
|
|
||||||
|
|
||||||
`Search.Label`, `Search.Control`, `Search.Input`, `Search.Trigger`, `Search.Description` and `Search.ErrorMesssage` shares the same data-attributes.
|
|
||||||
|
|
||||||
### Search.Control
|
|
||||||
|
|
||||||
| Render Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| selectedOptions | `Accessor<T[]>`<br> An array of selected options. |
|
|
||||||
| remove | `(option: T) => void`<br> A function to remove an option from the selection. |
|
|
||||||
| clear | `() => void`<br> A function to clear the selection. |
|
|
||||||
|
|
||||||
### Search.Indicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| loadingComponent | `JSX.Element`<br> The component that is displayed when suggestion options are being fetched. |
|
|
||||||
|
|
||||||
### Search.Icon
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the search component is open. |
|
|
||||||
| data-closed | Present when the search component is close. |
|
|
||||||
|
|
||||||
### Search.Content
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the search component is open. |
|
|
||||||
| data-closed | Present when the search component is close. |
|
|
||||||
|
|
||||||
### Search.Arrow
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| size | `number`<br> The size of the arrow. |
|
|
||||||
|
|
||||||
### Search.Listbox
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| scrollRef | `Accessor<HTMLElement | undefined>`<br> The ref attached to the scrollable element, used to provide automatic scrolling on item focus. If not provided, defaults to the listbox. |
|
|
||||||
| scrollToItem | `(key: string) => void`<br> When virtualized, the Virtualizer function used to scroll to the item of the given key. |
|
|
||||||
| children | `(items: Accessor<Collection<CollectionNode<T | U>>>) => JSX.Element`<br> When virtualized, a map function that receives an _items_ signal representing all items and sections. |
|
|
||||||
|
|
||||||
### Search.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| item | `CollectionNode`<br> The collection node to render. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-selected | Present when the item is selected. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
`Search.ItemLabel` and `Search.ItemDescription` shares the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Search` | `div` |
|
|
||||||
| `Search.Label` | `span` |
|
|
||||||
| `Search.Description` | `div` |
|
|
||||||
| `Search.Control` | `div` |
|
|
||||||
| `Search.Indicator` | `div` |
|
|
||||||
| `Search.Icon` | `span` |
|
|
||||||
| `Search.Input` | `input` |
|
|
||||||
| `Search.Portal` | `Portal` |
|
|
||||||
| `Search.Content` | `div` |
|
|
||||||
| `Search.Arrow` | `div` |
|
|
||||||
| `Search.Listbox` | `ul` |
|
|
||||||
| `Search.Section` | `li` |
|
|
||||||
| `Search.Item` | `li` |
|
|
||||||
| `Search.ItemLabel` | `div` |
|
|
||||||
| `Search.ItemDescription` | `div` |
|
|
||||||
| `Search.NoResult` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Enter` | When focus is virtualy on an item, selects the focused item. |
|
|
||||||
| `ArrowDown` | When focus is on the input, opens the search suggestion and virtual focuses the first or selected item. <br> When focus is virtualy on an item, moves virtual focus to the next item. |
|
|
||||||
| `ArrowUp` | When focus is on the input, opens the search suggestion and virtual focuses the last or selected item. <br> When focus is virtualy on an item, moves virtual focus to the previous item. |
|
|
||||||
| `Alt` \+ `ArrowDown` | When focus is on the input, opens the search suggestion. |
|
|
||||||
| `Alt` \+ `ArrowUp` | When focus is on the input, closes the search suggestion. |
|
|
||||||
| `Home` | When focus is on the input, moves virtual focus to first item. |
|
|
||||||
| `End` | When focus is on the input, moves virtual focus to last item. |
|
|
||||||
| `Esc` | When the search suggestion is open, closes the search suggestion. <br> When the search suggestion is closed, clear the input and selection. |
|
|
||||||
|
|
||||||
Previous[←Rating Group](https://kobalte.dev/docs/core/components/rating-group)Next[Segmented Control→](https://kobalte.dev/docs/core/components/segmented-control)
|
|
||||||
@ -1,560 +0,0 @@
|
|||||||
# Segmented Control
|
|
||||||
|
|
||||||
A linear set of two or more segments, each of which functions as a radio input, and a default value is required.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { SegmentedControl } from "@kobalte/core/segmented-control";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/segmented-control";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { SegmentedControl } from "@kobalte/core/segmented-control";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/segmented-control";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton/) design pattern.
|
|
||||||
- Each segment is built with a native HTML `<input>` element, which is visually hidden to allow custom styling.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Group and segment labeling support for assistive technology.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Supports animatable indicator.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The segmented control consists of:
|
|
||||||
|
|
||||||
- **SegmentedControl**: The root container for the segmented control.
|
|
||||||
- **SegmentedControl.Label**: The label that gives the user information on the segmented control.
|
|
||||||
- **SegmentedControl.Description**: The description that gives the user more information on the segmented control.
|
|
||||||
- **SegmentedControl.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the segmented control.
|
|
||||||
- **SegmentedControl.Indicator:** The visual indicator displayed below the items to indicate the selected item.
|
|
||||||
|
|
||||||
The segmented control item consists of:
|
|
||||||
|
|
||||||
- **SegmentedControl.Item**: The root container for an item's radio button.
|
|
||||||
- **SegmentedControl.ItemInput**: The native html input that is visually hidden in the item's radio button.
|
|
||||||
- **SegmentedControl.ItemControl**: The element that visually represents an item's radio button.
|
|
||||||
- **SegmentedControl.ItemIndicator**: The visual indicator rendered when the item's radio button is in a checked state.
|
|
||||||
- **SegmentedControl.ItemLabel**: The label that gives the user information on the item's radio button.
|
|
||||||
- **SegmentedControl.ItemDescription**: The description that gives the user more information on the item's radio button.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<SegmentedControl>
|
|
||||||
<SegmentedControl.Label />
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<SegmentedControl.Item>
|
|
||||||
<SegmentedControl.ItemInput />
|
|
||||||
<SegmentedControl.ItemControl>
|
|
||||||
<SegmentedControl.ItemIndicator />
|
|
||||||
</SegmentedControl.ItemControl>
|
|
||||||
<SegmentedControl.ItemLabel />
|
|
||||||
<SegmentedControl.ItemDescription />
|
|
||||||
</SegmentedControl.Item>
|
|
||||||
<SegmentedControl.Description />
|
|
||||||
<SegmentedControl.ErrorMessage />
|
|
||||||
</SegmentedControl>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<SegmentedControl>
|
|
||||||
<SegmentedControl.Label />
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<SegmentedControl.Item>
|
|
||||||
<SegmentedControl.ItemInput />
|
|
||||||
<SegmentedControl.ItemControl>
|
|
||||||
<SegmentedControl.ItemIndicator />
|
|
||||||
</SegmentedControl.ItemControl>
|
|
||||||
<SegmentedControl.ItemLabel />
|
|
||||||
<SegmentedControl.ItemDescription />
|
|
||||||
</SegmentedControl.Item>
|
|
||||||
<SegmentedControl.Description />
|
|
||||||
<SegmentedControl.ErrorMessage />
|
|
||||||
</SegmentedControl>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { SegmentedControl } from "@kobalte/core/segmented-control";
|
|
||||||
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<SegmentedControl class={style["segmented-control"]} defaultValue="Apple">
|
|
||||||
<SegmentedControl.Label class={style["segmented-control__label"]}>
|
|
||||||
Favorite fruit
|
|
||||||
</SegmentedControl.Label>
|
|
||||||
<div class={style["segmented-control__wrapper"]} role="presentation">
|
|
||||||
<SegmentedControl.Indicator class={style["segmented-control__indicator"]} />
|
|
||||||
<div class={style["segmented-control__items"]} role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{(fruit) => (
|
|
||||||
<SegmentedControl.Item value={fruit} class={style["segmented-control__item"]}>
|
|
||||||
<SegmentedControl.ItemInput class={style["segmented-control__item-input"]} />
|
|
||||||
<SegmentedControl.ItemLabel class={style["segmented-control__item-label"]}>
|
|
||||||
{fruit}
|
|
||||||
</SegmentedControl.ItemLabel>
|
|
||||||
</SegmentedControl.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SegmentedControl>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { SegmentedControl } from "@kobalte/core/segmented-control";
|
|
||||||
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<SegmentedControl class={style["segmented-control"]} defaultValue="Apple">
|
|
||||||
<SegmentedControl.Label class={style["segmented-control__label"]}>
|
|
||||||
Favorite fruit
|
|
||||||
</SegmentedControl.Label>
|
|
||||||
<div class={style["segmented-control__wrapper"]} role="presentation">
|
|
||||||
<SegmentedControl.Indicator class={style["segmented-control__indicator"]} />
|
|
||||||
<div class={style["segmented-control__items"]} role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{(fruit) => (
|
|
||||||
<SegmentedControl.Item value={fruit} class={style["segmented-control__item"]}>
|
|
||||||
<SegmentedControl.ItemInput class={style["segmented-control__item-input"]} />
|
|
||||||
<SegmentedControl.ItemLabel class={style["segmented-control__item-label"]}>
|
|
||||||
{fruit}
|
|
||||||
</SegmentedControl.ItemLabel>
|
|
||||||
</SegmentedControl.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SegmentedControl>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The `role="presentation"` is required for all non content elements between the `SegmentedControl` and `SegmentedControl.Item` due to a bug in Chromium based browsers that incorrectly parse semantics and break screen readers.
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `value` prop, which accepts a value corresponding with the `value` prop of each radio, can be used to make the value controlled. The `onChange` event is fired when the user selects a radio, and receives the new value.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
Your favorite fruit is: Orange.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SegmentedControl value={value()} onChange={setValue}>
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => (
|
|
||||||
<SegmentedControl.Item value={fruit}>
|
|
||||||
<SegmentedControl.ItemInput />
|
|
||||||
<SegmentedControl.ItemLabel>{fruit}</SegmentedControl.ItemLabel>
|
|
||||||
</SegmentedControl.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SegmentedControl>
|
|
||||||
<p class="not-prose text-sm mt-4">Your favorite fruit is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SegmentedControl value={value()} onChange={setValue}>
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => (
|
|
||||||
<SegmentedControl.Item value={fruit}>
|
|
||||||
<SegmentedControl.ItemInput />
|
|
||||||
<SegmentedControl.ItemLabel>{fruit}</SegmentedControl.ItemLabel>
|
|
||||||
</SegmentedControl.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SegmentedControl>
|
|
||||||
<p class="not-prose text-sm mt-4">Your favorite fruit is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `SegmentedControl.Description` component can be used to associate additional help text with a segmented control.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
Choose the fruit you like the most.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<SegmentedControl defaultValue="Apple">
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<SegmentedControl.Description>Choose the fruit you like the most.</SegmentedControl.Description>
|
|
||||||
</SegmentedControl>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<SegmentedControl defaultValue="Apple">
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<SegmentedControl.Description>Choose the fruit you like the most.</SegmentedControl.Description>
|
|
||||||
</SegmentedControl>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `SegmentedControl.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the segmented control as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
Hmm, I prefer apples.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SegmentedControl
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "Apple" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<SegmentedControl.ErrorMessage>Hmm, I prefer apples.</SegmentedControl.ErrorMessage>
|
|
||||||
</SegmentedControl>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SegmentedControl
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "Apple" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<SegmentedControl.ErrorMessage>Hmm, I prefer apples.</SegmentedControl.ErrorMessage>
|
|
||||||
</SegmentedControl>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The segmented control `name` prop, paired with the item's radio `value` prop, can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<SegmentedControl name="favorite-fruit" defaultValue="Orange">
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SegmentedControl>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<SegmentedControl name="favorite-fruit" defaultValue="Orange">
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SegmentedControl>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Orientation
|
|
||||||
|
|
||||||
The segmented control `orientation` prop can be used to change the segmented control's orientation.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<SegmentedControl orientation="vertical" defaultValue="Apple">
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<SegmentedControl.Description>Choose the fruit you like the most.</SegmentedControl.Description>
|
|
||||||
</SegmentedControl>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<SegmentedControl orientation="vertical" defaultValue="Apple">
|
|
||||||
<SegmentedControl.Label>Favorite fruit</SegmentedControl.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<SegmentedControl.Indicator />
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <SegmentedControl.Item value={fruit}>...</SegmentedControl.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<SegmentedControl.Description>Choose the fruit you like the most.</SegmentedControl.Description>
|
|
||||||
</SegmentedControl>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### SegmentedControl
|
|
||||||
|
|
||||||
`SegmentedControl` is equivalent to the `Root` import from `@kobalte/core/segmented-control`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the item's radio button to check. |
|
|
||||||
| defaultValue | `string`<br> The value of the item's radio button that should be checked when initially rendered. Useful when you do not need to control the state of the radio buttons. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value changes. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The axis the segmented control items should align with. |
|
|
||||||
| name | `string`<br> The name of the segmented control. Submitted with its owning form as part of a name/value pair. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the segmented control should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check a segmented control item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the segmented control is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the segmented control items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the segmented control is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the segmented control is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must check a segmented control item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the segmented control is disabled. |
|
|
||||||
| data-readonly | Present when the segmented control is read only. |
|
|
||||||
|
|
||||||
`SegmentedControl.Label`, `SegmentedControl.Description` and `SegmentedControl.ErrorMesssage` shares the same data-attributes.
|
|
||||||
|
|
||||||
### SegmentedControl.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### SegmentedControl.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The value of the item's radio button, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#Value). |
|
|
||||||
| disabled | `boolean`<br> Whether the item's radio button is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the parent segmented control is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the parent segmented control is invalid according to the validation rules. |
|
|
||||||
| data-checked | Present when the segmented control checked. |
|
|
||||||
| data-disabled | Present when the segmented control disabled. |
|
|
||||||
|
|
||||||
`SegmentedControl.ItemInput`, `SegmentedControl.ItemControl`, `SegmentedControl.ItemIndicator` and `SegmentedControl.ItemLabel` shares the same data-attributes.
|
|
||||||
|
|
||||||
### SegmentedControl.ItemIndicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `SegmentedControl` | `div` |
|
|
||||||
| `SegmentedControl.Label` | `span` |
|
|
||||||
| `SegmentedControl.Description` | `div` |
|
|
||||||
| `SegmentedControl.ErrorMessage` | `div` |
|
|
||||||
| `SegmentedControl.Indicator` | `div` |
|
|
||||||
| `SegmentedControl.Item` | `div` |
|
|
||||||
| `SegmentedControl.ItemInput` | `input` |
|
|
||||||
| `SegmentedControl.ItemControl` | `div` |
|
|
||||||
| `SegmentedControl.ItemIndicator` | `div` |
|
|
||||||
| `SegmentedControl.ItemLabel` | `label` |
|
|
||||||
| `SegmentedControl.ItemDescription` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tab` | Moves focus to either the checked item's radio button or the first item's radio button in the group. |
|
|
||||||
| `Space` | When focus is on an unchecked item's radio button, checks it. |
|
|
||||||
| `ArrowDown` | Moves focus and checks the next item's radio button in the group. |
|
|
||||||
| `ArrowRight` | Moves focus and checks the next item's radio button in the group. |
|
|
||||||
| `ArrowUp` | Moves focus and checks the previous item's radio button in the group. |
|
|
||||||
| `ArrowLeft` | Moves focus and checks the previous item's radio button in the group. |
|
|
||||||
|
|
||||||
Previous[←Search](https://kobalte.dev/docs/core/components/search)Next[Select→](https://kobalte.dev/docs/core/components/select)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,315 +0,0 @@
|
|||||||
# Styling
|
|
||||||
|
|
||||||
Kobalte components are unstyled, allowing you to completely customize the look and feel. Bring your preferred styling solution (vanilla CSS, Tailwind, CSS-in-JS libraries, etc...).
|
|
||||||
|
|
||||||
## Styling a component part
|
|
||||||
|
|
||||||
All components and their parts accept a `class` prop. This class will be passed through to the DOM element. You can style a component part by targeting the `class` that you provide.
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover as KPopover } from "@kobalte/core";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
export const Popover = () => {
|
|
||||||
return (
|
|
||||||
<KPopover>
|
|
||||||
<KPopover.Trigger class="popover__trigger">
|
|
||||||
Open
|
|
||||||
</KPopover.Trigger>
|
|
||||||
<KPopover.Content class="popover__content">
|
|
||||||
...
|
|
||||||
</KPopover.Content>
|
|
||||||
</KPopover>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover as KPopover } from "@kobalte/core";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
export const Popover = () => {
|
|
||||||
return (
|
|
||||||
<KPopover>
|
|
||||||
<KPopover.Trigger class="popover__trigger">
|
|
||||||
Open
|
|
||||||
</KPopover.Trigger>
|
|
||||||
<KPopover.Content class="popover__content">
|
|
||||||
...
|
|
||||||
</KPopover.Content>
|
|
||||||
</KPopover>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## Styling a state
|
|
||||||
|
|
||||||
When a component or its parts can have multiple states, we automatically attach `data-*` attributes that represents the specific state. For example, a popover's trigger can have:
|
|
||||||
|
|
||||||
- `data-expanded` — When the popover is expanded.
|
|
||||||
- `data-disabled` — When the popover is disabled.
|
|
||||||
|
|
||||||
You can style a component state by targeting the `data-*` attributes added by Kobalte.
|
|
||||||
|
|
||||||
style.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
.popover__trigger[data-disabled] {
|
|
||||||
/* The popover trigger style when disabled. */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
.popover__trigger[data-disabled] {
|
|
||||||
/* The popover trigger style when disabled. */
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using the TailwindCSS plugin
|
|
||||||
|
|
||||||
If you are using [TailwindCSS](https://tailwindcss.com/), you can use the `@kobalte/tailwindcss` plugin to target Kobalte's `data-*` attributes with modifiers like `ui-expanded:*`.
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
npmyarnpnpm
|
|
||||||
|
|
||||||
```
|
|
||||||
Copybash
|
|
||||||
npm install @kobalte/tailwindcss
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copybash
|
|
||||||
npm install @kobalte/tailwindcss
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
Add the plugin to your `tailwind.config.js` :
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyjs
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: [],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [\
|
|
||||||
// default prefix is "ui"\
|
|
||||||
require("@kobalte/tailwindcss"),\
|
|
||||||
\
|
|
||||||
// or with a custom prefix:\
|
|
||||||
require("@kobalte/tailwindcss")({ prefix: "kb" }),\
|
|
||||||
],
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyjs
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: [],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [\
|
|
||||||
// default prefix is "ui"\
|
|
||||||
require("@kobalte/tailwindcss"),\
|
|
||||||
\
|
|
||||||
// or with a custom prefix:\
|
|
||||||
require("@kobalte/tailwindcss")({ prefix: "kb" }),\
|
|
||||||
],
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Style your component:
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover as KPopover } from "@kobalte/core/popover";
|
|
||||||
|
|
||||||
export const Popover = () => (
|
|
||||||
<KPopover>
|
|
||||||
<KPopover.Trigger class="inline-flex px-4 py-2 rounded ui-disabled:bg-slate-100">
|
|
||||||
Open
|
|
||||||
</KPopover.Trigger>
|
|
||||||
<KPopover.Content class="flex p-4 rounded bg-white">...</KPopover.Content>
|
|
||||||
</KPopover>
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover as KPopover } from "@kobalte/core/popover";
|
|
||||||
|
|
||||||
export const Popover = () => (
|
|
||||||
<KPopover>
|
|
||||||
<KPopover.Trigger class="inline-flex px-4 py-2 rounded ui-disabled:bg-slate-100">
|
|
||||||
Open
|
|
||||||
</KPopover.Trigger>
|
|
||||||
<KPopover.Content class="flex p-4 rounded bg-white">...</KPopover.Content>
|
|
||||||
</KPopover>
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use the following modifiers:
|
|
||||||
|
|
||||||
| Modifier | CSS Selector |
|
|
||||||
| --- | --- |
|
|
||||||
| `ui-valid` | `&[data-valid]` |
|
|
||||||
| `ui-invalid` | `&[data-invalid]` |
|
|
||||||
| `ui-required` | `&[data-required]` |
|
|
||||||
| `ui-disabled` | `&[data-disabled]` |
|
|
||||||
| `ui-readonly` | `&[data-readonly]` |
|
|
||||||
| `ui-checked` | `&[data-checked]` |
|
|
||||||
| `ui-indeterminate` | `&[data-indeterminate]` |
|
|
||||||
| `ui-selected` | `&[data-selected]` |
|
|
||||||
| `ui-pressed` | `&[data-pressed]` |
|
|
||||||
| `ui-expanded` | `&[data-expanded]` |
|
|
||||||
| `ui-highlighted` | `&[data-highlighted]` |
|
|
||||||
| `ui-current` | `&[data-current]` |
|
|
||||||
|
|
||||||
It's also possible to use _inverse modifiers_ in the form of `ui-not-*`, _group and peer modifiers_ in the form of `ui-group-*` and `ui-peer-*`.
|
|
||||||
|
|
||||||
## Using the Vanilla Extract plugin
|
|
||||||
|
|
||||||
If you are using [Vanilla Extract](https://vanilla-extract.style/), you can use the `@kobalte/vanilla-extract` plugin to target Kobalte's `data-*` attributes.
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
npmyarnpnpm
|
|
||||||
|
|
||||||
```
|
|
||||||
Copybash
|
|
||||||
npm install @kobalte/vanilla-extract
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copybash
|
|
||||||
npm install @kobalte/vanilla-extract
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
Use the `componentStateStyles` utility function to create vanilla-extract styles that target `data-*` attributes of Kobalte components.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
// styles.css
|
|
||||||
import { componentStateStyles } from "@kobalte/vanilla-extract";
|
|
||||||
import { style } from "@vanilla-extract/css";
|
|
||||||
|
|
||||||
const button = style([\
|
|
||||||
{\
|
|
||||||
background: "blue",\
|
|
||||||
padding: "2px 6px",\
|
|
||||||
},\
|
|
||||||
componentStateStyles({\
|
|
||||||
disabled: {\
|
|
||||||
opacity: 0.4,\
|
|
||||||
},\
|
|
||||||
invalid: {\
|
|
||||||
backgroundColor: "red",\
|
|
||||||
not: {\
|
|
||||||
backgroundColor: "yellow",\
|
|
||||||
},\
|
|
||||||
},\
|
|
||||||
}),\
|
|
||||||
componentStateStyles(\
|
|
||||||
{\
|
|
||||||
invalid: {\
|
|
||||||
backgroundColor: "red",\
|
|
||||||
},\
|
|
||||||
},\
|
|
||||||
{ parentSelector: "[data-theme=dark]" },\
|
|
||||||
),\
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
// styles.css
|
|
||||||
import { componentStateStyles } from "@kobalte/vanilla-extract";
|
|
||||||
import { style } from "@vanilla-extract/css";
|
|
||||||
|
|
||||||
const button = style([\
|
|
||||||
{\
|
|
||||||
background: "blue",\
|
|
||||||
padding: "2px 6px",\
|
|
||||||
},\
|
|
||||||
componentStateStyles({\
|
|
||||||
disabled: {\
|
|
||||||
opacity: 0.4,\
|
|
||||||
},\
|
|
||||||
invalid: {\
|
|
||||||
backgroundColor: "red",\
|
|
||||||
not: {\
|
|
||||||
backgroundColor: "yellow",\
|
|
||||||
},\
|
|
||||||
},\
|
|
||||||
}),\
|
|
||||||
componentStateStyles(\
|
|
||||||
{\
|
|
||||||
invalid: {\
|
|
||||||
backgroundColor: "red",\
|
|
||||||
},\
|
|
||||||
},\
|
|
||||||
{ parentSelector: "[data-theme=dark]" },\
|
|
||||||
),\
|
|
||||||
]);
|
|
||||||
```
|
|
||||||
|
|
||||||
Then apply your styles to the component:
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Button } from "@kobalte/core/button";
|
|
||||||
import { button } from "./styles.css";
|
|
||||||
|
|
||||||
export const MyButton = () => <Button class={button}>...</Button>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Button } from "@kobalte/core/button";
|
|
||||||
import { button } from "./styles.css";
|
|
||||||
|
|
||||||
export const MyButton = () => <Button class={button}>...</Button>;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage with UnoCSS
|
|
||||||
|
|
||||||
The [UnoCSS preset](https://github.com/zirbest/unocss-preset-primitives#kobalte) made by the community can be used to achieve the same behavior of the TailwindCSS plugin.
|
|
||||||
|
|
||||||
## Extending a component
|
|
||||||
|
|
||||||
Extending a component is done the same way you extend any SolidJS component.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover as KPopover } from "@kobalte/core/popover";
|
|
||||||
import { ComponentProps } from "solid-js";
|
|
||||||
|
|
||||||
export const PopoverTrigger = (props: ComponentProps<typeof KPopover.Trigger>) => {
|
|
||||||
return <KPopover.Trigger {...props} />;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Popover as KPopover } from "@kobalte/core/popover";
|
|
||||||
import { ComponentProps } from "solid-js";
|
|
||||||
|
|
||||||
export const PopoverTrigger = (props: ComponentProps<typeof KPopover.Trigger>) => {
|
|
||||||
return <KPopover.Trigger {...props} />;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Previous[←Getting started](https://kobalte.dev/docs/core/overview/getting-started)Next[Animation→](https://kobalte.dev/docs/core/overview/animation)
|
|
||||||
@ -1,648 +0,0 @@
|
|||||||
# Time Field
|
|
||||||
|
|
||||||
A time field allows users to enter and edit time values using a keyboard. Each part of a time value is displayed in an individually editable segment.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { TimeField } from "@kobalte/core/time-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/time-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { TimeField } from "@kobalte/core/time-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/time-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Times can optionally include a time zone. All modifications follow time zone rules such as daylight saving time.
|
|
||||||
- Support for locale-specific formatting, number systems, hour cycles, and right-to-left layout.
|
|
||||||
- Each time unit is displayed as an individually focusable and editable segment, which allows users an easy way to edit times using the keyboard, in any format and locale.
|
|
||||||
- Time segments are editable using an easy to use numeric keypad, and all interactions are accessible using touch-based screen readers.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Integrates with HTML forms.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The time field consists of:
|
|
||||||
|
|
||||||
- **TimeField**: The root container for the time field.
|
|
||||||
- **TimeField.Label**: The label that gives the user information on the time field.
|
|
||||||
- **TimeField.Field**: The container for the segments.
|
|
||||||
- **TimeField.Segment**: The component that represents a unit of a time.
|
|
||||||
- **TimeField.Description**: The description that gives the user more information on the time field.
|
|
||||||
- **TimeField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the time field.
|
|
||||||
- **TimeField.HiddenInput**: The native html input that is visually hidden in the time field.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField>
|
|
||||||
<TimeField.Label />
|
|
||||||
<TimeField.Field>
|
|
||||||
<TimeField.Segment />
|
|
||||||
</TimeField.Field>
|
|
||||||
<TimeField.Description />
|
|
||||||
<TimeField.ErrorMessage />
|
|
||||||
<TimeField.HiddenInput />
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField>
|
|
||||||
<TimeField.Label />
|
|
||||||
<TimeField.Field>
|
|
||||||
<TimeField.Segment />
|
|
||||||
</TimeField.Field>
|
|
||||||
<TimeField.Description />
|
|
||||||
<TimeField.ErrorMessage />
|
|
||||||
<TimeField.HiddenInput />
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Event time
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { TimeField } from "@kobalte/core/time-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<TimeField class="time-field">
|
|
||||||
<TimeField.Label class="time-field__label">Event time</TimeField.Label>
|
|
||||||
<TimeField.Field class="time-field__field">
|
|
||||||
{segment => <TimeField.Segment class="time-field__segment" segment={segment()} />}
|
|
||||||
</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { TimeField } from "@kobalte/core/time-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<TimeField class="time-field">
|
|
||||||
<TimeField.Label class="time-field__label">Event time</TimeField.Label>
|
|
||||||
<TimeField.Field class="time-field__field">
|
|
||||||
{segment => <TimeField.Segment class="time-field__segment" segment={segment()} />}
|
|
||||||
</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default Value
|
|
||||||
|
|
||||||
A TimeField displays a placeholder by default. An initial, uncontrolled value can be provided to the TimeField using the `defaultValue` prop.
|
|
||||||
|
|
||||||
Time values are provided using objects in the [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/) package. This library handles correct international date and time manipulation across calendars, time zones, and other localization concerns.
|
|
||||||
|
|
||||||
11
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
45
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
Selected Time: 11:45 AM
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Time } from "@internationalized/date";
|
|
||||||
|
|
||||||
<TimeField defaultValue={new Time(11, 45)}>
|
|
||||||
<TimeField.Field>
|
|
||||||
{(segment) => (
|
|
||||||
<TimeField.Segment segment={segment()} />
|
|
||||||
)}
|
|
||||||
</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Time } from "@internationalized/date";
|
|
||||||
|
|
||||||
<TimeField defaultValue={new Time(11, 45)}>
|
|
||||||
<TimeField.Field>
|
|
||||||
{(segment) => (
|
|
||||||
<TimeField.Segment segment={segment()} />
|
|
||||||
)}
|
|
||||||
</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled Value
|
|
||||||
|
|
||||||
The `value` prop can be used to make the value controlled. The `onChange` event is fired when the time value changes.
|
|
||||||
|
|
||||||
9
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
45
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
Selected Time: 9:45 AM
|
|
||||||
|
|
||||||
Selected time: 9:45 AM
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { createDateFormatter } from "@kobalte/core/i18n";
|
|
||||||
import { getLocalTimeZone, Time, toCalendarDateTime, today } from "@internationalized/date";
|
|
||||||
|
|
||||||
function ControlledValueExample() {
|
|
||||||
const [value, setValue] = createSignal(new Time(9, 45));
|
|
||||||
|
|
||||||
const dateFormatter = createDateFormatter({
|
|
||||||
hour12: true,
|
|
||||||
timeStyle: "short",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TimeField value={value()} onChange={setValue}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
<p>
|
|
||||||
Selected time:{" "}
|
|
||||||
{value()
|
|
||||||
? dateFormatter().format(
|
|
||||||
toCalendarDateTime(today(getLocalTimeZone()), value()).toDate(getLocalTimeZone()),
|
|
||||||
)
|
|
||||||
: "––"}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { createDateFormatter } from "@kobalte/core/i18n";
|
|
||||||
import { getLocalTimeZone, Time, toCalendarDateTime, today } from "@internationalized/date";
|
|
||||||
|
|
||||||
function ControlledValueExample() {
|
|
||||||
const [value, setValue] = createSignal(new Time(9, 45));
|
|
||||||
|
|
||||||
const dateFormatter = createDateFormatter({
|
|
||||||
hour12: true,
|
|
||||||
timeStyle: "short",
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TimeField value={value()} onChange={setValue}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
<p>
|
|
||||||
Selected time:{" "}
|
|
||||||
{value()
|
|
||||||
? dateFormatter().format(
|
|
||||||
toCalendarDateTime(today(getLocalTimeZone()), value()).toDate(getLocalTimeZone()),
|
|
||||||
)
|
|
||||||
: "––"}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Time Zones
|
|
||||||
|
|
||||||
TimeField is time zone aware when a `ZonedDateTime` object is provided as the value. In this case, the time zone abbreviation is displayed, and time zone concerns such as daylight saving time are taken into account when the value is manipulated.
|
|
||||||
|
|
||||||
[@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/) includes functions for parsing strings in multiple formats into `ZonedDateTime` objects.
|
|
||||||
|
|
||||||
12
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
45
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
PST
|
|
||||||
|
|
||||||
Selected Time: 12:45 AM PST
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { parseZonedDateTime } from "@internationalized/date";
|
|
||||||
|
|
||||||
<TimeField defaultValue={parseZonedDateTime("2022-11-07T00:45[America/Los_Angeles]")}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { parseZonedDateTime } from "@internationalized/date";
|
|
||||||
|
|
||||||
<TimeField defaultValue={parseZonedDateTime("2022-11-07T00:45[America/Los_Angeles]")}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Granularity
|
|
||||||
|
|
||||||
The `granularity` prop allows you to control the smallest unit that is displayed by a TimeField. By default, times are displayed with "minute" granularity. More granular time values can be displayed by setting the `granularity` prop to "second".
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField granularity="second">
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField granularity="second">
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Minimum and Maximum Values
|
|
||||||
|
|
||||||
The `minValue` and `maxValue` props can be used to perform builtin validation. This marks the time field as invalid using ARIA if the user enters an invalid time.
|
|
||||||
|
|
||||||
9
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
45
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
Selected Time: 9:45 AM
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField defaultValue={new Time(9, 45)} minValue={new Time(9)} maxValue={new Time(17)}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.ErrorMessage>Select time between 9 AM and 5 PM.</TimeField.ErrorMessage>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField defaultValue={new Time(9, 45)} minValue={new Time(9)} maxValue={new Time(17)}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.ErrorMessage>Select time between 9 AM and 5 PM.</TimeField.ErrorMessage>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Placeholder Value
|
|
||||||
|
|
||||||
When no value is set, a placeholder is shown. The format of the placeholder is influenced by the `granularity` and `placeholderValue` props. `placeholderValue` also controls the default values of each segment when the user first interacts with them, e.g. using the up and down arrow keys. By default, the `placeholderValue` is midnight.
|
|
||||||
|
|
||||||
9
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField placeholderValue={new Time(9)}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField placeholderValue={new Time(9)}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hide Time Zone
|
|
||||||
|
|
||||||
When a `ZonedDateTime` object is provided as the value of a TimeField, the time zone abbreviation is displayed by default. It can be hidden using the `hideTimeZone` prop.
|
|
||||||
|
|
||||||
12
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
45
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
Selected Time: 12:45 AM
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField defaultValue={parseZonedDateTime("2022-11-07T00:45[America/Los_Angeles]")} hideTimeZone>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField defaultValue={parseZonedDateTime("2022-11-07T00:45[America/Los_Angeles]")} hideTimeZone>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hour Cycle
|
|
||||||
|
|
||||||
By default, TimeField displays times in either 12 or 24 hour format depending on the user's locale. This can be overridden using the `hourCycle` prop.
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField hourCycle={24}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField hourCycle={24}>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `TimeField.Description` component can be used to associate additional help text with a time field.
|
|
||||||
|
|
||||||
Time
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
Select a meeting time.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField>
|
|
||||||
<TimeField.Label>Time</TimeField.Label>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.Description>Select a meeting time.</TimeField.Description>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TimeField>
|
|
||||||
<TimeField.Label>Time</TimeField.Label>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.Description>Select a meeting time.</TimeField.Description>
|
|
||||||
</TimeField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `TimeField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the time field as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Time
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
Please select a time.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal(undefined);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TimeField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() === undefined ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<TimeField.Label>Time</TimeField.Label>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.ErrorMessage>Please select a time.</TimeField.ErrorMessage>
|
|
||||||
</TimeField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal(undefined);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TimeField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() === undefined ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<TimeField.Label>Time</TimeField.Label>
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.ErrorMessage>Please select a time.</TimeField.ErrorMessage>
|
|
||||||
</TimeField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The `name` prop can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
:
|
|
||||||
|
|
||||||
––
|
|
||||||
|
|
||||||
AM
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<TimeField name="time">
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.HiddenInput />
|
|
||||||
</TimeField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<TimeField name="time">
|
|
||||||
<TimeField.Field>{segment => <TimeField.Segment segment={segment()} />}</TimeField.Field>
|
|
||||||
<TimeField.HiddenInput />
|
|
||||||
</TimeField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### TimeField
|
|
||||||
|
|
||||||
`TimeField` is equivalent to the `Root` import from `@kobalte/core/time-field`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `TimeValue`<br> The current value (controlled). |
|
|
||||||
| defaultValue | `TimeValue`<br> The default value (uncontrolled). |
|
|
||||||
| onChange | `(value: MappedTimeValue<TimeValue>) => void`<br> Handler that is called when the value changes. |
|
|
||||||
| hourCycle | `12 | 24`<br> Whether to display the time in 12 or 24-hour format. By default, this is determined by the user's locale. |
|
|
||||||
| granularity | `'hour' | 'minute' | 'second'`<br> Determines the smallest unit that is displayed in the time field. Defaults to `"minute"`. |
|
|
||||||
| hideTimeZone | `boolean`<br> Whether to hide the time zone abbreviation. |
|
|
||||||
| shouldForceLeadingZeros | `boolean`<br> Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale. |
|
|
||||||
| placeholderValue | `TimeValue`<br> A placeholder time that influences the format of the placeholder shown when no value is selected. Defaults to 12:00 AM or 00:00 depending on the hour cycle. |
|
|
||||||
| minValue | `TimeValue`<br> The minimum allowed time that a user may select. |
|
|
||||||
| maxValue | `TimeValue`<br> The maximum allowed time that a user may select. |
|
|
||||||
| name | `string`<br> The name of the time field. Submitted with its owning form as part of a name/value pair. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the time field should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the time field is required. |
|
|
||||||
| disabled | `boolean`<br> Whether the time field is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the time field is read only. |
|
|
||||||
| translations | `TimeFieldIntlTranslations`<br> The localized strings of the component. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the time field is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the time field is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the time field is required. |
|
|
||||||
| data-disabled | Present when the time field is disabled. |
|
|
||||||
| data-readonly | Present when the time field is read only. |
|
|
||||||
|
|
||||||
`TimeField.Label`, `TimeField.Field`, `TimeField.Segment`, `TimeField.Description` and `TimeField.ErrorMesssage` share the same data-attributes.
|
|
||||||
|
|
||||||
### TimeField.Segment
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| segment | `TimeSegment`<br> A segment of the time field. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-separator | Present when the segment is a separator. |
|
|
||||||
| data-type | Always present. |
|
|
||||||
| data-placeholder | Present when the segment's value is a placeholder. |
|
|
||||||
|
|
||||||
### TimeField.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `TimeField` | `div` |
|
|
||||||
| `TimeField.Label` | `span` |
|
|
||||||
| `TimeField.Field` | `div` |
|
|
||||||
| `TimeField.Segment` | `div` |
|
|
||||||
| `TimeField.Description` | `div` |
|
|
||||||
| `TimeField.ErrorMessage` | `div` |
|
|
||||||
| `TimeField.HiddenInput` | `input` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Backspace` | Deletes the value in the current segment and moves focus to the previous segment when empty. |
|
|
||||||
| `Delete` | Deletes the value in the current segment and moves focus to the previous segment when empty. |
|
|
||||||
| `ArrowRight` | Moves focus to the next segment. |
|
|
||||||
| `ArrowLeft` | Moves focus to the previous segment. |
|
|
||||||
| `ArrowUp` | Increments the given segment. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
|
|
||||||
| `ArrowDown` | Decrements the given segment. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
|
|
||||||
| `PageUp` | Increments the given segment by a larger amount, rounding it to the nearest increment. The amount to increment by depends on the segment, for example 2 hours, 15 minutes, and 15 seconds. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
|
|
||||||
| `PageDown` | Decrements the given segment by a larger amount, rounding it to the nearest decrement. The amount to decrement by depends on the segment, for example 2 hours, 15 minutes, and 15 seconds. Upon reaching the minimum or maximum value, the value wraps around to the opposite limit. |
|
|
||||||
| `Home` | Decrements the given segment by the segment's minimum value. |
|
|
||||||
| `End` | Increments the given segment by the segment's maximum value. |
|
|
||||||
|
|
||||||
Previous[←Text Field](https://kobalte.dev/docs/core/components/text-field)Next[Toast→](https://kobalte.dev/docs/core/components/toast)
|
|
||||||
@ -1,860 +0,0 @@
|
|||||||
# Toast
|
|
||||||
|
|
||||||
A succinct message that is displayed temporarily.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
// or
|
|
||||||
import { Root, toaster, ... } from "@kobalte/core/toast";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Toast, toaster } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
// or
|
|
||||||
import { Root, toaster, ... } from "@kobalte/core/toast";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Toast, toaster } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Automatically closes.
|
|
||||||
- Pauses closing on hover, focus and window blur.
|
|
||||||
- Supports hotkey to jump to toast region.
|
|
||||||
- Supports closing via swipe gesture.
|
|
||||||
- Exposes CSS variables for swipe gesture animations.
|
|
||||||
- Limit the number of visible toasts.
|
|
||||||
- Manage promises within toast.
|
|
||||||
- Can remove or update toast programmatically.
|
|
||||||
- Multiple toast regions.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The toast region consists of:
|
|
||||||
|
|
||||||
- **Toast.Region:** The fixed area where toasts appear. Users can jump to the viewport by pressing a hotkey.
|
|
||||||
- **Toast.List:** The list containing all rendered toasts.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
```
|
|
||||||
|
|
||||||
The toast consists of:
|
|
||||||
|
|
||||||
- **Toast:** The root container for a toast.
|
|
||||||
- **Toast.CloseButton:** The button that closes the toast.
|
|
||||||
- **Toast.Title:** An accessible title to be announced when the toast is opened.
|
|
||||||
- **Toast.Description:** An optional accessible description to be announced when the toast is opened.
|
|
||||||
- **Toast.ProgressTrack:** The component that visually represents the lifetime of the toast.
|
|
||||||
- **Toast.ProgressFill:** The component that visually represents the remaining lifetime of the toast.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast>
|
|
||||||
<Toast.CloseButton />
|
|
||||||
<Toast.Title />
|
|
||||||
<Toast.Description />
|
|
||||||
<Toast.ProgressTrack>
|
|
||||||
<Toast.ProgressFill />
|
|
||||||
</Toast.ProgressTrack>
|
|
||||||
</Toast>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast>
|
|
||||||
<Toast.CloseButton />
|
|
||||||
<Toast.Title />
|
|
||||||
<Toast.Description />
|
|
||||||
<Toast.ProgressTrack>
|
|
||||||
<Toast.ProgressFill />
|
|
||||||
</Toast.ProgressTrack>
|
|
||||||
</Toast>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Show toastUpdate toast
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
let id: number;
|
|
||||||
|
|
||||||
const showToast = () => {
|
|
||||||
id = toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
<div class="toast__content">
|
|
||||||
<div>
|
|
||||||
<Toast.Title class="toast__title">Event has been created</Toast.Title>
|
|
||||||
<Toast.Description class="toast__description">
|
|
||||||
Monday, January 3rd at 6:00pm
|
|
||||||
</Toast.Description>
|
|
||||||
</div>
|
|
||||||
<Toast.CloseButton class="toast__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Toast.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Toast.ProgressTrack class="toast__progress-track">
|
|
||||||
<Toast.ProgressFill class="toast__progress-fill" />
|
|
||||||
</Toast.ProgressTrack>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateToast = () => {
|
|
||||||
toaster.update(id, props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
<div class="toast__content">
|
|
||||||
<div>
|
|
||||||
<Toast.Title class="toast__title">Event has been updated</Toast.Title>
|
|
||||||
<Toast.Description class="toast__description">
|
|
||||||
Friday, January 7th at 10:00pm
|
|
||||||
</Toast.Description>
|
|
||||||
</div>
|
|
||||||
<Toast.CloseButton class="toast__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Toast.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Toast.ProgressTrack class="toast__progress-track">
|
|
||||||
<Toast.ProgressFill class="toast__progress-fill" />
|
|
||||||
</Toast.ProgressTrack>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={showToast}>
|
|
||||||
Show toast
|
|
||||||
</button>
|
|
||||||
<button onClick={updateToast}>
|
|
||||||
Update toast
|
|
||||||
</button>
|
|
||||||
<Portal>
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List class="toast__list" />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
let id: number;
|
|
||||||
|
|
||||||
const showToast = () => {
|
|
||||||
id = toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
<div class="toast__content">
|
|
||||||
<div>
|
|
||||||
<Toast.Title class="toast__title">Event has been created</Toast.Title>
|
|
||||||
<Toast.Description class="toast__description">
|
|
||||||
Monday, January 3rd at 6:00pm
|
|
||||||
</Toast.Description>
|
|
||||||
</div>
|
|
||||||
<Toast.CloseButton class="toast__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Toast.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Toast.ProgressTrack class="toast__progress-track">
|
|
||||||
<Toast.ProgressFill class="toast__progress-fill" />
|
|
||||||
</Toast.ProgressTrack>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateToast = () => {
|
|
||||||
toaster.update(id, props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
<div class="toast__content">
|
|
||||||
<div>
|
|
||||||
<Toast.Title class="toast__title">Event has been updated</Toast.Title>
|
|
||||||
<Toast.Description class="toast__description">
|
|
||||||
Friday, January 7th at 10:00pm
|
|
||||||
</Toast.Description>
|
|
||||||
</div>
|
|
||||||
<Toast.CloseButton class="toast__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</Toast.CloseButton>
|
|
||||||
</div>
|
|
||||||
<Toast.ProgressTrack class="toast__progress-track">
|
|
||||||
<Toast.ProgressFill class="toast__progress-fill" />
|
|
||||||
</Toast.ProgressTrack>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={showToast}>
|
|
||||||
Show toast
|
|
||||||
</button>
|
|
||||||
<button onClick={updateToast}>
|
|
||||||
Update toast
|
|
||||||
</button>
|
|
||||||
<Portal>
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List class="toast__list" />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Showing a toast
|
|
||||||
|
|
||||||
To create a toast, use the `toaster.show()` method and pass the generated `toastId` to `Toast.Root`.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
const id = toaster.show(props => <Toast toastId={props.toastId}>...</Toast>);
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
const id = toaster.show(props => <Toast toastId={props.toastId}>...</Toast>);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Updating a toast
|
|
||||||
|
|
||||||
The `toaster.update()` method can be used to update a toast by providing a toast id and the new component to render.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.update(id, props => <Toast toastId={props.toastId}>...</Toast>);
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.update(id, props => <Toast toastId={props.toastId}>...</Toast>);
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice that you always need to pass the `toastId` to `Toast`, because it doesn't know anything
|
|
||||||
about the `toaster` nor the toast it is supposed to represent.
|
|
||||||
|
|
||||||
### Dismissing a toast
|
|
||||||
|
|
||||||
The `toaster.dismiss()` method can be used to dismiss a toast by providing a toast id.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.dismiss(id);
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.dismiss(id);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Clearing the toast stack and queue
|
|
||||||
|
|
||||||
Use `toaster.clear()` method to dismiss all toasts.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.clear();
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.clear();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Handling promises
|
|
||||||
|
|
||||||
The toaster API exposes a `toaster.promise()` method to allow you update a toast when the promise resolves or rejects.
|
|
||||||
|
|
||||||
In addition to the `toastId`, props will contain the following properties:
|
|
||||||
|
|
||||||
- **state**: The state of the promise, can be `"pending" | "fulfilled" | "rejected"`.
|
|
||||||
- **data**: The data returned by the promise when fulfilled, if any.
|
|
||||||
- **error**: The error returned by the promise when rejected, if any.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.promise(promise, props => (
|
|
||||||
<Toast toastId={props.toastId}>
|
|
||||||
<Switch>
|
|
||||||
<Match when={props.state === "pending"}>Loading</Match>
|
|
||||||
<Match when={props.state === "fulfilled"}>{props.data}</Match>
|
|
||||||
<Match when={props.state === "rejected"}>{props.error}</Match>
|
|
||||||
</Switch>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.promise(promise, props => (
|
|
||||||
<Toast toastId={props.toastId}>
|
|
||||||
<Switch>
|
|
||||||
<Match when={props.state === "pending"}>Loading</Match>
|
|
||||||
<Match when={props.state === "fulfilled"}>{props.data}</Match>
|
|
||||||
<Match when={props.state === "rejected"}>{props.error}</Match>
|
|
||||||
</Switch>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pausing the toasts
|
|
||||||
|
|
||||||
The `Toast.Region` component exposes the following props to pause the toasts it contains.
|
|
||||||
|
|
||||||
- `pauseOnInteraction`: prop can be used to pause the toasts close timeout when a toast is hovered or focused.
|
|
||||||
- `pauseOnPageIdle`: prop can be used to pause the toasts close timeout when the document loses focus or the page is idle (e.g. switching to a new browser tab).
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast.Region pauseOnPageIdle pauseOnInteraction>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast.Region pauseOnPageIdle pauseOnInteraction>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Limiting the number of visible toasts
|
|
||||||
|
|
||||||
Use the `limit` prop of the `Toast.Region` to limit the number of toasts visible at the same time. All toasts added after limit was reached will be added into queue and displayed when a visible toast is closed.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast.Region limit={3}>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Toast.Region limit={3}>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Progress bar fill width
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-toast-progress-fill-width` which corresponds to the remaining toast lifetime (in percentage). If you are building a linear progress bar to show the toast duration, you can use it to set the width of the `Toast.ProgressFill` component in CSS.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css*/
|
|
||||||
|
|
||||||
.toast__progress-fill {
|
|
||||||
background-color: hsl(200 98% 39%);
|
|
||||||
border-radius: 3px;
|
|
||||||
height: 100%;
|
|
||||||
width: var(--kb-toast-progress-fill-width);
|
|
||||||
transition: width 250ms linear;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css*/
|
|
||||||
|
|
||||||
.toast__progress-fill {
|
|
||||||
background-color: hsl(200 98% 39%);
|
|
||||||
border-radius: 3px;
|
|
||||||
height: 100%;
|
|
||||||
width: var(--kb-toast-progress-fill-width);
|
|
||||||
transition: width 250ms linear;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Animating swipe gesture
|
|
||||||
|
|
||||||
We expose the CSS custom properties `--kb-toast-swipe-move-[x|y]` and `--kb-toast-swipe-end-[x|y]` which can be used with `data-swipe="[start|move|cancel|end]"` attributes to animate a swipe to close gesture.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
// index.tsx
|
|
||||||
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const showToast = () => {
|
|
||||||
toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
...
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={showToast}>Show toast</button>
|
|
||||||
<Portal>
|
|
||||||
<Toast.Region swipeDirection="right">
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
// index.tsx
|
|
||||||
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const showToast = () => {
|
|
||||||
toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
...
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={showToast}>Show toast</button>
|
|
||||||
<Portal>
|
|
||||||
<Toast.Region swipeDirection="right">
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
|
|
||||||
.toast[data-swipe="move"] {
|
|
||||||
transform: translateX(var(--kb-toast-swipe-move-x));
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast[data-swipe="cancel"] {
|
|
||||||
transform: translateX(0);
|
|
||||||
transition: transform 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast[data-swipe="end"] {
|
|
||||||
animation: slideRight 100ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideRight {
|
|
||||||
from {
|
|
||||||
transform: translateX(var(--kb-toast-swipe-end-x));
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
|
|
||||||
.toast[data-swipe="move"] {
|
|
||||||
transform: translateX(var(--kb-toast-swipe-move-x));
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast[data-swipe="cancel"] {
|
|
||||||
transform: translateX(0);
|
|
||||||
transition: transform 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast[data-swipe="end"] {
|
|
||||||
animation: slideRight 100ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideRight {
|
|
||||||
from {
|
|
||||||
transform: translateX(var(--kb-toast-swipe-end-x));
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Abstracting the `toaster` API
|
|
||||||
|
|
||||||
It's common in toast libraries to have method for displaying different type of toast like success or error. This can be done in Kobalte by abstracting the toaster API like below.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
// toast.tsx
|
|
||||||
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
import { JSX } from "solid-js/jsx-runtime";
|
|
||||||
import { Switch, Match } from "solid-js/web";
|
|
||||||
|
|
||||||
function show(message: string) {
|
|
||||||
return toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
{message}
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function success(message: string) {
|
|
||||||
return toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast toast--success">
|
|
||||||
{message}
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function error(message: string) {
|
|
||||||
return toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast toast--error">
|
|
||||||
{message}
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function promise<T, U>(
|
|
||||||
promise: Promise<T> | (() => Promise<T>),
|
|
||||||
options: {
|
|
||||||
loading?: JSX.Element;
|
|
||||||
success?: (data: T) => JSX.Element;
|
|
||||||
error?: (error: U) => JSX.Element;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
return toaster.promise(promise, props => (
|
|
||||||
<Toast
|
|
||||||
toastId={props.toastId}
|
|
||||||
classList={{
|
|
||||||
toast: true,
|
|
||||||
"toast-loading": props.state === "pending",
|
|
||||||
"toast-success": props.state === "fulfilled",
|
|
||||||
"toast-error": props.state === "rejected",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Switch>
|
|
||||||
<Match when={props.state === "pending"}>{options.loading}</Match>
|
|
||||||
<Match when={props.state === "fulfilled"}>{options.success?.(props.data)}</Match>
|
|
||||||
<Match when={props.state === "rejected"}>{options.error?.(props.error)}</Match>
|
|
||||||
</Switch>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function custom(jsx: () => JSX.Element) {
|
|
||||||
return toaster.show(props => <Toast toastId={props.toastId}>{jsx}</Toast>);
|
|
||||||
}
|
|
||||||
|
|
||||||
function dismiss(id: number) {
|
|
||||||
return toaster.dismiss(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const toast = {
|
|
||||||
show,
|
|
||||||
success,
|
|
||||||
error,
|
|
||||||
promise,
|
|
||||||
custom,
|
|
||||||
dismiss,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
// toast.tsx
|
|
||||||
|
|
||||||
import { Toast, toaster } from "@kobalte/core/toast";
|
|
||||||
import { JSX } from "solid-js/jsx-runtime";
|
|
||||||
import { Switch, Match } from "solid-js/web";
|
|
||||||
|
|
||||||
function show(message: string) {
|
|
||||||
return toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast">
|
|
||||||
{message}
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function success(message: string) {
|
|
||||||
return toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast toast--success">
|
|
||||||
{message}
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function error(message: string) {
|
|
||||||
return toaster.show(props => (
|
|
||||||
<Toast toastId={props.toastId} class="toast toast--error">
|
|
||||||
{message}
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function promise<T, U>(
|
|
||||||
promise: Promise<T> | (() => Promise<T>),
|
|
||||||
options: {
|
|
||||||
loading?: JSX.Element;
|
|
||||||
success?: (data: T) => JSX.Element;
|
|
||||||
error?: (error: U) => JSX.Element;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
return toaster.promise(promise, props => (
|
|
||||||
<Toast
|
|
||||||
toastId={props.toastId}
|
|
||||||
classList={{
|
|
||||||
toast: true,
|
|
||||||
"toast-loading": props.state === "pending",
|
|
||||||
"toast-success": props.state === "fulfilled",
|
|
||||||
"toast-error": props.state === "rejected",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Switch>
|
|
||||||
<Match when={props.state === "pending"}>{options.loading}</Match>
|
|
||||||
<Match when={props.state === "fulfilled"}>{options.success?.(props.data)}</Match>
|
|
||||||
<Match when={props.state === "rejected"}>{options.error?.(props.error)}</Match>
|
|
||||||
</Switch>
|
|
||||||
</Toast>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function custom(jsx: () => JSX.Element) {
|
|
||||||
return toaster.show(props => <Toast toastId={props.toastId}>{jsx}</Toast>);
|
|
||||||
}
|
|
||||||
|
|
||||||
function dismiss(id: number) {
|
|
||||||
return toaster.dismiss(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const toast = {
|
|
||||||
show,
|
|
||||||
success,
|
|
||||||
error,
|
|
||||||
promise,
|
|
||||||
custom,
|
|
||||||
dismiss,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Then inside your application, use your own toast API:
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
// App.tsx
|
|
||||||
|
|
||||||
import { toast } from "./toast";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const showToast = () => {
|
|
||||||
toast.success("Event has been created");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={showToast}>Show toast</button>
|
|
||||||
<Portal>
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
// App.tsx
|
|
||||||
|
|
||||||
import { toast } from "./toast";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const showToast = () => {
|
|
||||||
toast.success("Event has been created");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={showToast}>Show toast</button>
|
|
||||||
<Portal>
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multiple regions
|
|
||||||
|
|
||||||
The `region` option in `toaster.show()` allows you to display toast in multiple regions at the same time. Not providing a region uses the default one.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.show(props => <Toast toastId={props.toastId}>...</Toast>, {
|
|
||||||
region: "custom-region-id",
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
toaster.show(props => <Toast toastId={props.toastId}>...</Toast>, {
|
|
||||||
region: "custom-region-id",
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Inside your application, use add your custom region:
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Portal>
|
|
||||||
{/* Default region */}
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
<Toast.Region regionId="custom-region-id">
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Portal>
|
|
||||||
{/* Default region */}
|
|
||||||
<Toast.Region>
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
<Toast.Region regionId="custom-region-id">
|
|
||||||
<Toast.List />
|
|
||||||
</Toast.Region>
|
|
||||||
</Portal>
|
|
||||||
```
|
|
||||||
|
|
||||||
Show toastShow toast (custom region)
|
|
||||||
|
|
||||||
## API reference
|
|
||||||
|
|
||||||
### toaster
|
|
||||||
|
|
||||||
| Method | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| show | `(toastComponent: ToastComponent, options?: ShowToastOptions) => number`<br> Adds a new toast to the visible toasts or queue depending on current state, region and limit, and return the id of the created toast. |
|
|
||||||
| update | `(id: number, toastComponent: ToastComponent) => void`<br> Update the toast of the given id with a new rendered component. |
|
|
||||||
| promise | `(promise: Promise<T> | (() => Promise<T>), toastComponent: ToastPromiseComponent<T, U>, options?: ShowToastOptions) => number`<br> Adds a new promise-based toast to the visible toasts or queue depending on current state and limit, and return the id of the created toast. |
|
|
||||||
| dismiss | `(id: number) => void`<br> Removes toast with given id from visible toasts and queue. |
|
|
||||||
| clear | `() => void`<br> Removes all toasts from visible toasts and queue. |
|
|
||||||
|
|
||||||
### Toast.Region
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| aria-label | `string`<br>**default:** "Notifications ({hotkey})" <br> A label for the toast region to provide context for screen reader users when navigating page landmarks. Can contain a `{hotkey}` placeholder which will be replaced for you. |
|
|
||||||
| hotkey | `string[]`<br>**default:** alt + T <br> The keys to use as the keyboard shortcut that will move focus to the toast region. Use `event.code` value for each key from [keycode.info](https://www.toptal.com/developers/keycode). For meta keys, use `ctrlKey`, `shiftKey`, `altKey` and/or `metaKey`. |
|
|
||||||
| duration | `number`<br>**default:** 5000 <br> The time in milliseconds that should elapse before automatically closing each toast. |
|
|
||||||
| limit | `number`<br>**default:** 3 <br> The maximum amount of toasts that can be displayed at the same time. |
|
|
||||||
| swipeDirection | `"up" | "down" | "left" | "right"`<br>**default:** "right" <br> The direction of the pointer swipe that should close the toast. |
|
|
||||||
| swipeThreshold | `number`<br>**default:** 50 <br> The distance in pixels that the swipe gesture must travel before a close is triggered. |
|
|
||||||
| pauseOnInteraction | `boolean`<br>**default:** true <br> Whether the toasts close timeout should pause when a toast is hovered or focused. |
|
|
||||||
| pauseOnPageIdle | `boolean`<br>**default:** true <br> Whether the toasts close timeout should pause when the document loses focus or the page is idle (e.g. switching to a new browser tab). |
|
|
||||||
| topLayer | `boolean`<br>**default:** true <br> Whether the toast region is marked as a "top layer", so that it: <br> \- is not aria-hidden when opening an overlay. <br> \- allows focus even outside a containing focus scope. <br> \- doesn’t dismiss overlays when clicking on it, even though it is outside. |
|
|
||||||
| regionId | `string`<br> The custom id of the region used for multiple regions. |
|
|
||||||
| translations | [`ToastRegionIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/toast/toast.intl.ts)<br> Localization strings. |
|
|
||||||
|
|
||||||
### Toast
|
|
||||||
|
|
||||||
`Toast` is equivalent to the `Root` import from `@kobalte/core/toast` (and deprecated `Toast.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| toastId | `number`<br> The id of the toast provided by the `toaster`. |
|
|
||||||
| priority | `"high" | "low"`<br>**default:** "high" <br> Control the sensitivity of the toast for accessibility purposes. For toasts that are the result of a user action, choose `high`. Toasts generated from background tasks should use `low`. |
|
|
||||||
| duration | `number`<br> The time in milliseconds that should elapse before automatically closing the toast. This will override the value supplied to `Toast.Region`. |
|
|
||||||
| persistent | `boolean`<br> Whether the toast should ignore duration and disappear only by a user action. |
|
|
||||||
| onPause | `() => void`<br> Event handler called when the dismiss timer is paused. This occurs when the pointer is moved over the region or the region is focused. |
|
|
||||||
| onResume | `() => void`<br> Event handler called when the dismiss timer is resumed. This occurs when the pointer is moved away from the region or the region is blurred. |
|
|
||||||
| onSwipeStart | `(event: SwipeEvent) => void`<br> Event handler called when starting a swipe interaction. |
|
|
||||||
| onSwipeMove | `(event: SwipeEvent) => void`<br> Event handler called during a swipe interaction. |
|
|
||||||
| onSwipeCancel | `(event: SwipeEvent) => void`<br> Event handler called when a swipe interaction is cancelled. |
|
|
||||||
| onSwipeEnd | `(event: SwipeEvent) => void`<br> Event handler called at the end of a swipe interaction. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| translations | [`ToastIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/toast/toast.intl.ts)<br> Localization strings. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-opened | Present when the toast is open. |
|
|
||||||
| data-closed | Present when the toast disappear. |
|
|
||||||
| data-swipe | The state of the swipe, can be `"start" | "move" | "cancel" | "end"`. |
|
|
||||||
| data-swipe-direction | The direction of the pointer swipe that should close the toast. |
|
|
||||||
|
|
||||||
| CSS custom property | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| --kb-toast-swipe-move-x | The offset position of the toast when horizontally swiping. |
|
|
||||||
| --kb-toast-swipe-move-y | The offset position of the toast when vertically swiping. |
|
|
||||||
| --kb-toast-swipe-end-x | The offset end position of the toast after horizontally swiping. |
|
|
||||||
| --kb-toast-swipe-end-y | The offset end position of the toast after vertically swiping. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Toast` | `li` |
|
|
||||||
| `Toast.CloseButton` | `button` |
|
|
||||||
| `Toast.Title` | `div` |
|
|
||||||
| `Toast.Description` | `div` |
|
|
||||||
| `Toast.ProgressTrack` | `div` |
|
|
||||||
| `Toast.ProgressFill` | `div` |
|
|
||||||
| `Toast.Region` | `div` |
|
|
||||||
| `Toast.List` | `ol` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Alt` \+ `T` | Focuses toasts region. |
|
|
||||||
| `Tab` | Moves focus to the next focusable element. |
|
|
||||||
| `Shift` \+ `Tab` | Moves focus to the previous focusable element. |
|
|
||||||
| `Space` | When focus is on a `Toast.CloseButton`, closes the toast. |
|
|
||||||
| `Enter` | When focus is on a `Toast.CloseButton`, closes the toast. |
|
|
||||||
| `Esc` | When focus is on a toast, closes the toast. |
|
|
||||||
|
|
||||||
Previous[←Time Field](https://kobalte.dev/docs/core/components/time-field)Next[Toggle Button→](https://kobalte.dev/docs/core/components/toggle-button)
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
# @kobalte/utils 
|
|
||||||
|
|
||||||
0.9.1 • Public • Published 2 years ago
|
|
||||||
|
|
||||||
- [Readme](https://www.npmjs.com/package/@kobalte/utils?activeTab=readme)
|
|
||||||
- [Code Beta](https://www.npmjs.com/package/@kobalte/utils?activeTab=code)
|
|
||||||
- [7 Dependencies](https://www.npmjs.com/package/@kobalte/utils?activeTab=dependencies)
|
|
||||||
- [10 Dependents](https://www.npmjs.com/package/@kobalte/utils?activeTab=dependents)
|
|
||||||
- [16 Versions](https://www.npmjs.com/package/@kobalte/utils?activeTab=versions)
|
|
||||||
|
|
||||||
# @kobalte/utils
|
|
||||||
|
|
||||||
[Permalink: @kobalte/utils](https://www.npmjs.com/package/@kobalte/utils#kobalteutils)
|
|
||||||
|
|
||||||
Common utilities and types for Kobalte.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
[Permalink: Installation](https://www.npmjs.com/package/@kobalte/utils#installation)
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install @kobalte/utils
|
|
||||||
# or
|
|
||||||
yarn add @kobalte/utils
|
|
||||||
# or
|
|
||||||
pnpm add @kobalte/utils
|
|
||||||
```
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
[Permalink: Documentation](https://www.npmjs.com/package/@kobalte/utils#documentation)
|
|
||||||
|
|
||||||
For full documentation, visit [kobalte.dev](https://kobalte.dev/).
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
[Permalink: Changelog](https://www.npmjs.com/package/@kobalte/utils#changelog)
|
|
||||||
|
|
||||||
All notable changes are described in the [CHANGELOG.md](https://github.com/kobaltedev/kobalte/blob/HEAD/CHANGELOG.md) file.
|
|
||||||
|
|
||||||
## Readme
|
|
||||||
|
|
||||||
### Keywords
|
|
||||||
|
|
||||||
- [solid](https://www.npmjs.com/search?q=keywords:solid)
|
|
||||||
- [solidjs](https://www.npmjs.com/search?q=keywords:solidjs)
|
|
||||||
- [ui](https://www.npmjs.com/search?q=keywords:ui)
|
|
||||||
- [library](https://www.npmjs.com/search?q=keywords:library)
|
|
||||||
- [design-system](https://www.npmjs.com/search?q=keywords:design-system)
|
|
||||||
- [components](https://www.npmjs.com/search?q=keywords:components)
|
|
||||||
- [headless](https://www.npmjs.com/search?q=keywords:headless)
|
|
||||||
- [unstyled](https://www.npmjs.com/search?q=keywords:unstyled)
|
|
||||||
- [aria](https://www.npmjs.com/search?q=keywords:aria)
|
|
||||||
|
|
||||||
Viewing @kobalte/utils version 0.9.1
|
|
||||||
@ -1,258 +0,0 @@
|
|||||||
# Alert Dialog
|
|
||||||
|
|
||||||
A modal dialog that interrupts the user's workflow to communicate an important message and acquire a response. Examples include action confirmation prompts and error message confirmations. The alertdialog role enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { AlertDialog } from "@kobalte/core/alert-dialog";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/alert-dialog";
|
|
||||||
// or (deprecated)
|
|
||||||
import { AlertDialog } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { AlertDialog } from "@kobalte/core/alert-dialog";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/alert-dialog";
|
|
||||||
// or (deprecated)
|
|
||||||
import { AlertDialog } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Alert Dialog](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/) design pattern.
|
|
||||||
- Supports modal and non-modal modes.
|
|
||||||
- Provides screen reader announcements via rendered title and description.
|
|
||||||
- Focus is trapped and scrolling is blocked while it is open.
|
|
||||||
- Pressing `Esc` closes the alert dialog.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The alert dialog consists of:
|
|
||||||
|
|
||||||
- **AlertDialog:** Contains all the parts of a dialog.
|
|
||||||
- **AlertDialog.Trigger:** The button that opens the dialog.
|
|
||||||
- **AlertDialog.Portal:** Portals its children into the `body` when the dialog is open.
|
|
||||||
- **AlertDialog.Overlay:** The layer that covers the inert portion of the view when the dialog is open.
|
|
||||||
- **AlertDialog.Content:** Contains the content to be rendered when the dialog is open.
|
|
||||||
- **AlertDialog.CloseButton:** The button that closes the dialog.
|
|
||||||
- **AlertDialog.Title:** An accessible title to be announced when the dialog is opened.
|
|
||||||
- **AlertDialog.Description:** An optional accessible description to be announced when the dialog is opened.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialog.Trigger />
|
|
||||||
<AlertDialog.Portal>
|
|
||||||
<AlertDialog.Overlay />
|
|
||||||
<AlertDialog.Content>
|
|
||||||
<AlertDialog.CloseButton />
|
|
||||||
<AlertDialog.Title />
|
|
||||||
<AlertDialog.Description />
|
|
||||||
</AlertDialog.Content>
|
|
||||||
</AlertDialog.Portal>
|
|
||||||
</AlertDialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialog.Trigger />
|
|
||||||
<AlertDialog.Portal>
|
|
||||||
<AlertDialog.Overlay />
|
|
||||||
<AlertDialog.Content>
|
|
||||||
<AlertDialog.CloseButton />
|
|
||||||
<AlertDialog.Title />
|
|
||||||
<AlertDialog.Description />
|
|
||||||
</AlertDialog.Content>
|
|
||||||
</AlertDialog.Portal>
|
|
||||||
</AlertDialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Open
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { AlertDialog } from "@kobalte/core/alert-dialog";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialog.Trigger class="alert-dialog__trigger">Open</AlertDialog.Trigger>
|
|
||||||
<AlertDialog.Portal>
|
|
||||||
<AlertDialog.Overlay class="alert-dialog__overlay" />
|
|
||||||
<div class="alert-dialog__positioner">
|
|
||||||
<AlertDialog.Content class="alert-dialog__content">
|
|
||||||
<div class="alert-dialog__header">
|
|
||||||
<AlertDialog.Title class="alert-dialog__title">Alert Dialog</AlertDialog.Title>
|
|
||||||
<AlertDialog.CloseButton class="alert-dialog__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</AlertDialog.CloseButton>
|
|
||||||
</div>
|
|
||||||
<AlertDialog.Description class="alert-dialog__description">
|
|
||||||
An Alert Dialog enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound.
|
|
||||||
</AlertDialog.Description>
|
|
||||||
</AlertDialog.Content>
|
|
||||||
</div>
|
|
||||||
</AlertDialog.Portal>
|
|
||||||
</AlertDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { AlertDialog } from "@kobalte/core/alert-dialog";
|
|
||||||
import { CrossIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialog.Trigger class="alert-dialog__trigger">Open</AlertDialog.Trigger>
|
|
||||||
<AlertDialog.Portal>
|
|
||||||
<AlertDialog.Overlay class="alert-dialog__overlay" />
|
|
||||||
<div class="alert-dialog__positioner">
|
|
||||||
<AlertDialog.Content class="alert-dialog__content">
|
|
||||||
<div class="alert-dialog__header">
|
|
||||||
<AlertDialog.Title class="alert-dialog__title">Alert Dialog</AlertDialog.Title>
|
|
||||||
<AlertDialog.CloseButton class="alert-dialog__close-button">
|
|
||||||
<CrossIcon />
|
|
||||||
</AlertDialog.CloseButton>
|
|
||||||
</div>
|
|
||||||
<AlertDialog.Description class="alert-dialog__description">
|
|
||||||
An Alert Dialog enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound.
|
|
||||||
</AlertDialog.Description>
|
|
||||||
</AlertDialog.Content>
|
|
||||||
</div>
|
|
||||||
</AlertDialog.Portal>
|
|
||||||
</AlertDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default open
|
|
||||||
|
|
||||||
An initial, uncontrolled open value can be provided using the `defaultOpen` prop.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<AlertDialog defaultOpen>...</AlertDialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<AlertDialog defaultOpen>...</AlertDialog>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled open
|
|
||||||
|
|
||||||
The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, close button or overlay, and receives the new value.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AlertDialog open={open()} onOpenChange={setOpen}>
|
|
||||||
...
|
|
||||||
</AlertDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AlertDialog open={open()} onOpenChange={setOpen}>
|
|
||||||
...
|
|
||||||
</AlertDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### AlertDialog
|
|
||||||
|
|
||||||
`AlertDialog` is equivalent to the `Root` import from `@kobalte/core/alert-dialog` (and deprecated `AlertDialog.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the dialog. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the dialog changes. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| modal | `boolean`<br> Whether the dialog should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the dialog content. <br> \- elements outside the dialog content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the alert dialog is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the dialog (portal, overlay and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### AlertDialog.Trigger
|
|
||||||
|
|
||||||
`AlertDialog.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button).
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the dialog is open. |
|
|
||||||
| data-closed | Present when the dialog is close. |
|
|
||||||
|
|
||||||
`AlertDialog.Content` and `AlertDialog.Overlay` shares the same data-attributes.
|
|
||||||
|
|
||||||
### AlertDialog.Content
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `AlertDialog` | none |
|
|
||||||
| `AlertDialog.Trigger` | `button` |
|
|
||||||
| `AlertDialog.Portal` | `Portal` |
|
|
||||||
| `AlertDialog.Overlay` | `div` |
|
|
||||||
| `AlertDialog.Content` | `div` |
|
|
||||||
| `AlertDialog.CloseButton` | `button` |
|
|
||||||
| `AlertDialog.Title` | `h2` |
|
|
||||||
| `AlertDialog.Description` | `p` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on the trigger, opens/closes the dialog. |
|
|
||||||
| `Enter` | When focus is on the trigger, opens/closes the dialog. |
|
|
||||||
| `Tab` | Moves focus to the next focusable element. |
|
|
||||||
| `Shift` \+ `Tab` | Moves focus to the previous focusable element. |
|
|
||||||
| `Esc` | Closes the dialog and moves focus to the trigger. |
|
|
||||||
|
|
||||||
Previous[←Alert](https://kobalte.dev/docs/core/components/alert)Next[Badge→](https://kobalte.dev/docs/core/components/badge)
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
# Alert
|
|
||||||
|
|
||||||
Display a brief, important message in a way that attracts the user's attention without interrupting the user's task.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Alert } from "@kobalte/core/alert";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/alert";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Alert } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Alert } from "@kobalte/core/alert";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/alert";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Alert } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Adhere to the [WAI ARIA Alert](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) design pattern.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The alert consists of :
|
|
||||||
|
|
||||||
- **Alert:** The root container for an alert.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Alert />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Alert />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Kobalte is going live soon, get ready!
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Alert } from "@kobalte/core/alert";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return <Alert class="alert">Kobalte is going live soon, get ready!</Alert>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Alert } from "@kobalte/core/alert";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return <Alert class="alert">Kobalte is going live soon, get ready!</Alert>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API reference
|
|
||||||
|
|
||||||
### Alert
|
|
||||||
|
|
||||||
`Alert` is equivalent to the `Root` import from `@kobalte/core/alert` (and deprecated `Alert.Root`).
|
|
||||||
|
|
||||||
Renders a `div` by default and support all its props.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Alert` | `div` |
|
|
||||||
|
|
||||||
Previous[←Accordion](https://kobalte.dev/docs/core/components/accordion)Next[Alert Dialog→](https://kobalte.dev/docs/core/components/alert-dialog)
|
|
||||||
@ -1,92 +0,0 @@
|
|||||||
# Badge
|
|
||||||
|
|
||||||
A `Badge` component is used to display small pieces of information or status indicators.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Badge } from "@kobalte/core/badge";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/badge";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Badge } from "@kobalte/core/badge";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/badge";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Auto-populated ARIA labeling via the textValue prop for enhanced accessibility.
|
|
||||||
- Built-in ARIA support with role="status" to communicate dynamic updates.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The badge consists of:
|
|
||||||
|
|
||||||
- **Badge:** The root container for the badge that supports accessibility and content customization.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Badge />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Badge />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
5 messages
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Badge } from "@kobalte/core/badge";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Badge class="badge" textValue="5 unread messages">
|
|
||||||
5 messages
|
|
||||||
</Badge>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Badge } from "@kobalte/core/badge";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Badge class="badge" textValue="5 unread messages">
|
|
||||||
5 messages
|
|
||||||
</Badge>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Badge
|
|
||||||
|
|
||||||
`Badge` is equivalent to the `Root` import from `@kobalte/core/badge`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string | undefined`<br> Accessible text description of the badge if child is not text |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Badge` | `span` |
|
|
||||||
|
|
||||||
Previous[←Alert Dialog](https://kobalte.dev/docs/core/components/alert-dialog)Next[Breadcrumbs→](https://kobalte.dev/docs/core/components/breadcrumbs)
|
|
||||||
@ -1,233 +0,0 @@
|
|||||||
Show hierarchy and navigational context for a user’s location within an application.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Breadcrumbs } from "@kobalte/core/breadcrumbs";
|
|
||||||
// or
|
|
||||||
import { Root, Link, ... } from "@kobalte/core/breadcrumbs";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Breadcrumbs } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Breadcrumbs } from "@kobalte/core/breadcrumbs";
|
|
||||||
// or
|
|
||||||
import { Root, Link, ... } from "@kobalte/core/breadcrumbs";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Breadcrumbs } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Support for navigation links via `<a>` elements or custom element types via ARIA.
|
|
||||||
- Localized ARIA labeling support for landmark navigation region.
|
|
||||||
- Support for disabled breadcrumb links.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The breadcrumbs consist of:
|
|
||||||
|
|
||||||
- **Breadcrumbs:** The root container for a breadcrumbs.
|
|
||||||
- **Breadcrumbs.Link:** The breadcrumb link.
|
|
||||||
- **Breadcrumbs.Separator:** The visual separator between each breadcrumb items. It will not be visible by screen readers.
|
|
||||||
- **ol:** The native HTML `<ol>` element used to contain breadcrumb items.
|
|
||||||
- **li:** The native HTML `<li>` element used to contain breadcrumb link and separator.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Breadcrumbs>
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<Breadcrumbs.Link />
|
|
||||||
<Breadcrumbs.Separator />
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</Breadcrumbs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Breadcrumbs>
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<Breadcrumbs.Link />
|
|
||||||
<Breadcrumbs.Separator />
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</Breadcrumbs>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Breadcrumbs } from "@kobalte/core/breadcrumbs";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Breadcrumbs>
|
|
||||||
<ol class="breadcrumbs__list">
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/" class="breadcrumbs__link">
|
|
||||||
Home
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/components" class="breadcrumbs__link">
|
|
||||||
Components
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link current class="breadcrumbs__link">
|
|
||||||
Breadcrumbs
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</Breadcrumbs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Breadcrumbs } from "@kobalte/core/breadcrumbs";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Breadcrumbs>
|
|
||||||
<ol class="breadcrumbs__list">
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/" class="breadcrumbs__link">
|
|
||||||
Home
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/components" class="breadcrumbs__link">
|
|
||||||
Components
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link current class="breadcrumbs__link">
|
|
||||||
Breadcrumbs
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</Breadcrumbs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Custom separator
|
|
||||||
|
|
||||||
Use the `separator` prop to provide a default content for all `Breadcrumbs.Separator`. You can pass it a `string` or a SolidJS component.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ChevronRightIcon } from "some-icon-library";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Breadcrumbs separator={<ChevronRightIcon />}>
|
|
||||||
<ol class="breadcrumbs__list">
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/" class="breadcrumbs__link">
|
|
||||||
Home
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/components" class="breadcrumbs__link">
|
|
||||||
Components
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link current class="breadcrumbs__link">
|
|
||||||
Breadcrumbs
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</Breadcrumbs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ChevronRightIcon } from "some-icon-library";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Breadcrumbs separator={<ChevronRightIcon />}>
|
|
||||||
<ol class="breadcrumbs__list">
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/" class="breadcrumbs__link">
|
|
||||||
Home
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link href="/components" class="breadcrumbs__link">
|
|
||||||
Components
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
<Breadcrumbs.Separator class="breadcrumbs__separator" />
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs__item">
|
|
||||||
<Breadcrumbs.Link current class="breadcrumbs__link">
|
|
||||||
Breadcrumbs
|
|
||||||
</Breadcrumbs.Link>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</Breadcrumbs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also override each `Breadcrumbs.Separator` content by providing your own `children`.
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Breadcrumbs
|
|
||||||
|
|
||||||
`Breadcrumbs` is equivalent to the `Root` import from `@kobalte/core/breadcrumbs` (and deprecated `Breadcrumbs.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| separator | `string | JSX.Element`<br> The visual separator between each breadcrumb item. It will be used as the default children of `Breadcrumbs.Separator`. |
|
|
||||||
| translations | [`BreadcrumbsIntlTranslations`](https://github.com/kobaltedev/kobalte/blob/main/packages/core/src/breadcrumbs/breadcrumbs.intl.ts)<br> Localization strings. |
|
|
||||||
|
|
||||||
### Breadcrumbs.Link
|
|
||||||
|
|
||||||
`Breadcrumbs.Link` consists of [Link](https://kobalte.dev/docs/core/components/link).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| current | `boolean`<br> Whether the breadcrumb link represents the current page. |
|
|
||||||
| disabled | `boolean`<br> Whether the breadcrumb link is disabled. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-current | Present when the breadcrumb link represents the current page. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Breadcrumbs` | `nav` |
|
|
||||||
| `Breadcrumbs.Link` | `a` |
|
|
||||||
| `Breadcrumbs.Separator` | `span` |
|
|
||||||
|
|
||||||
Previous[←Badge](https://kobalte.dev/docs/core/components/badge)Next[Button→](https://kobalte.dev/docs/core/components/button)
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
# Button
|
|
||||||
|
|
||||||
Enables users to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Button } from "@kobalte/core/button";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/button";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Button } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Button } from "@kobalte/core/button";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/button";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Button } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Native HTML `<button>` element support.
|
|
||||||
- `<a>` and custom element type support via the [WAI ARIA Button](https://www.w3.org/WAI/ARIA/apg/patterns/button/) design pattern.
|
|
||||||
- Keyboard event support for `Space` and `Enter` keys.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The button consists of:
|
|
||||||
|
|
||||||
- **Button:** The root container for a button.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Button />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Button />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Click me
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Button } from "@kobalte/core/button";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return <Button class="button">Click me</Button>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Button } from "@kobalte/core/button";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return <Button class="button">Click me</Button>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Button
|
|
||||||
|
|
||||||
`Button` is equivalent to the `Root` import from `@kobalte/core/button` (and deprecated `Button.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| disabled | `boolean`<br> Whether the button is disabled. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the button is disabled. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Button` | `button` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | Activates the button. |
|
|
||||||
| `Enter` | Activates the button. |
|
|
||||||
|
|
||||||
Previous[←Breadcrumbs](https://kobalte.dev/docs/core/components/breadcrumbs)Next[Checkbox→](https://kobalte.dev/docs/core/components/checkbox)
|
|
||||||
@ -1,400 +0,0 @@
|
|||||||
# Checkbox
|
|
||||||
|
|
||||||
A control that allows the user to toggle between checked and not checked.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Checkbox } from "@kobalte/core/checkbox";
|
|
||||||
// or
|
|
||||||
import { Root, Input, ... } from "@kobalte/core/checkbox";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Checkbox } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Checkbox } from "@kobalte/core/checkbox";
|
|
||||||
// or
|
|
||||||
import { Root, Input, ... } from "@kobalte/core/checkbox";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Checkbox } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Built with a native HTML `<input>` element, which is visually hidden to allow custom styling.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Labeling support for assistive technology.
|
|
||||||
- Support for description and error message help text linked to the input via ARIA.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The checkbox consists of:
|
|
||||||
|
|
||||||
- **Checkbox:** The root container for a checkbox.
|
|
||||||
- **Checkbox.Input:** The native html input that is visually hidden in the checkbox.
|
|
||||||
- **Checkbox.Control:** The element that visually represents a checkbox.
|
|
||||||
- **Checkbox.Indicator:** The visual indicator rendered when the checkbox is in a checked or indeterminate state.
|
|
||||||
- **Checkbox.Label:** The label that gives the user information on the checkbox.
|
|
||||||
- **Checkbox.Description**: The description that gives the user more information on the checkbox.
|
|
||||||
- **Checkbox.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the checkbox.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Checkbox>
|
|
||||||
<Checkbox.Input />
|
|
||||||
<Checkbox.Control>
|
|
||||||
<Checkbox.Indicator />
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label />
|
|
||||||
<Checkbox.Description />
|
|
||||||
<Checkbox.ErrorMessage />
|
|
||||||
</Checkbox>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Checkbox>
|
|
||||||
<Checkbox.Input />
|
|
||||||
<Checkbox.Control>
|
|
||||||
<Checkbox.Indicator />
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label />
|
|
||||||
<Checkbox.Description />
|
|
||||||
<Checkbox.ErrorMessage />
|
|
||||||
</Checkbox>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Subscribe
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Checkbox } from "@kobalte/core/checkbox";
|
|
||||||
import { CheckIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Checkbox class="checkbox">
|
|
||||||
<Checkbox.Input class="checkbox__input" />
|
|
||||||
<Checkbox.Control class="checkbox__control">
|
|
||||||
<Checkbox.Indicator>
|
|
||||||
<CheckIcon />
|
|
||||||
</Checkbox.Indicator>
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label class="checkbox__label">Subscribe</Checkbox.Label>
|
|
||||||
</Checkbox>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Checkbox } from "@kobalte/core/checkbox";
|
|
||||||
import { CheckIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Checkbox class="checkbox">
|
|
||||||
<Checkbox.Input class="checkbox__input" />
|
|
||||||
<Checkbox.Control class="checkbox__control">
|
|
||||||
<Checkbox.Indicator>
|
|
||||||
<CheckIcon />
|
|
||||||
</Checkbox.Indicator>
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label class="checkbox__label">Subscribe</Checkbox.Label>
|
|
||||||
</Checkbox>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default checked
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultChecked` prop.
|
|
||||||
|
|
||||||
Check
|
|
||||||
|
|
||||||
Subscribe
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Checkbox defaultChecked>...</Checkbox>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Checkbox defaultChecked>...</Checkbox>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled checked
|
|
||||||
|
|
||||||
The `checked` prop can be used to make the checked state controlled. The `onChange` event is fired when the user presses the checkbox, and receives the new value.
|
|
||||||
|
|
||||||
Subscribe
|
|
||||||
|
|
||||||
You are unsubscribed.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Checkbox checked={checked()} onChange={setChecked}>
|
|
||||||
...
|
|
||||||
</Checkbox>
|
|
||||||
<p>You are {checked() ? "subscribed" : "unsubscribed"}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Checkbox checked={checked()} onChange={setChecked}>
|
|
||||||
...
|
|
||||||
</Checkbox>
|
|
||||||
<p>You are {checked() ? "subscribed" : "unsubscribed"}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `Checkbox.Description` component can be used to associate additional help text with a checkbox.
|
|
||||||
|
|
||||||
Subscribe
|
|
||||||
|
|
||||||
You will receive our weekly newsletter.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Checkbox>
|
|
||||||
<Checkbox.Input />
|
|
||||||
<Checkbox.Control>
|
|
||||||
<Checkbox.Indicator>
|
|
||||||
<CheckIcon />
|
|
||||||
</Checkbox.Indicator>
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label>Subscribe</Checkbox.Label>
|
|
||||||
<Checkbox.Description>You will receive our weekly newsletter.</Checkbox.Description>
|
|
||||||
</Checkbox>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Checkbox>
|
|
||||||
<Checkbox.Input />
|
|
||||||
<Checkbox.Control>
|
|
||||||
<Checkbox.Indicator>
|
|
||||||
<CheckIcon />
|
|
||||||
</Checkbox.Indicator>
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label>Subscribe</Checkbox.Label>
|
|
||||||
<Checkbox.Description>You will receive our weekly newsletter.</Checkbox.Description>
|
|
||||||
</Checkbox>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `Checkbox.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the checkbox as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Subscribe
|
|
||||||
|
|
||||||
You must agree to our Terms and Conditions.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Checkbox
|
|
||||||
checked={checked()}
|
|
||||||
onChange={setChecked}
|
|
||||||
validationState={!checked() ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<Checkbox.Input />
|
|
||||||
<Checkbox.Control>
|
|
||||||
<Checkbox.Indicator>
|
|
||||||
<CheckIcon />
|
|
||||||
</Checkbox.Indicator>
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label>Agree</Checkbox.Label>
|
|
||||||
<Checkbox.ErrorMessage>You must agree to our Terms and Conditions.</Checkbox.ErrorMessage>
|
|
||||||
</Checkbox>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Checkbox
|
|
||||||
checked={checked()}
|
|
||||||
onChange={setChecked}
|
|
||||||
validationState={!checked() ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<Checkbox.Input />
|
|
||||||
<Checkbox.Control>
|
|
||||||
<Checkbox.Indicator>
|
|
||||||
<CheckIcon />
|
|
||||||
</Checkbox.Indicator>
|
|
||||||
</Checkbox.Control>
|
|
||||||
<Checkbox.Label>Agree</Checkbox.Label>
|
|
||||||
<Checkbox.ErrorMessage>You must agree to our Terms and Conditions.</Checkbox.ErrorMessage>
|
|
||||||
</Checkbox>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The `name` and `value` props can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Subscribe
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<Checkbox name="newsletter" value="subscribe">
|
|
||||||
...
|
|
||||||
</Checkbox>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<Checkbox name="newsletter" value="subscribe">
|
|
||||||
...
|
|
||||||
</Checkbox>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Checkbox
|
|
||||||
|
|
||||||
`Checkbox` is equivalent to the `Root` import from `@kobalte/core/checkbox` (and deprecated `Checkbox.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `boolean`<br> The controlled checked state of the checkbox. |
|
|
||||||
| defaultChecked | `boolean`<br> The default checked state when initially rendered. Useful when you do not need to control the checked state. |
|
|
||||||
| onChange | `(checked: boolean) => void`<br> Event handler called when the checked state of the checkbox changes. |
|
|
||||||
| indeterminate | `boolean`<br> Whether the checkbox is in an indeterminate state. |
|
|
||||||
| name | `string`<br> The name of the checkbox, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| value | `string`<br> The value of the checkbox, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefvalue). |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the checkbox should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check the checkbox before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the checkbox is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the checkbox can be checked but not changed by the user. |
|
|
||||||
| children | `JSX.Element | (state: CheckboxState) => JSX.Element`<br> The children of the checkbox. Can be a `JSX.Element` or a _render prop_ for having access to the internal state. |
|
|
||||||
|
|
||||||
| Render Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `Accessor<boolean>`<br> Whether the checkbox is checked or not. |
|
|
||||||
| indeterminate | `Accessor<boolean>`<br> Whether the checkbox is in an indeterminate state. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the checkbox is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the checkbox is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the checkbox is required. |
|
|
||||||
| data-disabled | Present when the checkbox is disabled. |
|
|
||||||
| data-readonly | Present when the checkbox is read only. |
|
|
||||||
| data-checked | Present when the checkbox is checked. |
|
|
||||||
| data-indeterminate | Present when the checkbox is in an indeterminate state. |
|
|
||||||
|
|
||||||
`Checkbox.Input`, `Checkbox.Control`, `Checkbox.Indicator`, `Checkbox.Label`, `Checkbox.Description` and `Checkbox.ErrorMessage` share the same data-attributes.
|
|
||||||
|
|
||||||
### Checkbox.Indicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### Checkbox.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Checkbox` | `div` |
|
|
||||||
| `Checkbox.Input` | `input` |
|
|
||||||
| `Checkbox.Control` | `div` |
|
|
||||||
| `Checkbox.Indicator` | `div` |
|
|
||||||
| `Checkbox.Label` | `label` |
|
|
||||||
| `Checkbox.Description` | `div` |
|
|
||||||
| `Checkbox.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | Toggles the checkbox on and off. |
|
|
||||||
|
|
||||||
Previous[←Button](https://kobalte.dev/docs/core/components/button)Next[Collapsible→](https://kobalte.dev/docs/core/components/collapsible)
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
# Collapsible
|
|
||||||
|
|
||||||
An interactive component which expands/collapses a content.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Collapsible } from "@kobalte/core/collapsible";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/collapsible";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Collapsible } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Collapsible } from "@kobalte/core/collapsible";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/collapsible";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Collapsible } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Disclosure](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) design pattern.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The collapsible consists of:
|
|
||||||
|
|
||||||
- **Collapsible:** The root container for a collapsible.
|
|
||||||
- **Collapsible.Trigger:** The button that expands/collapses the collapsible content.
|
|
||||||
- **Collapsible.Content:** Contains the content to be rendered when the collapsible is expanded.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Collapsible>
|
|
||||||
<Collapsible.Trigger />
|
|
||||||
<Collapsible.Content />
|
|
||||||
</Collapsible>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Collapsible>
|
|
||||||
<Collapsible.Trigger />
|
|
||||||
<Collapsible.Content />
|
|
||||||
</Collapsible>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
What is Kobalte?Chevron
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Collapsible } from "@kobalte/core/collapsible";
|
|
||||||
import { ChevronDownIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Collapsible class="collapsible">
|
|
||||||
<Collapsible.Trigger class="collapsible__trigger">
|
|
||||||
<span>What is Kobalte?</span>
|
|
||||||
<ChevronDownIcon class="collapsible__trigger-icon" />
|
|
||||||
</Collapsible.Trigger>
|
|
||||||
<Collapsible.Content class="collapsible__content">
|
|
||||||
<p class="collapsible__content-text">
|
|
||||||
Kobalte is a UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
It provides a set of low-level UI components and primitives which can be the foundation
|
|
||||||
for your design system implementation.
|
|
||||||
</p>
|
|
||||||
</Collapsible.Content>
|
|
||||||
</Collapsible>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Collapsible } from "@kobalte/core/collapsible";
|
|
||||||
import { ChevronDownIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Collapsible class="collapsible">
|
|
||||||
<Collapsible.Trigger class="collapsible__trigger">
|
|
||||||
<span>What is Kobalte?</span>
|
|
||||||
<ChevronDownIcon class="collapsible__trigger-icon" />
|
|
||||||
</Collapsible.Trigger>
|
|
||||||
<Collapsible.Content class="collapsible__content">
|
|
||||||
<p class="collapsible__content-text">
|
|
||||||
Kobalte is a UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
It provides a set of low-level UI components and primitives which can be the foundation
|
|
||||||
for your design system implementation.
|
|
||||||
</p>
|
|
||||||
</Collapsible.Content>
|
|
||||||
</Collapsible>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Animating content size
|
|
||||||
|
|
||||||
We expose the CSS custom properties `--kb-collapsible-content-width` and `--kb-collapsible-content-height` which you can use to animate the size of the content when it opens/closes.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.collapsible__content {
|
|
||||||
overflow: hidden;
|
|
||||||
animation: slideUp 300ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsible__content[data-expanded] {
|
|
||||||
animation: slideDown 300ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideDown {
|
|
||||||
from {
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
height: var(--kb-collapsible-content-height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideUp {
|
|
||||||
from {
|
|
||||||
height: var(--kb-collapsible-content-height);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.collapsible__content {
|
|
||||||
overflow: hidden;
|
|
||||||
animation: slideUp 300ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsible__content[data-expanded] {
|
|
||||||
animation: slideDown 300ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideDown {
|
|
||||||
from {
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
height: var(--kb-collapsible-content-height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideUp {
|
|
||||||
from {
|
|
||||||
height: var(--kb-collapsible-content-height);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Collapsible
|
|
||||||
|
|
||||||
`Collapsible` is equivalent to the `Root` import from `@kobalte/core/collapsible` (and deprecated `Collapsible.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the collapsible. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the collapsible changes. |
|
|
||||||
| disabled | `boolean`<br> Whether the collapsible is disabled. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the collapsible content when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the collapsible is expanded. |
|
|
||||||
| data-closed | Present when the collapsible is collapsed. |
|
|
||||||
| data-disabled | Present when the collapsible is disabled. |
|
|
||||||
|
|
||||||
`Collapsible.Trigger` and `Collapsible.Content` share the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Collapsible` | `div` |
|
|
||||||
| `Collapsible.Trigger` | `button` |
|
|
||||||
| `Collapsible.Content` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on the trigger, opens/closes the collapsible. |
|
|
||||||
| `Enter` | When focus is on the trigger, opens/closes the collapsible. |
|
|
||||||
|
|
||||||
Previous[←Checkbox](https://kobalte.dev/docs/core/components/checkbox)Next[Color Area→](https://kobalte.dev/docs/core/components/color-area)
|
|
||||||
@ -1,493 +0,0 @@
|
|||||||
# Color Channel Field
|
|
||||||
|
|
||||||
A number input that allow users to edit individual color channel value.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorChannelField } from "@kobalte/core/color-channel-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/color-channel-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorChannelField } from "@kobalte/core/color-channel-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/color-channel-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follows the [WAI ARIA Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) design pattern.
|
|
||||||
- Built with a native `<input>` element.
|
|
||||||
- Visual and ARIA labeling support.
|
|
||||||
- Required and invalid states exposed to assistive technology via ARIA.
|
|
||||||
- Support for description and error message help text linked to the input via ARIA.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Supports increment and decrement buttons.
|
|
||||||
- Format and localize input number and raw input.
|
|
||||||
- Supports mouse wheel event and all keyboard events.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The color channel field consists of:
|
|
||||||
|
|
||||||
- **ColorChannelField**: The root container for the color channel field.
|
|
||||||
- **ColorChannelField.Label**: The label that gives the user information on the color channel field.
|
|
||||||
- **ColorChannelField.Input**: The native HTML input of the color channel field, used for display number.
|
|
||||||
- **ColorChannelField.HiddenInput**: The native HTML input of the color channel field, used for raw number form submition.
|
|
||||||
- **ColorChannelField.IncrementTrigger**: The increment button of the color channel field.
|
|
||||||
- **ColorChannelField.DecrementTrigger**: The decrement button of the color channel field.
|
|
||||||
- **ColorChannelField.Description**: The description that gives the user more information on the color channel field.
|
|
||||||
- **ColorChannelField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on a color channel field.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField>
|
|
||||||
<ColorChannelField.Label />
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.HiddenInput />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
<ColorChannelField.Description />
|
|
||||||
<ColorChannelField.ErrorMessage />
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField>
|
|
||||||
<ColorChannelField.Label />
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.HiddenInput />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
<ColorChannelField.Description />
|
|
||||||
<ColorChannelField.ErrorMessage />
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Hue
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorChannelField } from "@kobalte/core/color-channel-field";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorChannelField class={style["color-channel-field"]} channel="hue">
|
|
||||||
<ColorChannelField.Label class={style["color-channel-field__label"]}>
|
|
||||||
Hue
|
|
||||||
</ColorChannelField.Label>
|
|
||||||
<div class={style["color-channel-field__group"]}>
|
|
||||||
<ColorChannelField.Input class={style["color-channel-field__input"]} />
|
|
||||||
<ColorChannelField.IncrementTrigger
|
|
||||||
aria-label="Increment"
|
|
||||||
class={style["color-channel-field__increment"]}
|
|
||||||
>
|
|
||||||
<ArrowIcon />
|
|
||||||
</ColorChannelField.IncrementTrigger>
|
|
||||||
<ColorChannelField.DecrementTrigger
|
|
||||||
aria-label="Decrement"
|
|
||||||
class={style["color-channel-field__decrement"]}
|
|
||||||
>
|
|
||||||
<ArrowIcon style="transform: rotate(180deg);" />
|
|
||||||
</ColorChannelField.DecrementTrigger>
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorChannelField } from "@kobalte/core/color-channel-field";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorChannelField class={style["color-channel-field"]} channel="hue">
|
|
||||||
<ColorChannelField.Label class={style["color-channel-field__label"]}>
|
|
||||||
Hue
|
|
||||||
</ColorChannelField.Label>
|
|
||||||
<div class={style["color-channel-field__group"]}>
|
|
||||||
<ColorChannelField.Input class={style["color-channel-field__input"]} />
|
|
||||||
<ColorChannelField.IncrementTrigger
|
|
||||||
aria-label="Increment"
|
|
||||||
class={style["color-channel-field__increment"]}
|
|
||||||
>
|
|
||||||
<ArrowIcon />
|
|
||||||
</ColorChannelField.IncrementTrigger>
|
|
||||||
<ColorChannelField.DecrementTrigger
|
|
||||||
aria-label="Decrement"
|
|
||||||
class={style["color-channel-field__decrement"]}
|
|
||||||
>
|
|
||||||
<ArrowIcon style="transform: rotate(180deg);" />
|
|
||||||
</ColorChannelField.DecrementTrigger>
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The value provided to `defaultValue` or `value` should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string. The `channel` prop must also be provided to specify which color channel the field manipulates.
|
|
||||||
This must be one of the channels included in the color value, for example, for RGB colors, the "red", "green", and "blue" channels are available.
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
Saturation
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField defaultValue={parseColor("hsl(200, 98%, 39%)")} channel="saturation">
|
|
||||||
<ColorChannelField.Label>Saturation</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField defaultValue={parseColor("hsl(200, 98%, 39%)")} channel="saturation">
|
|
||||||
<ColorChannelField.Label>Saturation</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
Lightness
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
Lightness: 39%
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(200, 98%, 39%)"));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ColorChannelField value={value()} onChange={setValue}>
|
|
||||||
<ColorChannelField.Label>Lightness</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
<p>Lightness: {value().getChannelValue("lightness")}%</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(200, 98%, 39%)"));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ColorChannelField value={value()} onChange={setValue}>
|
|
||||||
<ColorChannelField.Label>Lightness</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
<p>Lightness: {value().getChannelValue("lightness")}%</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `ColorChannelField.Description` component can be used to associate additional help text with a color channel field.
|
|
||||||
|
|
||||||
Hue
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
Enter your favorite hue.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField defaultValue={parseColor("hsl(0, 98%, 39%)")} channel="hue">
|
|
||||||
<ColorChannelField.Label>Hue</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<ColorChannelField.Description>Enter your favorite hue.</ColorChannelField.Description>
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField defaultValue={parseColor("hsl(0, 98%, 39%)")} channel="hue">
|
|
||||||
<ColorChannelField.Label>Hue</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<ColorChannelField.Description>Enter your favorite hue.</ColorChannelField.Description>
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `ColorChannelField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the field as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Saturation
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
Hmm, I prefer 40% saturation.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(200, 30%, 39%)"));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ColorChannelField
|
|
||||||
value={value()}
|
|
||||||
channel="saturation"
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value().getChannelValue("saturation") !== 40 ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<ColorChannelField.Label>Saturation</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<ColorChannelField.ErrorMessage>Hmm, I prefer 40% saturation.</ColorChannelField.ErrorMessage>
|
|
||||||
</ColorChannelField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(200, 30%, 39%)"));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ColorChannelField
|
|
||||||
value={value()}
|
|
||||||
channel="saturation"
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value().getChannelValue("saturation") !== 40 ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<ColorChannelField.Label>Saturation</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<ColorChannelField.ErrorMessage>Hmm, I prefer 40% saturation.</ColorChannelField.ErrorMessage>
|
|
||||||
</ColorChannelField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The color channel field `name` prop along with `<ColorChannelField.HiddenInput/>` can be used for integration with HTML forms. Only the raw value is passed to the form.
|
|
||||||
|
|
||||||
If the formatted value is wanted (unrecommended) set the `name` attribute on `<ColorChannelField.Input/>`.
|
|
||||||
|
|
||||||
Hue
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<ColorChannelField name="hue" defaultValue={parseColor("hsl(10, 98%, 39%)")} channel="hue">
|
|
||||||
<ColorChannelField.Label>Hue</ColorChannelField.Label>
|
|
||||||
<ColorChannelField.HiddenInput />
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<ColorChannelField name="hue" defaultValue={parseColor("hsl(10, 98%, 39%)")} channel="hue">
|
|
||||||
<ColorChannelField.Label>Hue</ColorChannelField.Label>
|
|
||||||
<ColorChannelField.HiddenInput />
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger />
|
|
||||||
<ColorChannelField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Triggers
|
|
||||||
|
|
||||||
The color channel field supports optional increment/decrement triggers that are easily customizable.
|
|
||||||
|
|
||||||
Brightness
|
|
||||||
|
|
||||||
-+
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField defaultValue={parseColor("hsb(10, 98%, 50%)")} channel="brightness">
|
|
||||||
<ColorChannelField.Label>Brightness</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.DecrementTrigger class="custom-trigger">
|
|
||||||
-
|
|
||||||
</ColorChannelField.DecrementTrigger>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger class="custom-trigger">
|
|
||||||
+
|
|
||||||
</ColorChannelField.IncrementTrigger>
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorChannelField defaultValue={parseColor("hsb(10, 98%, 50%)")} channel="brightness">
|
|
||||||
<ColorChannelField.Label>Brightness</ColorChannelField.Label>
|
|
||||||
<div>
|
|
||||||
<ColorChannelField.DecrementTrigger class="custom-trigger">
|
|
||||||
-
|
|
||||||
</ColorChannelField.DecrementTrigger>
|
|
||||||
<ColorChannelField.Input />
|
|
||||||
<ColorChannelField.IncrementTrigger class="custom-trigger">
|
|
||||||
+
|
|
||||||
</ColorChannelField.IncrementTrigger>
|
|
||||||
</div>
|
|
||||||
</ColorChannelField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ColorChannelField
|
|
||||||
|
|
||||||
`ColorChannelField` is equivalent to the `Root` import from `@kobalte/core/color-channel-field`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `Color`<br> The controlled value of the field. |
|
|
||||||
| defaultValue | `Color`<br> The default value when initially rendered. Useful when you do not need to control the value. |
|
|
||||||
| colorSpace | `ColorSpace`<br> The color space that the field operates in. The `channel` must be in this color space. |
|
|
||||||
| onChange | `(value: Color) => void`<br> Event handler called when the value of the field changes. |
|
|
||||||
| minValue | `number`<br> The smallest value allowed in the number field. |
|
|
||||||
| maxValue | `number`<br> The largest value allowed in the number field. |
|
|
||||||
| step | `number`<br> Increment/Decrement step when using the triggers or the arrows on keyboard in the field. |
|
|
||||||
| largeStep | `number`<br> Increment/Decrement step when using the Page UP/Down keys in the field, defaults `10 * step`. |
|
|
||||||
| changeOnWheel | `boolean`<br> Whether to increment/decrement on wheel scroll inside the field. |
|
|
||||||
| format | `boolean`<br> Whether to format the input value. |
|
|
||||||
| name | `string`<br> The name of the ColorChannelField.HiddenInput of the field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the field should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must fill the field before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the field is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the field items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the field is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the field is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must fill the field before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the field is disabled. |
|
|
||||||
| data-readonly | Present when the field is read only. |
|
|
||||||
|
|
||||||
`ColorChannelField.Label`, `ColorChannelField.Input`, `ColorChannelField.HiddenInput`, `ColorChannelField.Description` and `ColorChannelField.ErrorMesssage` share the same data-attributes.
|
|
||||||
|
|
||||||
### ColorChannelField.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ColorChannelField` | `div` |
|
|
||||||
| `ColorChannelField.Label` | `label` |
|
|
||||||
| `ColorChannelField.Input` | `input` |
|
|
||||||
| `ColorChannelField.HiddenInput` | `input` |
|
|
||||||
| `ColorChannelField.IncrementTrigger` | `button` |
|
|
||||||
| `ColorChannelField.DecrementTrigger` | `button` |
|
|
||||||
| `ColorChannelField.Description` | `div` |
|
|
||||||
| `ColorChannelField.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
Previous[←Color Area](https://kobalte.dev/docs/core/components/color-area)Next[Color Field→](https://kobalte.dev/docs/core/components/color-field)
|
|
||||||
@ -1,336 +0,0 @@
|
|||||||
# Color Field
|
|
||||||
|
|
||||||
Allows users to enter and adjust a hex color value.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorField } from "@kobalte/core/color-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/color-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorField } from "@kobalte/core/color-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/color-field";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Support for parsing and formatting a hex color value.
|
|
||||||
- Validates keyboard entry as the user types so that only valid hex characters are accepted.
|
|
||||||
- Visual and ARIA labeling support.
|
|
||||||
- Required and invalid states exposed to assistive technology via ARIA.
|
|
||||||
- Support for description and error message help text linked to the input via ARIA.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The color field consists of:
|
|
||||||
|
|
||||||
- **ColorField**: The root container for the color field.
|
|
||||||
- **ColorField.Label**: The label that gives the user information on the color field.
|
|
||||||
- **ColorField.Input**: The native HTML input of the color field.
|
|
||||||
- **ColorField.Description**: The description that gives the user more information on the color field.
|
|
||||||
- **ColorField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the color field.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorField>
|
|
||||||
<ColorField.Label />
|
|
||||||
<ColorField.Input />
|
|
||||||
<ColorField.Description />
|
|
||||||
<ColorField.ErrorMessage />
|
|
||||||
</ColorField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorField>
|
|
||||||
<ColorField.Label />
|
|
||||||
<ColorField.Input />
|
|
||||||
<ColorField.Description />
|
|
||||||
<ColorField.ErrorMessage />
|
|
||||||
</ColorField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Favorite hex color
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorField } from "@kobalte/core/color-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorField class="color-field">
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
</ColorField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorField } from "@kobalte/core/color-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorField class="color-field">
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
</ColorField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultValue` prop.
|
|
||||||
|
|
||||||
Favorite hex color
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorField class="color-field" defaultValue="#7f007f">
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
</ColorField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorField class="color-field" defaultValue="#7f007f">
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
</ColorField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `value` prop can be used to make the value controlled. The `onChange` event is fired when the user type into the input and receive the new value.
|
|
||||||
|
|
||||||
Favorite hex color
|
|
||||||
|
|
||||||
Your favorite color is: #7f007f
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("#7f007f");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ColorField class="color-field" value={value()} onChange={setValue}>
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
</ColorField>
|
|
||||||
<p>Your favorite color is: {value()}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("#7f007f");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ColorField class="color-field" value={value()} onChange={setValue}>
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
</ColorField>
|
|
||||||
<p>Your favorite color is: {value()}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `ColorField.Description` component can be used to associate additional help text with a color field.
|
|
||||||
|
|
||||||
Favorite hex color
|
|
||||||
|
|
||||||
Choose the color you like the most.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorField class="color-field">
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
<ColorField.Description class="color-field__description">
|
|
||||||
Choose the color you like the most.
|
|
||||||
</ColorField.Description>
|
|
||||||
</ColorField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorField class="color-field">
|
|
||||||
<ColorField.Label class="color-field__label">Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input class="color-field__input" />
|
|
||||||
<ColorField.Description class="color-field__description">
|
|
||||||
Choose the color you like the most.
|
|
||||||
</ColorField.Description>
|
|
||||||
</ColorField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `ColorField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the color field as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Favorite hex color
|
|
||||||
|
|
||||||
Hmm, I prefer black.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("#7f007f");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ColorField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "#000000" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<ColorField.Label>Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input />
|
|
||||||
<ColorField.ErrorMessage>Hmm, I prefer black.</ColorField.ErrorMessage>
|
|
||||||
</ColorField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("#7f007f");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ColorField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "#000000" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<ColorField.Label>Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input />
|
|
||||||
<ColorField.ErrorMessage>Hmm, I prefer black.</ColorField.ErrorMessage>
|
|
||||||
</ColorField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The color field `name` prop can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Favorite hex color
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<ColorField name="favorite-color">
|
|
||||||
<ColorField.Label>Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input />
|
|
||||||
</ColorField>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<ColorField name="favorite-color">
|
|
||||||
<ColorField.Label>Favorite hex color</ColorField.Label>
|
|
||||||
<ColorField.Input />
|
|
||||||
</ColorField>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ColorField
|
|
||||||
|
|
||||||
`ColorField` is equivalent to the `Root` import from `@kobalte/core/color-field`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the color field to check. |
|
|
||||||
| defaultValue | `string`<br> The default value when initially rendered. Useful when you do not need to control the value. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value of the color field changes. |
|
|
||||||
| name | `string`<br> The name of the color field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the color field should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must fill the color field before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the color field is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the color field items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the color field is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the color field is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must fill the color field before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the color field is disabled. |
|
|
||||||
| data-readonly | Present when the color field is read only. |
|
|
||||||
|
|
||||||
`ColorField.Label`, `ColorField.Input`, `ColorField.Description` and `ColorField.ErrorMesssage` share the same data-attributes.
|
|
||||||
|
|
||||||
### ColorField.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ColorField` | `div` |
|
|
||||||
| `ColorField.Label` | `label` |
|
|
||||||
| `ColorField.Input` | `input` |
|
|
||||||
| `ColorField.Description` | `div` |
|
|
||||||
| `ColorField.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
Previous[←Color Channel Field](https://kobalte.dev/docs/core/components/color-channel-field)Next[Color Slider→](https://kobalte.dev/docs/core/components/color-slider)
|
|
||||||
@ -1,409 +0,0 @@
|
|||||||
# Color Slider
|
|
||||||
|
|
||||||
Adjusts an individual channel of a color value.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
// or
|
|
||||||
import { Root, Track, ... } from "@kobalte/core/color-slider";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
// or
|
|
||||||
import { Root, Track, ... } from "@kobalte/core/color-slider";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Localized color descriptions for screen reader users.
|
|
||||||
- Support for adjusting a single channel of RGBA, HSLA and HSBA colors, in both horizontal and vertical orientations.
|
|
||||||
- Support click or touch on track to change value.
|
|
||||||
- Support right or left direction.
|
|
||||||
- Support for custom value label.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The color slider consists of:
|
|
||||||
|
|
||||||
- **ColorSlider:** The root container for the color slider.
|
|
||||||
- **ColorSlider.Track:** The component that visually represents the color slider track.
|
|
||||||
- **ColorSlider.Thumb:** The thumb that is used to visually indicate a value in the color slider.
|
|
||||||
- **ColorSlider.Input:** The native html input that is visually hidden in the color slider thumb.
|
|
||||||
- **ColorSlider.Label:** The label that gives the user information on the color slider.
|
|
||||||
- **ColorSlider.ValueLabel:** The accessible label text representing the current value in a human-readable format.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorSlider>
|
|
||||||
<ColorSlider.Label />
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
<ColorSlider.Track>
|
|
||||||
<ColorSlider.Thumb>
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorSlider>
|
|
||||||
<ColorSlider.Label />
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
<ColorSlider.Track>
|
|
||||||
<ColorSlider.Thumb>
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Blue
|
|
||||||
|
|
||||||
197
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" channel="blue">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Blue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" channel="blue">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Blue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
The value provided to `defaultValue` or `value` should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string. The `channel` prop must also be provided to specify which color channel the slider should display.
|
|
||||||
This must be one of the channels included in the color value, for example, for RGB colors, the "red", "green", and "blue" channels are available.
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
Hue
|
|
||||||
|
|
||||||
0°
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" defaultValue={parseColor("hsl(0, 100%, 50%)")} channel="hue">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Hue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" defaultValue={parseColor("hsl(0, 100%, 50%)")} channel="hue">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Hue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
Hue
|
|
||||||
|
|
||||||
0°
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [value, setValue] = createSignal(parseColor('hsl(0, 100%, 50%)'));
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" value={value()} onChange={setValue} channel="hue">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Hue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [value, setValue] = createSignal(parseColor('hsl(0, 100%, 50%)'));
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" value={value()} onChange={setValue} channel="hue">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Hue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vertical Slider
|
|
||||||
|
|
||||||
Red
|
|
||||||
|
|
||||||
255
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" defaultValue={parseColor('#ff00ff')} channel="red" orientation="vertical">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Hue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" defaultValue={parseColor('#ff00ff')} channel="red" orientation="vertical">
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.Label>Hue</ColorSlider.Label>
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Value Label
|
|
||||||
|
|
||||||
rgb(255, 0, 255)
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" defaultValue={parseColor("#ff00ff")} channel="green" getValueLabel={param => `${param.toFormat("rgb")}`}>
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSlider } from "@kobalte/core/color-slider";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSlider class="ColorSliderRoot" defaultValue={parseColor("#ff00ff")} channel="green" getValueLabel={param => `${param.toFormat("rgb")}`}>
|
|
||||||
<div class="ColorSliderLabel">
|
|
||||||
<ColorSlider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<ColorSlider.Track class="ColorSliderTrack">
|
|
||||||
<ColorSlider.Thumb class="ColorSliderThumb">
|
|
||||||
<ColorSlider.Input />
|
|
||||||
</ColorSlider.Thumb>
|
|
||||||
</ColorSlider.Track>
|
|
||||||
</ColorSlider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ColorSlider
|
|
||||||
|
|
||||||
`ColorSlider` is equivalent to the `Root` import from `@kobalte/core/color-slider`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `Color`<br> The controlled value of the slider. Must be used in conjunction with `onChange`. |
|
|
||||||
| defaultValue | `Color`<br> The value of the slider when initially rendered. Use when you do not need to control the state of the slider. |
|
|
||||||
| channel | `ColorChannel`<br> The color channel that the slider manipulates. |
|
|
||||||
| colorSpace | `ColorSpace`<br> The color space that the slider operates in. The `channel` must be in this color space. |
|
|
||||||
| onChange | `(value: Color) => void`<br> Event handler called when the value changes. |
|
|
||||||
| onChangeEnd | `(value: Color) => void`<br> Event handler called when the value changes at the end of an interaction. |
|
|
||||||
| getValueLabel | `(param: Color) => string`<br> A function to get the accessible label text representing the current value in a human-readable format. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The orientation of the slider. |
|
|
||||||
| name | `string`<br> The name of the slider, used when submitting an HTML form. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the slider should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check a radio group item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the radio group items can be selected but not changed by the user. |
|
|
||||||
| translations | `ColorIntlTranslations`<br> Localization strings. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Present when the slider has horizontal orientation. |
|
|
||||||
| data-orientation='vertical' | Present when the slider has vertical orientation. |
|
|
||||||
| data-valid | Present when the slider is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the slider is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must slider an item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the slider is disabled. |
|
|
||||||
| data-readonly | Present when the slider is read only. |
|
|
||||||
|
|
||||||
`ColorSlider.ValueLabel`, `ColorSlider.Input`, `ColorSlider.Thumb` and `ColorSlider.Track` share the same data-attributes.
|
|
||||||
|
|
||||||
### ColorSlider.Thumb
|
|
||||||
|
|
||||||
The current color is available on the thumb using the custom css property `--kb-color-current`.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ColorSlider` | `div` |
|
|
||||||
| `ColorSlider.Track` | `div` |
|
|
||||||
| `ColorSlider.Thumb` | `span` |
|
|
||||||
| `ColorSlider.Input` | `input` |
|
|
||||||
| `ColorSlider.ValueLabel` | `div` |
|
|
||||||
| `ColorSlider.Label` | `label` |
|
|
||||||
| `ColorSlider.Description` | `div` |
|
|
||||||
| `ColorSlider.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `PageUp` | Increases the value of the thumb by a larger step. |
|
|
||||||
| `PageDown` | Decreases the value of the thumb by a larger step. |
|
|
||||||
| `ArrowDown` | Decreases the value of the thumb by the step amount. |
|
|
||||||
| `ArrowUp` | Increases the value of the thumb by the step amount. |
|
|
||||||
| `ArrowRight` | Increments/decrements by the step value depending on `orientation`. |
|
|
||||||
| `ArrowLeft` | Increments/decrements by the step value depending on `orientation`. |
|
|
||||||
| `Home` | Sets the value of the thumb to the minimum value. |
|
|
||||||
| `End` | Sets the value of the thumb to the maximum value. |
|
|
||||||
|
|
||||||
Previous[←Color Field](https://kobalte.dev/docs/core/components/color-field)Next[Color Swatch→](https://kobalte.dev/docs/core/components/color-swatch)
|
|
||||||
@ -1,153 +0,0 @@
|
|||||||
# Color Swatch
|
|
||||||
|
|
||||||
Displays a preview of a selected color.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/color-swatch";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/color-swatch";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Localized color descriptions for screen reader users.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The color swatch consists of:
|
|
||||||
|
|
||||||
- **ColorSwatch:** The root container for the color swatch.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorSwatch />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorSwatch />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSwatch class="ColorSwatchRoot" value={parseColor("hsl(200, 98%, 39%)")} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSwatch class="ColorSwatchRoot" value={parseColor("hsl(200, 98%, 39%)")} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
ColorSwatch accepts a value via the `value` prop. The value should be `Color` object. You can obtain a Color object by using the `parseColor` function to parse a color from a string.
|
|
||||||
|
|
||||||
### Value
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSwatch class="ColorSwatchRoot" value={parseColor("#7f0000")} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSwatch class="ColorSwatchRoot" value={parseColor("#7f0000")} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Color Name
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSwatch class="ColorSwatchRoot" value={parseColor("hsl(200, 98%, 39%)")} colorName="Kobalte blue" />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorSwatch } from "@kobalte/core/color-swatch";
|
|
||||||
import { parseColor } from "@kobalte/utils";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorSwatch class="ColorSwatchRoot" value={parseColor("hsl(200, 98%, 39%)")} colorName="Kobalte blue" />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ColorSwatch
|
|
||||||
|
|
||||||
`ColorSwatch` is equivalent to the `Root` import from `@kobalte/core/color-swatch`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `Color`<br> The color value to display in the swatch. |
|
|
||||||
| colorName | `string`<br> A localized accessible name for the color. By default, a description is generated from the color value, but this can be overridden if you have a more specific color name (e.g. Pantone colors). |
|
|
||||||
| translations | `ColorSwatchIntlTranslations`<br> Localization strings. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ColorSwatch` | `div` |
|
|
||||||
|
|
||||||
Previous[←Color Slider](https://kobalte.dev/docs/core/components/color-slider)Next[Color Wheel→](https://kobalte.dev/docs/core/components/color-wheel)
|
|
||||||
@ -1,408 +0,0 @@
|
|||||||
# Color Wheel
|
|
||||||
|
|
||||||
Allows users to adjust the hue of an HSL or HSB color value on a circular track.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorWheel } from "@kobalte/core/color-wheel";
|
|
||||||
// or
|
|
||||||
import { Root, Track, ... } from "@kobalte/core/color-wheel";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ColorWheel } from "@kobalte/core/color-wheel";
|
|
||||||
// or
|
|
||||||
import { Root, Track, ... } from "@kobalte/core/color-wheel";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Support for adjusting the hue of an HSL or HSB color value.
|
|
||||||
- Support click or touch on track to change value.
|
|
||||||
- Support right or left direction.
|
|
||||||
- Support for custom value label.
|
|
||||||
- Localized color descriptions for screen reader users.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The color wheel consists of:
|
|
||||||
|
|
||||||
- **ColorWheel:** The root container for the color wheel.
|
|
||||||
- **ColorWheel.Track:** The component that visually represents the color wheel track.
|
|
||||||
- **ColorWheel.Thumb:** The thumb that is used to visually indicate a value in the color wheel.
|
|
||||||
- **ColorWheel.Input:** The native html input that is visually hidden in the color wheel thumb.
|
|
||||||
- **ColorWheel.Label:** The label that gives the user information on the color wheel.
|
|
||||||
- **ColorWheel.ValueLabel:** The accessible label text representing the current value in a human-readable format.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorWheel>
|
|
||||||
<ColorWheel.Label />
|
|
||||||
<ColorWheel.ValueLabel />
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorWheel>
|
|
||||||
<ColorWheel.Label />
|
|
||||||
<ColorWheel.ValueLabel />
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorWheel } from "@kobalte/core/color-wheel";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorWheel class="ColorWheelRoot">
|
|
||||||
<ColorWheel.Label class="ColorWheelLabel">Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track class="ColorWheelTrack">
|
|
||||||
<ColorWheel.Thumb class="ColorWheelThumb">
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorWheel } from "@kobalte/core/color-wheel";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorWheel class="ColorWheelRoot">
|
|
||||||
<ColorWheel.Label class="ColorWheelLabel">Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track class="ColorWheelTrack">
|
|
||||||
<ColorWheel.Thumb class="ColorWheelThumb">
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
By default, `ColorWheel` is uncontrolled with a default value of red (hue = 0). You can change the default value using the `defaultValue` prop.
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorWheel } from "@kobalte/core/color-wheel";
|
|
||||||
import { parseColor } from "@kobalte/core";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorWheel defaultValue={parseColor("hsl(80, 100%, 50%)")}>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ColorWheel } from "@kobalte/core/color-wheel";
|
|
||||||
import { parseColor } from "@kobalte/core";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ColorWheel defaultValue={parseColor("hsl(80, 100%, 50%)")}>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
A `ColorWheel` can be made controlled using the `value` prop. The `onChange` event is fired when the user drags the thumb and receive the new value.
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
Current color value: hsl(0 100% 50%)
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledValueExample() {
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)"));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ColorWheel value={value()} onChange={setValue}>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
<p>Current color value: {value().toString("hsl")}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledValueExample() {
|
|
||||||
const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)"));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ColorWheel value={value()} onChange={setValue}>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
<p>Current color value: {value().toString("hsl")}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Thickness
|
|
||||||
|
|
||||||
The `thickness` prop controls the width of the `ColorWheel`'s circular track. This prop is required.
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorWheel thickness={60}>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorWheel thickness={60}>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Value Label
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
hsla(0 100% 50% / 1)
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorWheel
|
|
||||||
getValueLabel={color =>
|
|
||||||
color
|
|
||||||
.toFormat("hsl")
|
|
||||||
.withChannelValue("saturation", 100)
|
|
||||||
.withChannelValue("lightness", 50)
|
|
||||||
.withChannelValue("alpha", 1)
|
|
||||||
.toString()
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
<div>
|
|
||||||
<ColorWheel.ValueLabel />
|
|
||||||
</div>
|
|
||||||
</ColorWheel>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ColorWheel
|
|
||||||
getValueLabel={color =>
|
|
||||||
color
|
|
||||||
.toFormat("hsl")
|
|
||||||
.withChannelValue("saturation", 100)
|
|
||||||
.withChannelValue("lightness", 50)
|
|
||||||
.withChannelValue("alpha", 1)
|
|
||||||
.toString()
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ColorWheel.Label>Label</ColorWheel.Label>
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
<div>
|
|
||||||
<ColorWheel.ValueLabel />
|
|
||||||
</div>
|
|
||||||
</ColorWheel>
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
`ColorWheel` supports the `name` prop for integration with HTML forms.
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<ColorWheel name="hue">
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<ColorWheel name="hue">
|
|
||||||
<ColorWheel.Track>
|
|
||||||
<ColorWheel.Thumb>
|
|
||||||
<ColorWheel.Input />
|
|
||||||
</ColorWheel.Thumb>
|
|
||||||
</ColorWheel.Track>
|
|
||||||
</ColorWheel>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ColorWheel
|
|
||||||
|
|
||||||
`ColorWheel` is equivalent to the `Root` import from `@kobalte/core/color-wheel`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `Color`<br> The controlled value of the color wheel. Must be used in conjunction with `onChange`. |
|
|
||||||
| defaultValue | `Color`<br> The value of the color wheel when initially rendered. Use when you do not need to control the state of the color wheel. |
|
|
||||||
| thickness | `number`<br> The thickness of the track `0-100`. |
|
|
||||||
| onChange | `(value: Color) => void`<br> Event handler called when the value changes. |
|
|
||||||
| onChangeEnd | `(value: Color) => void`<br> Event handler called when the value changes at the end of an interaction. |
|
|
||||||
| getValueLabel | `(param: Color) => string`<br> A function to get the accessible label text representing the current value in a human-readable format. |
|
|
||||||
| name | `string`<br> The name of the color wheel, used when submitting an HTML form. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the color wheel should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check a radio group item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the color wheel is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the color wheel items can be selected but not changed by the user. |
|
|
||||||
| translations | `ColorIntlTranslations`<br> Localization strings. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the color wheel is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the color wheel is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the color wheel is required. |
|
|
||||||
| data-disabled | Present when the color wheel is disabled. |
|
|
||||||
| data-readonly | Present when the color wheel is read only. |
|
|
||||||
|
|
||||||
`ColorWheel.ValueLabel`, `ColorWheel.Input`, `ColorWheel.Thumb` and `ColorWheel.Track` share the same data-attributes.
|
|
||||||
|
|
||||||
### ColorWheel.Thumb
|
|
||||||
|
|
||||||
The current color is available on the thumb using the custom css property `--kb-color-current`.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ColorWheel` | `div` |
|
|
||||||
| `ColorWheel.Track` | `div` |
|
|
||||||
| `ColorWheel.Thumb` | `span` |
|
|
||||||
| `ColorWheel.Input` | `input` |
|
|
||||||
| `ColorWheel.ValueLabel` | `div` |
|
|
||||||
| `ColorWheel.Label` | `label` |
|
|
||||||
| `ColorWheel.Description` | `div` |
|
|
||||||
| `ColorWheel.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `PageUp` | Increments the value of the thumb by a larger step. |
|
|
||||||
| `PageDown` | Decrements the value of the thumb by a larger step. |
|
|
||||||
| `ArrowDown` | Decrements the value of the thumb by the step amount. |
|
|
||||||
| `ArrowUp` | Increments the value of the thumb by the step amount. |
|
|
||||||
| `ArrowRight` | Increments the value of the thumb by the step value. |
|
|
||||||
| `ArrowLeft` | Decrements the value of the thumb by the step value. |
|
|
||||||
| `Home` | Sets the value of the thumb to the minimum value. |
|
|
||||||
| `End` | Sets the value of the thumb to the maximum value. |
|
|
||||||
|
|
||||||
Previous[←Color Swatch](https://kobalte.dev/docs/core/components/color-swatch)Next[Combobox→](https://kobalte.dev/docs/core/components/combobox)
|
|
||||||
@ -1,669 +0,0 @@
|
|||||||
# Context Menu
|
|
||||||
|
|
||||||
Displays a menu located at the pointer, triggered by a right-click or a long-press.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ContextMenu } from "@kobalte/core/context-menu";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/context-menu";
|
|
||||||
// or (deprecated)
|
|
||||||
import { ContextMenu } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ContextMenu } from "@kobalte/core/context-menu";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/context-menu";
|
|
||||||
// or (deprecated)
|
|
||||||
import { ContextMenu } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follows the [WAI ARIA Menu](https://www.w3.org/WAI/ARIA/apg/patterns/menu/) design pattern.
|
|
||||||
- Triggers with a long-press on touch devices.
|
|
||||||
- Supports modal and non-modal modes.
|
|
||||||
- Supports submenus.
|
|
||||||
- Supports items, labels, groups of items.
|
|
||||||
- Supports checkable items (single or multiple) with optional indeterminate state.
|
|
||||||
- Support disabled items.
|
|
||||||
- Complex item labeling support for accessibility.
|
|
||||||
- Keyboard opening and navigation support.
|
|
||||||
- Automatic scrolling support during keyboard navigation.
|
|
||||||
- Typeahead to allow focusing items by typing text.
|
|
||||||
- Optionally render a pointing arrow.
|
|
||||||
- Focus is fully managed.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The context menu consists of:
|
|
||||||
|
|
||||||
- **ContextMenu:** The root container for a context menu.
|
|
||||||
- **ContextMenu.Trigger:** The button that toggles the menu.
|
|
||||||
- **ContextMenu.Icon:** A small icon that can be displayed inside the menu trigger as a visual affordance for the fact it can be open.
|
|
||||||
- **ContextMenu.Portal:** Portals its children into the `body` when the menu is open.
|
|
||||||
- **ContextMenu.Content:** Contains the content to be rendered when the menu is open.
|
|
||||||
- **ContextMenu.Arrow:** An optional arrow element to render alongside the menu content.
|
|
||||||
- **ContextMenu.Separator:** Used to visually separate items in the menu.
|
|
||||||
- **ContextMenu.Group:** Used to group multiple items. Use in conjunction with `ContextMenu.GroupLabel` to ensure good accessibility via automatic labelling.
|
|
||||||
- **ContextMenu.GroupLabel:** Used to render the label of a group. It won't be focusable using arrow keys.
|
|
||||||
- **ContextMenu.Sub:** Contains all the parts of a submenu.
|
|
||||||
- **ContextMenu.SubTrigger:** An item that opens a submenu. Must be rendered inside `ContextMenu.Sub`.
|
|
||||||
- **ContextMenu.SubContent:** The component that pops out when a submenu is open. Must be rendered inside `ContextMenu.Sub`.
|
|
||||||
|
|
||||||
The menu item consists of:
|
|
||||||
|
|
||||||
- **ContextMenu.Item:** An item of the select.
|
|
||||||
- **ContextMenu.ItemLabel:** An accessible label to be announced for the item.
|
|
||||||
- **ContextMenu.ItemDescription:** An optional accessible description to be announced for the item.
|
|
||||||
- **ContextMenu.ItemIndicator:** The visual indicator rendered when the item is checked.
|
|
||||||
|
|
||||||
The checkable menu item consists of:
|
|
||||||
|
|
||||||
- **ContextMenu.RadioGroup:** Used to group multiple `ContextMenu.RadioItem`s and manage the selection.
|
|
||||||
- **ContextMenu.RadioItem:** An item that can be controlled and rendered like a radio.
|
|
||||||
- **ContextMenu.CheckboxItem:** An item that can be controlled and rendered like a checkbox.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ContextMenu>
|
|
||||||
<ContextMenu.Trigger>
|
|
||||||
<ContextMenu.Icon />
|
|
||||||
</ContextMenu.Trigger>
|
|
||||||
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.Content>
|
|
||||||
<ContextMenu.Arrow />
|
|
||||||
|
|
||||||
<ContextMenu.Item>
|
|
||||||
<ContextMenu.ItemLabel />
|
|
||||||
<ContextMenu.ItemDescription />
|
|
||||||
</ContextMenu.Item>
|
|
||||||
|
|
||||||
<ContextMenu.Group>
|
|
||||||
<ContextMenu.GroupLabel />
|
|
||||||
<ContextMenu.Item />
|
|
||||||
</ContextMenu.Group>
|
|
||||||
|
|
||||||
<ContextMenu.CheckboxItem>
|
|
||||||
<ContextMenu.ItemIndicator />
|
|
||||||
</ContextMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<ContextMenu.RadioGroup>
|
|
||||||
<ContextMenu.RadioItem>
|
|
||||||
<ContextMenu.ItemIndicator />
|
|
||||||
</ContextMenu.RadioItem>
|
|
||||||
</ContextMenu.RadioGroup>
|
|
||||||
|
|
||||||
<ContextMenu.Sub>
|
|
||||||
<ContextMenu.SubTrigger />
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.SubContent />
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu.Sub>
|
|
||||||
|
|
||||||
<ContextMenu.Separator />
|
|
||||||
</ContextMenu.Content>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ContextMenu>
|
|
||||||
<ContextMenu.Trigger>
|
|
||||||
<ContextMenu.Icon />
|
|
||||||
</ContextMenu.Trigger>
|
|
||||||
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.Content>
|
|
||||||
<ContextMenu.Arrow />
|
|
||||||
|
|
||||||
<ContextMenu.Item>
|
|
||||||
<ContextMenu.ItemLabel />
|
|
||||||
<ContextMenu.ItemDescription />
|
|
||||||
</ContextMenu.Item>
|
|
||||||
|
|
||||||
<ContextMenu.Group>
|
|
||||||
<ContextMenu.GroupLabel />
|
|
||||||
<ContextMenu.Item />
|
|
||||||
</ContextMenu.Group>
|
|
||||||
|
|
||||||
<ContextMenu.CheckboxItem>
|
|
||||||
<ContextMenu.ItemIndicator />
|
|
||||||
</ContextMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<ContextMenu.RadioGroup>
|
|
||||||
<ContextMenu.RadioItem>
|
|
||||||
<ContextMenu.ItemIndicator />
|
|
||||||
</ContextMenu.RadioItem>
|
|
||||||
</ContextMenu.RadioGroup>
|
|
||||||
|
|
||||||
<ContextMenu.Sub>
|
|
||||||
<ContextMenu.SubTrigger />
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.SubContent />
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu.Sub>
|
|
||||||
|
|
||||||
<ContextMenu.Separator />
|
|
||||||
</ContextMenu.Content>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Right click here.
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ContextMenu } from "@kobalte/core/context-menu";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [showGitLog, setShowGitLog] = createSignal(true);
|
|
||||||
const [showHistory, setShowHistory] = createSignal(false);
|
|
||||||
const [branch, setBranch] = createSignal("main");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ContextMenu>
|
|
||||||
<ContextMenu.Trigger class="context-menu__trigger">
|
|
||||||
Right click here.
|
|
||||||
</ContextMenu.Trigger>
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.Content class="context-menu__content">
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Commit <div class="context-menu__item-right-slot">⌘+K</div>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Push <div class="context-menu__item-right-slot">⇧+⌘+K</div>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item" disabled>
|
|
||||||
Update Project <div class="context-menu__item-right-slot">⌘+T</div>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<ContextMenu.SubTrigger class="context-menu__sub-trigger">
|
|
||||||
GitHub
|
|
||||||
<div class="context-menu__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</ContextMenu.SubTrigger>
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.SubContent class="context-menu__sub-content">
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Create Pull Request…
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
View Pull Requests
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Sync Fork
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Separator class="context-menu__separator" />
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Open on GitHub
|
|
||||||
</ContextMenu.Item>
|
|
||||||
</ContextMenu.SubContent>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu.Sub>
|
|
||||||
|
|
||||||
<ContextMenu.Separator class="context-menu__separator" />
|
|
||||||
|
|
||||||
<ContextMenu.CheckboxItem
|
|
||||||
class="context-menu__checkbox-item"
|
|
||||||
checked={showGitLog()}
|
|
||||||
onChange={setShowGitLog}
|
|
||||||
>
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
Show Git Log
|
|
||||||
</ContextMenu.CheckboxItem>
|
|
||||||
<ContextMenu.CheckboxItem
|
|
||||||
class="context-menu__checkbox-item"
|
|
||||||
checked={showHistory()}
|
|
||||||
onChange={setShowHistory}
|
|
||||||
>
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
Show History
|
|
||||||
</ContextMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<ContextMenu.Separator class="context-menu__separator" />
|
|
||||||
|
|
||||||
<ContextMenu.Group>
|
|
||||||
<ContextMenu.GroupLabel class="context-menu__group-label">
|
|
||||||
Branches
|
|
||||||
</ContextMenu.GroupLabel>
|
|
||||||
<ContextMenu.RadioGroup value={branch()} onChange={setBranch}>
|
|
||||||
<ContextMenu.RadioItem class="context-menu__radio-item" value="main">
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
main
|
|
||||||
</ContextMenu.RadioItem>
|
|
||||||
<ContextMenu.RadioItem class="context-menu__radio-item" value="develop">
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
develop
|
|
||||||
</ContextMenu.RadioItem>
|
|
||||||
</ContextMenu.RadioGroup>
|
|
||||||
</ContextMenu.Group>
|
|
||||||
</ContextMenu.Content>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ContextMenu } from "@kobalte/core/context-menu";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [showGitLog, setShowGitLog] = createSignal(true);
|
|
||||||
const [showHistory, setShowHistory] = createSignal(false);
|
|
||||||
const [branch, setBranch] = createSignal("main");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ContextMenu>
|
|
||||||
<ContextMenu.Trigger class="context-menu__trigger">
|
|
||||||
Right click here.
|
|
||||||
</ContextMenu.Trigger>
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.Content class="context-menu__content">
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Commit <div class="context-menu__item-right-slot">⌘+K</div>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Push <div class="context-menu__item-right-slot">⇧+⌘+K</div>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item" disabled>
|
|
||||||
Update Project <div class="context-menu__item-right-slot">⌘+T</div>
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<ContextMenu.SubTrigger class="context-menu__sub-trigger">
|
|
||||||
GitHub
|
|
||||||
<div class="context-menu__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</ContextMenu.SubTrigger>
|
|
||||||
<ContextMenu.Portal>
|
|
||||||
<ContextMenu.SubContent class="context-menu__sub-content">
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Create Pull Request…
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
View Pull Requests
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Sync Fork
|
|
||||||
</ContextMenu.Item>
|
|
||||||
<ContextMenu.Separator class="context-menu__separator" />
|
|
||||||
<ContextMenu.Item class="context-menu__item">
|
|
||||||
Open on GitHub
|
|
||||||
</ContextMenu.Item>
|
|
||||||
</ContextMenu.SubContent>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu.Sub>
|
|
||||||
|
|
||||||
<ContextMenu.Separator class="context-menu__separator" />
|
|
||||||
|
|
||||||
<ContextMenu.CheckboxItem
|
|
||||||
class="context-menu__checkbox-item"
|
|
||||||
checked={showGitLog()}
|
|
||||||
onChange={setShowGitLog}
|
|
||||||
>
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
Show Git Log
|
|
||||||
</ContextMenu.CheckboxItem>
|
|
||||||
<ContextMenu.CheckboxItem
|
|
||||||
class="context-menu__checkbox-item"
|
|
||||||
checked={showHistory()}
|
|
||||||
onChange={setShowHistory}
|
|
||||||
>
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
Show History
|
|
||||||
</ContextMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<ContextMenu.Separator class="context-menu__separator" />
|
|
||||||
|
|
||||||
<ContextMenu.Group>
|
|
||||||
<ContextMenu.GroupLabel class="context-menu__group-label">
|
|
||||||
Branches
|
|
||||||
</ContextMenu.GroupLabel>
|
|
||||||
<ContextMenu.RadioGroup value={branch()} onChange={setBranch}>
|
|
||||||
<ContextMenu.RadioItem class="context-menu__radio-item" value="main">
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
main
|
|
||||||
</ContextMenu.RadioItem>
|
|
||||||
<ContextMenu.RadioItem class="context-menu__radio-item" value="develop">
|
|
||||||
<ContextMenu.ItemIndicator class="context-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</ContextMenu.ItemIndicator>
|
|
||||||
develop
|
|
||||||
</ContextMenu.RadioItem>
|
|
||||||
</ContextMenu.RadioGroup>
|
|
||||||
</ContextMenu.Group>
|
|
||||||
</ContextMenu.Content>
|
|
||||||
</ContextMenu.Portal>
|
|
||||||
</ContextMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Origin-aware animations
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-popper-content-transform-origin` which can be used to animate the content from its computed origin.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.context-menu__content,
|
|
||||||
.context-menu__sub-content {
|
|
||||||
transform-origin: var(--kb-menu-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-menu__content[data-expanded],
|
|
||||||
.context-menu__sub-content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.context-menu__content,
|
|
||||||
.context-menu__sub-content {
|
|
||||||
transform-origin: var(--kb-menu-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.context-menu__content[data-expanded],
|
|
||||||
.context-menu__sub-content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ContextMenu
|
|
||||||
|
|
||||||
`ContextMenu` is equivalent to the `Root` import from `@kobalte/core/context-menu` (and deprecated `ContextMenu.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the menu changes. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| modal | `boolean`<br> Whether the menu should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the menu content. <br> \- elements outside the menu content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the menu is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the menu (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
`ContextMenu` also accepts the following props to customize the placement of the `ContextMenu.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| placement | `Placement`<br> The placement of the menu content. |
|
|
||||||
| gutter | `number`<br> The distance between the menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the menu content along the trigger element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the menu content when it overflows the viewport:<br> \- If a `boolean`, specifies whether the menu content should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the menu content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the menu content can overlap the trigger element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the menu content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the menu content should fit the viewport. If this is set to true, the menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the menu content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the menu content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### ContextMenu.Trigger
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| disabled | `boolean`<br> Whether the context menu trigger is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the menu is open. |
|
|
||||||
| data-closed | Present when the menu is close. |
|
|
||||||
| data-disabled | Present when the trigger is disabled. |
|
|
||||||
|
|
||||||
`ContextMenu.Icon`, `ContextMenu.Content`, `ContextMenu.SubTrigger` and `ContextMenu.SubContent` share the same `data-expanded` attribute.
|
|
||||||
|
|
||||||
### ContextMenu.Content
|
|
||||||
|
|
||||||
The popper positioner will copy the same `z-index` as the `ContextMenu.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
### ContextMenu.Arrow
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| size | `number`<br> The size of the arrow. |
|
|
||||||
|
|
||||||
### ContextMenu.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.ItemLabel` part if provided, or fallback to the .textContent of the `ContextMenu.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is activated. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
`ContextMenu.ItemLabel`, `ContextMenu.ItemDescription` and `ContextMenu.ItemIndicator` shares the same data-attributes.
|
|
||||||
|
|
||||||
### ContextMenu.ItemIndicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### ContextMenu.RadioGroup
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the menu radio item to check. |
|
|
||||||
| defaultValue | `string`<br> The value of the menu radio item that should be checked when initially rendered. Useful when you do not need to control the state of the radio group. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value changes. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled or not. |
|
|
||||||
|
|
||||||
### ContextMenu.RadioItem
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The value of the menu item radio. |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.ItemLabel` part if provided, or fallback to the .textContent of the `ContextMenu.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is checked. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-checked | Present when the item is checked. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### ContextMenu.CheckboxItem
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `boolean`<br> The controlled checked state of the item. |
|
|
||||||
| defaultChecked | `boolean`<br> The default checked state when initially rendered. Useful when you do not need to control the checked state. |
|
|
||||||
| onChange | `(checked: boolean) => void`<br> Event handler called when the checked state of the item changes. |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.ItemLabel` part if provided, or fallback to the .textContent of the `ContextMenu.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| indeterminate | `boolean`<br> Whether the item is in an indeterminate state. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is checked/unchecked. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-indeterminate | Present when the item is in an indeterminate state. |
|
|
||||||
| data-checked | Present when the item is checked. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### ContextMenu.Sub
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the sub menu. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the sub menu changes. |
|
|
||||||
|
|
||||||
`ContextMenu.Sub` also accepts the following props to customize the placement of the `ContextMenu.SubContent`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the trigger element's DOMRect. |
|
|
||||||
| gutter | `number`<br> The distance between the sub menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the sub menu content along the trigger element. |
|
|
||||||
| slide | `boolean`<br> Whether the sub menu content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the sub menu content can overlap the trigger element when it overflows. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the sub menu content should fit the viewport. If this is set to true, the sub menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the sub menu content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the sub menu content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the sub menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### ContextMenu.SubTrigger
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `ContextMenu.SubTrigger`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the sub menu trigger is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### ContextMenu.SubContent
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ContextMenu` | none |
|
|
||||||
| `ContextMenu.Trigger` | `div` |
|
|
||||||
| `ContextMenu.Icon` | `div` |
|
|
||||||
| `ContextMenu.Portal` | `Portal` |
|
|
||||||
| `ContextMenu.Content` | `div` |
|
|
||||||
| `ContextMenu.Arrow` | `div` |
|
|
||||||
| `ContextMenu.Separator` | `hr` |
|
|
||||||
| `ContextMenu.Group` | `div` |
|
|
||||||
| `ContextMenu.GroupLabel` | `span` |
|
|
||||||
| `ContextMenu.Sub` | none |
|
|
||||||
| `ContextMenu.SubTrigger` | `div` |
|
|
||||||
| `ContextMenu.SubContent` | `div` |
|
|
||||||
| `ContextMenu.Item` | `div` |
|
|
||||||
| `ContextMenu.ItemLabel` | `div` |
|
|
||||||
| `ContextMenu.ItemDescription` | `div` |
|
|
||||||
| `ContextMenu.ItemIndicator` | `div` |
|
|
||||||
| `ContextMenu.RadioGroup` | `div` |
|
|
||||||
| `ContextMenu.RadioItem` | `div` |
|
|
||||||
| `ContextMenu.CheckboxItem` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on an item, activates the item. |
|
|
||||||
| `Enter` | When focus is on an item, activates the item. |
|
|
||||||
| `ArrowDown` | When focus is on an item, moves focus to the next item. |
|
|
||||||
| `ArrowUp` | When focus is on an item, moves focus to the previous item. |
|
|
||||||
| `ArrowRight` / `ArrowLeft` | When focus is on a sub menu trigger, opens or closes the submenu depending on reading direction. |
|
|
||||||
| `Home` | When focus is on an item, moves focus to first item. |
|
|
||||||
| `End` | When focus is on an item, moves focus to last item. |
|
|
||||||
| `Esc` | Closes the context menu. |
|
|
||||||
|
|
||||||
Previous[←Combobox](https://kobalte.dev/docs/core/components/combobox)Next[Dialog→](https://kobalte.dev/docs/core/components/dialog)
|
|
||||||
@ -1,735 +0,0 @@
|
|||||||
# Dropdown Menu
|
|
||||||
|
|
||||||
Displays a menu to the user —such as a set of actions or functions— triggered by a button.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { DropdownMenu } from "@kobalte/core/dropdown-menu";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/dropdown-menu";
|
|
||||||
// or (deprecated)
|
|
||||||
import { DropdownMenu } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { DropdownMenu } from "@kobalte/core/dropdown-menu";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/dropdown-menu";
|
|
||||||
// or (deprecated)
|
|
||||||
import { DropdownMenu } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Exposed to assistive technology as a button with a menu using the [WAI ARIA Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/) design pattern.
|
|
||||||
- Supports modal and non-modal modes.
|
|
||||||
- Supports submenus.
|
|
||||||
- Supports items, labels, groups of items.
|
|
||||||
- Supports checkable items (single or multiple) with optional indeterminate state.
|
|
||||||
- Support disabled items.
|
|
||||||
- Complex item labeling support for accessibility.
|
|
||||||
- Keyboard opening and navigation support.
|
|
||||||
- Automatic scrolling support during keyboard navigation.
|
|
||||||
- Typeahead to allow focusing items by typing text.
|
|
||||||
- Optionally render a pointing arrow.
|
|
||||||
- Focus is fully managed.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The dropdown menu consists of:
|
|
||||||
|
|
||||||
- **DropdownMenu:** The root container for a dropdown menu.
|
|
||||||
- **DropdownMenu.Trigger:** The button that toggles the menu.
|
|
||||||
- **DropdownMenu.Icon:** A small icon often displayed next to the menu trigger as a visual affordance for the fact it can be open.
|
|
||||||
- **DropdownMenu.Portal:** Portals its children into the `body` when the menu is open.
|
|
||||||
- **DropdownMenu.Content:** Contains the content to be rendered when the menu is open.
|
|
||||||
- **DropdownMenu.Arrow:** An optional arrow element to render alongside the menu content.
|
|
||||||
- **DropdownMenu.Separator:** Used to visually separate items in the menu.
|
|
||||||
- **DropdownMenu.Group:** Used to group multiple items. Use in conjunction with `DropdownMenu.GroupLabel` to ensure good accessibility via automatic labelling.
|
|
||||||
- **DropdownMenu.GroupLabel:** Used to render the label of a group. It won't be focusable using arrow keys.
|
|
||||||
- **DropdownMenu.Sub:** Contains all the parts of a submenu.
|
|
||||||
- **DropdownMenu.SubTrigger:** An item that opens a submenu. Must be rendered inside `DropdownMenu.Sub`.
|
|
||||||
- **DropdownMenu.SubContent:** The component that pops out when a submenu is open. Must be rendered inside `DropdownMenu.Sub`.
|
|
||||||
|
|
||||||
The menu item consists of:
|
|
||||||
|
|
||||||
- **DropdownMenu.Item:** An item of the select.
|
|
||||||
- **DropdownMenu.ItemLabel:** An accessible label to be announced for the item.
|
|
||||||
- **DropdownMenu.ItemDescription:** An optional accessible description to be announced for the item.
|
|
||||||
- **DropdownMenu.ItemIndicator:** The visual indicator rendered when the item is checked.
|
|
||||||
|
|
||||||
The checkable menu item consists of:
|
|
||||||
|
|
||||||
- **DropdownMenu.RadioGroup:** Used to group multiple `DropdownMenu.RadioItem`s and manage the selection.
|
|
||||||
- **DropdownMenu.RadioItem:** An item that can be controlled and rendered like a radio.
|
|
||||||
- **DropdownMenu.CheckboxItem:** An item that can be controlled and rendered like a checkbox.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Icon />
|
|
||||||
</DropdownMenu.Trigger>
|
|
||||||
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.Content>
|
|
||||||
<DropdownMenu.Arrow />
|
|
||||||
|
|
||||||
<DropdownMenu.Item>
|
|
||||||
<DropdownMenu.ItemLabel />
|
|
||||||
<DropdownMenu.ItemDescription />
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
|
|
||||||
<DropdownMenu.Group>
|
|
||||||
<DropdownMenu.GroupLabel />
|
|
||||||
<DropdownMenu.Item />
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem>
|
|
||||||
<DropdownMenu.ItemIndicator />
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<DropdownMenu.RadioGroup>
|
|
||||||
<DropdownMenu.RadioItem>
|
|
||||||
<DropdownMenu.ItemIndicator />
|
|
||||||
</DropdownMenu.RadioItem>
|
|
||||||
</DropdownMenu.RadioGroup>
|
|
||||||
|
|
||||||
<DropdownMenu.Sub>
|
|
||||||
<DropdownMenu.SubTrigger />
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.SubContent />
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu.Sub>
|
|
||||||
|
|
||||||
<DropdownMenu.Separator />
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Icon />
|
|
||||||
</DropdownMenu.Trigger>
|
|
||||||
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.Content>
|
|
||||||
<DropdownMenu.Arrow />
|
|
||||||
|
|
||||||
<DropdownMenu.Item>
|
|
||||||
<DropdownMenu.ItemLabel />
|
|
||||||
<DropdownMenu.ItemDescription />
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
|
|
||||||
<DropdownMenu.Group>
|
|
||||||
<DropdownMenu.GroupLabel />
|
|
||||||
<DropdownMenu.Item />
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem>
|
|
||||||
<DropdownMenu.ItemIndicator />
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<DropdownMenu.RadioGroup>
|
|
||||||
<DropdownMenu.RadioItem>
|
|
||||||
<DropdownMenu.ItemIndicator />
|
|
||||||
</DropdownMenu.RadioItem>
|
|
||||||
</DropdownMenu.RadioGroup>
|
|
||||||
|
|
||||||
<DropdownMenu.Sub>
|
|
||||||
<DropdownMenu.SubTrigger />
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.SubContent />
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu.Sub>
|
|
||||||
|
|
||||||
<DropdownMenu.Separator />
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Git SettingsChevron
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { DropdownMenu } from "@kobalte/core/dropdown-menu";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { CheckIcon, ChevronDownIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [showGitLog, setShowGitLog] = createSignal(true);
|
|
||||||
const [showHistory, setShowHistory] = createSignal(false);
|
|
||||||
const [branch, setBranch] = createSignal("main");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenu.Trigger class="dropdown-menu__trigger">
|
|
||||||
<span>Git Settings</span>
|
|
||||||
<DropdownMenu.Icon class="dropdown-menu__trigger-icon">
|
|
||||||
<ChevronDownIcon />
|
|
||||||
</DropdownMenu.Icon>
|
|
||||||
</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.Content class="dropdown-menu__content">
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Commit <div class="dropdown-menu__item-right-slot">⌘+K</div>
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Push <div class="dropdown-menu__item-right-slot">⇧+⌘+K</div>
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item" disabled>
|
|
||||||
Update Project <div class="dropdown-menu__item-right-slot">⌘+T</div>
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<DropdownMenu.SubTrigger class="dropdown-menu__sub-trigger">
|
|
||||||
GitHub
|
|
||||||
<div class="dropdown-menu__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</DropdownMenu.SubTrigger>
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.SubContent class="dropdown-menu__sub-content">
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Create Pull Request…
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
View Pull Requests
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Sync Fork
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Separator class="dropdown-menu__separator" />
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Open on GitHub
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
</DropdownMenu.SubContent>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu.Sub>
|
|
||||||
|
|
||||||
<DropdownMenu.Separator class="dropdown-menu__separator" />
|
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem
|
|
||||||
class="dropdown-menu__checkbox-item"
|
|
||||||
checked={showGitLog()}
|
|
||||||
onChange={setShowGitLog}
|
|
||||||
>
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
Show Git Log
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
<DropdownMenu.CheckboxItem
|
|
||||||
class="dropdown-menu__checkbox-item"
|
|
||||||
checked={showHistory()}
|
|
||||||
onChange={setShowHistory}
|
|
||||||
>
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
Show History
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<DropdownMenu.Separator class="dropdown-menu__separator" />
|
|
||||||
|
|
||||||
<DropdownMenu.Group>
|
|
||||||
<DropdownMenu.GroupLabel class="dropdown-menu__group-label">
|
|
||||||
Branches
|
|
||||||
</DropdownMenu.GroupLabel>
|
|
||||||
<DropdownMenu.RadioGroup value={branch()} onChange={setBranch}>
|
|
||||||
<DropdownMenu.RadioItem class="dropdown-menu__radio-item" value="main">
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
main
|
|
||||||
</DropdownMenu.RadioItem>
|
|
||||||
<DropdownMenu.RadioItem class="dropdown-menu__radio-item" value="develop">
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
develop
|
|
||||||
</DropdownMenu.RadioItem>
|
|
||||||
</DropdownMenu.RadioGroup>
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
|
|
||||||
<DropdownMenu.Arrow />
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { DropdownMenu } from "@kobalte/core/dropdown-menu";
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
import { CheckIcon, ChevronDownIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [showGitLog, setShowGitLog] = createSignal(true);
|
|
||||||
const [showHistory, setShowHistory] = createSignal(false);
|
|
||||||
const [branch, setBranch] = createSignal("main");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenu.Trigger class="dropdown-menu__trigger">
|
|
||||||
<span>Git Settings</span>
|
|
||||||
<DropdownMenu.Icon class="dropdown-menu__trigger-icon">
|
|
||||||
<ChevronDownIcon />
|
|
||||||
</DropdownMenu.Icon>
|
|
||||||
</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.Content class="dropdown-menu__content">
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Commit <div class="dropdown-menu__item-right-slot">⌘+K</div>
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Push <div class="dropdown-menu__item-right-slot">⇧+⌘+K</div>
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item" disabled>
|
|
||||||
Update Project <div class="dropdown-menu__item-right-slot">⌘+T</div>
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Sub overlap gutter={4} shift={-8}>
|
|
||||||
<DropdownMenu.SubTrigger class="dropdown-menu__sub-trigger">
|
|
||||||
GitHub
|
|
||||||
<div class="dropdown-menu__item-right-slot">
|
|
||||||
<ChevronRightIcon width={20} height={20} />
|
|
||||||
</div>
|
|
||||||
</DropdownMenu.SubTrigger>
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.SubContent class="dropdown-menu__sub-content">
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Create Pull Request…
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
View Pull Requests
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Sync Fork
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
<DropdownMenu.Separator class="dropdown-menu__separator" />
|
|
||||||
<DropdownMenu.Item class="dropdown-menu__item">
|
|
||||||
Open on GitHub
|
|
||||||
</DropdownMenu.Item>
|
|
||||||
</DropdownMenu.SubContent>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu.Sub>
|
|
||||||
|
|
||||||
<DropdownMenu.Separator class="dropdown-menu__separator" />
|
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem
|
|
||||||
class="dropdown-menu__checkbox-item"
|
|
||||||
checked={showGitLog()}
|
|
||||||
onChange={setShowGitLog}
|
|
||||||
>
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
Show Git Log
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
<DropdownMenu.CheckboxItem
|
|
||||||
class="dropdown-menu__checkbox-item"
|
|
||||||
checked={showHistory()}
|
|
||||||
onChange={setShowHistory}
|
|
||||||
>
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<CheckIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
Show History
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<DropdownMenu.Separator class="dropdown-menu__separator" />
|
|
||||||
|
|
||||||
<DropdownMenu.Group>
|
|
||||||
<DropdownMenu.GroupLabel class="dropdown-menu__group-label">
|
|
||||||
Branches
|
|
||||||
</DropdownMenu.GroupLabel>
|
|
||||||
<DropdownMenu.RadioGroup value={branch()} onChange={setBranch}>
|
|
||||||
<DropdownMenu.RadioItem class="dropdown-menu__radio-item" value="main">
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
main
|
|
||||||
</DropdownMenu.RadioItem>
|
|
||||||
<DropdownMenu.RadioItem class="dropdown-menu__radio-item" value="develop">
|
|
||||||
<DropdownMenu.ItemIndicator class="dropdown-menu__item-indicator">
|
|
||||||
<DotFilledIcon />
|
|
||||||
</DropdownMenu.ItemIndicator>
|
|
||||||
develop
|
|
||||||
</DropdownMenu.RadioItem>
|
|
||||||
</DropdownMenu.RadioGroup>
|
|
||||||
</DropdownMenu.Group>
|
|
||||||
|
|
||||||
<DropdownMenu.Arrow />
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default open
|
|
||||||
|
|
||||||
An initial, uncontrolled open value can be provided using the `defaultOpen` prop.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<DropdownMenu defaultOpen>...</DropdownMenu>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<DropdownMenu defaultOpen>...</DropdownMenu>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled open
|
|
||||||
|
|
||||||
The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, an item or interact outside, and receives the new value.
|
|
||||||
|
|
||||||
Open
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownMenu open={open()} onOpenChange={setOpen}>
|
|
||||||
<DropdownMenu.Trigger>{open() ? "Close" : "Open"}</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.Content>...</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownMenu open={open()} onOpenChange={setOpen}>
|
|
||||||
<DropdownMenu.Trigger>{open() ? "Close" : "Open"}</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Portal>
|
|
||||||
<DropdownMenu.Content>...</DropdownMenu.Content>
|
|
||||||
</DropdownMenu.Portal>
|
|
||||||
</DropdownMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Origin-aware animations
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-menu-content-transform-origin` which can be used to animate the content from its computed origin.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.dropdown-menu__content,
|
|
||||||
.dropdown-menu__sub-content {
|
|
||||||
transform-origin: var(--kb-menu-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu__content[data-expanded],
|
|
||||||
.dropdown-menu__sub-content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.dropdown-menu__content,
|
|
||||||
.dropdown-menu__sub-content {
|
|
||||||
transform-origin: var(--kb-menu-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu__content[data-expanded],
|
|
||||||
.dropdown-menu__sub-content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### DropdownMenu
|
|
||||||
|
|
||||||
`DropdownMenu` is equivalent to the `Root` import from `@kobalte/core/dropdown-menu` (and deprecated `DropdownMenu.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the menu. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the menu changes. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| modal | `boolean`<br> Whether the menu should be the only visible content for screen readers, when set to `true`: <br> \- interaction with outside elements will be disabled. <br> \- scroll will be locked. <br> \- focus will be locked inside the menu content. <br> \- elements outside the menu content will not be visible for screen readers. |
|
|
||||||
| preventScroll | `boolean`<br> Whether the scroll should be locked even if the menu is not modal. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the menu (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
`DropdownMenu` also accepts the following props to customize the placement of the `DropdownMenu.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the trigger element's DOMRect. |
|
|
||||||
| placement | `Placement`<br> The placement of the menu content. |
|
|
||||||
| gutter | `number`<br> The distance between the menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the menu content along the trigger element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the menu content when it overflows the viewport:<br> \- If a `boolean`, specifies whether the menu content should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the menu content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the menu content can overlap the trigger element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the menu content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the menu content should fit the viewport. If this is set to true, the menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-content-available-width` and `--kb-popper-content-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the menu content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the menu content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### DropdownMenu.Trigger
|
|
||||||
|
|
||||||
`DropdownMenu.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button).
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the menu is open. |
|
|
||||||
| data-closed | Present when the menu is close. |
|
|
||||||
|
|
||||||
`DropdownMenu.Icon`, `DropdownMenu.Content`, `DropdownMenu.SubTrigger` and `DropdownMenu.SubContent` share the same data-attributes.
|
|
||||||
|
|
||||||
### DropdownMenu.Content
|
|
||||||
|
|
||||||
The popper positioner will copy the same `z-index` as the `DropdownMenu.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onOpenAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onCloseAutoFocus | `(event: Event) => void`<br> Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
### DropdownMenu.Arrow
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| size | `number`<br> The size of the arrow. |
|
|
||||||
|
|
||||||
### DropdownMenu.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is activated. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
`DropdownMenu.ItemLabel`, `DropdownMenu.ItemDescription` and `DropdownMenu.ItemIndicator` shares the same data-attributes.
|
|
||||||
|
|
||||||
### DropdownMenu.ItemIndicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### DropdownMenu.RadioGroup
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the menu radio item to check. |
|
|
||||||
| defaultValue | `string`<br> The value of the menu radio item that should be checked when initially rendered. Useful when you do not need to control the state of the radio group. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value changes. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled or not. |
|
|
||||||
|
|
||||||
### DropdownMenu.RadioItem
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The value of the menu item radio. |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is checked. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-checked | Present when the item is checked. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### DropdownMenu.CheckboxItem
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `boolean`<br> The controlled checked state of the item. |
|
|
||||||
| defaultChecked | `boolean`<br> The default checked state when initially rendered. Useful when you do not need to control the checked state. |
|
|
||||||
| onChange | `(checked: boolean) => void`<br> Event handler called when the checked state of the item changes. |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| indeterminate | `boolean`<br> Whether the item is in an indeterminate state. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled or not. |
|
|
||||||
| closeOnSelect | `boolean`<br> Whether the menu should close when the item is checked/unchecked. |
|
|
||||||
| onSelect | `() => void`<br> Event handler called when the user selects an item (via mouse or keyboard). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-indeterminate | Present when the item is in an indeterminate state. |
|
|
||||||
| data-checked | Present when the item is checked. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### DropdownMenu.Sub
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the sub menu. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the sub menu changes. |
|
|
||||||
|
|
||||||
`DropdownMenu.Sub` also accepts the following props to customize the placement of the `DropdownMenu.SubContent`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the trigger element's DOMRect. |
|
|
||||||
| gutter | `number`<br> The distance between the sub menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the sub menu content along the trigger element. |
|
|
||||||
| slide | `boolean`<br> Whether the sub menu content should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the sub menu content can overlap the trigger element when it overflows. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the sub menu content should fit the viewport. If this is set to true, the sub menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-content-available-width` and `--kb-popper-content-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the sub menu content when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the sub menu content corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the sub menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### DropdownMenu.SubTrigger
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| textValue | `string`<br> Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.SubTrigger`. Use this when the content is complex, or you have non-textual content inside. |
|
|
||||||
| disabled | `boolean`<br> Whether the sub menu trigger is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the item is disabled. |
|
|
||||||
| data-highlighted | Present when the item is highlighted. |
|
|
||||||
|
|
||||||
### DropdownMenu.SubContent
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onFocusOutside | `(event: FocusOutsideEvent) => void`<br> Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onInteractOutside | `(event: InteractOutsideEvent) => void`<br> Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `DropdownMenu` | none |
|
|
||||||
| `DropdownMenu.Trigger` | `button` |
|
|
||||||
| `DropdownMenu.Icon` | `span` |
|
|
||||||
| `DropdownMenu.Portal` | `Portal` |
|
|
||||||
| `DropdownMenu.Content` | `div` |
|
|
||||||
| `DropdownMenu.Arrow` | `div` |
|
|
||||||
| `DropdownMenu.Separator` | `hr` |
|
|
||||||
| `DropdownMenu.Group` | `div` |
|
|
||||||
| `DropdownMenu.GroupLabel` | `span` |
|
|
||||||
| `DropdownMenu.Sub` | none |
|
|
||||||
| `DropdownMenu.SubTrigger` | `div` |
|
|
||||||
| `DropdownMenu.SubContent` | `div` |
|
|
||||||
| `DropdownMenu.Item` | `div` |
|
|
||||||
| `DropdownMenu.ItemLabel` | `div` |
|
|
||||||
| `DropdownMenu.ItemDescription` | `div` |
|
|
||||||
| `DropdownMenu.ItemIndicator` | `div` |
|
|
||||||
| `DropdownMenu.RadioGroup` | `div` |
|
|
||||||
| `DropdownMenu.RadioItem` | `div` |
|
|
||||||
| `DropdownMenu.CheckboxItem` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | When focus is on the trigger, opens the menu and focuses the first item. <br> When focus is on an item, activates the item. |
|
|
||||||
| `Enter` | When focus is on the trigger, opens the menu and focuses the first item. <br> When focus is on an item, activates the item. |
|
|
||||||
| `ArrowDown` | When focus is on the trigger, opens the menu and focuses the first item. <br> When focus is on an item, moves focus to the next item. |
|
|
||||||
| `ArrowUp` | When focus is on the trigger, opens the menu and focuses the last item. <br> When focus is on an item, moves focus to the previous item. |
|
|
||||||
| `ArrowRight` / `ArrowLeft` | When focus is on a sub menu trigger, opens or closes the submenu depending on reading direction. |
|
|
||||||
| `Home` | When focus is on an item, moves focus to first item. |
|
|
||||||
| `End` | When focus is on an item, moves focus to last item. |
|
|
||||||
| `Esc` | Closes the menu and moves focus to the trigger. |
|
|
||||||
|
|
||||||
Previous[←Dialog](https://kobalte.dev/docs/core/components/dialog)Next[File Field→](https://kobalte.dev/docs/core/components/file-field)
|
|
||||||
@ -1,331 +0,0 @@
|
|||||||
# Hover Card
|
|
||||||
|
|
||||||
Allows sighted users to preview content available behind a link.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { HoverCard } from "@kobalte/core/hover-card";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/hover-card";
|
|
||||||
// or (deprecated)
|
|
||||||
import { HoverCard } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { HoverCard } from "@kobalte/core/hover-card";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/hover-card";
|
|
||||||
// or (deprecated)
|
|
||||||
import { HoverCard } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Opens on hover only.
|
|
||||||
- Supports custom open and close delays.
|
|
||||||
- Optionally render a pointing arrow.
|
|
||||||
- Ignored by screen readers.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The hovercard consists of:
|
|
||||||
|
|
||||||
- **HoverCard:** The root container for a hovercard.
|
|
||||||
- **HoverCard.Trigger:** The link that opens the hovercard.
|
|
||||||
- **HoverCard.Portal:** Portals its children into the `body` when the hovercard is open.
|
|
||||||
- **HoverCard.Content:** Contains the content to be rendered when the hovercard is open.
|
|
||||||
- **HoverCard.Arrow:** An optional arrow element to render alongside the hovercard.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCard.Trigger />
|
|
||||||
<HoverCard.Portal>
|
|
||||||
<HoverCard.Content>
|
|
||||||
<HoverCard.Arrow />
|
|
||||||
</HoverCard.Content>
|
|
||||||
</HoverCard.Portal>
|
|
||||||
</HoverCard>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCard.Trigger />
|
|
||||||
<HoverCard.Portal>
|
|
||||||
<HoverCard.Content>
|
|
||||||
<HoverCard.Arrow />
|
|
||||||
</HoverCard.Content>
|
|
||||||
</HoverCard.Portal>
|
|
||||||
</HoverCard>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
[@MLFabien](https://twitter.com/mlfabien)
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { HoverCard } from "@kobalte/core/hover-card";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCard.Trigger
|
|
||||||
class="hovercard__trigger"
|
|
||||||
href="https://twitter.com/mlfabien"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
@MLFabien
|
|
||||||
</HoverCard.Trigger>
|
|
||||||
<HoverCard.Portal>
|
|
||||||
<HoverCard.Content class="hovercard__content">
|
|
||||||
<HoverCard.Arrow />
|
|
||||||
<img
|
|
||||||
src="https://pbs.twimg.com/profile_images/1509139491671445507/pzWYjlYN_400x400.jpg"
|
|
||||||
alt="Fabien MARIE-LOUISE"
|
|
||||||
class="hovercard__avatar"
|
|
||||||
/>
|
|
||||||
<h2 class="hovercard__title">Fabien MARIE-LOUISE</h2>
|
|
||||||
<p class="hovercard__description">
|
|
||||||
Developer and UI Design enthusiast. Building UI related stuffs for @solid_js
|
|
||||||
</p>
|
|
||||||
</HoverCard.Content>
|
|
||||||
</HoverCard.Portal>
|
|
||||||
</HoverCard>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { HoverCard } from "@kobalte/core/hover-card";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCard.Trigger
|
|
||||||
class="hovercard__trigger"
|
|
||||||
href="https://twitter.com/mlfabien"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
@MLFabien
|
|
||||||
</HoverCard.Trigger>
|
|
||||||
<HoverCard.Portal>
|
|
||||||
<HoverCard.Content class="hovercard__content">
|
|
||||||
<HoverCard.Arrow />
|
|
||||||
<img
|
|
||||||
src="https://pbs.twimg.com/profile_images/1509139491671445507/pzWYjlYN_400x400.jpg"
|
|
||||||
alt="Fabien MARIE-LOUISE"
|
|
||||||
class="hovercard__avatar"
|
|
||||||
/>
|
|
||||||
<h2 class="hovercard__title">Fabien MARIE-LOUISE</h2>
|
|
||||||
<p class="hovercard__description">
|
|
||||||
Developer and UI Design enthusiast. Building UI related stuffs for @solid_js
|
|
||||||
</p>
|
|
||||||
</HoverCard.Content>
|
|
||||||
</HoverCard.Portal>
|
|
||||||
</HoverCard>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default open
|
|
||||||
|
|
||||||
An initial, uncontrolled open value can be provided using the `defaultOpen` prop.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<HoverCard defaultOpen>...</HoverCard>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<HoverCard defaultOpen>...</HoverCard>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled open
|
|
||||||
|
|
||||||
The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user pointer enter or leave the trigger, and receives the new value.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<HoverCard open={open()} onOpenChange={setOpen}>
|
|
||||||
...
|
|
||||||
</HoverCard>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<HoverCard open={open()} onOpenChange={setOpen}>
|
|
||||||
...
|
|
||||||
</HoverCard>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Origin-aware animations
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-hovercard-content-transform-origin` which can be used to animate the content from its computed origin.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.hovercard__content {
|
|
||||||
transform-origin: var(--kb-hovercard-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hovercard__content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.hovercard__content {
|
|
||||||
transform-origin: var(--kb-hovercard-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hovercard__content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### HoverCard
|
|
||||||
|
|
||||||
`HoverCard` is equivalent to the `Root` import from `@kobalte/core/hover-card` (and deprecated `HoverCard.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the hovercard. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the hovercard changes. |
|
|
||||||
| openDelay | `number`<br> The duration from when the mouse enters the trigger until the hovercard opens. |
|
|
||||||
| closeDelay | `number`<br> The duration from when the mouse leaves the trigger or content until the hovercard closes. |
|
|
||||||
| ignoreSafeArea | `boolean`<br> Whether to close the hovercard even if the user cursor is inside the safe area between the trigger and hovercard. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the hovercard (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
`HoverCard` also accepts the following props to customize the placement of the `HoverCard.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the anchor element's DOMRect. |
|
|
||||||
| placement | `Placement`<br> The placement of the hovercard. |
|
|
||||||
| gutter | `number`<br> The distance between the hovercard and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the hovercard along the trigger element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the hovercard when it overflows the viewport:<br> \- If a `boolean`, specifies whether the hovercard should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the hovercard should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the hovercard can overlap the trigger element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the hovercard should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the hovercard should fit the viewport. If this is set to true, the hovercard content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the hovercard when the trigger element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the trigger element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the hovercard corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the hovercard and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### HoverCard.Content
|
|
||||||
|
|
||||||
The popper positioner will copy the same `z-index` as the `HoverCard.Content`.
|
|
||||||
|
|
||||||
### HoverCard.Trigger
|
|
||||||
|
|
||||||
`HoverCard.Trigger` consists of [Link](https://kobalte.dev/docs/core/components/link).
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the hovercard is open. |
|
|
||||||
| data-closed | Present when the hovercard is close. |
|
|
||||||
|
|
||||||
`HoverCard.Content` share the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `HoverCard` | none |
|
|
||||||
| `HoverCard.Trigger` | `a` |
|
|
||||||
| `HoverCard.Portal` | `Portal` |
|
|
||||||
| `HoverCard.Content` | `div` |
|
|
||||||
| `HoverCard.Arrow` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
The hover card is intended for mouse users only so will not respond to keyboard navigation.
|
|
||||||
|
|
||||||
Previous[←File Field](https://kobalte.dev/docs/core/components/file-field)Next[Image→](https://kobalte.dev/docs/core/components/image)
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
# I18nProvider
|
|
||||||
|
|
||||||
Provides the locale for the application to all child components.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { I18nProvider, useLocale } from "@kobalte/core/i18n";
|
|
||||||
// or (deprecated)
|
|
||||||
import { I18nProvider, useLocale } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { I18nProvider, useLocale } from "@kobalte/core/i18n";
|
|
||||||
// or (deprecated)
|
|
||||||
import { I18nProvider, useLocale } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
`I18nProvider` allows you to override the default locale as determined by the browser/system setting with a locale defined by your application (e.g. application setting).
|
|
||||||
|
|
||||||
This should be done by wrapping your entire application in the provider, which will cause all child elements to receive the new locale information via the `useLocale` primitive.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { I18nProvider } from "@kobalte/core/i18n";
|
|
||||||
|
|
||||||
<I18nProvider locale="fr-FR">
|
|
||||||
<YourApp />
|
|
||||||
</I18nProvider>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { I18nProvider } from "@kobalte/core/i18n";
|
|
||||||
|
|
||||||
<I18nProvider locale="fr-FR">
|
|
||||||
<YourApp />
|
|
||||||
</I18nProvider>;
|
|
||||||
```
|
|
||||||
|
|
||||||
### The `useLocale` primitive
|
|
||||||
|
|
||||||
`useLocale` allows components to access the current locale and interface layout direction. It should be used in the root of your app to define the lang and dir attributes so that the browser knows which language and direction the user interface should be rendered in.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { useLocale } from "@kobalte/core/i18n";
|
|
||||||
|
|
||||||
function YourApp() {
|
|
||||||
const { locale, direction } = useLocale();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div lang={locale()} dir={direction()}>
|
|
||||||
{/* your app here */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { useLocale } from "@kobalte/core/i18n";
|
|
||||||
|
|
||||||
function YourApp() {
|
|
||||||
const { locale, direction } = useLocale();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div lang={locale()} dir={direction()}>
|
|
||||||
{/* your app here */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API reference
|
|
||||||
|
|
||||||
### I18nProvider
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| locale | `string`<br> The locale to apply to the children. |
|
|
||||||
| children | `JSX.Element`<br> The contents that should have the locale applied. |
|
|
||||||
|
|
||||||
### useLocale
|
|
||||||
|
|
||||||
The `useLocale` primitive returns the follows properties.
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| locale | `Accessor<string>`<br> The [BCP47](https://www.ietf.org/rfc/bcp/bcp47.txt) language code for the locale. |
|
|
||||||
| direction | `Accessor<Direction>`<br> The writing direction for the locale. |
|
|
||||||
|
|
||||||
Previous[←Tooltip](https://kobalte.dev/docs/core/components/tooltip)Next→
|
|
||||||
@ -1,160 +0,0 @@
|
|||||||
# Image
|
|
||||||
|
|
||||||
An image element with an optional fallback for loading and error status.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Image } from "@kobalte/core/image";
|
|
||||||
// or
|
|
||||||
import { Root, Img, ... } from "@kobalte/core/image";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Image } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Image } from "@kobalte/core/image";
|
|
||||||
// or
|
|
||||||
import { Root, Img, ... } from "@kobalte/core/image";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Image } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Automatic and manual control over when the image renders.
|
|
||||||
- Fallback part accepts any children.
|
|
||||||
- Optionally delay fallback rendering to avoid content flashing.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The image consists of:
|
|
||||||
|
|
||||||
- **Image:** The root container for an image.
|
|
||||||
- **Image.Img:** The image to render. By default, it will only render when it has loaded.
|
|
||||||
- **Image.Fallback:** An element that renders when the image hasn't loaded. This means whilst it's loading, or if there was an error.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Image>
|
|
||||||
<Image.Img />
|
|
||||||
<Image.Fallback />
|
|
||||||
</Image>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Image>
|
|
||||||
<Image.Img />
|
|
||||||
<Image.Fallback />
|
|
||||||
</Image>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
MD
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Image } from "@kobalte/core/image";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Image fallbackDelay={600} class="image">
|
|
||||||
<Image.Img
|
|
||||||
class="image__img"
|
|
||||||
src="https://randomuser.me/api/portraits/women/44.jpg"
|
|
||||||
alt="Nicole Steeves"
|
|
||||||
/>
|
|
||||||
<Image.Fallback class="image__fallback">NS</Image.Fallback>
|
|
||||||
</Image>
|
|
||||||
<Image class="image">
|
|
||||||
<Image.Fallback class="image__fallback">MD</Image.Fallback>
|
|
||||||
</Image>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Image } from "@kobalte/core/image";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Image fallbackDelay={600} class="image">
|
|
||||||
<Image.Img
|
|
||||||
class="image__img"
|
|
||||||
src="https://randomuser.me/api/portraits/women/44.jpg"
|
|
||||||
alt="Nicole Steeves"
|
|
||||||
/>
|
|
||||||
<Image.Fallback class="image__fallback">NS</Image.Fallback>
|
|
||||||
</Image>
|
|
||||||
<Image class="image">
|
|
||||||
<Image.Fallback class="image__fallback">MD</Image.Fallback>
|
|
||||||
</Image>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Avoid flash during loading
|
|
||||||
|
|
||||||
By default `Image.Fallback` will render when the image hasn't loaded. This means whilst it's loading, or if there was an error.
|
|
||||||
|
|
||||||
If you notice a flash during loading, use the `fallbackDelay` prop to delay its rendering, so it only renders for those with slower internet connections.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Image fallbackDelay={600} class="image">
|
|
||||||
<Image.Img
|
|
||||||
class="image__img"
|
|
||||||
src="https://randomuser.me/api/portraits/women/44.jpg"
|
|
||||||
alt="Nicole Steeves"
|
|
||||||
/>
|
|
||||||
<Image.Fallback class="image__fallback">NS</Image.Fallback>
|
|
||||||
</Image>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Image fallbackDelay={600} class="image">
|
|
||||||
<Image.Img
|
|
||||||
class="image__img"
|
|
||||||
src="https://randomuser.me/api/portraits/women/44.jpg"
|
|
||||||
alt="Nicole Steeves"
|
|
||||||
/>
|
|
||||||
<Image.Fallback class="image__fallback">NS</Image.Fallback>
|
|
||||||
</Image>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Image
|
|
||||||
|
|
||||||
`Image` is equivalent to the `Root` import from `@kobalte/core/image` (and deprecated `Image.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| fallbackDelay | `number`<br> The delay (in ms) before displaying the image fallback. Useful if you notice a flash during loading for delaying rendering, so it only appears for those with slower internet connections. |
|
|
||||||
| onLoadingStatusChange | `(status: "idle" | "loading" | "loaded" | "error") => void`<br> A callback providing information about the loading status of the image. This is useful in case you want to control more precisely what to render as the image is loading. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Image` | `span` |
|
|
||||||
| `Image.Img` | `img` |
|
|
||||||
| `Image.Fallback` | `span` |
|
|
||||||
|
|
||||||
Previous[←Hover Card](https://kobalte.dev/docs/core/components/hover-card)Next[Link→](https://kobalte.dev/docs/core/components/link)
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
# Link
|
|
||||||
|
|
||||||
Allows a user to navigate to another page or resource within a web page or application.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Link } from "@kobalte/core/link";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/link";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Link } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Link } from "@kobalte/core/link";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/link";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Link } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Native HTML `<a>` element support.
|
|
||||||
- Custom element type support via the [WAI ARIA Link](https://www.w3.org/WAI/ARIA/apg/patterns/link/) design pattern.
|
|
||||||
- Support for disabled links.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The link consists of:
|
|
||||||
|
|
||||||
- **Link:** The root container for a link.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Link />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Link />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
[Kobalte](https://kobalte.dev/)
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Link } from "@kobalte/core/link";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Link class="link" href="https://kobalte.dev">
|
|
||||||
Kobalte
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Link } from "@kobalte/core/link";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Link class="link" href="https://kobalte.dev">
|
|
||||||
Kobalte
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Disabled state
|
|
||||||
|
|
||||||
Use the `disabled` prop to disable a link while keeping it accessible for screen readers.
|
|
||||||
|
|
||||||
Kobalte
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Link href="https://kobalte.dev" disabled>
|
|
||||||
Kobalte
|
|
||||||
</Link>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Link href="https://kobalte.dev" disabled>
|
|
||||||
Kobalte
|
|
||||||
</Link>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Link
|
|
||||||
|
|
||||||
`Link` is equivalent to the `Root` import from `@kobalte/core/link` (and deprecated `Link.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| disabled | `boolean`<br> Whether the link is disabled. Native navigation will be disabled, and the link will be exposed as disabled to assistive technology. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the link is disabled. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Link` | `a` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Enter` | Activates the link. |
|
|
||||||
|
|
||||||
Previous[←Image](https://kobalte.dev/docs/core/components/image)Next[Menubar→](https://kobalte.dev/docs/core/components/menubar)
|
|
||||||
@ -1,221 +0,0 @@
|
|||||||
# Meter
|
|
||||||
|
|
||||||
Displays numeric value that varies within a defined range
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Meter } from "@kobalte/core/meter";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/meter";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Meter } from "@kobalte/core/meter";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/meter";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Exposed to assistive technology as a meter via ARIA.
|
|
||||||
- Labeling support for accessibility.
|
|
||||||
- Internationalized number formatting as a percentage or value.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The meter consists of:
|
|
||||||
|
|
||||||
- **Meter:** The root container for a meter.
|
|
||||||
- **Meter.Label:** An accessible label that gives the user information on the meter.
|
|
||||||
- **Meter.ValueLabel:** The accessible label text representing the current value in a human-readable format.
|
|
||||||
- **Meter.Track:** The component that visually represents the meter track.
|
|
||||||
- **Meter.Fill:** The component that visually represents the meter value.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Meter>
|
|
||||||
<Meter.Label />
|
|
||||||
<Meter.ValueLabel />
|
|
||||||
<Meter.Track>
|
|
||||||
<Meter.Fill />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Meter>
|
|
||||||
<Meter.Label />
|
|
||||||
<Meter.ValueLabel />
|
|
||||||
<Meter.Track>
|
|
||||||
<Meter.Fill />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Battery Level:
|
|
||||||
|
|
||||||
80%
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Meter } from "@kobalte/core/meter";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Meter value={80} class="meter">
|
|
||||||
<div class="meter__label-container">
|
|
||||||
<Meter.Label class="meter__label">Battery Level:</Meter.Label>
|
|
||||||
<Meter.ValueLabel class="meter__value-label" />
|
|
||||||
</div>
|
|
||||||
<Meter.Track class="meter__track">
|
|
||||||
<Meter.Fill class="meter__fill" />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Meter } from "@kobalte/core/meter";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Meter value={80} class="meter">
|
|
||||||
<div class="meter__label-container">
|
|
||||||
<Meter.Label class="meter__label">Battery Level:</Meter.Label>
|
|
||||||
<Meter.ValueLabel class="meter__value-label" />
|
|
||||||
</div>
|
|
||||||
<Meter.Track class="meter__track">
|
|
||||||
<Meter.Fill class="meter__fill" />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Custom value scale
|
|
||||||
|
|
||||||
By default, the `value` prop represents the current value of meter, as the minimum and maximum values default to 0 and 100, respectively. Alternatively, a different scale can be used by setting the `minValue` and `maxValue` props.
|
|
||||||
|
|
||||||
Disk Space Usage:
|
|
||||||
|
|
||||||
40%
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Meter value={100} minValue={0} maxValue={250} class="meter">
|
|
||||||
<div class="meter__label-container">
|
|
||||||
<Meter.Label class="meter__label">Disk Space Usage:</Meter.Label>
|
|
||||||
<Meter.ValueLabel class="meter__value-label" />
|
|
||||||
</div>
|
|
||||||
<Meter.Track class="meter__track">
|
|
||||||
<Meter.Fill class="meter__fill" />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Meter value={100} minValue={0} maxValue={250} class="meter">
|
|
||||||
<div class="meter__label-container">
|
|
||||||
<Meter.Label class="meter__label">Disk Space Usage:</Meter.Label>
|
|
||||||
<Meter.ValueLabel class="meter__value-label" />
|
|
||||||
</div>
|
|
||||||
<Meter.Track class="meter__track">
|
|
||||||
<Meter.Fill class="meter__fill" />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom value label
|
|
||||||
|
|
||||||
The `getValueLabel` prop allows the formatted value used in `Meter.ValueLabel` and ARIA to be replaced with a custom string. It receives the current value, min and max values as parameters.
|
|
||||||
|
|
||||||
Processing...
|
|
||||||
|
|
||||||
3 of 10 tasks completed
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Meter
|
|
||||||
value={3}
|
|
||||||
minValue={0}
|
|
||||||
maxValue={10}
|
|
||||||
getValueLabel={({ value, max }) => `${value} of ${max} tasks completed`}
|
|
||||||
class="meter"
|
|
||||||
>
|
|
||||||
<div class="meter__label-container">
|
|
||||||
<Meter.Label class="meter__label">Processing...</Meter.Label>
|
|
||||||
<Meter.ValueLabel class="meter__value-label" />
|
|
||||||
</div>
|
|
||||||
<Meter.Track class="meter__track">
|
|
||||||
<Meter.Fill class="meter__fill" />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Meter
|
|
||||||
value={3}
|
|
||||||
minValue={0}
|
|
||||||
maxValue={10}
|
|
||||||
getValueLabel={({ value, max }) => `${value} of ${max} tasks completed`}
|
|
||||||
class="meter"
|
|
||||||
>
|
|
||||||
<div class="meter__label-container">
|
|
||||||
<Meter.Label class="meter__label">Processing...</Meter.Label>
|
|
||||||
<Meter.ValueLabel class="meter__value-label" />
|
|
||||||
</div>
|
|
||||||
<Meter.Track class="meter__track">
|
|
||||||
<Meter.Fill class="meter__fill" />
|
|
||||||
</Meter.Track>
|
|
||||||
</Meter>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Meter fill width
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-meter-fill-width` which corresponds to the percentage of meterion (ex: 80%). If you are building a linear meter, you can use it to set the width of the `Meter.Fill` component in CSS.
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Meter
|
|
||||||
|
|
||||||
`Meter` is equivalent to the `Root` import from `@kobalte/core/meter`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `number`<br> The meter value. |
|
|
||||||
| minValue | `number`<br> The minimum meter value. |
|
|
||||||
| maxValue | `number`<br> The maximum meter value. |
|
|
||||||
| getValueLabel | `(params: { value: number; min: number; max: number }) => string`<br> A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
|
|
||||||
`Meter.Label`, `Meter.ValueLabel`, `Meter.Track` and `Meter.Fill` shares the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Meter` | `div` |
|
|
||||||
| `Meter.Label` | `span` |
|
|
||||||
| `Meter.ValueLabel` | `div` |
|
|
||||||
| `Meter.Track` | `div` |
|
|
||||||
| `Meter.Fill` | `div` |
|
|
||||||
|
|
||||||
Previous[←Menubar](https://kobalte.dev/docs/core/components/menubar)Next[Navigation Menu→](https://kobalte.dev/docs/core/components/navigation-menu)
|
|
||||||
@ -1,549 +0,0 @@
|
|||||||
# Number Field
|
|
||||||
|
|
||||||
A number input that allow users to input custom number entries with a keyboard.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { NumberField } from "@kobalte/core/number-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/number-field";
|
|
||||||
// or (deprecated)
|
|
||||||
import { NumberField } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { NumberField } from "@kobalte/core/number-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/number-field";
|
|
||||||
// or (deprecated)
|
|
||||||
import { NumberField } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follows the [WAI ARIA Spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) design pattern.
|
|
||||||
- Built with a native `<input>` element.
|
|
||||||
- Visual and ARIA labeling support.
|
|
||||||
- Required and invalid states exposed to assistive technology via ARIA.
|
|
||||||
- Support for description and error message help text linked to the input via ARIA.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Supports increment and decrement buttons.
|
|
||||||
- Format and localize input number and raw input.
|
|
||||||
- Supports mouse wheel event and all keyboard events.
|
|
||||||
- Supports browser autofill.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The number field consists of:
|
|
||||||
|
|
||||||
- **NumberField**: The root container for the number field.
|
|
||||||
- **NumberField.Label**: The label that gives the user information on the number field.
|
|
||||||
- **NumberField.Input**: The native HTML input of the number field, used for display number.
|
|
||||||
- **NumberField.HiddenInput**: The native HTML input of the number field, used for raw number form submition.
|
|
||||||
- **NumberField.IncrementTrigger**: The increment button of the number field.
|
|
||||||
- **NumberField.DecrementTrigger**: The increment button of the number field.
|
|
||||||
- **NumberField.Description**: The description that gives the user more information on the number field.
|
|
||||||
- **NumberField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on number field.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label />
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.HiddenInput />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
<NumberField.Description />
|
|
||||||
<NumberField.ErrorMessage />
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label />
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.HiddenInput />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
<NumberField.Description />
|
|
||||||
<NumberField.ErrorMessage />
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { NumberField } from "@kobalte/core/number-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<NumberField class="number-field">
|
|
||||||
<NumberField.Label class="number-field__label">
|
|
||||||
Quantity
|
|
||||||
</NumberField.Label>
|
|
||||||
<div class="number-field__group">
|
|
||||||
<NumberField.Input class="number-field__input" />
|
|
||||||
<NumberField.IncrementTrigger aria-label="Increment" class="number-field__increment"><ArrowUpIcon/></NumberField.IncrementTrigger>
|
|
||||||
<NumberField.DecrementTrigger aria-label="Decrement" class="number-field__decrement"><ArrowDownIcon/></NumberField.DecrementTrigger>
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { NumberField } from "@kobalte/core/number-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<NumberField class="number-field">
|
|
||||||
<NumberField.Label class="number-field__label">
|
|
||||||
Quantity
|
|
||||||
</NumberField.Label>
|
|
||||||
<div class="number-field__group">
|
|
||||||
<NumberField.Input class="number-field__input" />
|
|
||||||
<NumberField.IncrementTrigger aria-label="Increment" class="number-field__increment"><ArrowUpIcon/></NumberField.IncrementTrigger>
|
|
||||||
<NumberField.DecrementTrigger aria-label="Decrement" class="number-field__decrement"><ArrowDownIcon/></NumberField.DecrementTrigger>
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultValue` prop.
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField defaultValue={40}>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField defaultValue={40}>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `value` and `rawValue` props can be used to make the value controlled.
|
|
||||||
It is recommended to only use the `rawValue` as it is of type `number`.
|
|
||||||
The `onChange` event is fired when the user type into the input and receive the new value.
|
|
||||||
The `onRawValueChange` prop is called when the value changes and receives a `number`.
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
Quantity: 40. Raw: 40.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("40");
|
|
||||||
const [rawValue, setRawValue] = createSignal<number>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<NumberField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
rawValue={rawValue()}
|
|
||||||
onRawValueChange={setRawValue}
|
|
||||||
>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
<p>
|
|
||||||
Quantity: {value()}. Raw: {rawValue()}.
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("40");
|
|
||||||
const [rawValue, setRawValue] = createSignal<number>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<NumberField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
rawValue={rawValue()}
|
|
||||||
onRawValueChange={setRawValue}
|
|
||||||
>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
<p>
|
|
||||||
Quantity: {value()}. Raw: {rawValue()}.
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `NumberField.Description` component can be used to associate additional help text with a number field.
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
Choose a quantity.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<NumberField.Description>Choose a quantity.</NumberField.Description>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<NumberField.Description>Choose a quantity.</NumberField.Description>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `NumberField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the text field as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
Hmm, I prefer 40.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [rawValue, setRawValue] = createSignal<number>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NumberField
|
|
||||||
onRawValueChange={setRawValue}
|
|
||||||
validationState={rawValue() !== 40 ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<NumberField.ErrorMessage>Hmm, I prefer 40.</NumberField.ErrorMessage>
|
|
||||||
</NumberField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [rawValue, setRawValue] = createSignal<number>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NumberField
|
|
||||||
onRawValueChange={setRawValue}
|
|
||||||
validationState={rawValue() !== 40 ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
<NumberField.ErrorMessage>Hmm, I prefer 40.</NumberField.ErrorMessage>
|
|
||||||
</NumberField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The number field `name` prop along with `<NumberField.HiddenInput/>` can be used for integration with HTML forms. Only the raw value is passed to the form.
|
|
||||||
|
|
||||||
If the formatted value is wanted (unrecommended) set the `name` attribute on `<NumberField.Input/>`.
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<NumberField name="quantity">
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<NumberField.HiddenInput />
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<NumberField name="quantity">
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<NumberField.HiddenInput />
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Triggers
|
|
||||||
|
|
||||||
The number field supports optional increment/decrement triggers that are easily customizable.
|
|
||||||
|
|
||||||
Quantity
|
|
||||||
|
|
||||||
-+
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.DecrementTrigger class="custom-trigger">-</NumberField.DecrementTrigger>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger class="custom-trigger">+</NumberField.IncrementTrigger>
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.DecrementTrigger class="custom-trigger">-</NumberField.DecrementTrigger>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger class="custom-trigger">+</NumberField.IncrementTrigger>
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Format
|
|
||||||
|
|
||||||
The value of the number field component can be formatted based on the [locale with the `I18NProvider`](https://kobalte.dev/docs/core/components/i18n-provider) and `formatOptions`. For more information see [React Spectrum NumberField](https://react-spectrum.adobe.com/react-spectrum/NumberField.html).
|
|
||||||
|
|
||||||
Price
|
|
||||||
|
|
||||||
ArrowArrow
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField formatOptions={{ style: "currency", currency: "USD" }} defaultValue={4}>
|
|
||||||
<NumberField.Label>Price</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField formatOptions={{ style: "currency", currency: "USD" }} defaultValue={4}>
|
|
||||||
<NumberField.Label>Price</NumberField.Label>
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Autofill
|
|
||||||
|
|
||||||
The number field supports autofill through `NumberField.HiddenInput`.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<NumberField.HiddenInput />
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<NumberField>
|
|
||||||
<NumberField.Label>Quantity</NumberField.Label>
|
|
||||||
<NumberField.HiddenInput />
|
|
||||||
<div>
|
|
||||||
<NumberField.Input />
|
|
||||||
<NumberField.IncrementTrigger />
|
|
||||||
<NumberField.DecrementTrigger />
|
|
||||||
</div>
|
|
||||||
</NumberField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### NumberField
|
|
||||||
|
|
||||||
`NumberField` is equivalent to the `Root` import from `@kobalte/core/number-field` (and deprecated `NumberField.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string | number`<br> The controlled formatted value of the number field. |
|
|
||||||
| defaultValue | `string | number`<br> The default value when initially rendered. Useful when you do not need to control the value. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value of the NumberField changes as a formatted value. |
|
|
||||||
| rawValue | `number`<br> The controlled raw value of the number field. |
|
|
||||||
| onRawValueChange | `(value: number) => void`<br> Event handler called when the value of the NumberField changes as a number. |
|
|
||||||
| minValue | `number`<br> The smallest value allowed in the number field, defaults to `Number.MIN_SAFE_INTEGER`. |
|
|
||||||
| maxValue | `number`<br> The largest value allowed in the number field, defaults to `Number.MAX_SAFE_INTEGER`. |
|
|
||||||
| step | `number`<br> Increment/Decrement step when using the triggers or the arrows on keyboard in the number field. |
|
|
||||||
| largeStep | `number`<br> Increment/Decrement step when using the Page UP/Down keys in the number field, defaults `10 * step`. |
|
|
||||||
| changeOnWheel | `boolean`<br> Whether to increment/decrement on wheel scroll inside the number field. |
|
|
||||||
| format | `boolean`<br> Whether to format the input value. |
|
|
||||||
| formatOptions | [`Intl.NumberFormatOptions`](https://github.com/microsoft/TypeScript/blob/353ccb7688351ae33ccf6e0acb913aa30621eaf4/src/lib/es2020.intl.d.ts#L243-L251)<br> Formating options for the value of the number field. |
|
|
||||||
| allowedInput | `RegExp`<br> Allowed input characters in the number field (only prevents onInput, not paste), defaults to locale and format characters. |
|
|
||||||
| name | `string`<br> The name of the NumberField.HiddenInput of the number field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the number field should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must fill the number field before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the number field is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the number field items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the number field is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the number field is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must fill the number field before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the number field is disabled. |
|
|
||||||
| data-readonly | Present when the number field is read only. |
|
|
||||||
|
|
||||||
`NumberField.Label`, `NumberField.Input`, `NumberField.HiddenInput`, `NumberField.Description` and `NumberField.ErrorMesssage` share the same data-attributes.
|
|
||||||
|
|
||||||
### NumberField.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `NumberField` | `div` |
|
|
||||||
| `NumberField.Label` | `label` |
|
|
||||||
| `NumberField.Input` | `input` |
|
|
||||||
| `NumberField.HiddenInput` | `input` |
|
|
||||||
| `NumberField.IncrementTrigger` | `button` |
|
|
||||||
| `NumberField.DecrementTrigger` | `button` |
|
|
||||||
| `NumberField.Description` | `div` |
|
|
||||||
| `NumberField.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
Previous[←Navigation Menu](https://kobalte.dev/docs/core/components/navigation-menu)Next[Pagination→](https://kobalte.dev/docs/core/components/pagination)
|
|
||||||
@ -1,368 +0,0 @@
|
|||||||
# Pagination
|
|
||||||
|
|
||||||
Allows the user to select a specific page from a range of pages.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Pagination } from "@kobalte/core/pagination";
|
|
||||||
// or
|
|
||||||
import { Root, Item, ... } from "@kobalte/core/pagination";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Pagination } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Pagination } from "@kobalte/core/pagination";
|
|
||||||
// or
|
|
||||||
import { Root, Item, ... } from "@kobalte/core/pagination";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Pagination } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Labeling support for accessibility.
|
|
||||||
- Tab focus management.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Customizable appearance.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The pagination consists of:
|
|
||||||
|
|
||||||
- **Pagination:** The root container for the pagination component.
|
|
||||||
- **Pagination.Item:** An item of the pagination.
|
|
||||||
- **Pagination.Ellipsis:** Ellipsis item of the pagination.
|
|
||||||
- **Pagination.Previous:** Previous button of the pagination.
|
|
||||||
- **Pagination.Next:** Next button of the pagination.
|
|
||||||
- **Pagination.Items:** Contains the list of items and allows a user to select one of them.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination>
|
|
||||||
<Pagination.Previous/>
|
|
||||||
<Pagination.Items/>
|
|
||||||
<Pagination.Next/>
|
|
||||||
</Select>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination>
|
|
||||||
<Pagination.Previous/>
|
|
||||||
<Pagination.Items/>
|
|
||||||
<Pagination.Next/>
|
|
||||||
</Select>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Pagination } from "@kobalte/core/pagination";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Pagination
|
|
||||||
class="pagination__root"
|
|
||||||
count={10}
|
|
||||||
itemComponent={props => (
|
|
||||||
<Pagination.Item class="pagination__item" page={props.page}>{props.page}</Pagination.Item>
|
|
||||||
)}
|
|
||||||
ellipsisComponent={() => (
|
|
||||||
<Pagination.Ellipsis class="pagination__ellipsis">...</Pagination.Ellipsis>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Pagination.Previous class="pagination__item">Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items/>
|
|
||||||
<Pagination.Next class="pagination__item">Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Pagination } from "@kobalte/core/pagination";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Pagination
|
|
||||||
class="pagination__root"
|
|
||||||
count={10}
|
|
||||||
itemComponent={props => (
|
|
||||||
<Pagination.Item class="pagination__item" page={props.page}>{props.page}</Pagination.Item>
|
|
||||||
)}
|
|
||||||
ellipsisComponent={() => (
|
|
||||||
<Pagination.Ellipsis class="pagination__ellipsis">...</Pagination.Ellipsis>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Pagination.Previous class="pagination__item">Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items/>
|
|
||||||
<Pagination.Next class="pagination__item">Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
An initial, uncontrolled page can be provided using the `defaultPage` prop, which accepts a number smaller or equal to the `count` and starts at 1.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
defaultPage={4}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
defaultPage={4}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `page` prop, which accepts a page number, can be used to make the value controlled. The `onPageChange` event is fired when the user selects an item, and receives the new page number.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
export function ControlledExample() {
|
|
||||||
const [page, setPage] = createSignal(4);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Pagination
|
|
||||||
page={page()}
|
|
||||||
onPageChange={setPage}
|
|
||||||
count={10}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
export function ControlledExample() {
|
|
||||||
const [page, setPage] = createSignal(4);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Pagination
|
|
||||||
page={page()}
|
|
||||||
onPageChange={setPage}
|
|
||||||
count={10}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Next / Previous buttons example
|
|
||||||
|
|
||||||
The appearance can be customized by omitting the Next and Previous Button.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Items />
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Items />
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
### First / Last item example
|
|
||||||
|
|
||||||
The First and Last item can be hidden instead of displaying at all times.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
showFirst={false}
|
|
||||||
showLast={false}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
showFirst={false}
|
|
||||||
showLast={false}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Siblings example
|
|
||||||
|
|
||||||
The number of items around the current page item can be customized.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
siblingCount={2}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
siblingCount={2}
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fixed Items example
|
|
||||||
|
|
||||||
The total number of items can be fixed to avoid content shift. If ellipsis are disabled (by returning an empty component) use `fixedItems="no-ellipsis"` instead.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
fixedItems
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Pagination
|
|
||||||
count={10}
|
|
||||||
fixedItems
|
|
||||||
itemComponent={props => <Pagination.Item page={props.page}>{props.page}</Pagination.Item>}
|
|
||||||
ellipsisComponent={() => <Pagination.Ellipsis>...</Pagination.Ellipsis>}
|
|
||||||
>
|
|
||||||
<Pagination.Previous>Previous</Pagination.Previous>
|
|
||||||
<Pagination.Items />
|
|
||||||
<Pagination.Next>Next</Pagination.Next>
|
|
||||||
</Pagination>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Pagination
|
|
||||||
|
|
||||||
`Pagination` is equivalent to the `Root` import from `@kobalte/core/pagination` (and deprecated `Pagination.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| page | `number`<br> The controlled page number of the pagination. (1-indexed) |
|
|
||||||
| defaultPage | `string`<br> The default page number when initially rendered. (1-indexed) |
|
|
||||||
| onPageChange | `(page: number) => void`<br> Event handler called when the page number changes. |
|
|
||||||
| count | `number`<br> The number of pages for the pagination. |
|
|
||||||
| siblingCount | `number`<br> The number of siblings to show around the current page item. |
|
|
||||||
| showFirst | `boolean`<br> Whether to always show the first page item. |
|
|
||||||
| showLast | `boolean`<br> Whether to always show the last page item. |
|
|
||||||
| fixedItems | `boolean | "no-ellipsis"`<br> Whether to always show the same number of items (to avoid content shift). Special value: `"no-ellipsis"` does not count the ellipsis as an item (used when ellipsis are disabled). |
|
|
||||||
| itemComponent | `Component<{page: number}>`<br> The component to render as an item in the `Pagination.Items`. |
|
|
||||||
| ellipsisComponent | `Component`<br> The component to render as an ellipsis item in the `Pagination.Items`. |
|
|
||||||
| disabled | `boolean`<br> Whether the pagination is disabled. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-disabled | Present when the pagination is disabled. |
|
|
||||||
|
|
||||||
### Pagination.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| page | `number`<br> The page number to render. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-current | Present when the item is the current page. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Pagination` | `div` |
|
|
||||||
| `Pagination.Item` | `button` |
|
|
||||||
| `Pagination.Ellipsis` | `div` |
|
|
||||||
| `Pagination.Previous` | `button` |
|
|
||||||
| `Pagination.Next` | `button` |
|
|
||||||
| `Pagination.Items` | none |
|
|
||||||
|
|
||||||
Previous[←Number Field](https://kobalte.dev/docs/core/components/number-field)Next[Popover→](https://kobalte.dev/docs/core/components/popover)
|
|
||||||
@ -1,230 +0,0 @@
|
|||||||
# Progress
|
|
||||||
|
|
||||||
Show either determinate or indeterminate progress of an operation over time.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Progress } from "@kobalte/core/progress";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/progress";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Progress } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Progress } from "@kobalte/core/progress";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/progress";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Progress } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Exposed to assistive technology as a progress bar via ARIA.
|
|
||||||
- Labeling support for accessibility.
|
|
||||||
- Internationalized number formatting as a percentage or value.
|
|
||||||
- Determinate and indeterminate progress support.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The progress consists of:
|
|
||||||
|
|
||||||
- **Progress:** The root container for a progress bar.
|
|
||||||
- **Progress.Label:** An accessible label that gives the user information on the progress.
|
|
||||||
- **Progress.ValueLabel:** The accessible label text representing the current value in a human-readable format.
|
|
||||||
- **Progress.Track:** The component that visually represents the progress track.
|
|
||||||
- **Progress.Fill:** The component that visually represents the progress value.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Progress>
|
|
||||||
<Progress.Label />
|
|
||||||
<Progress.ValueLabel />
|
|
||||||
<Progress.Track>
|
|
||||||
<Progress.Fill />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Progress>
|
|
||||||
<Progress.Label />
|
|
||||||
<Progress.ValueLabel />
|
|
||||||
<Progress.Track>
|
|
||||||
<Progress.Fill />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Loading...
|
|
||||||
|
|
||||||
80%
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Progress } from "@kobalte/core/progress";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Progress value={80} class="progress">
|
|
||||||
<div class="progress__label-container">
|
|
||||||
<Progress.Label class="progress__label">Loading...</Progress.Label>
|
|
||||||
<Progress.ValueLabel class="progress__value-label" />
|
|
||||||
</div>
|
|
||||||
<Progress.Track class="progress__track">
|
|
||||||
<Progress.Fill class="progress__fill" />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Progress } from "@kobalte/core/progress";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Progress value={80} class="progress">
|
|
||||||
<div class="progress__label-container">
|
|
||||||
<Progress.Label class="progress__label">Loading...</Progress.Label>
|
|
||||||
<Progress.ValueLabel class="progress__value-label" />
|
|
||||||
</div>
|
|
||||||
<Progress.Track class="progress__track">
|
|
||||||
<Progress.Fill class="progress__fill" />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Custom value scale
|
|
||||||
|
|
||||||
By default, the `value` prop represents the current percentage of progress, as the minimum and maximum values default to 0 and 100, respectively. Alternatively, a different scale can be used by setting the `minValue` and `maxValue` props.
|
|
||||||
|
|
||||||
Loading...
|
|
||||||
|
|
||||||
50%
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Progress value={100} minValue={50} maxValue={150} class="progress">
|
|
||||||
<div class="progress__label-container">
|
|
||||||
<Progress.Label class="progress__label">Loading...</Progress.Label>
|
|
||||||
<Progress.ValueLabel class="progress__value-label" />
|
|
||||||
</div>
|
|
||||||
<Progress.Track class="progress__track">
|
|
||||||
<Progress.Fill class="progress__fill" />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Progress value={100} minValue={50} maxValue={150} class="progress">
|
|
||||||
<div class="progress__label-container">
|
|
||||||
<Progress.Label class="progress__label">Loading...</Progress.Label>
|
|
||||||
<Progress.ValueLabel class="progress__value-label" />
|
|
||||||
</div>
|
|
||||||
<Progress.Track class="progress__track">
|
|
||||||
<Progress.Fill class="progress__fill" />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom value label
|
|
||||||
|
|
||||||
The `getValueLabel` prop allows the formatted value used in `Progress.ValueLabel` and ARIA to be replaced with a custom string. It receives the current value, min and max values as parameters.
|
|
||||||
|
|
||||||
Processing...
|
|
||||||
|
|
||||||
3 of 10 tasks completed
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Progress
|
|
||||||
value={3}
|
|
||||||
minValue={0}
|
|
||||||
maxValue={10}
|
|
||||||
getValueLabel={({ value, max }) => `${value} of ${max} tasks completed`}
|
|
||||||
class="progress"
|
|
||||||
>
|
|
||||||
<div class="progress__label-container">
|
|
||||||
<Progress.Label class="progress__label">Processing...</Progress.Label>
|
|
||||||
<Progress.ValueLabel class="progress__value-label" />
|
|
||||||
</div>
|
|
||||||
<Progress.Track class="progress__track">
|
|
||||||
<Progress.Fill class="progress__fill" />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Progress
|
|
||||||
value={3}
|
|
||||||
minValue={0}
|
|
||||||
maxValue={10}
|
|
||||||
getValueLabel={({ value, max }) => `${value} of ${max} tasks completed`}
|
|
||||||
class="progress"
|
|
||||||
>
|
|
||||||
<div class="progress__label-container">
|
|
||||||
<Progress.Label class="progress__label">Processing...</Progress.Label>
|
|
||||||
<Progress.ValueLabel class="progress__value-label" />
|
|
||||||
</div>
|
|
||||||
<Progress.Track class="progress__track">
|
|
||||||
<Progress.Fill class="progress__fill" />
|
|
||||||
</Progress.Track>
|
|
||||||
</Progress>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Progress bar fill width
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-progress-fill-width` which corresponds to the percentage of progression (ex: 80%). If you are building a linear progress bar, you can use it to set the width of the `Progress.Fill` component in CSS.
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Progress
|
|
||||||
|
|
||||||
`Progress` is equivalent to the `Root` import from `@kobalte/core/progress` (and deprecated `Progress.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `number`<br> The progress value. |
|
|
||||||
| minValue | `number`<br> The minimum progress value. |
|
|
||||||
| maxValue | `number`<br> The maximum progress value. |
|
|
||||||
| indeterminate | `boolean`<br> Whether the progress is in an indeterminate state. |
|
|
||||||
| getValueLabel | `(params: { value: number; min: number; max: number }) => string`<br> A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-progress='loading' | Present when the progress is not complete (`value` < `maxValue`). |
|
|
||||||
| data-progress='complete' | Present when the progress is complete (`value` === `maxValue`). |
|
|
||||||
| data-indeterminate | Present when the progress is in an indeterminate state. |
|
|
||||||
|
|
||||||
`Progress.Label`, `Progress.ValueLabel`, `Progress.Track` and `Progress.Fill` shares the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Progress` | `div` |
|
|
||||||
| `Progress.Label` | `span` |
|
|
||||||
| `Progress.ValueLabel` | `div` |
|
|
||||||
| `Progress.Track` | `div` |
|
|
||||||
| `Progress.Fill` | `div` |
|
|
||||||
|
|
||||||
Previous[←Popover](https://kobalte.dev/docs/core/components/popover)Next[Radio Group→](https://kobalte.dev/docs/core/components/radio-group)
|
|
||||||
@ -1,507 +0,0 @@
|
|||||||
# Radio Group
|
|
||||||
|
|
||||||
A set of checkable buttons, known as radio buttons, where no more than one of the buttons can be checked at a time.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { RadioGroup } from "@kobalte/core/radio-group";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/radio-group";
|
|
||||||
// or (deprecated)
|
|
||||||
import { RadioGroup } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { RadioGroup } from "@kobalte/core/radio-group";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/radio-group";
|
|
||||||
// or (deprecated)
|
|
||||||
import { RadioGroup } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Radio Group](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton/) design pattern.
|
|
||||||
- Each radio is built with a native HTML `<input>` element, which is visually hidden to allow custom styling.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Group and radio labeling support for assistive technology.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The radio group consists of:
|
|
||||||
|
|
||||||
- **RadioGroup**: The root container for the radio group.
|
|
||||||
- **RadioGroup.Label**: The label that gives the user information on the radio group.
|
|
||||||
- **RadioGroup.Description**: The description that gives the user more information on the radio group.
|
|
||||||
- **RadioGroup.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the radio group.
|
|
||||||
|
|
||||||
The radio item consists of:
|
|
||||||
|
|
||||||
- **RadioGroup.Item**: The root container for a radio button.
|
|
||||||
- **RadioGroup.ItemInput**: The native html input that is visually hidden in the radio button.
|
|
||||||
- **RadioGroup.ItemControl**: The element that visually represents a radio button.
|
|
||||||
- **RadioGroup.ItemIndicator**: The visual indicator rendered when the radio button is in a checked state.
|
|
||||||
- **RadioGroup.ItemLabel**: The label that gives the user information on the radio button.
|
|
||||||
- **RadioGroup.ItemDescription**: The description that gives the user more information on the radio button.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RadioGroup>
|
|
||||||
<RadioGroup.Label />
|
|
||||||
<RadioGroup.Item>
|
|
||||||
<RadioGroup.ItemInput />
|
|
||||||
<RadioGroup.ItemControl>
|
|
||||||
<RadioGroup.ItemIndicator />
|
|
||||||
</RadioGroup.ItemControl>
|
|
||||||
<RadioGroup.ItemLabel />
|
|
||||||
<RadioGroup.ItemDescription />
|
|
||||||
</RadioGroup.Item>
|
|
||||||
<RadioGroup.Description />
|
|
||||||
<RadioGroup.ErrorMessage />
|
|
||||||
</RadioGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RadioGroup>
|
|
||||||
<RadioGroup.Label />
|
|
||||||
<RadioGroup.Item>
|
|
||||||
<RadioGroup.ItemInput />
|
|
||||||
<RadioGroup.ItemControl>
|
|
||||||
<RadioGroup.ItemIndicator />
|
|
||||||
</RadioGroup.ItemControl>
|
|
||||||
<RadioGroup.ItemLabel />
|
|
||||||
<RadioGroup.ItemDescription />
|
|
||||||
</RadioGroup.Item>
|
|
||||||
<RadioGroup.Description />
|
|
||||||
<RadioGroup.ErrorMessage />
|
|
||||||
</RadioGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { RadioGroup } from "@kobalte/core/radio-group";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<RadioGroup class="radio-group">
|
|
||||||
<RadioGroup.Label class="radio-group__label">Favorite fruit</RadioGroup.Label>
|
|
||||||
<div class="radio-group__items" role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => (
|
|
||||||
<RadioGroup.Item value={fruit} class="radio">
|
|
||||||
<RadioGroup.ItemInput class="radio__input" />
|
|
||||||
<RadioGroup.ItemControl class="radio__control">
|
|
||||||
<RadioGroup.ItemIndicator class="radio__indicator" />
|
|
||||||
</RadioGroup.ItemControl>
|
|
||||||
<RadioGroup.ItemLabel class="radio__label">{fruit}</RadioGroup.ItemLabel>
|
|
||||||
</RadioGroup.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { RadioGroup } from "@kobalte/core/radio-group";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<RadioGroup class="radio-group">
|
|
||||||
<RadioGroup.Label class="radio-group__label">Favorite fruit</RadioGroup.Label>
|
|
||||||
<div class="radio-group__items" role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => (
|
|
||||||
<RadioGroup.Item value={fruit} class="radio">
|
|
||||||
<RadioGroup.ItemInput class="radio__input" />
|
|
||||||
<RadioGroup.ItemControl class="radio__control">
|
|
||||||
<RadioGroup.ItemIndicator class="radio__indicator" />
|
|
||||||
</RadioGroup.ItemControl>
|
|
||||||
<RadioGroup.ItemLabel class="radio__label">{fruit}</RadioGroup.ItemLabel>
|
|
||||||
</RadioGroup.Item>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultValue` prop, which accepts a value corresponding with the `value` prop of each radio.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RadioGroup defaultValue="Orange">
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RadioGroup defaultValue="Orange">
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
The `role="presentation"` is required for all non content elements between the `RadioGroup` and `RadioGroup.Item` due to a bug in Chromium based browsers that incorrectly parse semantics and break screen readers.
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `value` prop, which accepts a value corresponding with the `value` prop of each radio, can be used to make the value controlled. The `onChange` event is fired when the user selects a radio, and receives the new value.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
Your favorite fruit is: Orange.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<RadioGroup value={value()} onChange={setValue}>
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
<p>Your favorite fruit is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<RadioGroup value={value()} onChange={setValue}>
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
<p>Your favorite fruit is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `RadioGroup.Description` component can be used to associate additional help text with a radio group.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
Choose the fruit you like the most.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RadioGroup>
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<RadioGroup.Description>Choose the fruit you like the most.</RadioGroup.Description>
|
|
||||||
</RadioGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<RadioGroup>
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<RadioGroup.Description>Choose the fruit you like the most.</RadioGroup.Description>
|
|
||||||
</RadioGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `RadioGroup.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the radio group as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
Hmm, I prefer apples.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RadioGroup
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "Apple" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<RadioGroup.ErrorMessage>Hmm, I prefer apples.</RadioGroup.ErrorMessage>
|
|
||||||
</RadioGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RadioGroup
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "Apple" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
<RadioGroup.ErrorMessage>Hmm, I prefer apples.</RadioGroup.ErrorMessage>
|
|
||||||
</RadioGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The radio group `name` prop, paired with the radio `value` prop, can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Apple
|
|
||||||
|
|
||||||
Orange
|
|
||||||
|
|
||||||
Watermelon
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<RadioGroup name="favorite-fruit">
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<RadioGroup name="favorite-fruit">
|
|
||||||
<RadioGroup.Label>Favorite fruit</RadioGroup.Label>
|
|
||||||
<div role="presentation">
|
|
||||||
<For each={["Apple", "Orange", "Watermelon"]}>
|
|
||||||
{fruit => <RadioGroup.Item value={fruit}>...</RadioGroup.Item>}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### RadioGroup
|
|
||||||
|
|
||||||
`RadioGroup` is equivalent to the `Root` import from `@kobalte/core/radio-group` (and deprecated `RadioGroup.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the radio button to check. |
|
|
||||||
| defaultValue | `string`<br> The value of the radio button that should be checked when initially rendered. Useful when you do not need to control the state of the radio buttons. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value changes. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The axis the radio group items should align with. |
|
|
||||||
| name | `string`<br> The name of the radio group. Submitted with its owning form as part of a name/value pair. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the radio group should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check a radio group item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the radio group items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the radio group is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the radio group is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must check a radio group item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the radio group is disabled. |
|
|
||||||
| data-readonly | Present when the radio group is read only. |
|
|
||||||
|
|
||||||
`RadioGroup.Label`, `RadioGroup.Description` and `RadioGroup.ErrorMesssage` shares the same data-attributes.
|
|
||||||
|
|
||||||
### RadioGroup.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
### RadioGroup.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The value of the radio button, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio#Value). |
|
|
||||||
| disabled | `boolean`<br> Whether the radio button is disabled or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the parent radio group is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the parent radio group is invalid according to the validation rules. |
|
|
||||||
| data-checked | Present when the radio is checked. |
|
|
||||||
| data-disabled | Present when the radio is disabled. |
|
|
||||||
|
|
||||||
`RadioGroup.ItemInput`, `RadioGroup.ItemControl`, `RadioGroup.ItemIndicator` and `RadioGroup.ItemLabel` shares the same data-attributes.
|
|
||||||
|
|
||||||
### RadioGroup.ItemIndicator
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `RadioGroup` | `div` |
|
|
||||||
| `RadioGroup.Label` | `span` |
|
|
||||||
| `RadioGroup.Description` | `div` |
|
|
||||||
| `RadioGroup.ErrorMessage` | `div` |
|
|
||||||
| `RadioGroup.Item` | `div` |
|
|
||||||
| `RadioGroup.ItemInput` | `input` |
|
|
||||||
| `RadioGroup.ItemControl` | `div` |
|
|
||||||
| `RadioGroup.ItemIndicator` | `div` |
|
|
||||||
| `RadioGroup.ItemLabel` | `label` |
|
|
||||||
| `RadioGroup.ItemDescription` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tab` | Moves focus to either the checked radio button or the first radio button in the group. |
|
|
||||||
| `Space` | When focus is on an unchecked radio button, checks it. |
|
|
||||||
| `ArrowDown` | Moves focus and checks the next radio button in the group. |
|
|
||||||
| `ArrowRight` | Moves focus and checks the next radio button in the group. |
|
|
||||||
| `ArrowUp` | Moves focus and checks the previous radio button in the group. |
|
|
||||||
| `ArrowLeft` | Moves focus and checks the previous radio button in the group. |
|
|
||||||
|
|
||||||
Previous[←Progress](https://kobalte.dev/docs/core/components/progress)Next[Rating Group→](https://kobalte.dev/docs/core/components/rating-group)
|
|
||||||
@ -1,110 +0,0 @@
|
|||||||
# Separator
|
|
||||||
|
|
||||||
Visually or semantically separates content.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Separator } from "@kobalte/core/separator";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/separator";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Separator } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Separator } from "@kobalte/core/separator";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/separator";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Separator } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Native HTML `<hr>` element support.
|
|
||||||
- Custom element type support via the [WAI ARIA Separator](https://w3c.github.io/aria/#separator) role.
|
|
||||||
- Support for horizontal and vertical orientation.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The separator consists of:
|
|
||||||
|
|
||||||
- **Separator:** The root container for a separator.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Separator />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Separator />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Content above
|
|
||||||
|
|
||||||
* * *
|
|
||||||
|
|
||||||
Content below
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Separator } from "@kobalte/core/separator";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<span>Content above</span>
|
|
||||||
<Separator class="separator" />
|
|
||||||
<span>Content below</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Separator } from "@kobalte/core/separator";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<span>Content above</span>
|
|
||||||
<Separator class="separator" />
|
|
||||||
<span>Content below</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Separator
|
|
||||||
|
|
||||||
`Separator` is equivalent to the `Root` import from `@kobalte/core/separator` (and deprecated `Separator.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The orientation of the separator. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Present when the separator has horizontal orientation. |
|
|
||||||
| data-orientation='vertical' | Present when the separator has vertical orientation. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Separator` | `hr` |
|
|
||||||
|
|
||||||
Previous[←Select](https://kobalte.dev/docs/core/components/select)Next[Skeleton→](https://kobalte.dev/docs/core/components/skeleton)
|
|
||||||
@ -1,244 +0,0 @@
|
|||||||
# Skeleton
|
|
||||||
|
|
||||||
Visually indicates content loading
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/skeleton";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Skeleton } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/skeleton";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Skeleton } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Support for custom width and height.
|
|
||||||
- Support for circle skeleton.
|
|
||||||
- Can toggle visiblity and animation properties.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The skeleton consists of:
|
|
||||||
|
|
||||||
- **Skeleton:** The root container for a skeleton.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Skeleton />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Skeleton />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Skeleton class="skeleton" radius={10}>
|
|
||||||
<p>
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</p>
|
|
||||||
</Skeleton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Skeleton class="skeleton" radius={10}>
|
|
||||||
<p>
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</p>
|
|
||||||
</Skeleton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Multiple skeletons
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Kobalte
|
|
||||||
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
import { Image } from "@kobalte/core/image";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div class="multiple-root">
|
|
||||||
<div class="multiple-profile">
|
|
||||||
<Skeleton class="skeleton" height={50} circle>
|
|
||||||
<Image class="multiple-avatar">
|
|
||||||
<Image.Img
|
|
||||||
class="image__img"
|
|
||||||
src="https://pbs.twimg.com/profile_images/1509139491671445507/pzWYjlYN_400x400.jpg"
|
|
||||||
alt="Nicole Steeves"
|
|
||||||
/>
|
|
||||||
</Image>
|
|
||||||
</Skeleton>
|
|
||||||
<Skeleton class="skeleton" height={20} radius={10}>
|
|
||||||
Kobalte
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
<Skeleton class="skeleton" radius={10}>
|
|
||||||
<p>
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</p>
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
import { Image } from "@kobalte/core/image";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div class="multiple-root">
|
|
||||||
<div class="multiple-profile">
|
|
||||||
<Skeleton class="skeleton" height={50} circle>
|
|
||||||
<Image class="multiple-avatar">
|
|
||||||
<Image.Img
|
|
||||||
class="image__img"
|
|
||||||
src="https://pbs.twimg.com/profile_images/1509139491671445507/pzWYjlYN_400x400.jpg"
|
|
||||||
alt="Nicole Steeves"
|
|
||||||
/>
|
|
||||||
</Image>
|
|
||||||
</Skeleton>
|
|
||||||
<Skeleton class="skeleton" height={20} radius={10}>
|
|
||||||
Kobalte
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
<Skeleton class="skeleton" radius={10}>
|
|
||||||
<p>
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</p>
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Toggle example
|
|
||||||
|
|
||||||
Show content
|
|
||||||
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
import { ToggleButton } from "@kobalte/core/toggle-button";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [visible, setVisible] = createSignal(true);
|
|
||||||
return (
|
|
||||||
<div class="toggle-root">
|
|
||||||
<ToggleButton class="toggle-button" pressed={visible()} onChange={setVisible}>
|
|
||||||
Skeleton {visible() ? "Visible" : "Not Visible"}
|
|
||||||
</ToggleButton>
|
|
||||||
<Skeleton class="skeleton" visible={visible()}>
|
|
||||||
<p>
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</p>
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Skeleton } from "@kobalte/core/skeleton";
|
|
||||||
import { ToggleButton } from "@kobalte/core/toggle-button";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [visible, setVisible] = createSignal(true);
|
|
||||||
return (
|
|
||||||
<div class="toggle-root">
|
|
||||||
<ToggleButton class="toggle-button" pressed={visible()} onChange={setVisible}>
|
|
||||||
Skeleton {visible() ? "Visible" : "Not Visible"}
|
|
||||||
</ToggleButton>
|
|
||||||
<Skeleton class="skeleton" visible={visible()}>
|
|
||||||
<p>
|
|
||||||
A UI toolkit for building accessible web apps and design systems with SolidJS.
|
|
||||||
</p>
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Skeleton
|
|
||||||
|
|
||||||
`Skeleton` is equivalent to the `Root` import from `@kobalte/core/skeleton` (and deprecated `Skeleton.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| visible | `boolean`<br> The visible state of the Skeleton. Sets the `data-visible` data attribute. |
|
|
||||||
| animate | `boolean`<br> Whether the skeleton should animate. Sets the `data-animate` data attribute. |
|
|
||||||
| width | `number`<br> The width of the skeleton in px. Defaults to 100%. |
|
|
||||||
| height | `number`<br> The height of the skeleton in px. Defaults to auto. |
|
|
||||||
| radius | `number`<br> Roundness of the skeleton in px. Sets border-radius. |
|
|
||||||
| circle | `boolean`<br> Whether the skeleton should be a circle. Sets border-radius and width to the height. |
|
|
||||||
| children | `JSX.Element`<br> The children of the Skeleton. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-visible | Present when the Skeleton is visible. |
|
|
||||||
| data-animate | Present when the Skeleton can animate. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Skeleton` | `div` |
|
|
||||||
|
|
||||||
Previous[←Separator](https://kobalte.dev/docs/core/components/separator)Next[Slider→](https://kobalte.dev/docs/core/components/slider)
|
|
||||||
@ -1,638 +0,0 @@
|
|||||||
# Slider
|
|
||||||
|
|
||||||
An input where the user selects a value from within a given range.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
// or
|
|
||||||
import { Root, Track, ... } from "@kobalte/core/slider";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Slider } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
// or
|
|
||||||
import { Root, Track, ... } from "@kobalte/core/slider";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Slider } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Slider](https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/) design pattern.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
- Support for multiple thumbs.
|
|
||||||
- Support a minimum step between thumbs.
|
|
||||||
- Support click or touch on track to change value.
|
|
||||||
- Support right or left direction.
|
|
||||||
- Support for custom value label.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The slider consists of:
|
|
||||||
|
|
||||||
- **Slider:** The root container for the slider.
|
|
||||||
- **Slider.Track:** The component that visually represents the slider track.
|
|
||||||
- **Slider.Fill:** The component that visually represents the slider value.
|
|
||||||
- **Slider.Thumb:** The thumb that is used to visually indicate a value in the slider.
|
|
||||||
- **Slider.Input:** The native html input that is visually hidden in the slider thumb.
|
|
||||||
- **Slider.Label:** The label that gives the user information on the slider.
|
|
||||||
- **Slider.ValueLabel:** The accessible label text representing the current value in a human-readable format.
|
|
||||||
- **Slider.Description**: The description that gives the user more information on the slider.
|
|
||||||
- **Slider.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the slider.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Slider>
|
|
||||||
<Slider.Label />
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
<Slider.Track>
|
|
||||||
<Slider.Fill />
|
|
||||||
<Slider.Thumb>
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
<Slider.Description />
|
|
||||||
<Slider.ErrorMessage />
|
|
||||||
</Slider>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Slider>
|
|
||||||
<Slider.Label />
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
<Slider.Track>
|
|
||||||
<Slider.Fill />
|
|
||||||
<Slider.Thumb>
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
<Slider.Description />
|
|
||||||
<Slider.ErrorMessage />
|
|
||||||
</Slider>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot">
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot">
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Multiple Thumbs
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
0, 20
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" defaultValue={[0, 20]}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" defaultValue={[0, 20]}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Modify step size
|
|
||||||
|
|
||||||
Step size 8
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
Step size 10
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
Step size 20
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Slider class="SliderRoot" step={8}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Step size 8</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
<Slider class="SliderRoot" step={10}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Step size 10</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
<Slider class="SliderRoot" step={20}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Step size 20</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Slider class="SliderRoot" step={8}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Step size 8</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
<Slider class="SliderRoot" step={10}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Step size 10</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
<Slider class="SliderRoot" step={20}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Step size 20</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Steps between thumbs
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
10, 20
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" defaultValue={[10, 20]} minStepsBetweenThumbs={10}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" defaultValue={[10, 20]} minStepsBetweenThumbs={10}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vertical Slider
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
0
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" orientation="vertical">
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" orientation="vertical">
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Value Label
|
|
||||||
|
|
||||||
Money
|
|
||||||
|
|
||||||
$20 - $500
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot"
|
|
||||||
minValue={10}
|
|
||||||
maxValue={2000}
|
|
||||||
defaultValue={[20, 500]}
|
|
||||||
getValueLabel={params => `$${params.values[0]} - $${params.values[1]}`}
|
|
||||||
>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Money</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot"
|
|
||||||
minValue={10}
|
|
||||||
maxValue={2000}
|
|
||||||
defaultValue={[20, 500]}
|
|
||||||
getValueLabel={params => `$${params.values[0]} - $${params.values[1]}`}
|
|
||||||
>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Money</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
<Slider.Thumb class="SliderThumb SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled Value
|
|
||||||
|
|
||||||
Label
|
|
||||||
|
|
||||||
40
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from 'solid-js'
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [values, setValues] = createSignal<number[]>([40])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" value={values()} onChange={setValues}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from 'solid-js'
|
|
||||||
import { Slider } from "@kobalte/core/slider";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const [values, setValues] = createSignal<number[]>([40])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Slider class="SliderRoot" value={values()} onChange={setValues}>
|
|
||||||
<div class="SliderLabel">
|
|
||||||
<Slider.Label>Label</Slider.Label>
|
|
||||||
<Slider.ValueLabel />
|
|
||||||
</div>
|
|
||||||
<Slider.Track class="SliderTrack">
|
|
||||||
<Slider.Fill class="SliderRange" />
|
|
||||||
<Slider.Thumb class="SliderThumb">
|
|
||||||
<Slider.Input />
|
|
||||||
</Slider.Thumb>
|
|
||||||
</Slider.Track>
|
|
||||||
</Slider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Slider
|
|
||||||
|
|
||||||
`Slider` is equivalent to the `Root` import from `@kobalte/core/slider` (and deprecated `Slider.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `number[]`<br> The controlled values of the slider. Must be used in conjunction with `onChange`. |
|
|
||||||
| defaultValue | `number[]`<br> The value of the slider when initially rendered. Use when you do not need to control the state of the slider. |
|
|
||||||
| onChange | `(value: number[]) => void`<br> Event handler called when the value changes. |
|
|
||||||
| onChangeEnd | `(value: number[]) => void`<br> Event handler called when the value changes at the end of an interaction. |
|
|
||||||
| inverted | `boolean`<br> Whether the slider is visually inverted. Defaults to false. |
|
|
||||||
| minValue | `number`<br> The minimum slider value. Defaults to 0 |
|
|
||||||
| maxValue | `number`<br> The maximum slider value. Defaults to 100 |
|
|
||||||
| step | `number`<br> The stepping interval. Defaults to 1 |
|
|
||||||
| minStepsBetweenThumbs | `number`<br> The minimum permitted steps between thumbs. Defaults to 0 |
|
|
||||||
| getValueLabel | `(params: GetValueLabelParams) => string`<br> A function to get the accessible label text representing the current value in a human-readable format. If not provided, the value label will be read as a percentage of the max value. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The orientation of the slider. |
|
|
||||||
| name | `string`<br> The name of the slider, used when submitting an HTML form. |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the slider should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check a radio group item before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the radio group is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the radio group items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Present when the slider has horizontal orientation. |
|
|
||||||
| data-orientation='vertical' | Present when the slider has vertical orientation. |
|
|
||||||
| data-valid | Present when the slider is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the slider is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must slider an item before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the slider is disabled. |
|
|
||||||
| data-readonly | Present when the slider is read only. |
|
|
||||||
|
|
||||||
`Slider.ValueLabel`, `Slider.Fill`, `Slider.Input`, `Slider.Thumb` and `Slider.Track` share the same data-attributes.
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Slider` | `div` |
|
|
||||||
| `Slider.Track` | `div` |
|
|
||||||
| `Slider.Fill` | `div` |
|
|
||||||
| `Slider.Thumb` | `span` |
|
|
||||||
| `Slider.Input` | `input` |
|
|
||||||
| `Slider.ValueLabel` | `div` |
|
|
||||||
| `Slider.Description` | `div` |
|
|
||||||
| `Slider.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `PageUp` | Increases the value of the focused thumb by a larger `step`. |
|
|
||||||
| `PageDown` | Decreases the value of the focused thumb by a larger `step`. |
|
|
||||||
| `ArrowDown` | Decreases the value of the focused thumb by the `step` amount. |
|
|
||||||
| `ArrowUp` | Increases the value of the focused thumb by the `step` amount. |
|
|
||||||
| `ArrowRight` | Increments/decrements by the `step` value depending on `orientation`. |
|
|
||||||
| `ArrowLeft` | Increments/decrements by the `step` value depending on `orientation`. |
|
|
||||||
| `Home` | Sets the value of the first thumb to the minimum value. |
|
|
||||||
| `End` | Sets the value of the last thumb to the maximum value. |
|
|
||||||
|
|
||||||
Previous[←Skeleton](https://kobalte.dev/docs/core/components/skeleton)Next[Switch→](https://kobalte.dev/docs/core/components/switch)
|
|
||||||
@ -1,373 +0,0 @@
|
|||||||
# Switch
|
|
||||||
|
|
||||||
A control that allows users to choose one of two values: on or off.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Switch } from "@kobalte/core/switch";
|
|
||||||
// or
|
|
||||||
import { Root, Input, ... } from "@kobalte/core/switch";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Switch } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Switch } from "@kobalte/core/switch";
|
|
||||||
// or
|
|
||||||
import { Root, Input, ... } from "@kobalte/core/switch";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Switch } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/) design pattern.
|
|
||||||
- Built with a native HTML `<input>` element, which is visually hidden to allow custom styling.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Labeling support for assistive technology.
|
|
||||||
- Support for description and error message help text linked to the input via ARIA.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The switch consists of:
|
|
||||||
|
|
||||||
- **Switch:** The root container for a switch.
|
|
||||||
- **Switch.Input:** The native html input that is visually hidden in the switch.
|
|
||||||
- **Switch.Control:** The element that visually represents a switch.
|
|
||||||
- **Switch.Thumb:** The thumb that is used to visually indicate whether the switch is on or off.
|
|
||||||
- **Switch.Label:** The label that gives the user information on the switch.
|
|
||||||
- **Switch.Description**: The description that gives the user more information on the switch.
|
|
||||||
- **Switch.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the switch.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Switch>
|
|
||||||
<Switch.Label />
|
|
||||||
<Switch.Description />
|
|
||||||
<Switch.ErrorMessage />
|
|
||||||
<Switch.Input />
|
|
||||||
<Switch.Control>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Switch>
|
|
||||||
<Switch.Label />
|
|
||||||
<Switch.Description />
|
|
||||||
<Switch.ErrorMessage />
|
|
||||||
<Switch.Input />
|
|
||||||
<Switch.Control>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Airplane mode
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Switch } from "@kobalte/core/switch";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Switch class="switch">
|
|
||||||
<Switch.Label class="switch__label">Airplane mode</Switch.Label>
|
|
||||||
<Switch.Input class="switch__input" />
|
|
||||||
<Switch.Control class="switch__control">
|
|
||||||
<Switch.Thumb class="switch__thumb" />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Switch } from "@kobalte/core/switch";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Switch class="switch">
|
|
||||||
<Switch.Label class="switch__label">Airplane mode</Switch.Label>
|
|
||||||
<Switch.Input class="switch__input" />
|
|
||||||
<Switch.Control class="switch__control">
|
|
||||||
<Switch.Thumb class="switch__thumb" />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default checked
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultChecked` prop.
|
|
||||||
|
|
||||||
Airplane mode
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Switch defaultChecked>...</Switch>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Switch defaultChecked>...</Switch>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled checked
|
|
||||||
|
|
||||||
The `checked` prop can be used to make the checked state controlled. The `onChange` event is fired when the user toggle the switch, and receives the new value.
|
|
||||||
|
|
||||||
Airplane mode
|
|
||||||
|
|
||||||
Airplane mode is inactive.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
export function ControlledExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Switch checked={checked()} onChange={setChecked}>
|
|
||||||
...
|
|
||||||
</Switch>
|
|
||||||
<p>Airplane mode is {checked() ? "active" : "inactive"}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
export function ControlledExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Switch checked={checked()} onChange={setChecked}>
|
|
||||||
...
|
|
||||||
</Switch>
|
|
||||||
<p>Airplane mode is {checked() ? "active" : "inactive"}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `Switch.Description` component can be used to associate additional help text with a switch.
|
|
||||||
|
|
||||||
Airplane mode
|
|
||||||
|
|
||||||
Disable all network connections.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Switch>
|
|
||||||
<Switch.Label>Airplane mode</Switch.Label>
|
|
||||||
<Switch.Description>Disable all network connections.</Switch.Description>
|
|
||||||
<Switch.Input />
|
|
||||||
<Switch.Control>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Switch>
|
|
||||||
<Switch.Label>Airplane mode</Switch.Label>
|
|
||||||
<Switch.Description>Disable all network connections.</Switch.Description>
|
|
||||||
<Switch.Input />
|
|
||||||
<Switch.Control>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `Switch.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the switch as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Airplane mode
|
|
||||||
|
|
||||||
You must enable airplane mode.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Switch
|
|
||||||
checked={checked()}
|
|
||||||
onChange={setChecked}
|
|
||||||
validationState={!checked() ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<Switch.Label>Airplane mode</Switch.Label>
|
|
||||||
<Switch.ErrorMessage>You must enable airplane mode.</Switch.ErrorMessage>
|
|
||||||
<Switch.Input />
|
|
||||||
<Switch.Control>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [checked, setChecked] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Switch
|
|
||||||
checked={checked()}
|
|
||||||
onChange={setChecked}
|
|
||||||
validationState={!checked() ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<Switch.Label>Airplane mode</Switch.Label>
|
|
||||||
<Switch.ErrorMessage>You must enable airplane mode.</Switch.ErrorMessage>
|
|
||||||
<Switch.Input />
|
|
||||||
<Switch.Control>
|
|
||||||
<Switch.Thumb />
|
|
||||||
</Switch.Control>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The `name` and `value` props can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Airplane mode
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<Switch name="airplane-mode" value="on">
|
|
||||||
...
|
|
||||||
</Switch>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<Switch name="airplane-mode" value="on">
|
|
||||||
...
|
|
||||||
</Switch>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Switch
|
|
||||||
|
|
||||||
`Switch` is equivalent to the `Root` import from `@kobalte/core/switch` (and deprecated `Switch.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `boolean`<br> The controlled checked state of the switch. |
|
|
||||||
| defaultChecked | `boolean`<br> The default checked state when initially rendered. Useful when you do not need to control the checked state. |
|
|
||||||
| onChange | `(checked: boolean) => void`<br> Event handler called when the checked state of the switch changes. |
|
|
||||||
| name | `string`<br> The name of the switch, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| value | `string`<br> The value of the switch, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefvalue). |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the switch should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must check the switch before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the switch is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the switch can be checked but not changed by the user. |
|
|
||||||
|
|
||||||
| Render Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| checked | `Accessor<boolean>`<br> Whether the switch is checked or not. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the switch is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the switch is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the switch is required. |
|
|
||||||
| data-disabled | Present when the switch is disabled. |
|
|
||||||
| data-readonly | Present when the switch is read only. |
|
|
||||||
| data-checked | Present when the switch is checked. |
|
|
||||||
|
|
||||||
`Switch.Input`, `Switch.Control`, `Switch.Thumb`, `Switch.Label`, `Switch.Description` and `Switch.ErrorMessage` shares the same data-attributes.
|
|
||||||
|
|
||||||
### Switch.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Switch` | `div` |
|
|
||||||
| `Switch.Input` | `input` |
|
|
||||||
| `Switch.Control` | `div` |
|
|
||||||
| `Switch.Indicator` | `div` |
|
|
||||||
| `Switch.Label` | `label` |
|
|
||||||
| `Switch.Description` | `div` |
|
|
||||||
| `Switch.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | Toggles the switch on and off. |
|
|
||||||
|
|
||||||
Previous[←Slider](https://kobalte.dev/docs/core/components/slider)Next[Tabs→](https://kobalte.dev/docs/core/components/tabs)
|
|
||||||
@ -1,631 +0,0 @@
|
|||||||
# Tabs
|
|
||||||
|
|
||||||
A set of layered sections of content, known as tab panels, that display one panel of content at a time.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Tabs } from "@kobalte/core/tabs";
|
|
||||||
// or
|
|
||||||
import { Root, List, ... } from "@kobalte/core/tabs";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Tabs } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Tabs } from "@kobalte/core/tabs";
|
|
||||||
// or
|
|
||||||
import { Root, List, ... } from "@kobalte/core/tabs";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Tabs } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Follow the [WAI ARIA Tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/) design pattern, semantically linking tabs and their associated tab panels.
|
|
||||||
- Support for LTR and RTL keyboard navigation.
|
|
||||||
- Support for disabled tabs.
|
|
||||||
- Supports horizontal/vertical orientation.
|
|
||||||
- Supports automatic/manual activation.
|
|
||||||
- Focus management for tab panels without any focusable children.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The tabs consist of:
|
|
||||||
|
|
||||||
- **Tabs:** The root container for tabs and tab contents.
|
|
||||||
- **Tabs.List:** Contains the tabs that are aligned along the edge of the active tab content.
|
|
||||||
- **Tabs.Trigger:** The button that activates its associated tab content.
|
|
||||||
- **Tabs.Indicator:** The visual indicator displayed at the bottom of the tab list to indicate the selected tab.
|
|
||||||
- **Tabs.Content:** Contains the content associated with a tab trigger.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger />
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content />
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger />
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content />
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Profile details
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Tabs } from "@kobalte/core/tabs";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Tabs aria-label="Main navigation" class="tabs">
|
|
||||||
<Tabs.List class="tabs__list">
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator class="tabs__indicator" />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content class="tabs__content" value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content class="tabs__content" value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content class="tabs__content" value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content class="tabs__content" value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Tabs } from "@kobalte/core/tabs";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Tabs aria-label="Main navigation" class="tabs">
|
|
||||||
<Tabs.List class="tabs__list">
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger class="tabs__trigger" value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator class="tabs__indicator" />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content class="tabs__content" value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content class="tabs__content" value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content class="tabs__content" value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content class="tabs__content" value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
A default selected tab can be provided using the `defaultValue` prop, which should correspond to the `value` prop provided to each tab.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Dashboard details
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs defaultValue="dashboard">
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs defaultValue="dashboard">
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
Selected tab can be controlled using the `value` prop, paired with the `onChange` event. The `value` prop from the selected tab will be passed into the callback when the tab is selected, allowing you to update state accordingly.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Settings details
|
|
||||||
|
|
||||||
Selected tab: settings
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [selectedTab, setSelectedTab] = createSignal("settings");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Tabs value={selectedTab()} onChange={setSelectedTab}>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
<p>Selected tab: {selectedTab()}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [selectedTab, setSelectedTab] = createSignal("settings");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Tabs value={selectedTab()} onChange={setSelectedTab}>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
<p>Selected tab: {selectedTab()}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Focusable content
|
|
||||||
|
|
||||||
When the tab content doesn't contain any focusable content, the entire content is given a `tabIndex=0` so that the content can be navigated to with the keyboard.
|
|
||||||
|
|
||||||
When the tab content contains focusable content, such as an `<input>`, then the `tabIndex` is omitted because the content itself can receive focus.
|
|
||||||
|
|
||||||
This example uses the same Tabs components from above. Try navigating from the tabs to each content using the keyboard.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function FocusableContentExample() {
|
|
||||||
return (
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">
|
|
||||||
<input placeholder="Change password" />
|
|
||||||
</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function FocusableContentExample() {
|
|
||||||
return (
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">
|
|
||||||
<input placeholder="Change password" />
|
|
||||||
</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dynamic tabs
|
|
||||||
|
|
||||||
Tabs can be added/removed dynamically by using a signal and SolidJS `For`.
|
|
||||||
|
|
||||||
Add tabRemove tab
|
|
||||||
|
|
||||||
Tab 1Tab 2Tab 3
|
|
||||||
|
|
||||||
Tab body 1
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function DynamicContentExample() {
|
|
||||||
const [tabs, setTabs] = createSignal([\
|
|
||||||
{ id: "1", title: "Tab 1", content: "Tab body 1" },\
|
|
||||||
{ id: "2", title: "Tab 2", content: "Tab body 2" },\
|
|
||||||
{ id: "3", title: "Tab 3", content: "Tab body 3" },\
|
|
||||||
]);
|
|
||||||
|
|
||||||
const addTab = () => {
|
|
||||||
setTabs(prev => [\
|
|
||||||
...prev,\
|
|
||||||
{\
|
|
||||||
id: String(prev.length + 1),\
|
|
||||||
title: `Tab ${prev.length + 1}`,\
|
|
||||||
content: `Tab Body ${prev.length + 1}`,\
|
|
||||||
},\
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeTab = () => {
|
|
||||||
if (tabs().length > 1) {
|
|
||||||
setTabs(prev => prev.slice(0, -1));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={addTab}>Add tab</button>
|
|
||||||
<button onClick={removeTab}>Remove tab</button>
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<For each={tabs()}>{tab => <Tabs.Trigger value={tab.id}>{tab.title}</Tabs.Trigger>}</For>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<For each={tabs()}>{tab => <Tabs.Content value={tab.id}>{tab.content}</Tabs.Content>}</For>
|
|
||||||
</Tabs>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function DynamicContentExample() {
|
|
||||||
const [tabs, setTabs] = createSignal([\
|
|
||||||
{ id: "1", title: "Tab 1", content: "Tab body 1" },\
|
|
||||||
{ id: "2", title: "Tab 2", content: "Tab body 2" },\
|
|
||||||
{ id: "3", title: "Tab 3", content: "Tab body 3" },\
|
|
||||||
]);
|
|
||||||
|
|
||||||
const addTab = () => {
|
|
||||||
setTabs(prev => [\
|
|
||||||
...prev,\
|
|
||||||
{\
|
|
||||||
id: String(prev.length + 1),\
|
|
||||||
title: `Tab ${prev.length + 1}`,\
|
|
||||||
content: `Tab Body ${prev.length + 1}`,\
|
|
||||||
},\
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeTab = () => {
|
|
||||||
if (tabs().length > 1) {
|
|
||||||
setTabs(prev => prev.slice(0, -1));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button onClick={addTab}>Add tab</button>
|
|
||||||
<button onClick={removeTab}>Remove tab</button>
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<For each={tabs()}>{tab => <Tabs.Trigger value={tab.id}>{tab.title}</Tabs.Trigger>}</For>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<For each={tabs()}>{tab => <Tabs.Content value={tab.id}>{tab.content}</Tabs.Content>}</For>
|
|
||||||
</Tabs>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Activation mode
|
|
||||||
|
|
||||||
By default, pressing the arrow keys while focus is on a Tab will switch selection to the adjacent Tab in that direction, updating the content displayed accordingly.
|
|
||||||
|
|
||||||
If you would like to prevent selection change from happening automatically you can set the `activationMode` prop to `manual`. This will prevent tab selection from changing on arrow key press, requiring a subsequent `Enter` or `Space` key press to confirm tab selection.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Profile details
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs activationMode="manual">
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs activationMode="manual">
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Orientation
|
|
||||||
|
|
||||||
By default, tabs are horizontally oriented. The `orientation` prop can be set to `vertical` to change this. This affects keyboard navigation. You are responsible for styling your tabs accordingly.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Profile details
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs orientation="vertical">
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs orientation="vertical">
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Disabled
|
|
||||||
|
|
||||||
All tabs can be disabled using the `disabled` prop.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Profile details
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs disabled>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs disabled>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
Individual tab can be disabled using the `disabled` prop on the tab itself.
|
|
||||||
|
|
||||||
ProfileDashboardSettingsContact
|
|
||||||
|
|
||||||
Profile details
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings" disabled>
|
|
||||||
Settings
|
|
||||||
</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tabs>
|
|
||||||
<Tabs.List>
|
|
||||||
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="dashboard">Dashboard</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="settings" disabled>
|
|
||||||
Settings
|
|
||||||
</Tabs.Trigger>
|
|
||||||
<Tabs.Trigger value="contact">Contact</Tabs.Trigger>
|
|
||||||
<Tabs.Indicator />
|
|
||||||
</Tabs.List>
|
|
||||||
<Tabs.Content value="profile">Profile details</Tabs.Content>
|
|
||||||
<Tabs.Content value="dashboard">Dashboard details</Tabs.Content>
|
|
||||||
<Tabs.Content value="settings">Settings details</Tabs.Content>
|
|
||||||
<Tabs.Content value="contact">Contact details</Tabs.Content>
|
|
||||||
</Tabs>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Tabs
|
|
||||||
|
|
||||||
`Tabs` is equivalent to the `Root` import from `@kobalte/core/tabs` (and deprecated `Tabs.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the tab to activate. |
|
|
||||||
| defaultValue | `string`<br> The value of the tab that should be active when initially rendered. Useful when you do not need to control the state. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value changes. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The orientation of the tabs. |
|
|
||||||
| activationMode | `'automatic' | 'manual'`<br> Whether tabs are activated automatically on focus or manually. |
|
|
||||||
| disabled | `boolean`<br> Whether the tabs are disabled. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Present when the separator has horizontal orientation. |
|
|
||||||
| data-orientation='vertical' | Present when the separator has vertical orientation. |
|
|
||||||
|
|
||||||
`Tabs.List`, `Tabs.Trigger`, `Tabs.Indicator` and `Tabs.Content` share the same data-attributes.
|
|
||||||
|
|
||||||
### Tabs.Trigger
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The unique key that associates the tab with a tab panel. |
|
|
||||||
| disabled | `boolean`<br> Whether the tab should be disabled. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-selected | Present when the trigger is selected. |
|
|
||||||
| data-disabled | Present when the trigger is disabled. |
|
|
||||||
| data-highlighted | Present when the trigger is highlighted. |
|
|
||||||
|
|
||||||
### Tabs.Content
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The unique key that associates the tab panel with a tab. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-selected | Present when the associated trigger is selected. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tabs` | `div` |
|
|
||||||
| `Tabs.List` | `div` |
|
|
||||||
| `Tabs.Trigger` | `button` |
|
|
||||||
| `Tabs.Indicator` | `div` |
|
|
||||||
| `Tabs.Content` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tab` | When focus moves onto the tabs, focuses the active trigger.<br>When a trigger is focused, moves focus to the active content. |
|
|
||||||
| `ArrowDown` | Moves focus to the next trigger in vertical orientation and activates its associated content. |
|
|
||||||
| `ArrowRight` | Moves focus to the next trigger in horizontal orientation and activates its associated content. |
|
|
||||||
| `ArrowUp` | Moves focus to the previous trigger in vertical orientation and activates its associated content. |
|
|
||||||
| `ArrowLeft` | Moves focus to the previous trigger in horizontal orientation and activates its associated content. |
|
|
||||||
| `Home` | Moves focus to the first trigger and activates its associated content. |
|
|
||||||
| `End` | Moves focus to the last trigger and activates its associated content. |
|
|
||||||
| `Enter` | In manual mode, when a trigger is focused, moves focus to its associated content. |
|
|
||||||
| `Space` | In manual mode, when a trigger is focused, moves focus to its associated content. |
|
|
||||||
|
|
||||||
Previous[←Switch](https://kobalte.dev/docs/core/components/switch)Next[Text Field→](https://kobalte.dev/docs/core/components/text-field)
|
|
||||||
@ -1,394 +0,0 @@
|
|||||||
# Text Field
|
|
||||||
|
|
||||||
A text input that allow users to input custom text entries with a keyboard.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { TextField } from "@kobalte/core/text-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/text-field";
|
|
||||||
// or (deprecated)
|
|
||||||
import { TextField } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { TextField } from "@kobalte/core/text-field";
|
|
||||||
// or
|
|
||||||
import { Root, Label, ... } from "@kobalte/core/text-field";
|
|
||||||
// or (deprecated)
|
|
||||||
import { TextField } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Built with a native `<input>` or `<textarea>` element.
|
|
||||||
- Visual and ARIA labeling support.
|
|
||||||
- Required and invalid states exposed to assistive technology via ARIA.
|
|
||||||
- Support for description and error message help text linked to the input via ARIA.
|
|
||||||
- Syncs with form reset events.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The text field consists of:
|
|
||||||
|
|
||||||
- **TextField**: The root container for the text field.
|
|
||||||
- **TextField.Label**: The label that gives the user information on the text field.
|
|
||||||
- **TextField.Input**: The native HTML input of the text field, used for single line text.
|
|
||||||
- **TextField.TextArea**: The native HTML textarea of the text field, used for multiline text.
|
|
||||||
- **TextField.Description**: The description that gives the user more information on the text field.
|
|
||||||
- **TextField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the text field.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label />
|
|
||||||
<TextField.Input /> {/* or <TextField.TextArea /> */}
|
|
||||||
<TextField.Description />
|
|
||||||
<TextField.ErrorMessage />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label />
|
|
||||||
<TextField.Input /> {/* or <TextField.TextArea /> */}
|
|
||||||
<TextField.Description />
|
|
||||||
<TextField.ErrorMessage />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { TextField } from "@kobalte/core/text-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<TextField class="text-field">
|
|
||||||
<TextField.Label class="text-field__label">Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input class="text-field__input" />
|
|
||||||
</TextField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { TextField } from "@kobalte/core/text-field";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<TextField class="text-field">
|
|
||||||
<TextField.Label class="text-field__label">Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input class="text-field__input" />
|
|
||||||
</TextField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default value
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultValue` prop.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField defaultValue="Apple">
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField defaultValue="Apple">
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled value
|
|
||||||
|
|
||||||
The `value` prop can be used to make the value controlled. The `onChange` event is fired when the user type into the input and receive the new value.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Your favorite fruit is: Apple.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("Apple");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TextField value={value()} onChange={setValue}>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
</TextField>
|
|
||||||
<p>Your favorite fruit is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("Apple");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TextField value={value()} onChange={setValue}>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
</TextField>
|
|
||||||
<p>Your favorite fruit is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multiline
|
|
||||||
|
|
||||||
Use the `TextField.TextArea` component instead of `TextField.Input` to create a multiline text field.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.TextArea />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.TextArea />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
In addition, the `autoResize` prop can be used to make the textarea height adjust to it's content. Try typing in the text field below to see it in action.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.TextArea autoResize />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.TextArea autoResize />
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Description
|
|
||||||
|
|
||||||
The `TextField.Description` component can be used to associate additional help text with a text field.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Choose the fruit you like the most.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
<TextField.Description>Choose the fruit you like the most.</TextField.Description>
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<TextField>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
<TextField.Description>Choose the fruit you like the most.</TextField.Description>
|
|
||||||
</TextField>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error message
|
|
||||||
|
|
||||||
The `TextField.ErrorMessage` component can be used to help the user fix a validation error. It should be combined with the `validationState` prop to semantically mark the text field as invalid for assistive technologies.
|
|
||||||
|
|
||||||
By default, it will render only when the `validationState` prop is set to `invalid`, use the `forceMount` prop to always render the error message (ex: for usage with animation libraries).
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
Hmm, I prefer apples.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TextField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "Apple" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
<TextField.ErrorMessage>Hmm, I prefer apples.</TextField.ErrorMessage>
|
|
||||||
</TextField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ErrorMessageExample() {
|
|
||||||
const [value, setValue] = createSignal("Orange");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TextField
|
|
||||||
value={value()}
|
|
||||||
onChange={setValue}
|
|
||||||
validationState={value() !== "Apple" ? "invalid" : "valid"}
|
|
||||||
>
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
<TextField.ErrorMessage>Hmm, I prefer apples.</TextField.ErrorMessage>
|
|
||||||
</TextField>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTML forms
|
|
||||||
|
|
||||||
The text field `name` prop can be used for integration with HTML forms.
|
|
||||||
|
|
||||||
Favorite fruit
|
|
||||||
|
|
||||||
ResetSubmit
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<TextField name="favorite-fruit">
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
</TextField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
function HTMLFormExample() {
|
|
||||||
const onSubmit = (e: SubmitEvent) => {
|
|
||||||
// handle form submission.
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={onSubmit}>
|
|
||||||
<TextField name="favorite-fruit">
|
|
||||||
<TextField.Label>Favorite fruit</TextField.Label>
|
|
||||||
<TextField.Input />
|
|
||||||
</TextField>
|
|
||||||
<div>
|
|
||||||
<button type="reset">Reset</button>
|
|
||||||
<button type="submit">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### TextField
|
|
||||||
|
|
||||||
`TextField` is equivalent to the `Root` import from `@kobalte/core/text-field` (and deprecated `TextField.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> The controlled value of the text field to check. |
|
|
||||||
| defaultValue | `string`<br> The default value when initially rendered. Useful when you do not need to control the value. |
|
|
||||||
| onChange | `(value: string) => void`<br> Event handler called when the value of the textfield changes. |
|
|
||||||
| name | `string`<br> The name of the text field, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
|
|
||||||
| validationState | `'valid' | 'invalid'`<br> Whether the text field should display its "valid" or "invalid" visual styling. |
|
|
||||||
| required | `boolean`<br> Whether the user must fill the text field before the owning form can be submitted. |
|
|
||||||
| disabled | `boolean`<br> Whether the text field is disabled. |
|
|
||||||
| readOnly | `boolean`<br> Whether the text field items can be selected but not changed by the user. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-valid | Present when the text field is valid according to the validation rules. |
|
|
||||||
| data-invalid | Present when the text field is invalid according to the validation rules. |
|
|
||||||
| data-required | Present when the user must fill the text field before the owning form can be submitted. |
|
|
||||||
| data-disabled | Present when the text field is disabled. |
|
|
||||||
| data-readonly | Present when the text field is read only. |
|
|
||||||
|
|
||||||
`TextField.Label`, `TextField.Input`, `TextField.TextArea`, `TextField.Description` and `TextField.ErrorMesssage` share the same data-attributes.
|
|
||||||
|
|
||||||
### TextField.TextArea
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| autoResize | `boolean`<br> Whether the textarea should adjust its height when the value changes. |
|
|
||||||
| submitOnEnter | `boolean`<br> Whether the form should be submitted when the user presses the enter key. |
|
|
||||||
|
|
||||||
### TextField.ErrorMessage
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `TextField` | `div` |
|
|
||||||
| `TextField.Label` | `label` |
|
|
||||||
| `TextField.Input` | `input` |
|
|
||||||
| `TextField.TextArea` | `textarea` |
|
|
||||||
| `TextField.Description` | `div` |
|
|
||||||
| `TextField.ErrorMessage` | `div` |
|
|
||||||
|
|
||||||
Previous[←Tabs](https://kobalte.dev/docs/core/components/tabs)Next[Time Field→](https://kobalte.dev/docs/core/components/time-field)
|
|
||||||
@ -1,195 +0,0 @@
|
|||||||
# Toggle Button
|
|
||||||
|
|
||||||
A two-state button that can be either on (pressed) or off (not pressed).
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ToggleButton } from "@kobalte/core/toggle-button";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/toggle-button";
|
|
||||||
// or (deprecated)
|
|
||||||
import { ToggleButton } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ToggleButton } from "@kobalte/core/toggle-button";
|
|
||||||
// or
|
|
||||||
import { Root } from "@kobalte/core/toggle-button";
|
|
||||||
// or (deprecated)
|
|
||||||
import { ToggleButton } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Native HTML `<button>`, `<a>`, and custom element type support.
|
|
||||||
- Exposed as a toggle button via the [WAI ARIA Button](https://www.w3.org/WAI/ARIA/apg/patterns/button/) design pattern.
|
|
||||||
- Mouse and touch event handling, and press state management.
|
|
||||||
- Keyboard event support for `Space` and `Enter` keys.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The toggle button consists of:
|
|
||||||
|
|
||||||
- **ToggleButton:** the root container for a toggle button.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleButton />
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleButton />
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Volume On
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ToggleButton } from "@kobalte/core/toggle-button";
|
|
||||||
import { Show } from "solid-js";
|
|
||||||
import { VolumeOffIcon, VolumeOnIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ToggleButton class="toggle-button" aria-label="Mute">
|
|
||||||
{state => (
|
|
||||||
<Show when={state.pressed()} fallback={<VolumeOnIcon />}>
|
|
||||||
<VolumeOffIcon />
|
|
||||||
</Show>
|
|
||||||
)}
|
|
||||||
</ToggleButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { ToggleButton } from "@kobalte/core/toggle-button";
|
|
||||||
import { Show } from "solid-js";
|
|
||||||
import { VolumeOffIcon, VolumeOnIcon } from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<ToggleButton class="toggle-button" aria-label="Mute">
|
|
||||||
{state => (
|
|
||||||
<Show when={state.pressed()} fallback={<VolumeOnIcon />}>
|
|
||||||
<VolumeOffIcon />
|
|
||||||
</Show>
|
|
||||||
)}
|
|
||||||
</ToggleButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default pressed
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultPressed` prop.
|
|
||||||
|
|
||||||
Volume Off
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleButton defaultPressed>...</ToggleButton>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleButton defaultPressed>...</ToggleButton>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled pressed
|
|
||||||
|
|
||||||
The `pressed` prop can be used to make the pressed state controlled. The `onChange` event is fired when the user toggle the button, and receives the new value.
|
|
||||||
|
|
||||||
Volume On
|
|
||||||
|
|
||||||
The microphone is active.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [pressed, setPressed] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ToggleButton pressed={pressed()} onChange={setPressed}>
|
|
||||||
...
|
|
||||||
</ToggleButton>
|
|
||||||
<p>The microphone is {pressed() ? "muted" : "active"}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [pressed, setPressed] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ToggleButton pressed={pressed()} onChange={setPressed}>
|
|
||||||
...
|
|
||||||
</ToggleButton>
|
|
||||||
<p>The microphone is {pressed() ? "muted" : "active"}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ToggleButton
|
|
||||||
|
|
||||||
`ToggleButton` is equivalent to the `Root` import from `@kobalte/core/toggle-button` (and deprecated `ToggleButton.Root`).
|
|
||||||
|
|
||||||
`ToggleButton` consists of [Button](https://kobalte.dev/docs/core/components/button) and additional props.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| pressed | `boolean`<br> The controlled pressed state of the toggle button. |
|
|
||||||
| defaultPressed | `boolean`<br> The default pressed state when initially rendered. Useful when you do not need to control the pressed state. |
|
|
||||||
| onChange | `(pressed: boolean) => void`<br> Event handler called when the pressed state of the toggle button changes. |
|
|
||||||
| children | `JSX.Element | (state: ToggleButtonState) => JSX.Element`<br> The children of the toggle button. Can be a `JSX.Element` or a _render prop_ for having access to the internal state. |
|
|
||||||
|
|
||||||
| Render Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| pressed | `Accessor<boolean>`<br> Whether the toggle button is on (pressed) or off (not pressed). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-pressed | Present when the toggle button is on (pressed). |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ToggleButton` | `button` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Space` | Activates/deactivates the toggle button. |
|
|
||||||
| `Enter` | Activates/deactivates the toggle button. |
|
|
||||||
|
|
||||||
Previous[←Toast](https://kobalte.dev/docs/core/components/toast)Next[Toggle Group→](https://kobalte.dev/docs/core/components/toggle-group)
|
|
||||||
@ -1,295 +0,0 @@
|
|||||||
# Toggle Group
|
|
||||||
|
|
||||||
A set of two-state buttons that can be toggled on (pressed) or off (not pressed).
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ToggleGroup } from "@kobalte/core/toggle-group";
|
|
||||||
// or
|
|
||||||
import { Root, Item, ... } from "@kobalte/core/toggle-group";
|
|
||||||
// or (deprecated)
|
|
||||||
import { ToggleGroup } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { ToggleGroup } from "@kobalte/core/toggle-group";
|
|
||||||
// or
|
|
||||||
import { Root, Item, ... } from "@kobalte/core/toggle-group";
|
|
||||||
// or (deprecated)
|
|
||||||
import { ToggleGroup } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Supports horizontal/vertical orientation.
|
|
||||||
- Keyboard event support for `Space` and `Enter` keys.
|
|
||||||
- Can be controlled or uncontrolled.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The toggle group consists of:
|
|
||||||
|
|
||||||
- **ToggleGroup:** the root container for a toggle group.
|
|
||||||
|
|
||||||
The toggle item consists of:
|
|
||||||
|
|
||||||
- **ToggleGroup.Item:** the root container for a toggle button.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleGroup>
|
|
||||||
<ToggleGroup.Item />
|
|
||||||
</ToggleGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleGroup>
|
|
||||||
<ToggleGroup.Item />
|
|
||||||
</ToggleGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
BoldItalicUnderline
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import {ToggleButton} from "@kobalte/core/toggle-group";
|
|
||||||
import {BoldIcon, ItalicIcon, UnderlineIcon} from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
<ToggleGroup class="toggle-group">
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="bold" aria-label="Bold">
|
|
||||||
<BoldIcon/>
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="italic" aria-label="Italic">
|
|
||||||
<ItalicIcon/>
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="underline" aria-label="Underline">
|
|
||||||
<UnderlineIcon/>
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
</ToggleGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import {ToggleButton} from "@kobalte/core/toggle-group";
|
|
||||||
import {BoldIcon, ItalicIcon, UnderlineIcon} from "some-icon-library";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
<ToggleGroup class="toggle-group">
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="bold" aria-label="Bold">
|
|
||||||
<BoldIcon/>
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="italic" aria-label="Italic">
|
|
||||||
<ItalicIcon/>
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="underline" aria-label="Underline">
|
|
||||||
<UnderlineIcon/>
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
</ToggleGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default pressed
|
|
||||||
|
|
||||||
An initial, uncontrolled value can be provided using the `defaultValue` prop.
|
|
||||||
|
|
||||||
BoldItalicUnderline
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleGroup defaultValue="underline">
|
|
||||||
<ToggleGroup.Item value="bold" aria-label="Bold">
|
|
||||||
<BoldIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item value="italic" aria-label="Italic">
|
|
||||||
<ItalicIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item value="underline" aria-label="Underline">
|
|
||||||
<UnderlineIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
</ToggleGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<ToggleGroup defaultValue="underline">
|
|
||||||
<ToggleGroup.Item value="bold" aria-label="Bold">
|
|
||||||
<BoldIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item value="italic" aria-label="Italic">
|
|
||||||
<ItalicIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item value="underline" aria-label="Underline">
|
|
||||||
<UnderlineIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
</ToggleGroup>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled pressed
|
|
||||||
|
|
||||||
The `value` prop can be used to make the pressed state controlled. The `onChange` event is fired when the user toggle the button, and receives the new value.
|
|
||||||
|
|
||||||
BoldItalicUnderline
|
|
||||||
|
|
||||||
Your text style is: **bold**.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("underline");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ToggleGroup value={value()} onChange={setValue}>
|
|
||||||
...
|
|
||||||
</ToggleGroup>
|
|
||||||
<p>Your text style is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [value, setValue] = createSignal("underline");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ToggleGroup value={value()} onChange={setValue}>
|
|
||||||
...
|
|
||||||
</ToggleGroup>
|
|
||||||
<p>Your text style is: {value()}.</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multiple selection
|
|
||||||
|
|
||||||
The `multiple` prop can be used to create a select that allow multi-selection.
|
|
||||||
|
|
||||||
BoldItalicUnderline
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function MultipleSelectionExample() {
|
|
||||||
const [values, setValues] = createSignal(["bold", "underline"]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ToggleGroup class="toggle-group" value={values()} onChange={setValues}>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="bold" aria-label="Bold">
|
|
||||||
<BoldIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="italic" aria-label="Italic">
|
|
||||||
<ItalicIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="underline" aria-label="Underline">
|
|
||||||
<UnderlineIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
</ToggleGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function MultipleSelectionExample() {
|
|
||||||
const [values, setValues] = createSignal(["bold", "underline"]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ToggleGroup class="toggle-group" value={values()} onChange={setValues}>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="bold" aria-label="Bold">
|
|
||||||
<BoldIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="italic" aria-label="Italic">
|
|
||||||
<ItalicIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
<ToggleGroup.Item class="toggle-group__item" value="underline" aria-label="Underline">
|
|
||||||
<UnderlineIcon />
|
|
||||||
</ToggleGroup.Item>
|
|
||||||
</ToggleGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### ToggleGroup
|
|
||||||
|
|
||||||
`ToggleGroup` is equivalent to the `Root` import from `@kobalte/core/toggle-group` (and deprecated `ToggleGroup.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string | string[]`<br> The controlled pressed state of the toggle button. |
|
|
||||||
| defaultValue | `string | string[]`<br> The default pressed state when initially rendered. Useful when you do not need to control the pressed state. |
|
|
||||||
| onChange | `(value: string | string[]) => void`<br> Event handler called when the pressed state of an item changes. |
|
|
||||||
| multiple | `boolean`<br> Whether the toggle group allows multi-selection. |
|
|
||||||
| orientation | `'horizontal' | 'vertical'`<br> The orientation of the toggle group. |
|
|
||||||
| disabled | `boolean`<br> Whether toggle group should be disabled. |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Present when the separator has horizontal orientation. |
|
|
||||||
| data-orientation='vertical' | Present when the separator has vertical orientation. |
|
|
||||||
|
|
||||||
### ToggleGroup.Item
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| value | `string`<br> A unique value for the item. |
|
|
||||||
| disabled | `boolean`<br> Whether the item is disabled. |
|
|
||||||
| children | `JSX.Element | (state: ToggleButtonState) => JSX.Element`<br> The children of the item. Can be a `JSX.Element` or a _render prop_ for having access to the internal state. |
|
|
||||||
|
|
||||||
| Render Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| pressed | `Accessor<boolean>`<br> Whether the toggle button is on (pressed) or off (not pressed). |
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-orientation='horizontal' | Present when the separator has horizontal orientation. |
|
|
||||||
| data-orientation='vertical' | Present when the separator has vertical orientation. |
|
|
||||||
| data-disabled | Present when the accordion item is disabled. |
|
|
||||||
| data-pressed | Present when the toggle button is on (pressed). |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `ToggleGroup` | `div` |
|
|
||||||
| `ToggleGroup.Item` | `button` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tab` | Move focus to either the pressed item or the first item in the group. |
|
|
||||||
| `ArrowDown` | If orientation is vertical, moves focus to the next item. |
|
|
||||||
| `ArrowRight` | If orientation is horizontal, Moves focus to the next item. |
|
|
||||||
| `ArrowUp` | If orientation is vertical, moves focus to the previous item. |
|
|
||||||
| `ArrowLeft` | If orientation is vertical, moves focus to the previous item. |
|
|
||||||
| `Home` | Moves focus to the first item. |
|
|
||||||
| `End` | Moves focus to the last item. |
|
|
||||||
| `Enter` | Activates/deactivates the item. |
|
|
||||||
| `Space` | Activates/deactivates the item. |
|
|
||||||
|
|
||||||
Previous[←Toggle Button](https://kobalte.dev/docs/core/components/toggle-button)Next[Tooltip→](https://kobalte.dev/docs/core/components/tooltip)
|
|
||||||
@ -1,343 +0,0 @@
|
|||||||
# Tooltip
|
|
||||||
|
|
||||||
A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
|
|
||||||
|
|
||||||
## Import
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Tooltip } from "@kobalte/core/tooltip";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/tooltip";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Tooltip } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copyts
|
|
||||||
import { Tooltip } from "@kobalte/core/tooltip";
|
|
||||||
// or
|
|
||||||
import { Root, Trigger, ... } from "@kobalte/core/tooltip";
|
|
||||||
// or (deprecated)
|
|
||||||
import { Tooltip } from "@kobalte/core";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Exposed as a tooltip to assistive technology via ARIA.
|
|
||||||
- Opens when the trigger is focused or hovered.
|
|
||||||
- Closes when the trigger is activated or when pressing escape.
|
|
||||||
- Only one tooltip shows at a time.
|
|
||||||
- Labeling support for screen readers via `aria-describedby`.
|
|
||||||
- Custom show and hide delay support.
|
|
||||||
- Matches native tooltip behavior with delay on hover of first tooltip and no delay on subsequent tooltips.
|
|
||||||
|
|
||||||
## Anatomy
|
|
||||||
|
|
||||||
The tooltip consists of:
|
|
||||||
|
|
||||||
- **Tooltip:** The root container for a tooltip.
|
|
||||||
- **Tooltip.Trigger:** The button that toggles the tooltip.
|
|
||||||
- **Tooltip.Portal:** Portals its children into the `body` when the tooltip is open.
|
|
||||||
- **Tooltip.Content:** Contains the content to be rendered when the tooltip is open.
|
|
||||||
- **Tooltip.Arrow:** An optional arrow element to render alongside the tooltip.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tooltip>
|
|
||||||
<Tooltip.Trigger />
|
|
||||||
<Tooltip.Portal>
|
|
||||||
<Tooltip.Content>
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Portal>
|
|
||||||
</Tooltip>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tooltip>
|
|
||||||
<Tooltip.Trigger />
|
|
||||||
<Tooltip.Portal>
|
|
||||||
<Tooltip.Content>
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Portal>
|
|
||||||
</Tooltip>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Trigger
|
|
||||||
|
|
||||||
index.tsxstyle.css
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Tooltip } from "@kobalte/core/tooltip";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Tooltip>
|
|
||||||
<Tooltip.Trigger class="tooltip__trigger">Trigger</Tooltip.Trigger>
|
|
||||||
<Tooltip.Portal>
|
|
||||||
<Tooltip.Content class="tooltip__content">
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
<p>Tooltip content</p>
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Portal>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { Tooltip } from "@kobalte/core/tooltip";
|
|
||||||
import "./style.css";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Tooltip>
|
|
||||||
<Tooltip.Trigger class="tooltip__trigger">Trigger</Tooltip.Trigger>
|
|
||||||
<Tooltip.Portal>
|
|
||||||
<Tooltip.Content class="tooltip__content">
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
<p>Tooltip content</p>
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Portal>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Default open
|
|
||||||
|
|
||||||
An initial, uncontrolled open value can be provided using the `defaultOpen` prop.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tooltip defaultOpen>...</Tooltip>
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
<Tooltip defaultOpen>...</Tooltip>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Controlled open
|
|
||||||
|
|
||||||
The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, close button or interact outside, and receives the new value.
|
|
||||||
|
|
||||||
Tooltip is not showing.
|
|
||||||
|
|
||||||
Trigger
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>Tooltip is {open() ? "showing" : "not showing"}.</p>
|
|
||||||
<Tooltip open={open()} onOpenChange={setOpen}>
|
|
||||||
<Tooltip.Trigger>Trigger</Tooltip.Trigger>
|
|
||||||
<Tooltip.Portal>
|
|
||||||
<Tooltip.Content>
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
<p>Tooltip content</p>
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Portal>
|
|
||||||
</Tooltip>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copytsx
|
|
||||||
import { createSignal } from "solid-js";
|
|
||||||
|
|
||||||
function ControlledExample() {
|
|
||||||
const [open, setOpen] = createSignal(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>Tooltip is {open() ? "showing" : "not showing"}.</p>
|
|
||||||
<Tooltip open={open()} onOpenChange={setOpen}>
|
|
||||||
<Tooltip.Trigger>Trigger</Tooltip.Trigger>
|
|
||||||
<Tooltip.Portal>
|
|
||||||
<Tooltip.Content>
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
<p>Tooltip content</p>
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Portal>
|
|
||||||
</Tooltip>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Origin-aware animations
|
|
||||||
|
|
||||||
We expose a CSS custom property `--kb-tooltip-content-transform-origin` which can be used to animate the content from its computed origin.
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.tooltip__content {
|
|
||||||
transform-origin: var(--kb-tooltip-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip__content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Copycss
|
|
||||||
/* style.css */
|
|
||||||
.tooltip__content {
|
|
||||||
transform-origin: var(--kb-tooltip-content-transform-origin);
|
|
||||||
animation: contentHide 250ms ease-in forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip__content[data-expanded] {
|
|
||||||
animation: contentShow 250ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentShow {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes contentHide {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0.96);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### Tooltip
|
|
||||||
|
|
||||||
`Tooltip` is equivalent to the `Root` import from `@kobalte/core/tooltip` (and deprecated `Tooltip.Root`).
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| open | `boolean`<br> The controlled open state of the tooltip. |
|
|
||||||
| defaultOpen | `boolean`<br> The default open state when initially rendered. Useful when you do not need to control the open state. |
|
|
||||||
| onOpenChange | `(open: boolean) => void`<br> Event handler called when the open state of the tooltip changes. |
|
|
||||||
| triggerOnFocusOnly | `boolean`<br> Whether to open the tooltip only when the trigger is focused. By default, opens for both focus and hover. |
|
|
||||||
| openDelay | `number`<br> The duration from when the mouse enters the trigger until the tooltip opens. |
|
|
||||||
| skipDelayDuration | `number`<br> The duration from when the mouse leaves the trigger or content and moves to another tooltip trigger or content without incurring another openDelay |
|
|
||||||
| closeDelay | `number`<br> The duration from when the mouse leaves the trigger or content until the tooltip closes. |
|
|
||||||
| ignoreSafeArea | `boolean`<br> Whether to close the tooltip even if the user cursor is inside the safe area between the trigger and tooltip. |
|
|
||||||
| id | `string`<br> A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. |
|
|
||||||
| forceMount | `boolean`<br> Used to force mounting the tooltip (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
|
|
||||||
|
|
||||||
`Tooltip` also accepts the following props to customize the placement of the `Tooltip.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`<br> Function that returns the anchor element's DOMRect. |
|
|
||||||
| placement | `Placement`<br> The placement of the tooltip. |
|
|
||||||
| gutter | `number`<br> The distance between the tooltip and the trigger/anchor element. By default, it's 0 plus half of the arrow offset, if it exists. |
|
|
||||||
| shift | `number`<br> The skidding of the tooltip along the anchor element. |
|
|
||||||
| flip | `boolean | string`<br> Controls the behavior of the tooltip when it overflows the viewport:<br> \- If a `boolean`, specifies whether the tooltip should flip to the opposite side when it overflows.<br> \- If a `string`, indicates the preferred fallback placements when it overflows.<br>The placements must be spaced-delimited, e.g. "top left". |
|
|
||||||
| slide | `boolean`<br> Whether the tooltip should slide when it overflows. |
|
|
||||||
| overlap | `boolean`<br> Whether the tooltip can overlap the anchor element when it overflows. |
|
|
||||||
| sameWidth | `boolean`<br> Whether the tooltip should have the same width as the anchor element. This will be exposed to CSS as `--kb-popper-anchor-width`. |
|
|
||||||
| fitViewport | `boolean`<br> Whether the tooltip should fit the viewport. If this is set to true, the tooltip content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-available-width` and `--kb-popper-available-height`. |
|
|
||||||
| hideWhenDetached | `boolean`<br> Whether to hide the tooltip when the anchor element becomes occluded. |
|
|
||||||
| detachedPadding | `number`<br> The minimum padding in order to consider the anchor element occluded. |
|
|
||||||
| arrowPadding | `number`<br> The minimum padding between the arrow and the tooltip corner. |
|
|
||||||
| overflowPadding | `number`<br> The minimum padding between the tooltip and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. |
|
|
||||||
|
|
||||||
### Tooltip.Trigger
|
|
||||||
|
|
||||||
| Data attribute | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| data-expanded | Present when the tooltip is open. |
|
|
||||||
| data-closed | Present when the tooltip is close. |
|
|
||||||
|
|
||||||
`Tooltip.Content` and `Tooltip.Arrow` share the same data-attributes.
|
|
||||||
|
|
||||||
### Tooltip.Content
|
|
||||||
|
|
||||||
The popper positioner will copy the same `z-index` as the `Tooltip.Content`.
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| onEscapeKeyDown | `(event: KeyboardEvent) => void`<br> Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
| onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`<br> Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
|
|
||||||
|
|
||||||
### Tooltip.Arrow
|
|
||||||
|
|
||||||
| Prop | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| size | `number`<br> The size of the arrow. |
|
|
||||||
|
|
||||||
## Rendered elements
|
|
||||||
|
|
||||||
| Component | Default rendered element |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tooltip` | none |
|
|
||||||
| `Tooltip.Trigger` | `button` |
|
|
||||||
| `Tooltip.Portal` | `Portal` |
|
|
||||||
| `Tooltip.Content` | `div` |
|
|
||||||
| `Tooltip.Arrow` | `div` |
|
|
||||||
|
|
||||||
## Accessibility
|
|
||||||
|
|
||||||
### Keyboard Interactions
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| --- | --- |
|
|
||||||
| `Tab` | Opens/closes the tooltip without delay. |
|
|
||||||
| `Space` | When open, closes the tooltip without delay. |
|
|
||||||
| `Enter` | When open, closes the tooltip without delay. |
|
|
||||||
| `Esc` | When open, closes the tooltip without delay. |
|
|
||||||
|
|
||||||
Previous[←Toggle Group](https://kobalte.dev/docs/core/components/toggle-group)Next[I18nProvider→](https://kobalte.dev/docs/core/components/i18n-provider)
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
10
.mcp.json
10
.mcp.json
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"pettyui": {
|
|
||||||
"command": "node",
|
|
||||||
"args": [
|
|
||||||
"/Users/matsbosson/Documents/StayThree/PettyUI/packages/mcp/dist/index.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,124 +0,0 @@
|
|||||||
# PettyUI Kitchen Sink Showcase
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
A single-page component showcase app (`packages/showcase/`) that displays every PettyUI component grouped by category. Each component shows its name, description, and a live interactive demo. Built with Vite + SolidJS + Tailwind v4.
|
|
||||||
|
|
||||||
## Page Structure
|
|
||||||
|
|
||||||
Vertical scroll, sectioned by category. Sticky top bar with project title and TOC dropdown for jumping to categories. Smooth scroll behavior with scroll-margin offsets for anchor links.
|
|
||||||
|
|
||||||
### Sticky Header
|
|
||||||
|
|
||||||
- "PettyUI" branding left
|
|
||||||
- Category quick-links right (horizontal list on desktop, dropdown on mobile)
|
|
||||||
|
|
||||||
### Category Sections
|
|
||||||
|
|
||||||
Each section has:
|
|
||||||
- Category title (h2) with a horizontal rule
|
|
||||||
- Components listed vertically within the section
|
|
||||||
|
|
||||||
### Component Blocks
|
|
||||||
|
|
||||||
Each component block contains:
|
|
||||||
- Component name (h3)
|
|
||||||
- Description text (pulled from registry metadata)
|
|
||||||
- Demo area: bordered container with the live interactive demo inside
|
|
||||||
|
|
||||||
## Categories & Components (44 total)
|
|
||||||
|
|
||||||
### 1. Layout & Display (6)
|
|
||||||
- **Avatar** — image with fallback initials
|
|
||||||
- **Badge** — status indicator labels (info, success, warning, error variants)
|
|
||||||
- **Card** — header/content/footer container with sample content
|
|
||||||
- **Image** — image with fallback placeholder
|
|
||||||
- **Separator** — horizontal and vertical dividers
|
|
||||||
- **Skeleton** — loading placeholders in different shapes
|
|
||||||
|
|
||||||
### 2. Inputs & Forms (14)
|
|
||||||
- **Button** — primary, secondary, outline, ghost variants
|
|
||||||
- **TextField** — text input with label, placeholder, description, error state
|
|
||||||
- **NumberField** — numeric input with increment/decrement buttons
|
|
||||||
- **Checkbox** — checked, unchecked, indeterminate states
|
|
||||||
- **Switch** — on/off toggle
|
|
||||||
- **RadioGroup** — group of 3 radio options
|
|
||||||
- **Slider** — range slider with value display
|
|
||||||
- **Toggle** — pressed/unpressed states
|
|
||||||
- **ToggleGroup** — single and multi-select toggle groups
|
|
||||||
- **Select** — dropdown with grouped options
|
|
||||||
- **Combobox** — searchable select with filtering
|
|
||||||
- **Listbox** — inline selectable list
|
|
||||||
- **Form** — complete form with Zod validation, multiple field types, submit + error display
|
|
||||||
- **DatePicker** — date input with calendar dropdown
|
|
||||||
|
|
||||||
### 3. Navigation (8)
|
|
||||||
- **Link** — internal, external, disabled states
|
|
||||||
- **Breadcrumbs** — 3-level breadcrumb trail
|
|
||||||
- **Tabs** — 3 tabs with content panels
|
|
||||||
- **Accordion** — 3 collapsible sections
|
|
||||||
- **Collapsible** — single expand/collapse section
|
|
||||||
- **Pagination** — page navigation with ellipsis
|
|
||||||
- **NavigationMenu** — horizontal nav with dropdown submenus
|
|
||||||
- **Wizard** — 3-step wizard flow
|
|
||||||
|
|
||||||
### 4. Overlays (9)
|
|
||||||
- **Dialog** — modal with title, description, close
|
|
||||||
- **AlertDialog** — confirmation dialog with cancel/action
|
|
||||||
- **Drawer** — slide-in panel from right
|
|
||||||
- **Popover** — floating content panel with arrow
|
|
||||||
- **Tooltip** — hover tooltip on a button
|
|
||||||
- **HoverCard** — rich preview card on hover
|
|
||||||
- **DropdownMenu** — action menu with groups and separators
|
|
||||||
- **ContextMenu** — right-click context menu
|
|
||||||
- **CommandPalette** — search-driven command menu (opened via button)
|
|
||||||
|
|
||||||
### 5. Feedback & Status (4)
|
|
||||||
- **Alert** — info, success, warning, error variants
|
|
||||||
- **Toast** — button that triggers a temporary notification
|
|
||||||
- **Progress** — determinate progress bar at 60%
|
|
||||||
- **Meter** — value gauge indicator
|
|
||||||
|
|
||||||
### 6. Data (3)
|
|
||||||
- **Calendar** — month grid with selectable dates
|
|
||||||
- **DataTable** — sortable table with sample data rows
|
|
||||||
- **VirtualList** — virtualized list of 10,000 items
|
|
||||||
|
|
||||||
## Tech Stack
|
|
||||||
|
|
||||||
- **Package**: `packages/showcase/`
|
|
||||||
- **Build**: Vite + vite-plugin-solid
|
|
||||||
- **Styling**: Tailwind CSS v4
|
|
||||||
- **Imports**: Direct source imports via workspace path aliases (`pettyui/*` -> `../core/src/components/*/index.ts`)
|
|
||||||
- **Dev**: `pnpm dev` from showcase package
|
|
||||||
|
|
||||||
## File Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
packages/showcase/
|
|
||||||
package.json
|
|
||||||
vite.config.ts
|
|
||||||
tailwind.config.ts (if needed for v4)
|
|
||||||
index.html
|
|
||||||
src/
|
|
||||||
index.tsx (mount point)
|
|
||||||
app.tsx (main page layout, sticky header, category sections)
|
|
||||||
sections/
|
|
||||||
layout-display.tsx (Avatar, Badge, Card, Image, Separator, Skeleton)
|
|
||||||
inputs-forms.tsx (Button, TextField, NumberField, Checkbox, Switch, RadioGroup, Slider, Toggle, ToggleGroup, Select, Combobox, Listbox, Form, DatePicker)
|
|
||||||
navigation.tsx (Link, Breadcrumbs, Tabs, Accordion, Collapsible, Pagination, NavigationMenu, Wizard)
|
|
||||||
overlays.tsx (Dialog, AlertDialog, Drawer, Popover, Tooltip, HoverCard, DropdownMenu, ContextMenu, CommandPalette)
|
|
||||||
feedback-status.tsx (Alert, Toast, Progress, Meter)
|
|
||||||
data.tsx (Calendar, DataTable, VirtualList)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Styling Approach
|
|
||||||
|
|
||||||
Components are headless — each demo applies Tailwind classes directly to the component parts to make them visible and interactive. Demos should look clean and professional but don't need to be production-grade designs. The goal is to show what each component does, not to be a design system showcase.
|
|
||||||
|
|
||||||
## Scroll Behavior
|
|
||||||
|
|
||||||
- `scroll-behavior: smooth` on html
|
|
||||||
- Each category section has an `id` for anchor linking
|
|
||||||
- `scroll-margin-top` on sections to offset the sticky header
|
|
||||||
- No sidebar — the sticky header contains the category links
|
|
||||||
@ -1,234 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "pettyui",
|
"name": "pettyui",
|
||||||
"version": "0.1.0",
|
"version": "2.0.0-alpha.0",
|
||||||
"description": "AI-native headless UI component library for SolidJS",
|
"description": "Zero-dependency headless Web Components built on browser standards. AI-native.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
"./dialog": {
|
"./signals": "./src/signals.ts",
|
||||||
"solid": "./src/components/dialog/index.ts",
|
"./router": "./src/router.ts",
|
||||||
"import": "./dist/dialog/index.js",
|
"./theme": "./src/theme.css",
|
||||||
"require": "./dist/dialog/index.cjs"
|
"./dialog": "./src/components/dialog/index.ts",
|
||||||
},
|
"./select": "./src/components/select/index.ts",
|
||||||
"./presence": {
|
"./tabs": "./src/components/tabs/index.ts",
|
||||||
"solid": "./src/utilities/presence/index.ts",
|
"./accordion": "./src/components/accordion/index.ts",
|
||||||
"import": "./dist/utilities/presence/index.js",
|
"./form": "./src/components/form/index.ts",
|
||||||
"require": "./dist/utilities/presence/index.cjs"
|
"./toast": "./src/components/toast/index.ts",
|
||||||
},
|
"./dropdown-menu": "./src/components/dropdown-menu/index.ts",
|
||||||
"./focus-trap": {
|
"./popover": "./src/components/popover/index.ts"
|
||||||
"solid": "./src/utilities/focus-trap/index.ts",
|
|
||||||
"import": "./dist/utilities/focus-trap/index.js",
|
|
||||||
"require": "./dist/utilities/focus-trap/index.cjs"
|
|
||||||
},
|
|
||||||
"./scroll-lock": {
|
|
||||||
"solid": "./src/utilities/scroll-lock/index.ts",
|
|
||||||
"import": "./dist/utilities/scroll-lock/index.js",
|
|
||||||
"require": "./dist/utilities/scroll-lock/index.cjs"
|
|
||||||
},
|
|
||||||
"./dismiss": {
|
|
||||||
"solid": "./src/utilities/dismiss/index.ts",
|
|
||||||
"import": "./dist/utilities/dismiss/index.js",
|
|
||||||
"require": "./dist/utilities/dismiss/index.cjs"
|
|
||||||
},
|
|
||||||
"./portal": {
|
|
||||||
"solid": "./src/utilities/portal/index.ts",
|
|
||||||
"import": "./dist/utilities/portal/index.js",
|
|
||||||
"require": "./dist/utilities/portal/index.cjs"
|
|
||||||
},
|
|
||||||
"./visually-hidden": {
|
|
||||||
"solid": "./src/utilities/visually-hidden/index.ts",
|
|
||||||
"import": "./dist/utilities/visually-hidden/index.js",
|
|
||||||
"require": "./dist/utilities/visually-hidden/index.cjs"
|
|
||||||
},
|
|
||||||
"./toggle": {
|
|
||||||
"solid": "./src/components/toggle/index.ts",
|
|
||||||
"import": "./dist/components/toggle/index.js",
|
|
||||||
"require": "./dist/components/toggle/index.cjs"
|
|
||||||
},
|
|
||||||
"./switch": {
|
|
||||||
"solid": "./src/components/switch/index.ts",
|
|
||||||
"import": "./dist/components/switch/index.js",
|
|
||||||
"require": "./dist/components/switch/index.cjs"
|
|
||||||
},
|
|
||||||
"./checkbox": {
|
|
||||||
"solid": "./src/components/checkbox/index.ts",
|
|
||||||
"import": "./dist/components/checkbox/index.js",
|
|
||||||
"require": "./dist/components/checkbox/index.cjs"
|
|
||||||
},
|
|
||||||
"./progress": {
|
|
||||||
"solid": "./src/components/progress/index.ts",
|
|
||||||
"import": "./dist/components/progress/index.js",
|
|
||||||
"require": "./dist/components/progress/index.cjs"
|
|
||||||
},
|
|
||||||
"./text-field": {
|
|
||||||
"solid": "./src/components/text-field/index.ts",
|
|
||||||
"import": "./dist/components/text-field/index.js",
|
|
||||||
"require": "./dist/components/text-field/index.cjs"
|
|
||||||
},
|
|
||||||
"./radio-group": {
|
|
||||||
"solid": "./src/components/radio-group/index.ts",
|
|
||||||
"import": "./dist/components/radio-group/index.js",
|
|
||||||
"require": "./dist/components/radio-group/index.cjs"
|
|
||||||
},
|
|
||||||
"./toggle-group": {
|
|
||||||
"solid": "./src/components/toggle-group/index.ts",
|
|
||||||
"import": "./dist/components/toggle-group/index.js",
|
|
||||||
"require": "./dist/components/toggle-group/index.cjs"
|
|
||||||
},
|
|
||||||
"./collapsible": {
|
|
||||||
"solid": "./src/components/collapsible/index.ts",
|
|
||||||
"import": "./dist/components/collapsible/index.js",
|
|
||||||
"require": "./dist/components/collapsible/index.cjs"
|
|
||||||
},
|
|
||||||
"./accordion": {
|
|
||||||
"solid": "./src/components/accordion/index.ts",
|
|
||||||
"import": "./dist/components/accordion/index.js",
|
|
||||||
"require": "./dist/components/accordion/index.cjs"
|
|
||||||
},
|
|
||||||
"./alert-dialog": {
|
|
||||||
"solid": "./src/components/alert-dialog/index.ts",
|
|
||||||
"import": "./dist/components/alert-dialog/index.js",
|
|
||||||
"require": "./dist/components/alert-dialog/index.cjs"
|
|
||||||
},
|
|
||||||
"./tabs": {
|
|
||||||
"solid": "./src/components/tabs/index.ts",
|
|
||||||
"import": "./dist/components/tabs/index.js",
|
|
||||||
"require": "./dist/components/tabs/index.cjs"
|
|
||||||
},
|
|
||||||
"./slider": {
|
|
||||||
"solid": "./src/components/slider/index.ts",
|
|
||||||
"import": "./dist/components/slider/index.js",
|
|
||||||
"require": "./dist/components/slider/index.cjs"
|
|
||||||
},
|
|
||||||
"./drawer": {
|
|
||||||
"solid": "./src/components/drawer/index.ts",
|
|
||||||
"import": "./dist/components/drawer/index.js",
|
|
||||||
"require": "./dist/components/drawer/index.cjs"
|
|
||||||
},
|
|
||||||
"./select": {
|
|
||||||
"solid": "./src/components/select/index.ts",
|
|
||||||
"import": "./dist/components/select/index.js",
|
|
||||||
"require": "./dist/components/select/index.cjs"
|
|
||||||
},
|
|
||||||
"./combobox": {
|
|
||||||
"solid": "./src/components/combobox/index.ts",
|
|
||||||
"import": "./dist/components/combobox/index.js",
|
|
||||||
"require": "./dist/components/combobox/index.cjs"
|
|
||||||
},
|
|
||||||
"./listbox": {
|
|
||||||
"solid": "./src/components/listbox/index.ts",
|
|
||||||
"import": "./dist/components/listbox/index.js",
|
|
||||||
"require": "./dist/components/listbox/index.cjs"
|
|
||||||
},
|
|
||||||
"./dropdown-menu": {
|
|
||||||
"solid": "./src/components/dropdown-menu/index.ts",
|
|
||||||
"import": "./dist/components/dropdown-menu/index.js",
|
|
||||||
"require": "./dist/components/dropdown-menu/index.cjs"
|
|
||||||
},
|
|
||||||
"./toast": {
|
|
||||||
"solid": "./src/components/toast/index.ts",
|
|
||||||
"import": "./dist/components/toast/index.js",
|
|
||||||
"require": "./dist/components/toast/index.cjs"
|
|
||||||
},
|
|
||||||
"./tooltip": {
|
|
||||||
"solid": "./src/components/tooltip/index.ts",
|
|
||||||
"import": "./dist/components/tooltip/index.js",
|
|
||||||
"require": "./dist/components/tooltip/index.cjs"
|
|
||||||
},
|
|
||||||
"./alert": {
|
|
||||||
"solid": "./src/components/alert/index.ts",
|
|
||||||
"import": "./dist/components/alert/index.js",
|
|
||||||
"require": "./dist/components/alert/index.cjs"
|
|
||||||
},
|
|
||||||
"./badge": {
|
|
||||||
"solid": "./src/components/badge/index.ts",
|
|
||||||
"import": "./dist/components/badge/index.js",
|
|
||||||
"require": "./dist/components/badge/index.cjs"
|
|
||||||
},
|
|
||||||
"./skeleton": {
|
|
||||||
"solid": "./src/components/skeleton/index.ts",
|
|
||||||
"import": "./dist/components/skeleton/index.js",
|
|
||||||
"require": "./dist/components/skeleton/index.cjs"
|
|
||||||
},
|
|
||||||
"./popover": {
|
|
||||||
"solid": "./src/components/popover/index.ts",
|
|
||||||
"import": "./dist/components/popover/index.js",
|
|
||||||
"require": "./dist/components/popover/index.cjs"
|
|
||||||
},
|
|
||||||
"./breadcrumbs": {
|
|
||||||
"solid": "./src/components/breadcrumbs/index.ts",
|
|
||||||
"import": "./dist/components/breadcrumbs/index.js",
|
|
||||||
"require": "./dist/components/breadcrumbs/index.cjs"
|
|
||||||
},
|
|
||||||
"./link": {
|
|
||||||
"solid": "./src/components/link/index.ts",
|
|
||||||
"import": "./dist/components/link/index.js",
|
|
||||||
"require": "./dist/components/link/index.cjs"
|
|
||||||
},
|
|
||||||
"./button": {
|
|
||||||
"solid": "./src/components/button/index.ts",
|
|
||||||
"import": "./dist/components/button/index.js",
|
|
||||||
"require": "./dist/components/button/index.cjs"
|
|
||||||
},
|
|
||||||
"./hover-card": {
|
|
||||||
"solid": "./src/components/hover-card/index.ts",
|
|
||||||
"import": "./dist/components/hover-card/index.js",
|
|
||||||
"require": "./dist/components/hover-card/index.cjs"
|
|
||||||
},
|
|
||||||
"./number-field": {
|
|
||||||
"solid": "./src/components/number-field/index.ts",
|
|
||||||
"import": "./dist/components/number-field/index.js",
|
|
||||||
"require": "./dist/components/number-field/index.cjs"
|
|
||||||
},
|
|
||||||
"./card": {
|
|
||||||
"solid": "./src/components/card/index.ts",
|
|
||||||
"import": "./dist/card/index.js",
|
|
||||||
"require": "./dist/card/index.cjs"
|
|
||||||
},
|
|
||||||
"./avatar": {
|
|
||||||
"solid": "./src/components/avatar/index.ts",
|
|
||||||
"import": "./dist/avatar/index.js",
|
|
||||||
"require": "./dist/avatar/index.cjs"
|
|
||||||
},
|
|
||||||
"./navigation-menu": {
|
|
||||||
"solid": "./src/components/navigation-menu/index.ts",
|
|
||||||
"import": "./dist/navigation-menu/index.js",
|
|
||||||
"require": "./dist/navigation-menu/index.cjs"
|
|
||||||
},
|
|
||||||
"./virtual-list": {
|
|
||||||
"solid": "./src/components/virtual-list/index.ts",
|
|
||||||
"import": "./dist/virtual-list/index.js",
|
|
||||||
"require": "./dist/virtual-list/index.cjs"
|
|
||||||
},
|
|
||||||
"./calendar": {
|
|
||||||
"solid": "./src/components/calendar/index.ts",
|
|
||||||
"import": "./dist/calendar/index.js",
|
|
||||||
"require": "./dist/calendar/index.cjs"
|
|
||||||
},
|
|
||||||
"./date-picker": {
|
|
||||||
"solid": "./src/components/date-picker/index.ts",
|
|
||||||
"import": "./dist/date-picker/index.js",
|
|
||||||
"require": "./dist/date-picker/index.cjs"
|
|
||||||
},
|
|
||||||
"./command-palette": {
|
|
||||||
"solid": "./src/components/command-palette/index.ts",
|
|
||||||
"import": "./dist/command-palette/index.js",
|
|
||||||
"require": "./dist/command-palette/index.cjs"
|
|
||||||
},
|
|
||||||
"./form": {
|
|
||||||
"solid": "./src/components/form/index.ts",
|
|
||||||
"import": "./dist/form/index.js",
|
|
||||||
"require": "./dist/form/index.cjs"
|
|
||||||
},
|
|
||||||
"./wizard": {
|
|
||||||
"solid": "./src/components/wizard/index.ts",
|
|
||||||
"import": "./dist/wizard/index.js",
|
|
||||||
"require": "./dist/wizard/index.cjs"
|
|
||||||
},
|
|
||||||
"./data-table": {
|
|
||||||
"solid": "./src/components/data-table/index.ts",
|
|
||||||
"import": "./dist/data-table/index.js",
|
|
||||||
"require": "./dist/data-table/index.cjs"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsdown",
|
"build": "tsdown",
|
||||||
@ -236,22 +22,12 @@
|
|||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
|
||||||
"solid-js": "^1.9.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "^1.7.6",
|
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@solidjs/testing-library": "^0.8.10",
|
|
||||||
"@testing-library/jest-dom": "^6.0.0",
|
|
||||||
"@testing-library/user-event": "^14.0.0",
|
|
||||||
"jsdom": "^26.0.0",
|
|
||||||
"solid-js": "^1.9.12",
|
|
||||||
"tsdown": "^0.21.7",
|
"tsdown": "^0.21.7",
|
||||||
"vite": "^8.0.3",
|
"typescript": "^6.0.2",
|
||||||
"vite-plugin-solid": "^2.11.11",
|
|
||||||
"vitest": "^4.1.2"
|
"vitest": "^4.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { splitProps } from "solid-js";
|
|
||||||
import { useAccordionItemContext } from "./accordion-context";
|
|
||||||
|
|
||||||
/** Props for the collapsible content panel of an Accordion item. */
|
|
||||||
export interface AccordionContentProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Content panel for an Accordion item. Stays in DOM (uses hidden attribute)
|
|
||||||
* so CSS transitions work when animating open/closed.
|
|
||||||
*/
|
|
||||||
export function AccordionContent(props: AccordionContentProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children"]);
|
|
||||||
const itemCtx = useAccordionItemContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
id={itemCtx.contentId}
|
|
||||||
role="region"
|
|
||||||
aria-labelledby={itemCtx.triggerId}
|
|
||||||
hidden={!itemCtx.isExpanded() || undefined}
|
|
||||||
data-state={itemCtx.isExpanded() ? "open" : "closed"}
|
|
||||||
{...rest}
|
|
||||||
>
|
|
||||||
{local.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
import type { Accessor } from "solid-js";
|
|
||||||
import { createContext, useContext } from "solid-js";
|
|
||||||
|
|
||||||
/** Shared state provided by AccordionRoot to all descendant accordion parts. */
|
|
||||||
export interface AccordionRootContextValue {
|
|
||||||
isExpanded: (value: string) => boolean;
|
|
||||||
toggleItem: (value: string) => void;
|
|
||||||
disabled: Accessor<boolean>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Per-item state provided by AccordionItem to its trigger and content. */
|
|
||||||
export interface AccordionItemContextValue {
|
|
||||||
value: string;
|
|
||||||
isExpanded: Accessor<boolean>;
|
|
||||||
triggerId: string;
|
|
||||||
contentId: string;
|
|
||||||
disabled: Accessor<boolean>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AccordionRootContext = createContext<AccordionRootContextValue>();
|
|
||||||
const AccordionItemContext = createContext<AccordionItemContextValue>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Accordion root context. Throws if used outside <Accordion>.
|
|
||||||
*/
|
|
||||||
export function useAccordionRootContext(): AccordionRootContextValue {
|
|
||||||
const ctx = useContext(AccordionRootContext);
|
|
||||||
if (!ctx) throw new Error("[PettyUI] Accordion parts must be used inside <Accordion>.");
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the AccordionItem context. Throws if used outside <Accordion.Item>.
|
|
||||||
*/
|
|
||||||
export function useAccordionItemContext(): AccordionItemContextValue {
|
|
||||||
const ctx = useContext(AccordionItemContext);
|
|
||||||
if (!ctx)
|
|
||||||
throw new Error("[PettyUI] Accordion.Trigger/Content must be used inside <Accordion.Item>.");
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AccordionRootContextProvider = AccordionRootContext.Provider;
|
|
||||||
export const AccordionItemContextProvider = AccordionItemContext.Provider;
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { splitProps } from "solid-js";
|
|
||||||
import { Dynamic } from "solid-js/web";
|
|
||||||
|
|
||||||
/** Props for the heading wrapper rendered around an Accordion trigger. */
|
|
||||||
export interface AccordionHeaderProps extends JSX.HTMLAttributes<HTMLHeadingElement> {
|
|
||||||
/** Heading level element. @default "h3" */
|
|
||||||
as?: string;
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Heading wrapper for an Accordion trigger. Defaults to h3. */
|
|
||||||
export function AccordionHeader(props: AccordionHeaderProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["as", "children"]);
|
|
||||||
return (
|
|
||||||
<Dynamic component={local.as ?? "h3"} {...rest}>
|
|
||||||
{local.children}
|
|
||||||
</Dynamic>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
82
packages/core/src/components/accordion/accordion-item.ts
Normal file
82
packages/core/src/components/accordion/accordion-item.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* PettyAccordionItem — wraps a single `<details>` element within a PettyAccordion.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* ```html
|
||||||
|
* <petty-accordion-item value="section-1">
|
||||||
|
* <details>
|
||||||
|
* <summary>Section 1</summary>
|
||||||
|
* <div data-part="content">Content 1</div>
|
||||||
|
* </details>
|
||||||
|
* </petty-accordion-item>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Manages data-state ("open" | "closed") and disabled behaviour on the
|
||||||
|
* underlying `<details>` and `<summary>` elements.
|
||||||
|
*/
|
||||||
|
export class PettyAccordionItem extends HTMLElement {
|
||||||
|
static observedAttributes = ["value", "disabled"];
|
||||||
|
|
||||||
|
/** The `<details>` element nested directly inside this item. */
|
||||||
|
get detailsElement(): HTMLDetailsElement | null {
|
||||||
|
return this.querySelector("details");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the item's details element is currently open. */
|
||||||
|
get isOpen(): boolean {
|
||||||
|
return this.detailsElement?.open ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The value attribute, falling back to summary text content. */
|
||||||
|
get value(): string {
|
||||||
|
const explicit = this.getAttribute("value");
|
||||||
|
if (explicit !== null) return explicit;
|
||||||
|
return this.querySelector("summary")?.textContent?.trim() ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
connectedCallback(): void {
|
||||||
|
this.#syncState();
|
||||||
|
this.#applyDisabled();
|
||||||
|
const details = this.detailsElement;
|
||||||
|
if (details) {
|
||||||
|
details.addEventListener("toggle", this.#handleToggle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
disconnectedCallback(): void {
|
||||||
|
const details = this.detailsElement;
|
||||||
|
details?.removeEventListener("toggle", this.#handleToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
attributeChangedCallback(name: string): void {
|
||||||
|
if (name === "disabled") this.#applyDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleToggle = (): void => {
|
||||||
|
this.#syncState();
|
||||||
|
};
|
||||||
|
|
||||||
|
#syncState(): void {
|
||||||
|
const details = this.detailsElement;
|
||||||
|
const state = details?.open ? "open" : "closed";
|
||||||
|
this.setAttribute("data-state", state);
|
||||||
|
const summary = details?.querySelector("summary");
|
||||||
|
if (summary) summary.setAttribute("aria-expanded", String(details?.open ?? false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#applyDisabled(): void {
|
||||||
|
const disabled = this.hasAttribute("disabled");
|
||||||
|
const summary = this.detailsElement?.querySelector("summary");
|
||||||
|
if (!summary) return;
|
||||||
|
if (disabled) {
|
||||||
|
summary.setAttribute("aria-disabled", "true");
|
||||||
|
summary.setAttribute("tabindex", "-1");
|
||||||
|
} else {
|
||||||
|
summary.removeAttribute("aria-disabled");
|
||||||
|
summary.removeAttribute("tabindex");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,40 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { createUniqueId, splitProps } from "solid-js";
|
|
||||||
import { AccordionItemContextProvider, useAccordionRootContext } from "./accordion-context";
|
|
||||||
|
|
||||||
/** Props for a single collapsible item within an Accordion. */
|
|
||||||
export interface AccordionItemProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
||||||
value: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A single collapsible item within an Accordion. */
|
|
||||||
export function AccordionItem(props: AccordionItemProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["value", "disabled", "children"]);
|
|
||||||
const rootCtx = useAccordionRootContext();
|
|
||||||
const triggerId = createUniqueId();
|
|
||||||
const contentId = createUniqueId();
|
|
||||||
|
|
||||||
const itemCtx = {
|
|
||||||
get value() {
|
|
||||||
return local.value;
|
|
||||||
},
|
|
||||||
isExpanded: () => rootCtx.isExpanded(local.value),
|
|
||||||
triggerId,
|
|
||||||
contentId,
|
|
||||||
disabled: () => local.disabled ?? false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AccordionItemContextProvider value={itemCtx}>
|
|
||||||
<div
|
|
||||||
data-state={rootCtx.isExpanded(local.value) ? "open" : "closed"}
|
|
||||||
data-disabled={local.disabled || undefined}
|
|
||||||
{...rest}
|
|
||||||
>
|
|
||||||
{local.children}
|
|
||||||
</div>
|
|
||||||
</AccordionItemContextProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { createSignal, splitProps } from "solid-js";
|
|
||||||
import { AccordionRootContextProvider, type AccordionRootContextValue } from "./accordion-context";
|
|
||||||
|
|
||||||
/** Props for the root accordion container that manages expanded state. */
|
|
||||||
export interface AccordionRootProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
||||||
/** "single" allows one item open at a time; "multiple" allows any number. @default "single" */
|
|
||||||
type?: "single" | "multiple";
|
|
||||||
/** In single mode, whether the open item can be closed by clicking it again. @default false */
|
|
||||||
collapsible?: boolean;
|
|
||||||
value?: string | string[];
|
|
||||||
defaultValue?: string | string[];
|
|
||||||
onValueChange?: (value: string | string[]) => void;
|
|
||||||
disabled?: boolean;
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Root container for an accordion. Manages which items are expanded.
|
|
||||||
*/
|
|
||||||
export function AccordionRoot(props: AccordionRootProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, [
|
|
||||||
"type",
|
|
||||||
"collapsible",
|
|
||||||
"value",
|
|
||||||
"defaultValue",
|
|
||||||
"onValueChange",
|
|
||||||
"disabled",
|
|
||||||
"children",
|
|
||||||
]);
|
|
||||||
|
|
||||||
const type = () => local.type ?? "single";
|
|
||||||
|
|
||||||
const normalize = (v: string | string[] | undefined): string[] => {
|
|
||||||
if (v === undefined) return [];
|
|
||||||
return Array.isArray(v) ? v : [v];
|
|
||||||
};
|
|
||||||
|
|
||||||
const [expandedValues, setExpandedValues] = createSignal<string[]>(normalize(local.defaultValue));
|
|
||||||
|
|
||||||
const getValues = (): string[] =>
|
|
||||||
local.value !== undefined ? normalize(local.value) : expandedValues();
|
|
||||||
|
|
||||||
const ctx: AccordionRootContextValue = {
|
|
||||||
isExpanded: (value) => getValues().includes(value),
|
|
||||||
toggleItem: (value) => {
|
|
||||||
const current = getValues();
|
|
||||||
let next: string[];
|
|
||||||
if (type() === "single") {
|
|
||||||
if (current.includes(value)) {
|
|
||||||
next = local.collapsible ? [] : current;
|
|
||||||
} else {
|
|
||||||
next = [value];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next = current.includes(value) ? current.filter((v) => v !== value) : [...current, value];
|
|
||||||
}
|
|
||||||
if (local.value === undefined) setExpandedValues(next);
|
|
||||||
local.onValueChange?.(type() === "multiple" ? next : (next[0] ?? ""));
|
|
||||||
},
|
|
||||||
disabled: () => local.disabled ?? false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AccordionRootContextProvider value={ctx}>
|
|
||||||
<div data-accordion-root data-disabled={local.disabled || undefined} {...rest}>
|
|
||||||
{local.children}
|
|
||||||
</div>
|
|
||||||
</AccordionRootContextProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { splitProps } from "solid-js";
|
|
||||||
import { useAccordionItemContext, useAccordionRootContext } from "./accordion-context";
|
|
||||||
|
|
||||||
/** Props for the button that toggles an Accordion item open/closed. */
|
|
||||||
export interface AccordionTriggerProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Button that toggles an Accordion item open/closed. Supports ArrowDown/ArrowUp/Home/End navigation. */
|
|
||||||
export function AccordionTrigger(props: AccordionTriggerProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children"]);
|
|
||||||
const rootCtx = useAccordionRootContext();
|
|
||||||
const itemCtx = useAccordionItemContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
id={itemCtx.triggerId}
|
|
||||||
aria-expanded={itemCtx.isExpanded() ? "true" : "false"}
|
|
||||||
aria-controls={itemCtx.contentId}
|
|
||||||
data-state={itemCtx.isExpanded() ? "open" : "closed"}
|
|
||||||
data-accordion-trigger
|
|
||||||
disabled={rootCtx.disabled() || itemCtx.disabled()}
|
|
||||||
{...rest}
|
|
||||||
onClick={(e) => {
|
|
||||||
if (typeof rest.onClick === "function") rest.onClick(e);
|
|
||||||
if (!rootCtx.disabled() && !itemCtx.disabled()) rootCtx.toggleItem(itemCtx.value);
|
|
||||||
}}
|
|
||||||
onKeyDown={(e) => {
|
|
||||||
if (typeof rest.onKeyDown === "function") rest.onKeyDown(e);
|
|
||||||
const accordion = (e.currentTarget as HTMLButtonElement).closest("[data-accordion-root]");
|
|
||||||
if (!accordion) return;
|
|
||||||
const triggers = Array.from(
|
|
||||||
accordion.querySelectorAll<HTMLButtonElement>("[data-accordion-trigger]"),
|
|
||||||
);
|
|
||||||
const index = triggers.indexOf(e.currentTarget as HTMLButtonElement);
|
|
||||||
if (e.key === "ArrowDown") {
|
|
||||||
e.preventDefault();
|
|
||||||
triggers[(index + 1) % triggers.length]?.focus();
|
|
||||||
} else if (e.key === "ArrowUp") {
|
|
||||||
e.preventDefault();
|
|
||||||
triggers[(index - 1 + triggers.length) % triggers.length]?.focus();
|
|
||||||
} else if (e.key === "Home") {
|
|
||||||
e.preventDefault();
|
|
||||||
triggers[0]?.focus();
|
|
||||||
} else if (e.key === "End") {
|
|
||||||
e.preventDefault();
|
|
||||||
triggers[triggers.length - 1]?.focus();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{local.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
import type { JSX } from "solid-js";
|
|
||||||
import type { ComponentMeta } from "../../meta";
|
|
||||||
export declare const AccordionRootPropsSchema: z.ZodObject<{
|
|
||||||
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
||||||
defaultValue: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
||||||
multiple: z.ZodOptional<z.ZodBoolean>;
|
|
||||||
collapsible: z.ZodOptional<z.ZodBoolean>;
|
|
||||||
disabled: z.ZodOptional<z.ZodBoolean>;
|
|
||||||
}, z.core.$strip>;
|
|
||||||
export interface AccordionRootProps extends z.infer<typeof AccordionRootPropsSchema>, Omit<JSX.HTMLAttributes<HTMLDivElement>, keyof z.infer<typeof AccordionRootPropsSchema>> {
|
|
||||||
onValueChange?: (value: string | string[]) => void;
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
export declare const AccordionItemPropsSchema: z.ZodObject<{
|
|
||||||
value: z.ZodString;
|
|
||||||
disabled: z.ZodOptional<z.ZodBoolean>;
|
|
||||||
}, z.core.$strip>;
|
|
||||||
export declare const AccordionMeta: ComponentMeta;
|
|
||||||
//# sourceMappingURL=accordion.props.d.ts.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"accordion.props.d.ts","sourceRoot":"","sources":["accordion.props.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,eAAO,MAAM,wBAAwB;;;;;;iBAAqY,CAAC;AAC3a,MAAM,WAAW,kBAAmB,SAAQ,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;IAAG,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CAAE;AAC7P,eAAO,MAAM,wBAAwB;;;iBAAqJ,CAAC;AAC3L,eAAO,MAAM,aAAa,EAAE,aAA2R,CAAC"}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
const str = z.string(), bool = z.boolean().optional(), strArr = z.union([z.string(), z.array(z.string())]).optional();
|
|
||||||
export const AccordionRootPropsSchema = z.object({ value: strArr.describe("Controlled expanded item value(s)"), defaultValue: strArr.describe("Initial expanded item value(s) when uncontrolled"), multiple: bool.describe("Allow multiple items to be expanded simultaneously"), collapsible: bool.describe("Allow the currently open item to be closed by clicking it again"), disabled: bool.describe("Disable all accordion items") });
|
|
||||||
export const AccordionItemPropsSchema = z.object({ value: str.describe("Unique value identifying this accordion item"), disabled: bool.describe("Disable this specific accordion item") });
|
|
||||||
export const AccordionMeta = { name: "Accordion", description: "Vertically stacked sections that expand/collapse to show content one at a time or multiple", parts: ["Root", "Item", "Header", "Trigger", "Content"], requiredParts: ["Root", "Item", "Trigger", "Content"] };
|
|
||||||
//# sourceMappingURL=accordion.props.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"accordion.props.js","sourceRoot":"","sources":["accordion.props.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AACtH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,mCAAmC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,kDAAkD,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,oDAAoD,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,iEAAiE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAC;AAE3a,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,8CAA8C,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,sCAAsC,CAAC,EAAE,CAAC,CAAC;AAC3L,MAAM,CAAC,MAAM,aAAa,GAAkB,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,4FAA4F,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAU,EAAE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAU,EAAW,CAAC"}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
import type { JSX } from "solid-js";
|
|
||||||
import type { ComponentMeta } from "../../meta";
|
|
||||||
const str = z.string(), bool = z.boolean().optional(), strArr = z.union([z.string(), z.array(z.string())]).optional();
|
|
||||||
export const AccordionRootPropsSchema = z.object({ value: strArr.describe("Controlled expanded item value(s)"), defaultValue: strArr.describe("Initial expanded item value(s) when uncontrolled"), multiple: bool.describe("Allow multiple items to be expanded simultaneously"), collapsible: bool.describe("Allow the currently open item to be closed by clicking it again"), disabled: bool.describe("Disable all accordion items") });
|
|
||||||
export interface AccordionRootProps extends z.infer<typeof AccordionRootPropsSchema>, Omit<JSX.HTMLAttributes<HTMLDivElement>, keyof z.infer<typeof AccordionRootPropsSchema>> { onValueChange?: (value: string | string[]) => void; children: JSX.Element; }
|
|
||||||
export const AccordionItemPropsSchema = z.object({ value: str.describe("Unique value identifying this accordion item"), disabled: bool.describe("Disable this specific accordion item") });
|
|
||||||
export const AccordionMeta: ComponentMeta = { name: "Accordion", description: "Vertically stacked sections that expand/collapse to show content one at a time or multiple", parts: ["Root", "Item", "Header", "Trigger", "Content"] as const, requiredParts: ["Root", "Item", "Trigger", "Content"] as const } as const;
|
|
||||||
83
packages/core/src/components/accordion/accordion.ts
Normal file
83
packages/core/src/components/accordion/accordion.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* PettyAccordion — headless accordion built on native `<details>` elements.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* ```html
|
||||||
|
* <petty-accordion>
|
||||||
|
* <petty-accordion-item>
|
||||||
|
* <details>
|
||||||
|
* <summary>Section 1</summary>
|
||||||
|
* <div data-part="content">Content 1</div>
|
||||||
|
* </details>
|
||||||
|
* </petty-accordion-item>
|
||||||
|
* <petty-accordion-item>
|
||||||
|
* <details>
|
||||||
|
* <summary>Section 2</summary>
|
||||||
|
* <div data-part="content">Content 2</div>
|
||||||
|
* </details>
|
||||||
|
* </petty-accordion-item>
|
||||||
|
* </petty-accordion>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The browser handles: open/close toggle, keyboard navigation within summary.
|
||||||
|
* This element adds: single/multiple mode, petty-change event with open values.
|
||||||
|
*/
|
||||||
|
export class PettyAccordion extends HTMLElement {
|
||||||
|
static observedAttributes = ["type"];
|
||||||
|
|
||||||
|
/** The accordion mode: "single" closes others on open, "multiple" allows many open. */
|
||||||
|
get type(): "single" | "multiple" {
|
||||||
|
const val = this.getAttribute("type");
|
||||||
|
return val === "multiple" ? "multiple" : "single";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
connectedCallback(): void {
|
||||||
|
this.addEventListener("toggle", this.#handleToggle, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
disconnectedCallback(): void {
|
||||||
|
this.removeEventListener("toggle", this.#handleToggle, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleToggle = (event: Event): void => {
|
||||||
|
const target = event.target;
|
||||||
|
if (!(target instanceof HTMLDetailsElement)) return;
|
||||||
|
|
||||||
|
if (this.type === "single" && target.open) {
|
||||||
|
this.#closeOthers(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#dispatchChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
#closeOthers(opened: HTMLDetailsElement): void {
|
||||||
|
const items = this.querySelectorAll<HTMLDetailsElement>("details");
|
||||||
|
items.forEach((details) => {
|
||||||
|
if (details !== opened && details.open) {
|
||||||
|
details.open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#dispatchChange(): void {
|
||||||
|
const openValues = this.#collectOpenValues();
|
||||||
|
this.dispatchEvent(new CustomEvent("petty-change", {
|
||||||
|
bubbles: true,
|
||||||
|
detail: { value: openValues },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#collectOpenValues(): string[] {
|
||||||
|
const items = this.querySelectorAll("petty-accordion-item");
|
||||||
|
const values: string[] = [];
|
||||||
|
items.forEach((item) => {
|
||||||
|
const details = item.querySelector("details");
|
||||||
|
if (!details?.open) return;
|
||||||
|
const val = item.getAttribute("value") ?? item.querySelector("summary")?.textContent?.trim() ?? "";
|
||||||
|
if (val) values.push(val);
|
||||||
|
});
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,7 @@
|
|||||||
import { AccordionContent } from "./accordion-content";
|
export { PettyAccordion } from "./accordion";
|
||||||
import { useAccordionRootContext } from "./accordion-context";
|
export { PettyAccordionItem } from "./accordion-item";
|
||||||
import { AccordionHeader } from "./accordion-header";
|
|
||||||
import { AccordionItem } from "./accordion-item";
|
if (!customElements.get("petty-accordion")) {
|
||||||
import { AccordionRoot } from "./accordion-root";
|
customElements.define("petty-accordion", PettyAccordion);
|
||||||
import { AccordionTrigger } from "./accordion-trigger";
|
customElements.define("petty-accordion-item", PettyAccordionItem);
|
||||||
export { AccordionRootPropsSchema, AccordionItemPropsSchema, AccordionMeta } from "./accordion.props";
|
}
|
||||||
export type { AccordionRootProps } from "./accordion.props";
|
|
||||||
export type { AccordionItemProps } from "./accordion-item";
|
|
||||||
export type { AccordionHeaderProps } from "./accordion-header";
|
|
||||||
export type { AccordionTriggerProps } from "./accordion-trigger";
|
|
||||||
export type { AccordionContentProps } from "./accordion-content";
|
|
||||||
export type { AccordionRootContextValue, AccordionItemContextValue } from "./accordion-context";
|
|
||||||
export const Accordion = Object.assign(AccordionRoot, { Item: AccordionItem, Header: AccordionHeader, Trigger: AccordionTrigger, Content: AccordionContent, useContext: useAccordionRootContext });
|
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { splitProps } from "solid-js";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Action. */
|
|
||||||
export interface AlertDialogActionProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Confirms the action and closes the AlertDialog. */
|
|
||||||
export function AlertDialogAction(props: AlertDialogActionProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children", "onClick"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
|
|
||||||
const handleClick: JSX.EventHandler<HTMLButtonElement, MouseEvent> = (e) => {
|
|
||||||
if (typeof local.onClick === "function") local.onClick(e);
|
|
||||||
ctx.setOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button type="button" onClick={handleClick} {...rest}>
|
|
||||||
{local.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { splitProps } from "solid-js";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Cancel. */
|
|
||||||
export interface AlertDialogCancelProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Cancels the action and closes the AlertDialog. */
|
|
||||||
export function AlertDialogCancel(props: AlertDialogCancelProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children", "onClick"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
|
|
||||||
const handleClick: JSX.EventHandler<HTMLButtonElement, MouseEvent> = (e) => {
|
|
||||||
if (typeof local.onClick === "function") local.onClick(e);
|
|
||||||
ctx.setOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button type="button" onClick={handleClick} {...rest}>
|
|
||||||
{local.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { Show, createEffect, onCleanup, splitProps } from "solid-js";
|
|
||||||
import { createFocusTrap } from "../../utilities/focus-trap/create-focus-trap";
|
|
||||||
import { createScrollLock } from "../../utilities/scroll-lock/create-scroll-lock";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Content. */
|
|
||||||
export interface AlertDialogContentProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
||||||
forceMount?: boolean;
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AlertDialog content panel. Uses focus trap and scroll lock.
|
|
||||||
* Does NOT dismiss on Escape or outside pointer click (unlike Dialog).
|
|
||||||
*/
|
|
||||||
export function AlertDialogContent(props: AlertDialogContentProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children", "forceMount"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
let contentRef: HTMLDivElement | undefined;
|
|
||||||
|
|
||||||
const focusTrap = createFocusTrap(() => contentRef ?? null);
|
|
||||||
const scrollLock = createScrollLock();
|
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
if (ctx.isOpen()) {
|
|
||||||
focusTrap.activate();
|
|
||||||
scrollLock.lock();
|
|
||||||
} else {
|
|
||||||
focusTrap.deactivate();
|
|
||||||
scrollLock.unlock();
|
|
||||||
}
|
|
||||||
onCleanup(() => {
|
|
||||||
focusTrap.deactivate();
|
|
||||||
scrollLock.unlock();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Show when={local.forceMount || ctx.isOpen()}>
|
|
||||||
<div
|
|
||||||
ref={contentRef}
|
|
||||||
id={ctx.contentId()}
|
|
||||||
role="alertdialog"
|
|
||||||
aria-modal="true"
|
|
||||||
aria-labelledby={ctx.titleId() || undefined}
|
|
||||||
aria-describedby={ctx.descriptionId() || undefined}
|
|
||||||
data-state={ctx.isOpen() ? "open" : "closed"}
|
|
||||||
{...rest}
|
|
||||||
>
|
|
||||||
{local.children}
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
import type { Accessor } from "solid-js";
|
|
||||||
import { createContext, useContext } from "solid-js";
|
|
||||||
|
|
||||||
/** Internal context shared between all AlertDialog parts. */
|
|
||||||
export interface InternalAlertDialogContextValue {
|
|
||||||
isOpen: Accessor<boolean>;
|
|
||||||
setOpen: (open: boolean) => void;
|
|
||||||
contentId: Accessor<string>;
|
|
||||||
titleId: Accessor<string | undefined>;
|
|
||||||
setTitleId: (id: string | undefined) => void;
|
|
||||||
descriptionId: Accessor<string | undefined>;
|
|
||||||
setDescriptionId: (id: string | undefined) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const InternalAlertDialogContext = createContext<InternalAlertDialogContextValue>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the internal AlertDialog context. Throws if used outside <AlertDialog>.
|
|
||||||
*/
|
|
||||||
export function useInternalAlertDialogContext(): InternalAlertDialogContextValue {
|
|
||||||
const ctx = useContext(InternalAlertDialogContext);
|
|
||||||
if (!ctx) {
|
|
||||||
throw new Error(
|
|
||||||
"[PettyUI] AlertDialog parts must be used inside <AlertDialog>.\n" +
|
|
||||||
" Fix: Wrap AlertDialog.Content, AlertDialog.Trigger, etc. inside <AlertDialog>.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InternalAlertDialogContextProvider = InternalAlertDialogContext.Provider;
|
|
||||||
|
|
||||||
/** Public context exposed to consumers via AlertDialog.useContext(). */
|
|
||||||
export interface AlertDialogContextValue {
|
|
||||||
/** Whether the alert dialog is currently open. */
|
|
||||||
open: Accessor<boolean>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AlertDialogContext = createContext<AlertDialogContextValue>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the public AlertDialog context. Throws if used outside <AlertDialog>.
|
|
||||||
*/
|
|
||||||
export function useAlertDialogContext(): AlertDialogContextValue {
|
|
||||||
const ctx = useContext(AlertDialogContext);
|
|
||||||
if (!ctx) {
|
|
||||||
throw new Error("[PettyUI] AlertDialog.useContext() called outside of <AlertDialog>.");
|
|
||||||
}
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AlertDialogContextProvider = AlertDialogContext.Provider;
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { createUniqueId, onCleanup, onMount, splitProps } from "solid-js";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Description. */
|
|
||||||
export interface AlertDialogDescriptionProps extends JSX.HTMLAttributes<HTMLParagraphElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Description for the AlertDialog. Registers its ID for aria-describedby. */
|
|
||||||
export function AlertDialogDescription(props: AlertDialogDescriptionProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
const id = createUniqueId();
|
|
||||||
onMount(() => ctx.setDescriptionId(id));
|
|
||||||
onCleanup(() => ctx.setDescriptionId(undefined));
|
|
||||||
return (
|
|
||||||
<p id={id} {...rest}>
|
|
||||||
{local.children}
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { Show, splitProps } from "solid-js";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Overlay. */
|
|
||||||
export interface AlertDialogOverlayProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
||||||
forceMount?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Backdrop overlay behind AlertDialog content. */
|
|
||||||
export function AlertDialogOverlay(props: AlertDialogOverlayProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["forceMount"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
return (
|
|
||||||
<Show when={local.forceMount || ctx.isOpen()}>
|
|
||||||
<div aria-hidden="true" data-state={ctx.isOpen() ? "open" : "closed"} {...rest} />
|
|
||||||
</Show>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { Portal } from "../../utilities/portal/portal";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Portal. */
|
|
||||||
export interface AlertDialogPortalProps {
|
|
||||||
target?: Element | null;
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Renders children into a portal (defaults to document.body). */
|
|
||||||
export function AlertDialogPortal(props: AlertDialogPortalProps): JSX.Element {
|
|
||||||
return props.target !== undefined ? (
|
|
||||||
<Portal target={props.target}>{props.children}</Portal>
|
|
||||||
) : (
|
|
||||||
<Portal>{props.children}</Portal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { createUniqueId } from "solid-js";
|
|
||||||
import {
|
|
||||||
type CreateDisclosureStateOptions,
|
|
||||||
createDisclosureState,
|
|
||||||
} from "../../primitives/create-disclosure-state";
|
|
||||||
import { createRegisterId } from "../../primitives/create-register-id";
|
|
||||||
import {
|
|
||||||
AlertDialogContextProvider,
|
|
||||||
InternalAlertDialogContextProvider,
|
|
||||||
type InternalAlertDialogContextValue,
|
|
||||||
} from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for the AlertDialog root. */
|
|
||||||
export interface AlertDialogRootProps {
|
|
||||||
/** Controls open state externally. */
|
|
||||||
open?: boolean;
|
|
||||||
/** Initial open state when uncontrolled. */
|
|
||||||
defaultOpen?: boolean;
|
|
||||||
/** Called when open state changes. */
|
|
||||||
onOpenChange?: (open: boolean) => void;
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Root component for AlertDialog. Manages open state and provides context.
|
|
||||||
*/
|
|
||||||
export function AlertDialogRoot(props: AlertDialogRootProps): JSX.Element {
|
|
||||||
const disclosure = createDisclosureState({
|
|
||||||
get open() {
|
|
||||||
return props.open;
|
|
||||||
},
|
|
||||||
get defaultOpen() {
|
|
||||||
return props.defaultOpen;
|
|
||||||
},
|
|
||||||
get onOpenChange() {
|
|
||||||
return props.onOpenChange;
|
|
||||||
},
|
|
||||||
} as CreateDisclosureStateOptions);
|
|
||||||
|
|
||||||
const contentId = createUniqueId();
|
|
||||||
const [titleId, setTitleId] = createRegisterId();
|
|
||||||
const [descriptionId, setDescriptionId] = createRegisterId();
|
|
||||||
|
|
||||||
const internalCtx: InternalAlertDialogContextValue = {
|
|
||||||
isOpen: disclosure.isOpen,
|
|
||||||
setOpen: (open) => (open ? disclosure.open() : disclosure.close()),
|
|
||||||
contentId: () => contentId,
|
|
||||||
titleId,
|
|
||||||
setTitleId,
|
|
||||||
descriptionId,
|
|
||||||
setDescriptionId,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<InternalAlertDialogContextProvider value={internalCtx}>
|
|
||||||
<AlertDialogContextProvider value={{ open: disclosure.isOpen }}>
|
|
||||||
{props.children}
|
|
||||||
</AlertDialogContextProvider>
|
|
||||||
</InternalAlertDialogContextProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { createUniqueId, onCleanup, onMount, splitProps } from "solid-js";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Title. */
|
|
||||||
export interface AlertDialogTitleProps extends JSX.HTMLAttributes<HTMLHeadingElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Title for the AlertDialog. Registers its ID for aria-labelledby. */
|
|
||||||
export function AlertDialogTitle(props: AlertDialogTitleProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
const id = createUniqueId();
|
|
||||||
onMount(() => ctx.setTitleId(id));
|
|
||||||
onCleanup(() => ctx.setTitleId(undefined));
|
|
||||||
return (
|
|
||||||
<h2 id={id} {...rest}>
|
|
||||||
{local.children}
|
|
||||||
</h2>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import type { JSX } from "solid-js";
|
|
||||||
import { splitProps } from "solid-js";
|
|
||||||
import { useInternalAlertDialogContext } from "./alert-dialog-context";
|
|
||||||
|
|
||||||
/** Props for AlertDialog.Trigger. */
|
|
||||||
export interface AlertDialogTriggerProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
||||||
children?: JSX.Element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Opens the AlertDialog when clicked. */
|
|
||||||
export function AlertDialogTrigger(props: AlertDialogTriggerProps): JSX.Element {
|
|
||||||
const [local, rest] = splitProps(props, ["children", "onClick"]);
|
|
||||||
const ctx = useInternalAlertDialogContext();
|
|
||||||
|
|
||||||
const handleClick: JSX.EventHandler<HTMLButtonElement, MouseEvent> = (e) => {
|
|
||||||
if (typeof local.onClick === "function") local.onClick(e);
|
|
||||||
ctx.setOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
aria-haspopup="dialog"
|
|
||||||
aria-controls={ctx.contentId()}
|
|
||||||
aria-expanded={ctx.isOpen() ? "true" : "false"}
|
|
||||||
onClick={handleClick}
|
|
||||||
{...rest}
|
|
||||||
>
|
|
||||||
{local.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
import type { JSX } from "solid-js";
|
|
||||||
import type { ComponentMeta } from "../../meta";
|
|
||||||
export declare const AlertDialogRootPropsSchema: z.ZodObject<{
|
|
||||||
open: z.ZodOptional<z.ZodBoolean>;
|
|
||||||
defaultOpen: z.ZodOptional<z.ZodBoolean>;
|
|
||||||
}, z.core.$strip>;
|
|
||||||
export interface AlertDialogRootProps extends z.infer<typeof AlertDialogRootPropsSchema> {
|
|
||||||
onOpenChange?: (open: boolean) => void;
|
|
||||||
children: JSX.Element;
|
|
||||||
}
|
|
||||||
export declare const AlertDialogMeta: ComponentMeta;
|
|
||||||
//# sourceMappingURL=alert-dialog.props.d.ts.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"alert-dialog.props.d.ts","sourceRoot":"","sources":["alert-dialog.props.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,eAAO,MAAM,0BAA0B;;;iBAGrC,CAAC;AACH,MAAM,WAAW,oBAAqB,SAAQ,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC;IAAG,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CAAE;AAC3J,eAAO,MAAM,eAAe,EAAE,aAKpB,CAAC"}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user