diff --git a/src/accordion/AccordionTrigger.ts b/src/accordion/AccordionTrigger.ts index 2d84825fe..d6ace8556 100644 --- a/src/accordion/AccordionTrigger.ts +++ b/src/accordion/AccordionTrigger.ts @@ -48,7 +48,12 @@ export const useAccordionTrigger = createHook< useProps( options, - { onClick: htmlOnClick, onFocus: htmlOnFocus, ...htmlProps }, + { + onClick: htmlOnClick, + onKeyDown: htmlOnKeyDown, + onFocus: htmlOnFocus, + ...htmlProps + }, ) { const { manual, @@ -61,9 +66,30 @@ export const useAccordionTrigger = createHook< } = options; const selected = isAccordionSelected(options); const accordionPanelId = useAccordionPanelId(options); + const onKeyDownRef = useLiveRef(htmlOnKeyDown); const onClickRef = useLiveRef(htmlOnClick); const onFocusRef = useLiveRef(htmlOnFocus); + const onKeyDown = React.useCallback( + (event: React.KeyboardEvent) => { + const first = options.first && (() => setTimeout(options.first)); + const last = options.last && (() => setTimeout(options.last)); + const keyMap = { Home: first, End: last }; + const action = keyMap[event.key as keyof typeof keyMap]; + if (action) { + event.preventDefault(); + event.stopPropagation(); + action(); + return; + } + + onKeyDownRef.current?.(event); + }, + + // eslint-disable-next-line react-hooks/exhaustive-deps + [options.first, options.last], + ); + const handleSelection = React.useCallback(() => { if (disabled) return; if (!id) return; @@ -91,7 +117,8 @@ export const useAccordionTrigger = createHook< handleSelection(); }, - [handleSelection, onClickRef], + // eslint-disable-next-line react-hooks/exhaustive-deps + [handleSelection], ); const onFocus = React.useCallback( @@ -103,7 +130,8 @@ export const useAccordionTrigger = createHook< handleSelection(); }, - [onFocusRef, manual, handleSelection], + // eslint-disable-next-line react-hooks/exhaustive-deps + [manual, handleSelection], ); return { @@ -112,6 +140,7 @@ export const useAccordionTrigger = createHook< "aria-disabled": ariaAttr(!allowToggle && selected), onClick, onFocus, + onKeyDown, ...htmlProps, }; }, diff --git a/src/meter/Meter.ts b/src/meter/Meter.ts index 95067e437..459d02d99 100644 --- a/src/meter/Meter.ts +++ b/src/meter/Meter.ts @@ -1,5 +1,6 @@ +import { useWarning } from "reakit-warning"; import { BoxHTMLProps, BoxOptions, useBox } from "reakit"; -import { createHook, createComponent } from "reakit-system"; +import { createHook, createComponent, useCreateElement } from "reakit-system"; import { METER_KEYS } from "./__keys"; import { MeterStateReturn } from "./MeterState"; @@ -18,7 +19,6 @@ const useMeter = createHook({ useProps(options, htmlProps) { const { value, max, min, ariaValueText } = options; - console.log("%c ariaValueText", "color: #99adcc", ariaValueText); // Use the meter role if available, but fall back to progressbar if not // Chrome currently falls back from meter automatically, and Firefox @@ -30,7 +30,7 @@ const useMeter = createHook({ role: "meter progressbar", "aria-valuemax": max, "aria-valuemin": min, - "aria-valuenow": value == null ? undefined : value, + "aria-valuenow": value, "aria-valuetext": `${ariaValueText}`, ...htmlProps, }; @@ -41,4 +41,11 @@ export const Meter = createComponent({ as: "div", memo: true, useHook: useMeter, + useCreateElement: (type, props, children) => { + useWarning( + !props["aria-label"] && !props["aria-labelledby"], + "You should provide either `aria-label` or `aria-labelledby` props.", + ); + return useCreateElement(type, props, children); + }, }); diff --git a/src/progress/Progress.ts b/src/progress/Progress.ts index 4ea18dc87..9efc21e4d 100644 --- a/src/progress/Progress.ts +++ b/src/progress/Progress.ts @@ -4,8 +4,9 @@ * We improved the Progress Component [Progress](https://github.com/chakra-ui/chakra-ui/tree/develop/packages/progress) * to work with Reakit System */ +import { useWarning } from "reakit-warning"; import { BoxHTMLProps, BoxOptions, useBox } from "reakit"; -import { createHook, createComponent } from "reakit-system"; +import { createHook, createComponent, useCreateElement } from "reakit-system"; import { dataAttr } from "../utils"; import { PROGRESS_KEYS } from "./__keys"; @@ -45,4 +46,11 @@ export const Progress = createComponent({ as: "div", memo: true, useHook: useProgress, + useCreateElement: (type, props, children) => { + useWarning( + !props["aria-label"] && !props["aria-labelledby"], + "You should provide either `aria-label` or `aria-labelledby` props.", + ); + return useCreateElement(type, props, children); + }, }); diff --git a/src/progress/ProgressState.ts b/src/progress/ProgressState.ts index 8a97beae8..30c2f1d07 100644 --- a/src/progress/ProgressState.ts +++ b/src/progress/ProgressState.ts @@ -66,10 +66,12 @@ export function useProgressState( value: initialValue = 0, min = 0, max = 100, - ariaValueText, isIndeterminate = false, + ariaValueText, } = useSealedState(initialState); - const [value, setValue] = React.useState(initialValue); + const [value, setValue] = React.useState( + initialValue == null ? 0 : initialValue, + ); const percent = valueToPercent(value, min, max); return {