From b1df4a8299d187685b9d2979b3afa217e4dfffae Mon Sep 17 00:00:00 2001 From: Navin Date: Mon, 30 Nov 2020 14:51:03 +0530 Subject: [PATCH] =?UTF-8?q?docs(readme):=20=F0=9F=93=9D=20=20add=20docs=20?= =?UTF-8?q?for=20all=20the=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs-templates/Accordion.md | 9 +- docs-templates/Breadcrumb.md | 8 +- docs-templates/Calendar.md | 10 +- docs-templates/DatePicker.md | 14 +- docs-templates/Link.md | 8 +- docs-templates/drawer.md | 22 + docs-templates/meter.md | 23 + docs-templates/number-input.md | 22 + docs-templates/pagination.md | 22 + docs-templates/picker-base.md | 22 + docs-templates/progress.md | 23 + docs-templates/segment.md | 22 + docs-templates/select.md | 23 + docs-templates/slider.md | 23 + docs-templates/timepicker.md | 23 + docs-templates/toast.md | 16 + docs/Accordion.md | 10 +- docs/Breadcrumb.md | 8 +- docs/Calendar.md | 14 +- docs/DatePicker.md | 21 +- docs/Link.md | 8 +- docs/drawer.md | 149 ++++++ docs/meter.md | 145 ++++++ docs/number-input.md | 185 ++++++++ docs/pagination.md | 139 ++++++ docs/picker-base.md | 129 +++++ docs/progress.md | 174 +++++++ docs/segment.md | 200 ++++++++ docs/select.md | 755 ++++++++++++++++++++++++++++++ docs/slider.md | 273 +++++++++++ docs/timepicker.md | 832 +++++++++++++++++++++++++++++++++ docs/toast.md | 52 +++ scripts/inject-csb-links.js | 2 +- 33 files changed, 3334 insertions(+), 52 deletions(-) create mode 100644 docs-templates/drawer.md create mode 100644 docs-templates/meter.md create mode 100644 docs-templates/number-input.md create mode 100644 docs-templates/pagination.md create mode 100644 docs-templates/picker-base.md create mode 100644 docs-templates/progress.md create mode 100644 docs-templates/segment.md create mode 100644 docs-templates/select.md create mode 100644 docs-templates/slider.md create mode 100644 docs-templates/timepicker.md create mode 100644 docs-templates/toast.md create mode 100644 docs/drawer.md create mode 100644 docs/meter.md create mode 100644 docs/number-input.md create mode 100644 docs/pagination.md create mode 100644 docs/picker-base.md create mode 100644 docs/progress.md create mode 100644 docs/segment.md create mode 100644 docs/select.md create mode 100644 docs/slider.md create mode 100644 docs/timepicker.md create mode 100644 docs/toast.md diff --git a/docs-templates/Accordion.md b/docs-templates/Accordion.md index 4b715169c..16e9dd98c 100644 --- a/docs-templates/Accordion.md +++ b/docs-templates/Accordion.md @@ -7,13 +7,14 @@ Accessible Accordion component. It follows the link_title: Accordion Example Live Demo js: src/accordion/stories/__js/AccordionBasic.component.jsx css: src/accordion/stories/AccordionStyled.css +deps: [emotion] --> -# Props +## Props -### Accessibility +## Accessibility - `Accordion` extends the accessibility features of [Composite](https://github.com/reakit/reakit/blob/master/docs/composite/#accessibility). @@ -30,11 +31,11 @@ css: src/accordion/stories/AccordionStyled.css - `AccordionPanel` extends the accessibility features of [DisclosureContent](https://github.com/reakit/reakit/blob/master/docs/disclosure). -### Composition +## Composition -### Example +## Example ```js diff --git a/docs-templates/Breadcrumb.md b/docs-templates/Breadcrumb.md index afbba6b5e..4013e4bd1 100644 --- a/docs-templates/Breadcrumb.md +++ b/docs-templates/Breadcrumb.md @@ -4,22 +4,22 @@ Accessible `Breadcrumb` component that provides the required aria attributes for it's links. It follows the [WAI-ARIA Breadcrumb Pattern](https://www.w3.org/TR/wai-aria-practices-1.2/#breadcrumb). -# Props +## Props -### Accessibilty +## Accessibilty - `Breadcrumbs` should have `aria-label` or `aria-labelledby` attribute. - `BreadcrumbLink` should have `aria-current` set to `page` if the currenct page is loaded. - `BreadcrumbLink` extends the accessibility features of [Link](#Link). -### Composition +## Composition -### Example +## Example ```js diff --git a/docs-templates/Calendar.md b/docs-templates/Calendar.md index 05cbadc75..2a8b97325 100644 --- a/docs-templates/Calendar.md +++ b/docs-templates/Calendar.md @@ -14,23 +14,23 @@ js: src/calendar/stories/__js/CalendarRange.component.jsx css: src/calendar/stories/CalendarRange.css --> -# Props +## Props -# Composition +## Composition -### Example +## Example -#### Base Calendar +### Base Calendar ```js ``` -#### Range Calendar +### Range Calendar ```js diff --git a/docs-templates/DatePicker.md b/docs-templates/DatePicker.md index 94ea0590f..0ba1a9498 100644 --- a/docs-templates/DatePicker.md +++ b/docs-templates/DatePicker.md @@ -14,24 +14,24 @@ js: src/datepicker/stories/__js/DateRangePicker.component.jsx css: src/datepicker/stories/DatePickerRange.css --> -# Props +## Props -# Composition +## Composition -### Example +## Example -#### DatePicker +### DatePicker ```js - + ``` -#### Range Date Picker +### Range Date Picker ```js - + ``` diff --git a/docs-templates/Link.md b/docs-templates/Link.md index b0f129ff9..76e6034f6 100644 --- a/docs-templates/Link.md +++ b/docs-templates/Link.md @@ -4,19 +4,19 @@ Accessible `Link` component that provides the required aria role when used under different compositions. It follows the [WAI-ARIA Link Pattern](https://www.w3.org/TR/wai-aria-practices-1.2/#link). -# Props +## Props -### Accessibilty +## Accessibilty - `Link` has role `link`. -### Composition +## Composition -### Example +## Example ```js diff --git a/docs-templates/drawer.md b/docs-templates/drawer.md new file mode 100644 index 000000000..322f64648 --- /dev/null +++ b/docs-templates/drawer.md @@ -0,0 +1,22 @@ +## Drawer + +Accessible `Drawer` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/meter.md b/docs-templates/meter.md new file mode 100644 index 000000000..3bb4bb185 --- /dev/null +++ b/docs-templates/meter.md @@ -0,0 +1,23 @@ +## Meter + +Accessible `Meter` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/number-input.md b/docs-templates/number-input.md new file mode 100644 index 000000000..a25a37ae4 --- /dev/null +++ b/docs-templates/number-input.md @@ -0,0 +1,22 @@ +## NumberInput + +Accessible `NumberInput` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/pagination.md b/docs-templates/pagination.md new file mode 100644 index 000000000..b6c83bef3 --- /dev/null +++ b/docs-templates/pagination.md @@ -0,0 +1,22 @@ +## Pagination + +Accessible `Pagination` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/picker-base.md b/docs-templates/picker-base.md new file mode 100644 index 000000000..2489c937f --- /dev/null +++ b/docs-templates/picker-base.md @@ -0,0 +1,22 @@ +## PickerBase + +Accessible `PickerBase` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/progress.md b/docs-templates/progress.md new file mode 100644 index 000000000..f76e78f69 --- /dev/null +++ b/docs-templates/progress.md @@ -0,0 +1,23 @@ +## Progress + +Accessible `Progress` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/segment.md b/docs-templates/segment.md new file mode 100644 index 000000000..3d02e6550 --- /dev/null +++ b/docs-templates/segment.md @@ -0,0 +1,22 @@ +## Segment + +Accessible `Segment` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/select.md b/docs-templates/select.md new file mode 100644 index 000000000..d8bf8cfba --- /dev/null +++ b/docs-templates/select.md @@ -0,0 +1,23 @@ +## Select + +Accessible `Select` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/slider.md b/docs-templates/slider.md new file mode 100644 index 000000000..1a1556da3 --- /dev/null +++ b/docs-templates/slider.md @@ -0,0 +1,23 @@ +## Slider + +Accessible `Slider` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/timepicker.md b/docs-templates/timepicker.md new file mode 100644 index 000000000..8febd3975 --- /dev/null +++ b/docs-templates/timepicker.md @@ -0,0 +1,23 @@ +## TimePicker + +Accessible `TimePicker` component. + + + +## Props + + + +## Composition + + + +## Example + +```js + +``` diff --git a/docs-templates/toast.md b/docs-templates/toast.md new file mode 100644 index 000000000..9959961db --- /dev/null +++ b/docs-templates/toast.md @@ -0,0 +1,16 @@ +## Toast + +Accessible `Toast` component. + + + +## Example + +```js + +``` diff --git a/docs/Accordion.md b/docs/Accordion.md index b9a01a058..011c4d918 100644 --- a/docs/Accordion.md +++ b/docs/Accordion.md @@ -3,9 +3,9 @@ Accessible Accordion component. It follows the [WAI-ARIA Accordion Pattern](https://www.w3.org/TR/wai-aria-practices-1.2/#accordion). -[Accordion Example Live Demo](https://codesandbox.io/s/9qc1x) +[Accordion Example Live Demo](https://codesandbox.io/s/h7wdn) -# Props +## Props @@ -266,7 +266,7 @@ form elements. In this case, only `aria-disabled` will be set. -### Accessibility +## Accessibility - `Accordion` extends the accessibility features of [Composite](https://github.com/reakit/reakit/blob/master/docs/composite/#accessibility). @@ -283,7 +283,7 @@ form elements. In this case, only `aria-disabled` will be set. - `AccordionPanel` extends the accessibility features of [DisclosureContent](https://github.com/reakit/reakit/blob/master/docs/disclosure). -### Composition +## Composition - Accordion uses [useComposite](https://reakit.io/docs/composite) - AccordionPanel uses [unstable_useId](https://reakit.io/docs/id) and @@ -291,7 +291,7 @@ form elements. In this case, only `aria-disabled` will be set. - AccordionTrigger uses [useButton](https://reakit.io/docs/button) and [useCompositeItem](https://reakit.io/docs/composite) -### Example +## Example ```js import * as React from "react"; diff --git a/docs/Breadcrumb.md b/docs/Breadcrumb.md index dabd65bf8..59711184b 100644 --- a/docs/Breadcrumb.md +++ b/docs/Breadcrumb.md @@ -4,7 +4,7 @@ Accessible `Breadcrumb` component that provides the required aria attributes for it's links. It follows the [WAI-ARIA Breadcrumb Pattern](https://www.w3.org/TR/wai-aria-practices-1.2/#breadcrumb). -# Props +## Props @@ -22,19 +22,19 @@ it's links. It follows the No props to show -### Accessibilty +## Accessibilty - `Breadcrumbs` should have `aria-label` or `aria-labelledby` attribute. - `BreadcrumbLink` should have `aria-current` set to `page` if the currenct page is loaded. - `BreadcrumbLink` extends the accessibility features of [Link](#Link). -### Composition +## Composition - BreadcrumbLink uses [useLink](./link.md) - Breadcrumbs uses [useBox](https://reakit.io/docs/box) -### Example +## Example ```js import * as React from "react"; diff --git a/docs/Calendar.md b/docs/Calendar.md index 08844aab1..01a353aad 100644 --- a/docs/Calendar.md +++ b/docs/Calendar.md @@ -2,11 +2,11 @@ Accessible `Calendar` component. -[RangeCalendar - Open On Sandbox](https://codesandbox.io/s/khdp2) +[Calendar - Open On Sandbox](https://codesandbox.io/s/qte2l) -[Calendar - Open On Sandbox](https://codesandbox.io/s/pmtcs) +[RangeCalendar - Open On Sandbox](https://codesandbox.io/s/86dqv) -# Props +## Props @@ -184,7 +184,7 @@ form elements. In this case, only `aria-disabled` will be set. -# Composition +## Composition - Calendar uses [useBox](https://reakit.io/docs/box) - CalendarButton uses [useButton](https://reakit.io/docs/button) @@ -194,9 +194,9 @@ form elements. In this case, only `aria-disabled` will be set. - CalendarHeader uses [useBox](https://reakit.io/docs/box) - CalendarWeekTitle uses [useBox](https://reakit.io/docs/box) -### Example +## Example -#### Base Calendar +### Base Calendar ```js import React from "react"; @@ -316,7 +316,7 @@ const DoubleChevronRight = props => ( ); ``` -#### Range Calendar +### Range Calendar ```js import React from "react"; diff --git a/docs/DatePicker.md b/docs/DatePicker.md index c8cf744e3..293cf0e91 100644 --- a/docs/DatePicker.md +++ b/docs/DatePicker.md @@ -2,11 +2,11 @@ Accessible `DatePicker` component. -[DatePicker - Open On Sandbox](https://codesandbox.io/s/ixpqy) +[DatePicker - Open On Sandbox](https://codesandbox.io/s/4j912) -[RangeDatePicker - Open On Sandbox](https://codesandbox.io/s/wlu79) +[RangeDatePicker - Open On Sandbox](https://codesandbox.io/s/cq9ql) -# Props +## Props @@ -178,7 +178,7 @@ form elements. In this case, only `aria-disabled` will be set. -# Composition +## Composition - DatePicker uses [usePickerBase](undefined) - DatePickerContent uses [usePickerBaseContent](undefined) @@ -186,9 +186,9 @@ form elements. In this case, only `aria-disabled` will be set. - DatePickerSegmentField uses [useSegmentField](undefined) - DatePickerTrigger uses [usePickerBaseTrigger](undefined) -### Example +## Example -#### DatePicker +### DatePicker ```js import * as React from "react"; @@ -351,7 +351,7 @@ const DoubleChevronRight = props => ( ); ``` -#### Range Date Picker +### Range Date Picker ```js import React from "react"; @@ -533,3 +533,10 @@ const DoubleChevronRight = props => ( ); ``` + +ChevronRight = props => ( ); + +``` + +``` diff --git a/docs/Link.md b/docs/Link.md index 4f3c3f5c9..839668c06 100644 --- a/docs/Link.md +++ b/docs/Link.md @@ -4,7 +4,7 @@ Accessible `Link` component that provides the required aria role when used under different compositions. It follows the [WAI-ARIA Link Pattern](https://www.w3.org/TR/wai-aria-practices-1.2/#link). -# Props +## Props @@ -16,15 +16,15 @@ different compositions. It follows the form elements. In this case, only `aria-disabled` will be set. - **`isExternal`** boolean | undefined Opens the link in a new tab -### Accessibilty +## Accessibilty - `Link` has role `link`. -### Composition +## Composition - Link uses [useClickable](https://reakit.io/docs/clickable) -### Example +## Example ```js import * as React from "react"; diff --git a/docs/drawer.md b/docs/drawer.md new file mode 100644 index 000000000..af4d694b6 --- /dev/null +++ b/docs/drawer.md @@ -0,0 +1,149 @@ +## Drawer + +Accessible `Drawer` component. + +[Drawer - Open On Sandbox](https://codesandbox.io/s/c13ec) + +## Props + + + +### `Drawer` + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`visible`** boolean Whether it's visible or not. +- **`animating`** boolean Whether it's animating or not. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`hide`** () => void Changes the `visible` state to `false` +- **`hideOnEsc`** boolean | undefined When enabled, user can hide + the dialog by pressing `Escape`. +- **`hideOnClickOutside`** boolean | undefined When enabled, user + can hide the dialog by clicking outside it. +- **`preventBodyScroll`** boolean | undefined When enabled, user + can't scroll on body when the dialog is visible. This option doesn't work if + the dialog isn't modal. +- **`unstable_initialFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog shows. When not set, the first tabbable element + within the dialog will be used. +- **`unstable_finalFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog hides. When not set, the disclosure component will + be used. +- **`unstable_orphan`** ⚠️ boolean | + undefined Whether or not the dialog should be a child of its parent. + Opening a nested orphan dialog will close its parent dialog if + `hideOnClickOutside` is set to `true` on the parent. It will be set to `false` + if `modal` is `false`. +- **`placement`** "left" | "right" | "top" | + "bottom" | undefined + +### `DrawerCloseButton` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`visible`** boolean Whether it's visible or not. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`toggle`** () => void Toggles the `visible` state + +## Composition + +- Drawer uses [useDialog](undefined) +- DrawerCloseButton uses [useDialogDisclosure](undefined) + +## Example + +```js +import React from "react"; +import { css } from "emotion"; + +import { + Drawer, + useDrawerState, + DrawerBackdrop, + DrawerCloseButton, + DrawerDisclosure, +} from "renderless-components"; + +export const App = () => { + const dialog = useDrawerState({ animated: true }); + const inputRef = React.useRef(null); + const [placement, setPlacement] = React.useState("left"); + + return ( +
+ Open Drawer + + + + X +

