Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 1x 27x 1x | import { forwardRef, type ReactNode } from "react";
import { clsx } from "clsx";
import styles from "./Trigger.module.scss";
export interface TriggerProps {
/**
* The visual affordance (an icon, text, or any **non-interactive** node — it is
* wrapped in a `<button>`, so it must not itself be a button/link/input).
*/
children: ReactNode;
/** Current open state — reflected as `aria-expanded`. */
open: boolean;
/** The id of the keyboard element this trigger controls (`aria-controls`). */
controls: string;
/** Toggle the keyboard open/closed. */
onToggle: () => void;
/**
* Explicit accessible name. Leave `undefined` when the trigger has visible text
* (its content becomes the name); set it for an icon-only trigger.
*/
label?: string;
/** Extra class on the trigger button. */
className?: string;
}
/**
* The "keyboard icon" affordance. Wraps arbitrary **non-interactive** content in
* a real `<button>` so it is keyboard-operable (Enter/Space), and wires the ARIA
* relationship to the keyboard it toggles: `aria-expanded` reflects the open
* state and `aria-controls` points at the keyboard's id.
*
* The accessible name comes from the visible content by default; pass `label`
* only for an icon-only trigger (it becomes `aria-label`). It never forces an
* `aria-label` over visible text — that would break voice control (WCAG 2.5.3).
*
* @example
* ```tsx
* <Trigger open={open} controls={id} onToggle={toggle} label="Open keyboard">
* <KeyboardIcon />
* </Trigger>
* ```
*/
export const Trigger = forwardRef<HTMLButtonElement, TriggerProps>(
function Trigger(
{ children, open, controls, onToggle, label, className },
ref
) {
return (
<button
ref={ref}
type="button"
aria-expanded={open}
aria-controls={controls}
aria-label={label}
onClick={onToggle}
className={clsx(styles.trigger, className)}
>
{children}
</button>
);
}
);
Trigger.displayName = "Trigger";
|