Welcome to Reakit!

+ +
+
+
+ ); +}; + +export default App; + +const backdropStyles = css` + opacity: 0; + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + transition: opacity 250ms ease-in-out; + background-color: rgba(0, 0, 0, 0.2); + &[data-enter] { + opacity: 1; + } +`; + +const cssTransforms = { + top: "translate(0, -200px)", + bottom: "translate(0, 200px)", + left: "translate(-200px, 0)", + right: "translate(200px, 0)", +}; +``` diff --git a/docs/meter.md b/docs/meter.md new file mode 100644 index 000000000..a75e09d7a --- /dev/null +++ b/docs/meter.md @@ -0,0 +1,145 @@ +## Meter + +Accessible `Meter` component. + +[Meter - Open On Sandbox](https://codesandbox.io/s/n9f9q) + +## Props + + + +### `useMeterState` + +- **`value`** number The `value` of the meter indicator. + + If `undefined`/`not valid` the meter bar will be equal to `min` + +- **`min`** number The minimum value of the meter +- **`max`** number The maximum value of the meter +- **`low`** number The higher limit of min range. + + Defaults to `min`. + +- **`optimum`** number The lower limit of max range. + + Defaults to `median of low & high`. + +- **`high`** number The lower limit of max range. + + Defaults to `max`. + +### `Meter` + +
4 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`value`** number The `value` of the meter indicator. + + If `undefined`/`not valid` the meter bar will be equal to `min` + +- **`min`** number The minimum value of the meter +- **`max`** number The maximum value of the meter +- **`percent`** number Percentage of the value progressed with + respect to min & max + +
+ +## Composition + +- Meter uses [useBox](https://reakit.io/docs/box) + +## Example + +```js +import * as React from "react"; +import { css, keyframes } from "emotion"; + +import { Meter, useMeterState } from "renderless-components"; + +export const App = props => { + const { + children, + withLabel = false, + withStripe = false, + withStripeAnimation = false, + ...rest + } = props; + const meter = useMeterState(rest); + + return ( +
+ + {withLabel &&
{`${meter.percent}%`}
} +
+ ); +}; + +export default App; + +const meterStyle = css({ + position: "relative", + width: "500px", + height: "1rem", + background: "whiteSmoke", + borderRadius: "3px", + border: "1px solid #ccc", + boxShadow: "0 5px 5px -5px #333 inset", + overflow: "hidden", +}); + +const labelStyles = css({ + top: "50%", + left: "50%", + width: "100%", + textAlign: "center", + position: "absolute", + transform: "translate(-50%, -50%)", + fontWeight: "bold", + fontSize: "0.75em", + lineHeight: 1, +}); + +const stripeAnim = keyframes({ + from: { backgroundPosition: "1rem 0" }, + to: { backgroundPosition: "0 0" }, +}); + +const background = { + safe: "#8bcf69", + caution: "#e6d450", + danger: "#f28f68", +}; + +const generateStripe = { + backgroundImage: `linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent +)`, + backgroundSize: "1rem 1rem", +}; + +function meterBarStyle(meter, props) { + const { percent, status } = meter; + const { withStripe, withStripeAnimation } = props; + + return css({ + backgroundColor: status == null ? undefined : background[status], + width: percent != null ? `${percent}%` : 0, + height: "100%", + ...(withStripe && { ...generateStripe }), + ...(withStripe && + withStripeAnimation && { animation: `${stripeAnim} 1s linear infinite` }), + }); +} +``` diff --git a/docs/number-input.md b/docs/number-input.md new file mode 100644 index 000000000..699e22d46 --- /dev/null +++ b/docs/number-input.md @@ -0,0 +1,185 @@ +## NumberInput + +Accessible `NumberInput` component. + +[NumberInput - Open On Sandbox](https://codesandbox.io/s/ybuxv) + +## Props + + + +### `useNumberinputState` + +- **`value`** string | number The value of the counter. Should be + less than `max` and greater than `min` + + If no value, initial value is set to `""` + +- **`keepWithinRange`** boolean This controls the value update + behavior in general. + + - If `true` and you use the stepper or up/down arrow keys, the value will not + exceed the `max` or go lower than `min` + + - If `false`, the value will be allowed to go out of range. + +- **`min`** number The minimum value of the counter +- **`max`** number The maximum value of the counter +- **`step`** number The step used to increment or decrement the + value +- **`precision`** number The number of decimal points used to round + the value + + If no precision, initial value is from the decimal places from value/step - + `0` + +- **`defaultValue`** string | number | undefined The initial value + of the counter. Should be less than `max` and greater than `min` +- **`onChange`** + ((valueAsString: + string, valueAsNumber: number)... The callback fired when the value + changes +- **`focusInputOnChange`** boolean | undefined If `true`, the input + will be focused as you increment or decrement the value with the stepper + +### `NumberInput` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`clampValueOnBlur`** boolean | undefined This controls the + value update when you blur out of the input. +- If `true` and the value is greater than `max`, the value will be reset to + `max` +- Else, the value remains the same. +- **`allowMouseWheel`** boolean | undefined If `true`, the input's +value will change based on mouse wheel +
12 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`keepWithinRange`** boolean This controls the value update + behavior in general. + + - If `true` and you use the stepper or up/down arrow keys, the value will not + exceed the `max` or go lower than `min` + + - If `false`, the value will be allowed to go out of range. + +- **`value`** string | number The value of the counter. Should be + less than `max` and greater than `min` + + If no value, initial value is set to `""` + +- **`min`** number The minimum value of the counter +- **`max`** number The maximum value of the counter +- **`step`** number The step used to increment or decrement the + value +- **`valueAsNumber`** number The value of the counter in number. +- **`isOutOfRange`** boolean True, if value is less than `min` & + greater than `max`. +- **`inputRef`** RefObject<HTMLElement | null> The Input + Element. +- **`setValue`** (next: StringOrNumber) => void Set the value + which will be converted to string. +- **`increment`** (step: number) => void Increment the value + based on the step +- **`decrement`** (step: number) => void Decrement the value + based on the step +- **`setCastedValue`** (value: StringOrNumber) => void Set the + casted value based on precision & step. + +
+ +### `NumberInputDecrementButton` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
5 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`keepWithinRange`** boolean This controls the value update + behavior in general. + + - If `true` and you use the stepper or up/down arrow keys, the value will not + exceed the `max` or go lower than `min` + + - If `false`, the value will be allowed to go out of range. + +- **`isAtMin`** boolean Truw, if value is equal to min. +- **`focusInput`** () => void Focus input if focus input on + value change is `true` +- **`spinDown`** () => void Spinner handler that decrements the + value after an interval +- **`spinStop`** () => void Spinner handler that Stop it from + incrementing or decrementing + +
+ +### `NumberInputIncrementButton` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
5 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`keepWithinRange`** boolean This controls the value update + behavior in general. + + - If `true` and you use the stepper or up/down arrow keys, the value will not + exceed the `max` or go lower than `min` + + - If `false`, the value will be allowed to go out of range. + +- **`isAtMax`** boolean True, if value is equal to max. +- **`focusInput`** () => void Focus input if focus input on + value change is `true` +- **`spinUp`** () => void Spinner handler that increments the + value after an interval +- **`spinStop`** () => void Spinner handler that Stop it from + incrementing or decrementing + +
+ +## Composition + +- NumberInput uses [useInput](undefined) +- NumberInputDecrementButton uses [useButton](https://reakit.io/docs/button) +- NumberInputIncrementButton uses [useButton](https://reakit.io/docs/button) + +## Example + +```js +import * as React from "react"; + +import { + NumberInput, + useNumberInputState, + NumberInputDecrementButton, + NumberInputIncrementButton, +} from "renderless-components"; + +export const App = props => { + const state = useNumberInputState(props); + const { clampValueOnBlur, allowMouseWheel } = props; + + return ( + + ); +}; + +export default App; +``` diff --git a/docs/pagination.md b/docs/pagination.md new file mode 100644 index 000000000..d10e6ced4 --- /dev/null +++ b/docs/pagination.md @@ -0,0 +1,139 @@ +## Pagination + +Accessible `Pagination` component. + +[Pagination - Open On Sandbox](https://codesandbox.io/s/jp1fn) + +## Props + + + +### `usePaginationState` + +- **`defaultPage`** number | undefined Set the default + page(uncontrollable) +- **`page`** number | undefined Set the page(controllable) +- **`onChange`** ((page: number) => void) | undefined + +- **`count`** number | undefined Total no. of pages +- **`boundaryCount`** number | undefined No. of boundary pages to + be visible +- **`siblingCount`** number | undefined No. of sibiling pages + allowed before/after the current page + +### `Pagination` + +
9 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`currentPage`** number The current active page +- **`pages`** (string | number)[] All the page with start & end + ellipsis +- **`isAtFirstPage`** boolean True, if the currentPage is at first + page +- **`isAtLastPage`** boolean True, if the currentPage is at last + page +- **`movePage`** (page: number) => void Go to the specified + page number +- **`nextPage`** () => void Go to next page +- **`prevPage`** () => void Go to previous page +- **`firstPage`** () => void Go to first page +- **`lastPage`** () => void Go to last page + +
+ +### `PaginationButton` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`goto`** + number + | "nextPage" | "prevPage" | "firstPage" ... + +
8 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`currentPage`** number The current active page +- **`movePage`** (page: number) => void Go to the specified + page number +- **`nextPage`** () => void Go to next page +- **`prevPage`** () => void Go to previous page +- **`firstPage`** () => void Go to first page +- **`lastPage`** () => void Go to last page +- **`isAtLastPage`** boolean True, if the currentPage is at last + page +- **`isAtFirstPage`** boolean True, if the currentPage is at first + page + +
+ +## Composition + +- Pagination uses [useBox](https://reakit.io/docs/box) +- PaginationButton uses [useButton](https://reakit.io/docs/button) + +## Example + +```js +import * as React from "react"; + +import { + Pagination, + PaginationButton, + usePaginationState, +} from "renderless-components"; + +export const App = props => { + const state = usePaginationState({ count: 10, ...props }); + + return ( + +
    +
  • + + First + +
  • +
  • + + Previous + +
  • + {state.pages.map(page => { + if (page === "start-ellipsis" || page === "end-ellipsis") { + return
  • ...
  • ; + } + + return ( +
  • + + {page} + +
  • + ); + })} +
  • + + Next + +
  • +
  • + + Last + +
  • +
+
+ ); +}; + +export default App; +``` diff --git a/docs/picker-base.md b/docs/picker-base.md new file mode 100644 index 000000000..2c04e6da1 --- /dev/null +++ b/docs/picker-base.md @@ -0,0 +1,129 @@ +## PickerBase + +Accessible `PickerBase` component. + +[PickerBase - Open On Sandbox](https://codesandbox.io/s/rsuxm) + +## Props + + + +### `PickerBase` + +
7 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`visible`** boolean Whether it's visible or not. +- **`pickerId`** string | undefined + +- **`dialogId`** string | undefined + +- **`isDisabled`** boolean | undefined + +- **`isReadOnly`** boolean | undefined + +- **`segmentFocus`** (() => void) | undefined + +- **`show`** () => void Changes the `visible` state to `true` + +
+ +### `PickerBaseContent` + +- **`hideOnEsc`** boolean | undefined When enabled, user can hide + the dialog by pressing `Escape`. +- **`hideOnClickOutside`** boolean | undefined When enabled, user + can hide the dialog by clicking outside it. +- **`preventBodyScroll`** boolean | undefined When enabled, user + can't scroll on body when the dialog is visible. This option doesn't work if + the dialog isn't modal. +- **`unstable_initialFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog shows. When not set, the first tabbable element + within the dialog will be used. +- **`unstable_finalFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog hides. When not set, the disclosure component will + be used. +- **`unstable_orphan`** ⚠️ boolean | +undefined Whether or not the dialog should be a child of its parent. +Opening a nested orphan dialog will close its parent dialog if +`hideOnClickOutside` is set to `true` on the parent. It will be set to `false` +if `modal` is `false`. +
8 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`visible`** boolean Whether it's visible or not. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`animating`** boolean Whether it's animating or not. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`hide`** () => void Changes the `visible` state to `false` +- **`dialogId`** string | undefined + +
+ +### `PickerBaseTrigger` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
6 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`visible`** boolean Whether it's visible or not. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`toggle`** () => void Toggles the `visible` state +- **`unstable_referenceRef`** ⚠️ + RefObject<HTMLElement | null> The reference element. +- **`isDisabled`** boolean | undefined + +- **`isReadOnly`** boolean | undefined + +
+ +## Composition + +- PickerBase uses [useBox](https://reakit.io/docs/box) +- PickerBaseContent uses [usePopover](undefined) +- PickerBaseTrigger uses [usePopoverDisclosure](undefined) + +## Example + +```js +import * as React from "react"; + +import { + PickerBase, + PickerBaseTrigger, + PickerBaseContent, + usePickerBaseState, +} from "renderless-components"; + +export const App = props => { + const state = usePickerBaseState(props); + + return ( + <> + + open + + Content + + ); +}; + +export default App; +``` diff --git a/docs/progress.md b/docs/progress.md new file mode 100644 index 000000000..8d75c5bc8 --- /dev/null +++ b/docs/progress.md @@ -0,0 +1,174 @@ +## Progress + +Accessible `Progress` component. + +[Progress - Open On Sandbox](https://codesandbox.io/s/42dwp) + +## Props + + + +### `useProgressState` + +- **`value`** number | null The `value` of the progress indicator. + + If `null` the progress bar will be in `indeterminate` state + +- **`min`** number The minimum value of the progress +- **`max`** number The maximum value of the + +### `Progress` + +
4 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`value`** number | null The `value` of the progress indicator. + + If `null` the progress bar will be in `indeterminate` state + +- **`min`** number The minimum value of the progress +- **`max`** number The maximum value of the +- **`isIndeterminate`** boolean Set isInterminate state + +
+ +## Composition + +- Progress uses [useBox](https://reakit.io/docs/box) + +## Example + +```js +import * as React from "react"; +import { Button } from "reakit"; +import { css, keyframes } from "emotion"; + +import { cx, isNull, Progress, useProgressState } from "renderless-components"; + +export const App = props => { + const { + children, + withLabel = false, + withStripe = false, + withStripeAnimation = false, + ...rest + } = props; + const state = useProgressState(rest); + const { value, setValue, percent, isIndeterminate } = state; + + React.useEffect(() => { + const clearId = setInterval(() => { + !isIndeterminate && + setValue(prevValue => { + if (isNull(prevValue)) return prevValue; + return prevValue + 5; + }); + }, 500); + + if (value === 100) { + clearInterval(clearId); + } + + return () => { + clearInterval(clearId); + }; + }, [setValue, isIndeterminate, value]); + + return ( +
+
+ {withLabel ?
{`${percent}%`}
: null} + +
+
+ +
+ ); +}; + +export default App; + +const progressStyle = css({ + background: "rgb(237, 242, 247)", + height: "0.5rem", + width: "400px", + overflow: "hidden", + position: "relative", +}); + +const progressBarStyle = percent => { + return css({ + transition: "all 0.3s", + backgroundColor: "#3182ce", + width: `${percent}%`, + height: "100%", + }); +}; + +export const labelStyles = css({ + top: "50%", + left: "50%", + width: "100%", + textAlign: "center", + position: "absolute", + transform: "translate(-50%, -50%)", + fontWeight: "bold", + fontSize: "0.75em", + lineHeight: 1, +}); + +function generateStripe(size = "1rem", color = "rgba(255, 255, 255, 0.15)") { + return css({ + backgroundImage: `linear-gradient( + 45deg, + ${color} 25%, + transparent 25%, + transparent 50%, + ${color} 50%, + ${color} 75%, + transparent 75%, + transparent + )`, + backgroundSize: `${size} ${size}`, + }); +} + +const stripStyles = generateStripe(); + +const stripe = keyframes({ + from: { backgroundPosition: "1rem 0" }, + to: { backgroundPosition: "0 0" }, +}); + +const stripAnim = css({ + animation: `${stripe} 1s linear infinite`, +}); + +const progressAnim = keyframes({ + "0%": { left: "-40%" }, + "100%": { left: "100%" }, +}); + +const indeterminateStyles = css({ + position: "absolute", + willChange: "left", + minWidth: "50%", + width: "100%", + height: "100%", + backgroundImage: + "linear-gradient( to right, transparent 0%, #3182ce 50%, transparent 100% )", + animation: `${progressAnim} 1s ease infinite normal none running`, +}); +``` diff --git a/docs/segment.md b/docs/segment.md new file mode 100644 index 000000000..72ebe6bfa --- /dev/null +++ b/docs/segment.md @@ -0,0 +1,200 @@ +## Segment + +Accessible `Segment` component. + +[Segment - Open On Sandbox](https://codesandbox.io/s/pddby) + +## Props + + + +### `Segment` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`id`** string | undefined Same as the HTML attribute. +- **`segment`** DateSegment + +- **`isDisabled`** boolean | undefined + +- **`isReadOnly`** boolean | undefined + +- **`isRequired`** boolean | undefined + +
23 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`registerItem`** (item: Item) => void Registers a composite + item. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`fieldValue`** Date + +- **`setSegment`** (part: DateTimeFormatPartTypes, v: number) => + void + +- **`increment`** (part: DateTimeFormatPartTypes) => void + +- **`decrement`** (part: DateTimeFormatPartTypes) => void + +- **`incrementPage`** (part: DateTimeFormatPartTypes) => void + +- **`decrementPage`** (part: DateTimeFormatPartTypes) => void + +- **`dateFormatter`** DateTimeFormat + +- **`confirmPlaceholder`** (part: DateTimeFormatPartTypes) => + void + +
+ +### `SegmentField` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
12 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. + +
+ +## Composition + +- Segment uses [useCompositeItem](https://reakit.io/docs/composite) +- SegmentField uses [useComposite](https://reakit.io/docs/composite) + +## Example + +```js +import React from "react"; + +import { Segment, SegmentField, useSegmentState } from "renderless-components"; + +export const App = props => { + const state = useSegmentState(props); + + return ( +
+ + {state.segments.map((segment, i) => ( + + ))} + +
+ ); +}; + +export default App; +``` diff --git a/docs/select.md b/docs/select.md new file mode 100644 index 000000000..08f194919 --- /dev/null +++ b/docs/select.md @@ -0,0 +1,755 @@ +## Select + +Accessible `Select` component. + +[Select - Open On Sandbox](https://codesandbox.io/s/hrtki) + +## Props + + + +### `useSelectBaseState` + +- **`values`** string[] Options/values provided. +- **`selectedValue`** string | null Initial value to be selected + +### `useSelectListState` + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`rtl`** boolean Determines how `next` and `previous` functions + will behave. If `rtl` is set to `true`, they will be inverted. This only + affects the composite widget behavior. You still need to set `dir="rtl"` on + HTML/CSS. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`loop`** boolean | "horizontal" | "vertical" On + one-dimensional composites: + + - `true` loops from the last item to the first item and vice-versa. + - `horizontal` loops only if `orientation` is `horizontal` or not set. + - `vertical` loops only if `orientation` is `vertical` or not set. + - If `currentId` is initially set to `null`, the composite element will be + focused in between the last and first items. + + On two-dimensional composites: + + - `true` loops from the last row/column item to the first item in the same + row/column and vice-versa. If it's the last item in the last row, it moves + to the first item in the first row and vice-versa. + - `horizontal` loops only from the last row item to the first item in the same + row. + - `vertical` loops only from the last column item to the first item in the + column row. + - If `currentId` is initially set to `null`, vertical loop will have no effect + as moving down from the last row or up from the first row will focus the + composite element. + - If `wrap` matches the value of `loop`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. + +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`shift`** boolean **Has effect only on two-dimensional + composites**. If enabled, moving up or down when there's no next item or the + next item is disabled will shift to the item right before it. +- **`values`** string[] Options/values provided. +- **`selectedValue`** string | null Initial value to be selected + +### `useSelectPopoverState` + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`visible`** boolean Whether it's visible or not. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`placement`** + "auto-start" + | "auto" | "auto-end" | "top-start... Actual + `placement`. +- **`unstable_fixed`** ⚠️ boolean | + undefined Whether or not the popover should have `position` set to + `fixed`. +- **`unstable_flip`** ⚠️ boolean | + undefined Flip the popover's placement when it starts to overlap its + reference element. +- **`unstable_offset`** ⚠️ [string | + number, string | number] | undefined Offset between the reference and + the popover: [main axis, alt axis]. Should not be combined with `gutter`. +- **`gutter`** number | undefined Offset between the reference and + the popover on the main axis. Should not be combined with `unstable_offset`. +- **`unstable_preventOverflow`** ⚠️ + boolean | undefined Prevents popover from being positioned + outside the boundary. + +### `useSelectState` + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`visible`** boolean Whether it's visible or not. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`placement`** + "auto-start" + | "auto" | "auto-end" | "top-start... Actual + `placement`. +- **`unstable_fixed`** ⚠️ boolean | + undefined Whether or not the popover should have `position` set to + `fixed`. +- **`unstable_flip`** ⚠️ boolean | + undefined Flip the popover's placement when it starts to overlap its + reference element. +- **`unstable_offset`** ⚠️ [string | + number, string | number] | undefined Offset between the reference and + the popover: [main axis, alt axis]. Should not be combined with `gutter`. +- **`gutter`** number | undefined Offset between the reference and + the popover on the main axis. Should not be combined with `unstable_offset`. +- **`unstable_preventOverflow`** ⚠️ + boolean | undefined Prevents popover from being positioned + outside the boundary. +- **`rtl`** boolean Determines how `next` and `previous` functions + will behave. If `rtl` is set to `true`, they will be inverted. This only + affects the composite widget behavior. You still need to set `dir="rtl"` on + HTML/CSS. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`loop`** boolean | "horizontal" | "vertical" On + one-dimensional composites: + + - `true` loops from the last item to the first item and vice-versa. + - `horizontal` loops only if `orientation` is `horizontal` or not set. + - `vertical` loops only if `orientation` is `vertical` or not set. + - If `currentId` is initially set to `null`, the composite element will be + focused in between the last and first items. + + On two-dimensional composites: + + - `true` loops from the last row/column item to the first item in the same + row/column and vice-versa. If it's the last item in the last row, it moves + to the first item in the first row and vice-versa. + - `horizontal` loops only from the last row item to the first item in the same + row. + - `vertical` loops only from the last column item to the first item in the + column row. + - If `currentId` is initially set to `null`, vertical loop will have no effect + as moving down from the last row or up from the first row will focus the + composite element. + - If `wrap` matches the value of `loop`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. + +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`shift`** boolean **Has effect only on two-dimensional + composites**. If enabled, moving up or down when there's no next item or the + next item is disabled will shift to the item right before it. +- **`values`** string[] Options/values provided. +- **`selectedValue`** string | null Initial value to be selected + +### `Select` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`hideOnEsc`** boolean | undefined When enabled, user can hide +the select popover by pressing `esc` while focusing on the select input. +
53 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`visible`** boolean Whether it's visible or not. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`toggle`** () => void Toggles the `visible` state +- **`unstable_referenceRef`** ⚠️ + RefObject<HTMLElement | null> The reference element. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`animating`** boolean Whether it's animating or not. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`placement`** + "auto-start" + | "auto" | "auto-end" | "top-start... Actual + `placement`. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`rtl`** boolean Determines how `next` and `previous` functions + will behave. If `rtl` is set to `true`, they will be inverted. This only + affects the composite widget behavior. You still need to set `dir="rtl"` on + HTML/CSS. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`loop`** boolean | "horizontal" | "vertical" On + one-dimensional composites: + + - `true` loops from the last item to the first item and vice-versa. + - `horizontal` loops only if `orientation` is `horizontal` or not set. + - `vertical` loops only if `orientation` is `vertical` or not set. + - If `currentId` is initially set to `null`, the composite element will be + focused in between the last and first items. + + On two-dimensional composites: + + - `true` loops from the last row/column item to the first item in the same + row/column and vice-versa. If it's the last item in the last row, it moves + to the first item in the first row and vice-versa. + - `horizontal` loops only from the last row item to the first item in the same + row. + - `vertical` loops only from the last column item to the first item in the + column row. + - If `currentId` is initially set to `null`, vertical loop will have no effect + as moving down from the last row or up from the first row will focus the + composite element. + - If `wrap` matches the value of `loop`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. + +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`shift`** boolean **Has effect only on two-dimensional + composites**. If enabled, moving up or down when there's no next item or the + next item is disabled will shift to the item right before it. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`menuRole`** "listbox" | "tree" | "grid" | + "dialog" Indicates the type of the suggestions popup. +- **`items`** Item[] Lists all the select items with their `id`, + DOM `ref`, `disabled` state, `value` and `groupId` if any. This state is + automatically updated when `registerItem` and `unregisterItem` are called. +- **`values`** string[] Options/values provided. +- **`valuesById`** { id: string; value: string; }[] Initial value + to be selected +- **`selectedValue`** string | null Initial value to be selected +- **`currentValue`** string | undefined Initial value to be + selected +- **`selectedId`** string | null | undefined Id of the item that is + currently selected. +- **`setBaseId`** (value: SetStateAction<string>) => + void Sets `baseId`. +- **`show`** () => void Changes the `visible` state to `true` +- **`hide`** () => void Changes the `visible` state to `false` +- **`setVisible`** (value: SetStateAction<boolean>) => + void Sets `visible`. +- **`setAnimated`** (value: SetStateAction<number | boolean>) + => void Sets `animated`. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`setModal`** (value: SetStateAction<boolean>) => + void Sets `modal`. +- **`place`** (value: SetStateAction<Placement>) => + void Change the `placement` state. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`registerGroup`** (group: Group) => void Registers a + composite group. +- **`unregisterGroup`** (id: string) => void Unregisters a + composite group. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`sort`** () => void Sorts the `composite.items` based on + the items position in the DOM. This is especially useful after modifying the + composite items order in the DOM. Most of the time, though, you don't need to + manually call this function as the re-ordering happens automatically. +- **`unstable_setVirtual`** ⚠️ (value: + SetStateAction<boolean>) => void Sets `virtual`. +- **`setRTL`** (value: SetStateAction<boolean>) => void + Sets `rtl`. +- **`setOrientation`** + (value: + SetStateAction<"horizontal" | "vertical... Sets + `orientation`. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`setLoop`** + (value: + SetStateAction<boolean | "horizontal" |... Sets `loop`. +- **`setWrap`** + (value: + SetStateAction<boolean | "horizontal" |... Sets `wrap`. +- **`setShift`** (value: SetStateAction<boolean>) => + void Sets `shift`. +- **`reset`** () => void Resets to initial state. +- **`registerItem`** (item: Item) => void Registers a select + item. +- **`setSelectedValue`** (value: SetStateAction<string | null>) + => void Sets `values`. + +
+ +### `SelectItem` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`id`** string | undefined Same as the HTML attribute. +- **`value`** string | undefined Item's value that will be used to +fill input value and filter `matches` based on the input value. You can omit +this for items that perform actions other than filling a form. For example, +items may open a dialog. +
18 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`registerItem`** (item: Item) => void Registers a composite + item. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`visible`** boolean Whether it's visible or not. +- **`hide`** () => void Changes the `visible` state to `false` +- **`setSelectedValue`** (value: SetStateAction<string | null>) + => void Sets `values`. + +
+ +### `SelectList` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
13 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`menuRole`** "listbox" | "tree" | "grid" | + "dialog" Indicates the type of the suggestions popup. + +
+ +### `SelectOption` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`id`** string | undefined Same as the HTML attribute. +- **`value`** string | undefined Item's value that will be used to +fill input value and filter `matches` based on the input value. You can omit +this for items that perform actions other than filling a form. For example, +items may open a dialog. +
18 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`registerItem`** (item: Item) => void Registers a composite + item. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`visible`** boolean Whether it's visible or not. +- **`hide`** () => void Changes the `visible` state to `false` +- **`setSelectedValue`** (value: SetStateAction<string | null>) + => void Sets `values`. + +
+ +### `SelectPopover` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`hideOnEsc`** boolean | undefined When enabled, user can hide + the dialog by pressing `Escape`. +- **`hideOnClickOutside`** boolean | undefined When enabled, user + can hide the dialog by clicking outside it. +- **`preventBodyScroll`** boolean | undefined When enabled, user + can't scroll on body when the dialog is visible. This option doesn't work if + the dialog isn't modal. +- **`unstable_initialFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog shows. When not set, the first tabbable element + within the dialog will be used. +- **`unstable_finalFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog hides. When not set, the disclosure component will + be used. +- **`unstable_orphan`** ⚠️ boolean | +undefined Whether or not the dialog should be a child of its parent. +Opening a nested orphan dialog will close its parent dialog if +`hideOnClickOutside` is set to `true` on the parent. It will be set to `false` +if `modal` is `false`. +
22 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`menuRole`** "listbox" | "tree" | "grid" | + "dialog" Indicates the type of the suggestions popup. +- **`visible`** boolean Whether it's visible or not. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`animating`** boolean Whether it's animating or not. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`hide`** () => void Changes the `visible` state to `false` +- **`values`** string[] Options/values provided. +- **`valuesById`** { id: string; value: string; }[] Initial value + to be selected +- **`currentValue`** string | undefined Initial value to be + selected + +
+ +## Composition + +- Select uses [usePopoverDisclosure](undefined) +- SelectItem uses [useCompositeItem](https://reakit.io/docs/composite) +- SelectList uses [useComposite](https://reakit.io/docs/composite) +- SelectOption uses [useSelectItem](undefined) +- SelectPopover uses [useSelectList](undefined) and [usePopover](undefined) + +## Example + +```js +import * as React from "react"; + +import { + Select, + SelectOption, + SelectPopover, + useSelectState, +} from "renderless-components"; + +export const App = props => { + const select = useSelectState({ gutter: 8, ...props }); + + return ( + <> + + + + + + + + + ); +}; + +export default App; +``` diff --git a/docs/slider.md b/docs/slider.md new file mode 100644 index 000000000..37f695b18 --- /dev/null +++ b/docs/slider.md @@ -0,0 +1,273 @@ +## Slider + +Accessible `Slider` component. + +[Slider - Open On Sandbox](https://codesandbox.io/s/s20jt) + +## Props + + + +### `useSliderState` + +- **`values`** number[] The `value` of the slider indicator. + + If `undefined`/`not valid` the slider bar will be the optimum of min & max + +- **`min`** number The minimum value of the slider +- **`max`** number The maximum value of the slider +- **`step`** number The step in which increments/decrements have to + be made +- **`isDisabled`** boolean If `true`, the slider will be disabled +- **`orientation`** "horizontal" | "vertical" + Orientation of the slider +- **`reversed`** boolean Direction of the slider +- **`defaultValues`** number[] | undefined The `defaultValue` of + the slider indicator. +- **`onChange`** ((value: number[]) => void) | undefined + Handler that is called when the value changes. +- **`onChangeEnd`** ((value: number[]) => void) | undefined Get + the value when dragging is started +- **`onChangeStart`** ((value: number[]) => void) | undefined + Get the value when dragging is stopped +- **`formatOptions`** NumberFormatOptions | undefined Get the + formated value based on number format options + +### `SliderInput` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`id`** string | undefined Same as the HTML attribute. +- **`index`** number + +
10 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`step`** number The step in which increments/decrements have to + be made +- **`isDisabled`** boolean If `true`, the slider will be disabled +- **`orientation`** "horizontal" | "vertical" + Orientation of the slider +- **`getThumbMinValue`** (index: number) => number Returns the + min values for the index +- **`getThumbMaxValue`** (index: number) => number Returns the + max values for the index +- **`getThumbValueLabel`** (index: number) => string Returns + the formatted thumb value based on it's index +- **`registerInput`** (item: Item) => void Register the inputs + on mount +- **`unregisterInput`** (id: string) => void Unregister the + inputs on mount +- **`setFocusedThumb`** (index: number | undefined) => void Set + currently Focused Thumb +- **`setThumbValue`** (index: number, value: number) => void + Sets value for thumb. The actually value set will be clamped and rounded + according to min/max/step + +
+ +### `SliderThumb` + +- **`index`** number + +
13 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`step`** number The step in which increments/decrements have to + be made +- **`isDisabled`** boolean If `true`, the slider will be disabled +- **`orientation`** "horizontal" | "vertical" + Orientation of the slider +- **`reversed`** boolean Direction of the slider +- **`trackRef`** RefObject<HTMLElement | null> The track + slider element. +- **`focusedThumb`** number | undefined Currently focused thumb +- **`getThumbValue`** (index: number) => number Get Thumb value + based on its index +- **`getThumbPercent`** (index: number) => number Returns the + value offset as a percentage from 0 to 1. +- **`inputs`** Item[] Get all the inputs in the DOM +- **`setThumbValue`** (index: number, value: number) => void + Sets value for thumb. The actually value set will be clamped and rounded + according to min/max/step +- **`setThumbEditable`** (index: number, editable: boolean) => + void Set true if the thumb registered is editable +- **`setThumbDragging`** (index: number, dragging: boolean) => + void set dragging true if the thumb registered is being currently + dragged +- **`setThumbPercent`** (index: number, percent: number) => + void Sets value for thumb by percent offset (between 0 and 1) + +
+ +### `SliderTrack` + +
13 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`values`** number[] The `value` of the slider indicator. + + If `undefined`/`not valid` the slider bar will be the optimum of min & max + +- **`isDisabled`** boolean If `true`, the slider will be disabled +- **`orientation`** "horizontal" | "vertical" + Orientation of the slider +- **`reversed`** boolean Direction of the slider +- **`trackRef`** RefObject<HTMLElement | null> The track + slider element. +- **`getThumbPercent`** (index: number) => number Returns the + value offset as a percentage from 0 to 1. +- **`getPercentValue`** (percent: number) => number Converts a + percent along track (between 0 and 1) to the corresponding value +- **`isThumbEditable`** (index: number) => boolean Get + editableThumb based on the index +- **`isThumbDragging`** (index: number) => boolean Whether a + specific index is being dragged +- **`setFocusedThumb`** (index: number | undefined) => void Set + currently Focused Thumb +- **`setThumbValue`** (index: number, value: number) => void + Sets value for thumb. The actually value set will be clamped and rounded + according to min/max/step +- **`setThumbDragging`** (index: number, dragging: boolean) => + void set dragging true if the thumb registered is being currently + dragged +- **`setThumbPercent`** (index: number, percent: number) => + void Sets value for thumb by percent offset (between 0 and 1) + +
+ +## Composition + +- SliderInput uses [unstable_useId](https://reakit.io/docs/id) and + [useInput](undefined) +- SliderThumb uses [useBox](https://reakit.io/docs/box) +- SliderTrack uses [useBox](https://reakit.io/docs/box) + +## Example + +```js +import * as React from "react"; +import { VisuallyHidden } from "reakit"; + +import { + SliderTrack, + SliderThumb, + SliderInput, + useSliderState, +} from "renderless-components"; + +export const App = args => { + const { label, isReversed, origin: originProp, ...rest } = args; + const origin = originProp ?? args.min ?? 0; + + const state = useSliderState({ reversed: isReversed, ...rest }); + const { + values, + getValuePercent, + getThumbValueLabel, + getThumbPercent, + } = state; + + const isVertical = args.orientation === "vertical"; + const isRange = values.length === 2; + const isMulti = values.length > 2; + + const labelValue = !isRange + ? getThumbValueLabel(0) + : `${state.getThumbValueLabel(0)} to ${state.getThumbValueLabel(1)}`; + const trackWidth = !isRange + ? `${ + (getValuePercent(Math.max(values[0], origin)) - + getValuePercent(Math.min(values[0], origin))) * + 100 + }%` + : `${(state.getThumbPercent(1) - state.getThumbPercent(0)) * 100}%`; + const trackLeft = !isRange + ? `${getValuePercent(Math.min(values[0], origin)) * 100}%` + : `${getThumbPercent(0) * 100}%`; + const trackRight = !isRange ? "0px" : `${getThumbPercent(0) * 100}%`; + + return ( +
+
+ +
+ {!isMulti ? labelValue : JSON.stringify(state.values)} +
+
+ +
+ +
+ {!isMulti ? ( +
+ ) : null} + + + {[...new Array(values.length).keys()].map(index => { + return ( +
+ + + + + + {args.showTip && ( +
+ {getThumbValueLabel(index)} +
+ )} +
+ ); + })} +
+
+ ); +}; + +export default App; +``` diff --git a/docs/timepicker.md b/docs/timepicker.md new file mode 100644 index 000000000..c956c209d --- /dev/null +++ b/docs/timepicker.md @@ -0,0 +1,832 @@ +## TimePicker + +Accessible `TimePicker` component. + +[TimePicker - Open On Sandbox](https://codesandbox.io/s/5k3uo) + +## Props + + + +### `TimePicker` + +
7 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`visible`** boolean Whether it's visible or not. +- **`pickerId`** string | undefined + +- **`dialogId`** string | undefined + +- **`isDisabled`** boolean | undefined + +- **`isReadOnly`** boolean | undefined + +- **`segmentFocus`** (() => void) | undefined + +- **`show`** () => void Changes the `visible` state to `true` + +
+ +### `TimePickerColumn` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
13 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`columnType`** "hour" | "minute" | + "meridian" + +
+ +### `TimePickerColumnValue` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`id`** string | undefined Same as the HTML attribute. +- **`value`** number + +
19 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`registerItem`** (item: Item) => void Registers a composite + item. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`visible`** boolean | undefined + +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`selected`** number + +- **`setSelected`** (value: number) => void + +
+ +### `TimePickerContent` + +- **`hideOnEsc`** boolean | undefined When enabled, user can hide + the dialog by pressing `Escape`. +- **`hideOnClickOutside`** boolean | undefined When enabled, user + can hide the dialog by clicking outside it. +- **`preventBodyScroll`** boolean | undefined When enabled, user + can't scroll on body when the dialog is visible. This option doesn't work if + the dialog isn't modal. +- **`unstable_initialFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog shows. When not set, the first tabbable element + within the dialog will be used. +- **`unstable_finalFocusRef`** ⚠️ + RefObject<HTMLElement> | undefined The element that will + be focused when the dialog hides. When not set, the disclosure component will + be used. +- **`unstable_orphan`** ⚠️ boolean | +undefined Whether or not the dialog should be a child of its parent. +Opening a nested orphan dialog will close its parent dialog if +`hideOnClickOutside` is set to `true` on the parent. It will be set to `false` +if `modal` is `false`. +
8 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`visible`** boolean Whether it's visible or not. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`animating`** boolean Whether it's animating or not. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`hide`** () => void Changes the `visible` state to `false` +- **`dialogId`** string | undefined + +
+ +### `TimePickerSegment` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is + `disabled`, it may still be `focusable`. It works similarly to `readOnly` on + form elements. In this case, only `aria-disabled` will be set. +- **`id`** string | undefined Same as the HTML attribute. +- **`segment`** DateSegment + +- **`isRequired`** boolean | undefined + +
68 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`registerItem`** (item: Item) => void Registers a composite + item. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`fieldValue`** Date + +- **`setSegment`** (part: DateTimeFormatPartTypes, v: number) => + void + +- **`increment`** (part: DateTimeFormatPartTypes) => void + +- **`decrement`** (part: DateTimeFormatPartTypes) => void + +- **`incrementPage`** (part: DateTimeFormatPartTypes) => void + +- **`decrementPage`** (part: DateTimeFormatPartTypes) => void + +- **`dateFormatter`** DateTimeFormat + +- **`confirmPlaceholder`** (part: DateTimeFormatPartTypes) => + void + +- **`isDisabled`** boolean | undefined + +- **`isReadOnly`** boolean | undefined + +- **`setFieldValue`** (value: Date) => void + +- **`segments`** DateSegment[] + +- **`setBaseId`** (value: SetStateAction<string>) => + void Sets `baseId`. +- **`rtl`** boolean Determines how `next` and `previous` functions + will behave. If `rtl` is set to `true`, they will be inverted. This only + affects the composite widget behavior. You still need to set `dir="rtl"` on + HTML/CSS. +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`loop`** boolean | "horizontal" | "vertical" On + one-dimensional composites: + + - `true` loops from the last item to the first item and vice-versa. + - `horizontal` loops only if `orientation` is `horizontal` or not set. + - `vertical` loops only if `orientation` is `vertical` or not set. + - If `currentId` is initially set to `null`, the composite element will be + focused in between the last and first items. + + On two-dimensional composites: + + - `true` loops from the last row/column item to the first item in the same + row/column and vice-versa. If it's the last item in the last row, it moves + to the first item in the first row and vice-versa. + - `horizontal` loops only from the last row item to the first item in the same + row. + - `vertical` loops only from the last column item to the first item in the + column row. + - If `currentId` is initially set to `null`, vertical loop will have no effect + as moving down from the last row or up from the first row will focus the + composite element. + - If `wrap` matches the value of `loop`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. + +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`shift`** boolean **Has effect only on two-dimensional + composites**. If enabled, moving up or down when there's no next item or the + next item is disabled will shift to the item right before it. +- **`registerGroup`** (group: Group) => void Registers a + composite group. +- **`unregisterGroup`** (id: string) => void Unregisters a + composite group. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`sort`** () => void Sorts the `composite.items` based on + the items position in the DOM. This is especially useful after modifying the + composite items order in the DOM. Most of the time, though, you don't need to + manually call this function as the re-ordering happens automatically. +- **`unstable_setVirtual`** ⚠️ (value: + SetStateAction<boolean>) => void Sets `virtual`. +- **`setRTL`** (value: SetStateAction<boolean>) => void + Sets `rtl`. +- **`setOrientation`** + (value: + SetStateAction<"horizontal" | "vertical... Sets + `orientation`. +- **`setLoop`** + (value: + SetStateAction<boolean | "horizontal" |... Sets `loop`. +- **`setWrap`** + (value: + SetStateAction<boolean | "horizontal" |... Sets `wrap`. +- **`setShift`** (value: SetStateAction<boolean>) => + void Sets `shift`. +- **`reset`** () => void Resets to initial state. +- **`visible`** boolean Whether it's visible or not. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`animating`** boolean Whether it's animating or not. +- **`show`** () => void Changes the `visible` state to `true` +- **`hide`** () => void Changes the `visible` state to `false` +- **`toggle`** () => void Toggles the `visible` state +- **`setVisible`** (value: SetStateAction<boolean>) => + void Sets `visible`. +- **`setAnimated`** (value: SetStateAction<number | boolean>) + => void Sets `animated`. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`setModal`** (value: SetStateAction<boolean>) => + void Sets `modal`. +- **`unstable_referenceRef`** ⚠️ + RefObject<HTMLElement | null> The reference element. +- **`placement`** + "auto-start" + | "auto" | "auto-end" | "top-start... Actual + `placement`. +- **`place`** (value: SetStateAction<Placement>) => + void Change the `placement` state. +- **`pickerId`** string | undefined + +- **`dialogId`** string | undefined + +- **`segmentFocus`** (() => void) | undefined + +- **`time`** Date + +- **`hours`** number[] + +- **`minutes`** number[] + +- **`meridies`** string[] + +- **`hourState`** + { + baseId: string; unstable_idCountRef: MutableR... + +- **`minuteState`** + { + baseId: string; unstable_idCountRef: MutableR... + +- **`meridiesState`** + { + baseId: string; unstable_idCountRef: MutableR... + +
+ +### `TimePickerSegmentField` + +- **`disabled`** boolean | undefined Same as the HTML attribute. +- **`focusable`** boolean | undefined When an element is +`disabled`, it may still be `focusable`. It works similarly to `readOnly` on +form elements. In this case, only `aria-disabled` will be set. +
12 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. + +
+ +### `TimePickerTrigger` + +
68 state props +> These props are returned by the state hook. You can spread them into this component (`{...state}`) or pass them separately. You can also provide these props from your own state logic. + +- **`visible`** boolean Whether it's visible or not. +- **`pickerId`** string | undefined + +- **`dialogId`** string | undefined + +- **`isDisabled`** boolean | undefined + +- **`isReadOnly`** boolean | undefined + +- **`segmentFocus`** (() => void) | undefined + +- **`show`** () => void Changes the `visible` state to `true` +- **`fieldValue`** Date + +- **`setFieldValue`** (value: Date) => void + +- **`segments`** DateSegment[] + +- **`dateFormatter`** DateTimeFormat + +- **`increment`** (part: DateTimeFormatPartTypes) => void + +- **`decrement`** (part: DateTimeFormatPartTypes) => void + +- **`incrementPage`** (part: DateTimeFormatPartTypes) => void + +- **`decrementPage`** (part: DateTimeFormatPartTypes) => void + +- **`setSegment`** (part: DateTimeFormatPartTypes, v: number) => + void + +- **`confirmPlaceholder`** (part: DateTimeFormatPartTypes) => + void + +- **`baseId`** string ID that will serve as a base for all the + items IDs. +- **`setBaseId`** (value: SetStateAction<string>) => + void Sets `baseId`. +- **`unstable_virtual`** ⚠️ + boolean If enabled, the composite element will act as an + [aria-activedescendant](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant) + container instead of + [roving tabindex](https://www.w3.org/TR/wai-aria-practices/#kbd_roving_tabindex). + DOM focus will remain on the composite while its items receive virtual focus. +- **`rtl`** boolean Determines how `next` and `previous` functions + will behave. If `rtl` is set to `true`, they will be inverted. This only + affects the composite widget behavior. You still need to set `dir="rtl"` on + HTML/CSS. +- **`orientation`** "horizontal" | "vertical" | + undefined Defines the orientation of the composite widget. If the + composite has a single row or column (one-dimensional), the `orientation` + value determines which arrow keys can be used to move focus: + + - `undefined`: all arrow keys work. + - `horizontal`: only left and right arrow keys work. + - `vertical`: only up and down arrow keys work. + + It doesn't have any effect on two-dimensional composites. + +- **`items`** Item[] Lists all the composite items with their `id`, + DOM `ref`, `disabled` state and `groupId` if any. This state is automatically + updated when `registerItem` and `unregisterItem` are called. +- **`groups`** Group[] Lists all the composite groups with their + `id` and DOM `ref`. This state is automatically updated when `registerGroup` + and `unregisterGroup` are called. +- **`currentId`** string | null | undefined The current focused + item `id`. + - `undefined` will automatically focus the first enabled composite item. + - `null` will focus the base composite element and users will be able to + navigate out of it using arrow keys. + - If `currentId` is initially set to `null`, the base composite element itself + will have focus and users will be able to navigate to it using arrow keys. +- **`loop`** boolean | "horizontal" | "vertical" On + one-dimensional composites: + + - `true` loops from the last item to the first item and vice-versa. + - `horizontal` loops only if `orientation` is `horizontal` or not set. + - `vertical` loops only if `orientation` is `vertical` or not set. + - If `currentId` is initially set to `null`, the composite element will be + focused in between the last and first items. + + On two-dimensional composites: + + - `true` loops from the last row/column item to the first item in the same + row/column and vice-versa. If it's the last item in the last row, it moves + to the first item in the first row and vice-versa. + - `horizontal` loops only from the last row item to the first item in the same + row. + - `vertical` loops only from the last column item to the first item in the + column row. + - If `currentId` is initially set to `null`, vertical loop will have no effect + as moving down from the last row or up from the first row will focus the + composite element. + - If `wrap` matches the value of `loop`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. + +- **`wrap`** boolean | "horizontal" | "vertical" + **Has effect only on two-dimensional composites**. If enabled, moving to the + next item from the last one in a row or column will focus the first item in + the next row or column and vice-versa. + - `true` wraps between rows and columns. + - `horizontal` wraps only between rows. + - `vertical` wraps only between columns. + - If `loop` matches the value of `wrap`, it'll wrap between the last item in + the last row or column and the first item in the first row or column and + vice-versa. +- **`shift`** boolean **Has effect only on two-dimensional + composites**. If enabled, moving up or down when there's no next item or the + next item is disabled will shift to the item right before it. +- **`unstable_moves`** ⚠️ number + Stores the number of moves that have been performed by calling `move`, `next`, + `previous`, `up`, `down`, `first` or `last`. +- **`registerItem`** (item: Item) => void Registers a composite + item. +- **`unregisterItem`** (id: string) => void Unregisters a + composite item. +- **`registerGroup`** (group: Group) => void Registers a + composite group. +- **`unregisterGroup`** (id: string) => void Unregisters a + composite group. +- **`move`** (id: string | null) => void Moves focus to a given + item ID. +- **`next`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the next item. +- **`previous`** (unstable_allTheWay?: boolean | undefined) => + void Moves focus to the previous item. +- **`up`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item above. +- **`down`** (unstable_allTheWay?: boolean | undefined) => void + Moves focus to the item below. +- **`first`** () => void Moves focus to the first item. +- **`last`** () => void Moves focus to the last item. +- **`sort`** () => void Sorts the `composite.items` based on + the items position in the DOM. This is especially useful after modifying the + composite items order in the DOM. Most of the time, though, you don't need to + manually call this function as the re-ordering happens automatically. +- **`unstable_setVirtual`** ⚠️ (value: + SetStateAction<boolean>) => void Sets `virtual`. +- **`setRTL`** (value: SetStateAction<boolean>) => void + Sets `rtl`. +- **`setOrientation`** + (value: + SetStateAction<"horizontal" | "vertical... Sets + `orientation`. +- **`setCurrentId`** + (value: + SetStateAction<string | null | undefine... Sets `currentId`. This + is different from `composite.move` as this only updates the `currentId` state + without moving focus. When the composite widget gets focused by the user, the + item referred by the `currentId` state will get focus. +- **`setLoop`** + (value: + SetStateAction<boolean | "horizontal" |... Sets `loop`. +- **`setWrap`** + (value: + SetStateAction<boolean | "horizontal" |... Sets `wrap`. +- **`setShift`** (value: SetStateAction<boolean>) => + void Sets `shift`. +- **`reset`** () => void Resets to initial state. +- **`animated`** number | boolean If `true`, `animating` will be + set to `true` when `visible` is updated. It'll wait for `stopAnimation` to be + called or a CSS transition ends. If `animated` is set to a `number`, + `stopAnimation` will be called only after the same number of milliseconds have + passed. +- **`animating`** boolean Whether it's animating or not. +- **`hide`** () => void Changes the `visible` state to `false` +- **`toggle`** () => void Toggles the `visible` state +- **`setVisible`** (value: SetStateAction<boolean>) => + void Sets `visible`. +- **`setAnimated`** (value: SetStateAction<number | boolean>) + => void Sets `animated`. +- **`stopAnimation`** () => void Stops animation. It's called + automatically if there's a CSS transition. +- **`modal`** boolean Toggles Dialog's `modal` state. + - Non-modal: `preventBodyScroll` doesn't work and focus is free. + - Modal: `preventBodyScroll` is automatically enabled, focus is trapped within + the dialog and the dialog is rendered within a `Portal` by default. +- **`setModal`** (value: SetStateAction<boolean>) => + void Sets `modal`. +- **`unstable_referenceRef`** ⚠️ + RefObject<HTMLElement | null> The reference element. +- **`placement`** + "auto-start" + | "auto" | "auto-end" | "top-start... Actual + `placement`. +- **`place`** (value: SetStateAction<Placement>) => + void Change the `placement` state. +- **`time`** Date + +- **`hours`** number[] + +- **`minutes`** number[] + +- **`meridies`** string[] + +- **`hourState`** + { + baseId: string; unstable_idCountRef: MutableR... + +- **`minuteState`** + { + baseId: string; unstable_idCountRef: MutableR... + +- **`meridiesState`** + { + baseId: string; unstable_idCountRef: MutableR... + +
+ +## Composition + +- TimePicker uses [usePickerBase](undefined) +- TimePickerColumn uses [useComposite](https://reakit.io/docs/composite) +- TimePickerColumnValue uses [useButton](https://reakit.io/docs/button) and + [useCompositeItem](https://reakit.io/docs/composite) +- TimePickerContent uses [usePickerBaseContent](undefined) +- TimePickerSegment uses [useSegment](undefined) +- TimePickerSegmentField uses [useSegmentField](undefined) +- TimePickerTrigger uses [usePickerBaseTrigger](undefined) + +## Example + +```js +import React from "react"; +import { + TimePicker, + TimePickerColumn, + TimePickerSegment, + TimePickerTrigger, + TimePickerContent, + useTimePickerState, + TimePickerColumnValue, + TimePickerSegmentField, +} from "renderless-components"; + +const CalendarIcon = () => ( + +); + +export const App = props => { + const state = useTimePickerState(props); + + return ( + <> + +
+ + {state.segments.map((segment, i) => ( + + ))} + + + + +
+
+ + + {state.hours.map(n => { + return ( + + {n} + + ); + })} + + + {state.minutes.map((n, i) => { + return ( + + {n} + + ); + })} + + + {state.meridies.map((n, i) => { + return ( + + {n} + + ); + })} + + + + ); +}; + +export default App; +``` diff --git a/docs/toast.md b/docs/toast.md new file mode 100644 index 000000000..29854cf42 --- /dev/null +++ b/docs/toast.md @@ -0,0 +1,52 @@ +## Toast + +Accessible `Toast` component. + +[Toast - Open On Sandbox](https://codesandbox.io/s/fkpd6) + +## Example + +```js +import React from "react"; +import { ToastProvider } from "renderless-components"; + +import { Variants, Placements } from "./Utils.component"; + +export const App = () => { + return ( + { + return ( +
+ {content} +
+ ); + }, + success: ({ hideToast, content, id }) => { + return ( +
+ {content} +
+ ); + }, + warning: ({ hideToast, content, id }) => { + return ( +
+ {content} +
+ ); + }, + }} + > + +
+ +
+ ); +}; + +export default App; +``` diff --git a/scripts/inject-csb-links.js b/scripts/inject-csb-links.js index a6095b416..43b9d9658 100644 --- a/scripts/inject-csb-links.js +++ b/scripts/inject-csb-links.js @@ -44,7 +44,7 @@ const getSandboxDefineLink = (files, extraDeps) => { import * as React from "react"; import App from "./App"; import "./styles.css"; - + const rootElement = document.getElementById("root"); ReactDOM.render(, rootElement); `,