@allxsmith/bestax-bulma 5.27.8 → 5.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/HoverCard.js +127 -0
  4. package/dist/esm/components/HoverCard.js.map +1 -0
  5. package/dist/esm/form/DateInput.js.map +1 -1
  6. package/dist/esm/form/DateTimeInput.js.map +1 -1
  7. package/dist/esm/form/Field.js.map +1 -1
  8. package/dist/esm/form/File.js.map +1 -1
  9. package/dist/esm/form/Input.js.map +1 -1
  10. package/dist/esm/form/Numberinput.js.map +1 -1
  11. package/dist/esm/form/Select.js.map +1 -1
  12. package/dist/esm/form/Slider.js.map +1 -1
  13. package/dist/esm/form/Taginput.js.map +1 -1
  14. package/dist/esm/form/TextArea.js.map +1 -1
  15. package/dist/esm/form/TimeInput.js.map +1 -1
  16. package/dist/esm/helpers/useFocusTrap.js +2 -1
  17. package/dist/esm/helpers/useFocusTrap.js.map +1 -1
  18. package/dist/esm/helpers/useHoverOpen.js +390 -0
  19. package/dist/esm/helpers/useHoverOpen.js.map +1 -0
  20. package/dist/extras.css +1 -1
  21. package/dist/extras.css.map +1 -1
  22. package/dist/index.cjs +498 -0
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.esm.js +1 -0
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/types/components/HoverCard.d.ts +136 -0
  27. package/dist/types/form/DateInput.d.ts +1 -1
  28. package/dist/types/form/DateTimeInput.d.ts +1 -1
  29. package/dist/types/form/Field.d.ts +1 -1
  30. package/dist/types/form/File.d.ts +1 -1
  31. package/dist/types/form/Input.d.ts +1 -1
  32. package/dist/types/form/Numberinput.d.ts +1 -1
  33. package/dist/types/form/Select.d.ts +1 -1
  34. package/dist/types/form/Slider.d.ts +1 -1
  35. package/dist/types/form/Taginput.d.ts +1 -1
  36. package/dist/types/form/TextArea.d.ts +1 -1
  37. package/dist/types/form/TimeInput.d.ts +1 -1
  38. package/dist/types/helpers/useFocusTrap.d.ts +9 -0
  39. package/dist/types/helpers/useHoverOpen.d.ts +98 -0
  40. package/dist/types/index.d.ts +1 -0
  41. package/dist/types-cjs/components/HoverCard.d.ts +136 -0
  42. package/dist/types-cjs/form/DateInput.d.ts +1 -1
  43. package/dist/types-cjs/form/DateTimeInput.d.ts +1 -1
  44. package/dist/types-cjs/form/Field.d.ts +1 -1
  45. package/dist/types-cjs/form/File.d.ts +1 -1
  46. package/dist/types-cjs/form/Input.d.ts +1 -1
  47. package/dist/types-cjs/form/Numberinput.d.ts +1 -1
  48. package/dist/types-cjs/form/Select.d.ts +1 -1
  49. package/dist/types-cjs/form/Slider.d.ts +1 -1
  50. package/dist/types-cjs/form/Taginput.d.ts +1 -1
  51. package/dist/types-cjs/form/TextArea.d.ts +1 -1
  52. package/dist/types-cjs/form/TimeInput.d.ts +1 -1
  53. package/dist/types-cjs/helpers/useFocusTrap.d.ts +9 -0
  54. package/dist/types-cjs/helpers/useHoverOpen.d.ts +98 -0
  55. package/dist/types-cjs/index.d.ts +1 -0
  56. package/dist/versions/bestax-no-dark-mode.css +1 -1
  57. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  58. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  59. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  60. package/dist/versions/bestax-no-helpers.css +1 -1
  61. package/dist/versions/bestax-no-helpers.css.map +1 -1
  62. package/dist/versions/bestax-prefixed.css +1 -1
  63. package/dist/versions/bestax-prefixed.css.map +1 -1
  64. package/package.json +2 -2
  65. package/src/scss/components/_hovercard.scss +118 -0
  66. package/src/scss/components/_index.scss +1 -0
package/dist/index.esm.js CHANGED
@@ -19,6 +19,7 @@ export { Collapse } from './esm/components/Collapse.js';
19
19
  export { Collapses } from './esm/components/Collapses.js';
20
20
  export { Tooltip } from './esm/components/Tooltip.js';
21
21
  export { Popover, PopoverBody, PopoverClose, PopoverFooter, PopoverHeader } from './esm/components/Popover.js';
22
+ export { HoverCard } from './esm/components/HoverCard.js';
22
23
  export { Step, Steps } from './esm/components/Steps.js';
23
24
  export { Sidebar } from './esm/components/Sidebar.js';
24
25
  export { Toast, ToastContainer, toast } from './esm/components/Toast.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,136 @@
1
+ import React from 'react';
2
+ import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
3
+ import type { PickerPosition } from '../form/_pickerInternals/pickerTypes.js';
4
+ /**
5
+ * Where the card opens against its trigger: below (`bottom-*`) or above
6
+ * (`top-*`), lined up with the trigger's left or right edge. `auto` picks the
7
+ * one that keeps the card in the viewport, preferring below and lined up on
8
+ * the left. The same union `Popover` and the date and time pickers take.
9
+ */
10
+ export type HoverCardPosition = PickerPosition;
11
+ /**
12
+ * Props for the HoverCard component. `className`, `id`, the other HTML
13
+ * attributes and the helper props land on the `span` around the trigger, not
14
+ * on the card; `contentClassName` reaches the card.
15
+ * @extraProp {string} [className] - Additional classes for the `span` around the trigger. The card takes `contentClassName`.
16
+ */
17
+ export interface HoverCardProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'color' | 'children'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
18
+ /**
19
+ * The element the card previews, such as a link or a `Button`. The element
20
+ * itself has to take focus, so keyboard users can open the card too: a
21
+ * link inside a `<span>` doesn't do, since focus comes back to the trigger
22
+ * and its ARIA is on it. HoverCard gives it no role and no tab stop, since
23
+ * it can't know what the element is, and a development build warns when
24
+ * it can't take focus: use a link or a button, or give the element
25
+ * `tabIndex={0}`. A disabled button can't take focus either. HoverCard adds
26
+ * `aria-expanded` and `aria-controls`, both naming the card only while it
27
+ * is on the page, so it has to be a single element that passes those to
28
+ * its DOM node. Its own click and keys stay its own, and the card doesn't
29
+ * toggle on them, except Escape while the card is open, which closes the
30
+ * card before the trigger sees it.
31
+ */
32
+ trigger: React.ReactElement;
33
+ /**
34
+ * The card's content: a preview whose links and buttons are fine, but not a
35
+ * form, which belongs in a `Popover`. The card pads itself, so content goes
36
+ * straight in.
37
+ */
38
+ children?: React.ReactNode;
39
+ /**
40
+ * Controlled open state. When set, hover, focus and Escape only report
41
+ * through `onOpenChange`, so an action inside the card can close it. While
42
+ * the card is open, Escape is reported, and when focus is in the card, on
43
+ * its trigger or nowhere, the key stops there even if you keep the card
44
+ * open, so a `Modal` around it doesn't close from the keyboard until the
45
+ * card does.
46
+ */
47
+ open?: boolean;
48
+ /**
49
+ * Initial open state when uncontrolled. A card that starts open stays open
50
+ * until the pointer or focus has been and gone, or Escape closes it.
51
+ * @defaultValue false
52
+ */
53
+ defaultOpen?: boolean;
54
+ /**
55
+ * Called with the state asked for: when `openDelay` or `closeDelay` runs
56
+ * out, and right away on Escape. Fires in both controlled and uncontrolled
57
+ * use. An Escape it reports stops at the card when focus is in the card,
58
+ * on its trigger or nowhere, so nothing around it sees that key. With
59
+ * focus anywhere else, the card still closes and the key goes on to
60
+ * whatever has focus.
61
+ */
62
+ onOpenChange?: (open: boolean) => void;
63
+ /**
64
+ * How long the pointer or keyboard focus waits on the trigger before the
65
+ * card opens, in milliseconds.
66
+ * @defaultValue 600
67
+ */
68
+ openDelay?: number;
69
+ /**
70
+ * How long the card stays after the pointer and focus have left the trigger
71
+ * and the card, in milliseconds. It is the time the pointer has to cross
72
+ * the gap between the trigger and the card: with `0` the card closes as the
73
+ * pointer leaves the trigger, before the pointer can reach it.
74
+ * @defaultValue 300
75
+ */
76
+ closeDelay?: number;
77
+ /**
78
+ * Where the card opens against the trigger.
79
+ * @defaultValue 'bottom-left'
80
+ */
81
+ position?: HoverCardPosition;
82
+ /**
83
+ * Render the card at the end of `document.body` through `Portal`, fixed to
84
+ * the viewport, so an ancestor's `overflow`, `transform` or stacking
85
+ * context can't clip it. A trigger in running text needs it too, since the
86
+ * card's block content can't sit inside a `<p>`. The card then shows from
87
+ * the commit after hydration, never in server markup, and it sits last in
88
+ * the Tab order, at the end of `<body>`. Tab reaches it only after the rest
89
+ * of the page, and focus leaving the trigger on the way closes it, so
90
+ * keyboard users can open it, read it and close it with Escape, and
91
+ * whatever it links to has to be reachable from the page as well. It is
92
+ * measured against the trigger when it opens and on resize and scroll, so
93
+ * it doesn't follow content that changes size while it is open. Theming
94
+ * variables set on an ancestor of the trigger don't reach it there.
95
+ * @defaultValue false
96
+ */
97
+ appendToBody?: boolean;
98
+ /**
99
+ * Open the card with a tap on a touch screen. Touch has no hover, so
100
+ * without this a phone or tablet never opens the card. With it, a tap on
101
+ * the trigger opens the card at once, and it stays until a second tap on
102
+ * the trigger, a tap outside the trigger and the card, or Escape. The tap
103
+ * still does whatever the trigger does, so turn this on only for a trigger
104
+ * with no tap action of its own, such as a `Button` with no `onClick`: on
105
+ * a link, the first tap would follow the link rather than show the card.
106
+ * Mouse and pen work the same either way.
107
+ * @defaultValue false
108
+ */
109
+ openOnTap?: boolean;
110
+ /** Additional classes for the card (`.hover-card-content`). */
111
+ contentClassName?: string;
112
+ }
113
+ /**
114
+ * The `HoverCard` component shows a card previewing what's behind a link or a button while the pointer rests on it or keyboard focus is on it.
115
+ *
116
+ * Nothing moves focus when the card opens, and nothing traps it. In place,
117
+ * the card comes right after the trigger, so Tab goes from the trigger into
118
+ * its links and tabbing past them closes it. The pointer can move onto the
119
+ * card, Escape closes it from anywhere, and by default touch doesn't open it,
120
+ * so tapping the trigger just does what the trigger does. `openOnTap` opens
121
+ * it with a tap, for a trigger with no tap action of its own. For hints with nothing to
122
+ * click use `Tooltip`, and for content opened on purpose, such as a form,
123
+ * use `Popover`.
124
+ *
125
+ * @function
126
+ * @param {HoverCardProps} props - Props for the HoverCard component.
127
+ * @returns {JSX.Element} The trigger in its wrapper, and the card while open.
128
+ *
129
+ * @example
130
+ * <HoverCard trigger={<a href="/people/ada">Ada Lovelace</a>}>
131
+ * <Title as="p" size="6">Ada Lovelace</Title>
132
+ * <SubTitle as="p" size="6">Analytical Engine team</SubTitle>
133
+ * </HoverCard>
134
+ */
135
+ export declare const HoverCard: React.FC<HoverCardProps>;
136
+ export default HoverCard;
@@ -22,7 +22,7 @@ import { DateInputBaseProps } from './DateInputBase.js';
22
22
  * @extraProp {React.Ref<HTMLInputElement>} [ref] - Forwarded to the underlying `<input>`.
23
23
  */
24
24
  export interface DateInputProps extends DateInputBaseProps {
25
- /** Field label (component auto-wraps in a `Field` if not already inside). Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
25
+ /** Field label (component auto-wraps in a `Field` if not already inside). Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
26
26
  label?: React.ReactNode;
27
27
  /** Size for the label. */
28
28
  labelSize?: FieldProps['labelSize'];
@@ -20,7 +20,7 @@ import { DateTimeInputBaseProps } from './DateTimeInputBase.js';
20
20
  * @extraProp {boolean} [required=false] - Marks the field as required for native HTML form validation.
21
21
  */
22
22
  export interface DateTimeInputProps extends DateTimeInputBaseProps {
23
- /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
23
+ /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
24
24
  label?: React.ReactNode;
25
25
  /** Size for the label. */
26
26
  labelSize?: FieldProps['labelSize'];
@@ -12,7 +12,7 @@ export interface FieldProps extends React.HTMLAttributes<HTMLDivElement>, Omit<B
12
12
  hasAddons?: boolean | 'centered' | 'right';
13
13
  /** Constrains the field to its content's width (used inside horizontal field bodies). */
14
14
  narrow?: boolean;
15
- /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete` also names its open suggestion list after the label through `aria-labelledby`. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children. Only the single inputs take the `htmlFor`, so once the Field's content has mounted the label keeps it only while one of them holds the id, and drops it over anything else: a group, a `Checkbox`, `Radio` or `Switch`, an `inline` picker, an inner `Field`, an input with an `id` of its own, markup of your own, or nothing at all. A server render, and the first render while hydrating, still write the `htmlFor`, which keeps hydration matching, and an input that mounts later puts it back. Pass `labelProps={{ htmlFor }}` to wire your own `id`, a `for` the label always keeps, or `labelProps={{ htmlFor: undefined }}` to opt out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */
15
+ /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete` also names its open suggestion list after the label through `aria-labelledby`. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children, and the label names one only when you wire it as you would any control with an `id` of its own, `labelProps={{ htmlFor }}` plus that control's `id`. Only the single inputs take the `htmlFor`, so once the Field's content has mounted the label keeps it only while one of them holds the id, and drops it over anything else: a group, a `Checkbox`, `Radio` or `Switch`, an `inline` picker, an inner `Field`, an input with an `id` of its own, markup of your own, or nothing at all. A server render, and the first render while hydrating, still write the `htmlFor`, which keeps hydration matching, and an input that mounts later puts it back. The label names an input with an `id` of your own only through `labelProps={{ htmlFor }}` set to that `id`, a `for` it always keeps; `labelProps={{ htmlFor: undefined }}` opts out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */
16
16
  label?: React.ReactNode;
17
17
  /** Size for the label. */
18
18
  labelSize?: 'small' | 'normal' | 'medium' | 'large';
@@ -11,7 +11,7 @@ import { FormFieldProps } from './fieldProps.js';
11
11
  * name on that `Field`.
12
12
  */
13
13
  export interface FileProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'color' | 'type'>, Omit<BulmaClassesProps, 'color'>, FormFieldProps {
14
- /** Field label. Automatically associated with the file input via `htmlFor` — uses your `id` when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping `file-label`); assistive tech reads both. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
14
+ /** Field label. Automatically associated with the file input via `htmlFor` — uses your `id` when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping `file-label`); assistive tech reads both. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
15
15
  label?: React.ReactNode;
16
16
  /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */
17
17
  labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {
@@ -18,7 +18,7 @@ import { InputBaseProps } from './InputBase.js';
18
18
  * `label`, `horizontal` and class name on that `Field`.
19
19
  */
20
20
  export interface InputProps extends InputBaseProps {
21
- /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
21
+ /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
22
22
  label?: React.ReactNode;
23
23
  /** Size for the label. */
24
24
  labelSize?: FieldProps['labelSize'];
@@ -17,7 +17,7 @@ export type NumberinputVariant = 'plusminus' | 'stepper';
17
17
  * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the input element.
18
18
  */
19
19
  export interface NumberinputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'color' | 'size' | 'onChange' | 'value' | 'defaultValue' | 'type'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'>, FormFieldProps {
20
- /** Field label. Automatically associated with the number input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). Not rendered either by a plusminus `bare` Numberinput outside a `Field`. */
20
+ /** Field label. Automatically associated with the number input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. Not rendered either by a plusminus `bare` Numberinput outside a `Field`. */
21
21
  label?: React.ReactNode;
22
22
  /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */
23
23
  labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {
@@ -18,7 +18,7 @@ import { SelectBaseProps } from './SelectBase.js';
18
18
  * `label`, `horizontal` and class name on that `Field`.
19
19
  */
20
20
  export interface SelectProps extends SelectBaseProps {
21
- /** Field label. Automatically associated with the select via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
21
+ /** Field label. Automatically associated with the select via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
22
22
  label?: React.ReactNode;
23
23
  /** Size for the label. */
24
24
  labelSize?: FieldProps['labelSize'];
@@ -22,7 +22,7 @@ export interface SliderMark {
22
22
  * Shared base props for single and range Slider modes.
23
23
  */
24
24
  interface SliderBaseProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'color' | 'size' | 'onChange' | 'value' | 'defaultValue'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'>, FormFieldProps {
25
- /** Field label. Automatically associated with the slider input via `htmlFor` — uses your `id` when provided, otherwise a generated one. In range mode the `htmlFor` targets the low (minimum) thumb, and the label also starts each thumb's name through `aria-labelledby`, as in "Price Minimum value" and "Price Maximum value", unless an `aria-label` or `aria-labelledby` on the Slider takes its place there. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`), naming a range Slider's thumbs the same way. A `Field` label you wire by hand to the low thumb with `labelProps.htmlFor` names the thumbs too when you also give it an `id` there, since the `Field` generates none for it. */
25
+ /** Field label. Automatically associated with the slider input via `htmlFor` — uses your `id` when provided, otherwise a generated one. In range mode the `htmlFor` targets the low (minimum) thumb, and the label also starts each thumb's name through `aria-labelledby`, as in "Price Minimum value" and "Price Maximum value", unless an `aria-label` or `aria-labelledby` on the Slider takes its place there. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here, naming a range Slider's thumbs the same way. A `Field` label you wire by hand to the low thumb with `labelProps.htmlFor` names the thumbs too when you also give it an `id` there, since the `Field` generates none for it. */
26
26
  label?: React.ReactNode;
27
27
  /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). In range mode an `id` here is the one the thumbs' `aria-labelledby` points at, in place of a generated one. */
28
28
  labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {
@@ -26,7 +26,7 @@ type IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';
26
26
  * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.
27
27
  */
28
28
  export interface TaginputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>, Omit<BulmaClassesProps, 'color'>, FormFieldProps {
29
- /** Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired when the tag limit is reached (the input is not rendered). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`); it then replaces the `aria-label="Add tag"` fallback too. */
29
+ /** Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired when the tag limit is reached (the input is not rendered). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here; it then replaces the `aria-label="Add tag"` fallback too. */
30
30
  label?: React.ReactNode;
31
31
  /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */
32
32
  labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {
@@ -18,7 +18,7 @@ import { TextAreaBaseProps } from './TextAreaBase.js';
18
18
  * `label`, `horizontal` and class name on that `Field`.
19
19
  */
20
20
  export interface TextAreaProps extends TextAreaBaseProps {
21
- /** Field label. Automatically associated with the textarea via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
21
+ /** Field label. Automatically associated with the textarea via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
22
22
  label?: React.ReactNode;
23
23
  /** Size for the label. */
24
24
  labelSize?: FieldProps['labelSize'];
@@ -22,7 +22,7 @@ import { TimeInputBaseProps } from './TimeInputBase.js';
22
22
  * @extraProp {React.Ref<HTMLInputElement>} [ref] - Forwarded to the underlying `<input>`.
23
23
  */
24
24
  export interface TimeInputProps extends TimeInputBaseProps {
25
- /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
25
+ /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
26
26
  label?: React.ReactNode;
27
27
  /** Size for the label. */
28
28
  labelSize?: FieldProps['labelSize'];
@@ -1,4 +1,13 @@
1
1
  import type { RefObject } from 'react';
2
+ /**
3
+ * Whether the browser puts `el` in the tab order, before anything that hides
4
+ * or disables it. The `tabIndex` property can't answer this on its own: it
5
+ * can read `-1` for an editable region or an `<embed>` that Tab still visits,
6
+ * and `0` for a `<video>` without controls that it doesn't. So a valid
7
+ * `tabindex` attribute decides, and otherwise the element's kind does.
8
+ * Internal like `firstTabStop`: `src/index.ts` names what it takes from here.
9
+ */
10
+ export declare function isTabbableKind(el: Element): boolean;
2
11
  /**
3
12
  * The first tab stop inside `container`, found the way the trap finds it, or
4
13
  * `null` when there is none. For a component that moves focus into a panel
@@ -0,0 +1,98 @@
1
+ import type { FocusEvent, PointerEvent, RefObject } from 'react';
2
+ /**
3
+ * Options for `useHoverOpen`.
4
+ */
5
+ export interface UseHoverOpenOptions {
6
+ /** Whether the floating element is open now, controlled or not. */
7
+ open: boolean;
8
+ /**
9
+ * Asks for the floating element to open or close: when a delay runs out,
10
+ * and at once on Escape. It isn't asked for the state it is already in,
11
+ * except that an Escape between asking to open and the open showing takes
12
+ * the ask back by asking to close.
13
+ */
14
+ onOpenChange: (open: boolean) => void;
15
+ /** How long hover or keyboard focus waits before asking to open, in milliseconds. */
16
+ openDelay: number;
17
+ /**
18
+ * How long it waits once the pointer and focus have both left before
19
+ * asking to close, in milliseconds. Coming back in that time keeps it open,
20
+ * which is how the pointer crosses a gap to the floating element.
21
+ */
22
+ closeDelay: number;
23
+ /**
24
+ * The element that opens it, which has to take focus itself. The Escape
25
+ * listener goes on its document, an iframe's when it renders into one, and
26
+ * focus left in the floating element comes back here when the floating
27
+ * element closes.
28
+ */
29
+ triggerRef: RefObject<HTMLElement | null>;
30
+ /** The floating element, while it is open. */
31
+ floatingRef: RefObject<HTMLElement | null>;
32
+ /**
33
+ * Whether a tap on the trigger opens it at once, with the next tap closing
34
+ * it. Without it, a touch pointer never opens it. While a tap holds it
35
+ * open, no hover timer closes it, and a press outside the trigger and the
36
+ * floating element does, as Escape does. The trigger's own tap action
37
+ * still runs.
38
+ * @defaultValue false
39
+ */
40
+ openOnTap?: boolean;
41
+ }
42
+ /**
43
+ * Pointer and focus handlers for the element that holds the trigger. The
44
+ * floating element has to be inside it in React's tree, in place or through
45
+ * a portal, since React's events reach it from there either way, and it
46
+ * should hold nothing else: focus inside it that isn't on the trigger counts
47
+ * as focus in the floating element.
48
+ */
49
+ export interface HoverOpenHandlers {
50
+ onPointerEnter: (event: PointerEvent<HTMLElement>) => void;
51
+ onPointerLeave: (event: PointerEvent<HTMLElement>) => void;
52
+ onFocus: (event: FocusEvent<HTMLElement>) => void;
53
+ onBlur: (event: FocusEvent<HTMLElement>) => void;
54
+ onPointerDown: (event: PointerEvent<HTMLElement>) => void;
55
+ onPointerUp: (event: PointerEvent<HTMLElement>) => void;
56
+ }
57
+ /**
58
+ * Decides when a floating element that opens on hover or keyboard focus asks
59
+ * to open and to close. It renders nothing, and leaves roles, ARIA and
60
+ * placement to the component that calls it.
61
+ *
62
+ * - The pointer entering, or keyboard focus arriving on the trigger, asks to
63
+ * open after `openDelay`. A touch pointer doesn't count. Neither does focus
64
+ * that a press brings to the trigger: it counts when the browser shows it
65
+ * as `:focus-visible`.
66
+ * - Focus in the floating element holds it open however it got there,
67
+ * including focus in content it portals elsewhere, such as a nested card.
68
+ * Whether a click focuses what it lands on is up to the browser: Safari
69
+ * and Firefox on macOS don't focus a button on click, so there a clicked
70
+ * button doesn't hold it once the pointer leaves.
71
+ * - Once the pointer and focus have both left, it asks to close after
72
+ * `closeDelay`, and either coming back before then keeps it open. Nothing
73
+ * else closes it on a timer.
74
+ * - Escape closes it at once, wherever focus is, and stops there when focus
75
+ * is in it, on its trigger or nowhere, so a `Popover` or `Modal` around it
76
+ * keeps its own. With focus somewhere else, the key goes on after closing
77
+ * it. Inside another one, the inner one closes first. Escape before it
78
+ * opens takes the opening back and goes on its way. One key listener per
79
+ * document serves every hook on it, there only while one of them is open
80
+ * or on its way to open.
81
+ * - With `openOnTap`, a tap on the trigger opens it at once and the next tap
82
+ * on the trigger closes it. While a tap holds it open, a press outside the
83
+ * trigger and the floating element closes it, from a listener on the
84
+ * document that is there only then. Taps never count as hover, and mouse
85
+ * and pen work the same with it or without.
86
+ * - Once it closes, for any reason, whatever was holding it open has to
87
+ * leave and come back to open it again.
88
+ * - When the floating element closes with focus inside it, focus goes back
89
+ * to the trigger, unless the same update put it somewhere else. Handing it
90
+ * back doesn't count as focus arriving.
91
+ *
92
+ * Nothing it scheduled runs after the component unmounts.
93
+ *
94
+ * @function useHoverOpen
95
+ * @param options - The open state, how to ask for another, the delays, and the two elements.
96
+ * @returns Handlers for the element that holds the trigger.
97
+ */
98
+ export declare function useHoverOpen(options: UseHoverOpenOptions): HoverOpenHandlers;
@@ -18,6 +18,7 @@ export * from './components/Collapse.js';
18
18
  export * from './components/Collapses.js';
19
19
  export * from './components/Tooltip.js';
20
20
  export * from './components/Popover.js';
21
+ export * from './components/HoverCard.js';
21
22
  export * from './components/Steps.js';
22
23
  export * from './components/Sidebar.js';
23
24
  export * from './components/Toast.js';
@@ -0,0 +1,136 @@
1
+ import React from 'react';
2
+ import { BulmaClassesProps } from '../helpers/useBulmaClasses.js';
3
+ import type { PickerPosition } from '../form/_pickerInternals/pickerTypes.js';
4
+ /**
5
+ * Where the card opens against its trigger: below (`bottom-*`) or above
6
+ * (`top-*`), lined up with the trigger's left or right edge. `auto` picks the
7
+ * one that keeps the card in the viewport, preferring below and lined up on
8
+ * the left. The same union `Popover` and the date and time pickers take.
9
+ */
10
+ export type HoverCardPosition = PickerPosition;
11
+ /**
12
+ * Props for the HoverCard component. `className`, `id`, the other HTML
13
+ * attributes and the helper props land on the `span` around the trigger, not
14
+ * on the card; `contentClassName` reaches the card.
15
+ * @extraProp {string} [className] - Additional classes for the `span` around the trigger. The card takes `contentClassName`.
16
+ */
17
+ export interface HoverCardProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'color' | 'children'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
18
+ /**
19
+ * The element the card previews, such as a link or a `Button`. The element
20
+ * itself has to take focus, so keyboard users can open the card too: a
21
+ * link inside a `<span>` doesn't do, since focus comes back to the trigger
22
+ * and its ARIA is on it. HoverCard gives it no role and no tab stop, since
23
+ * it can't know what the element is, and a development build warns when
24
+ * it can't take focus: use a link or a button, or give the element
25
+ * `tabIndex={0}`. A disabled button can't take focus either. HoverCard adds
26
+ * `aria-expanded` and `aria-controls`, both naming the card only while it
27
+ * is on the page, so it has to be a single element that passes those to
28
+ * its DOM node. Its own click and keys stay its own, and the card doesn't
29
+ * toggle on them, except Escape while the card is open, which closes the
30
+ * card before the trigger sees it.
31
+ */
32
+ trigger: React.ReactElement;
33
+ /**
34
+ * The card's content: a preview whose links and buttons are fine, but not a
35
+ * form, which belongs in a `Popover`. The card pads itself, so content goes
36
+ * straight in.
37
+ */
38
+ children?: React.ReactNode;
39
+ /**
40
+ * Controlled open state. When set, hover, focus and Escape only report
41
+ * through `onOpenChange`, so an action inside the card can close it. While
42
+ * the card is open, Escape is reported, and when focus is in the card, on
43
+ * its trigger or nowhere, the key stops there even if you keep the card
44
+ * open, so a `Modal` around it doesn't close from the keyboard until the
45
+ * card does.
46
+ */
47
+ open?: boolean;
48
+ /**
49
+ * Initial open state when uncontrolled. A card that starts open stays open
50
+ * until the pointer or focus has been and gone, or Escape closes it.
51
+ * @defaultValue false
52
+ */
53
+ defaultOpen?: boolean;
54
+ /**
55
+ * Called with the state asked for: when `openDelay` or `closeDelay` runs
56
+ * out, and right away on Escape. Fires in both controlled and uncontrolled
57
+ * use. An Escape it reports stops at the card when focus is in the card,
58
+ * on its trigger or nowhere, so nothing around it sees that key. With
59
+ * focus anywhere else, the card still closes and the key goes on to
60
+ * whatever has focus.
61
+ */
62
+ onOpenChange?: (open: boolean) => void;
63
+ /**
64
+ * How long the pointer or keyboard focus waits on the trigger before the
65
+ * card opens, in milliseconds.
66
+ * @defaultValue 600
67
+ */
68
+ openDelay?: number;
69
+ /**
70
+ * How long the card stays after the pointer and focus have left the trigger
71
+ * and the card, in milliseconds. It is the time the pointer has to cross
72
+ * the gap between the trigger and the card: with `0` the card closes as the
73
+ * pointer leaves the trigger, before the pointer can reach it.
74
+ * @defaultValue 300
75
+ */
76
+ closeDelay?: number;
77
+ /**
78
+ * Where the card opens against the trigger.
79
+ * @defaultValue 'bottom-left'
80
+ */
81
+ position?: HoverCardPosition;
82
+ /**
83
+ * Render the card at the end of `document.body` through `Portal`, fixed to
84
+ * the viewport, so an ancestor's `overflow`, `transform` or stacking
85
+ * context can't clip it. A trigger in running text needs it too, since the
86
+ * card's block content can't sit inside a `<p>`. The card then shows from
87
+ * the commit after hydration, never in server markup, and it sits last in
88
+ * the Tab order, at the end of `<body>`. Tab reaches it only after the rest
89
+ * of the page, and focus leaving the trigger on the way closes it, so
90
+ * keyboard users can open it, read it and close it with Escape, and
91
+ * whatever it links to has to be reachable from the page as well. It is
92
+ * measured against the trigger when it opens and on resize and scroll, so
93
+ * it doesn't follow content that changes size while it is open. Theming
94
+ * variables set on an ancestor of the trigger don't reach it there.
95
+ * @defaultValue false
96
+ */
97
+ appendToBody?: boolean;
98
+ /**
99
+ * Open the card with a tap on a touch screen. Touch has no hover, so
100
+ * without this a phone or tablet never opens the card. With it, a tap on
101
+ * the trigger opens the card at once, and it stays until a second tap on
102
+ * the trigger, a tap outside the trigger and the card, or Escape. The tap
103
+ * still does whatever the trigger does, so turn this on only for a trigger
104
+ * with no tap action of its own, such as a `Button` with no `onClick`: on
105
+ * a link, the first tap would follow the link rather than show the card.
106
+ * Mouse and pen work the same either way.
107
+ * @defaultValue false
108
+ */
109
+ openOnTap?: boolean;
110
+ /** Additional classes for the card (`.hover-card-content`). */
111
+ contentClassName?: string;
112
+ }
113
+ /**
114
+ * The `HoverCard` component shows a card previewing what's behind a link or a button while the pointer rests on it or keyboard focus is on it.
115
+ *
116
+ * Nothing moves focus when the card opens, and nothing traps it. In place,
117
+ * the card comes right after the trigger, so Tab goes from the trigger into
118
+ * its links and tabbing past them closes it. The pointer can move onto the
119
+ * card, Escape closes it from anywhere, and by default touch doesn't open it,
120
+ * so tapping the trigger just does what the trigger does. `openOnTap` opens
121
+ * it with a tap, for a trigger with no tap action of its own. For hints with nothing to
122
+ * click use `Tooltip`, and for content opened on purpose, such as a form,
123
+ * use `Popover`.
124
+ *
125
+ * @function
126
+ * @param {HoverCardProps} props - Props for the HoverCard component.
127
+ * @returns {JSX.Element} The trigger in its wrapper, and the card while open.
128
+ *
129
+ * @example
130
+ * <HoverCard trigger={<a href="/people/ada">Ada Lovelace</a>}>
131
+ * <Title as="p" size="6">Ada Lovelace</Title>
132
+ * <SubTitle as="p" size="6">Analytical Engine team</SubTitle>
133
+ * </HoverCard>
134
+ */
135
+ export declare const HoverCard: React.FC<HoverCardProps>;
136
+ export default HoverCard;
@@ -22,7 +22,7 @@ import { DateInputBaseProps } from './DateInputBase.js';
22
22
  * @extraProp {React.Ref<HTMLInputElement>} [ref] - Forwarded to the underlying `<input>`.
23
23
  */
24
24
  export interface DateInputProps extends DateInputBaseProps {
25
- /** Field label (component auto-wraps in a `Field` if not already inside). Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
25
+ /** Field label (component auto-wraps in a `Field` if not already inside). Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
26
26
  label?: React.ReactNode;
27
27
  /** Size for the label. */
28
28
  labelSize?: FieldProps['labelSize'];
@@ -20,7 +20,7 @@ import { DateTimeInputBaseProps } from './DateTimeInputBase.js';
20
20
  * @extraProp {boolean} [required=false] - Marks the field as required for native HTML form validation.
21
21
  */
22
22
  export interface DateTimeInputProps extends DateTimeInputBaseProps {
23
- /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
23
+ /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Not wired in `inline` mode (no visible input to label). Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
24
24
  label?: React.ReactNode;
25
25
  /** Size for the label. */
26
26
  labelSize?: FieldProps['labelSize'];
@@ -12,7 +12,7 @@ export interface FieldProps extends React.HTMLAttributes<HTMLDivElement>, Omit<B
12
12
  hasAddons?: boolean | 'centered' | 'right';
13
13
  /** Constrains the field to its content's width (used inside horizontal field bodies). */
14
14
  narrow?: boolean;
15
- /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete` also names its open suggestion list after the label through `aria-labelledby`. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children. Only the single inputs take the `htmlFor`, so once the Field's content has mounted the label keeps it only while one of them holds the id, and drops it over anything else: a group, a `Checkbox`, `Radio` or `Switch`, an `inline` picker, an inner `Field`, an input with an `id` of its own, markup of your own, or nothing at all. A server render, and the first render while hydrating, still write the `htmlFor`, which keeps hydration matching, and an input that mounts later puts it back. Pass `labelProps={{ htmlFor }}` to wire your own `id`, a `for` the label always keeps, or `labelProps={{ htmlFor: undefined }}` to opt out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */
15
+ /** Field label, rendered above the widget. Automatically names the one control the Field holds: a composed `InputBase`, `SelectBase`, `TextAreaBase`, `DateInputBase`, `TimeInputBase` or `DateTimeInputBase` (an `inline` picker has no input, so it takes nothing), or a bestax input that renders a single input of its own (`Input`, `Select`, `TextArea`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`, `Taginput`, `File`), adopts a generated id that the label's `htmlFor` points at, and a group (`Radios`, `Checkboxes`, `Rate`, `DateRangeInput`, or a composed `DateRangeInputBase`, `inline` or not) points `aria-labelledby` at the label's own id unless you gave the group an `aria-label` or `aria-labelledby`. A range `Slider` takes the id on its low thumb and also starts each thumb's name with the label through `aria-labelledby`, unless its `ariaLabel` names that thumb or its own `aria-label` or `aria-labelledby` takes the label's place. An `Autocomplete` also names its open suggestion list after the label through `aria-labelledby`. Nothing else takes the label: `Checkbox`, `Radio` and `Switch` are named by their own children, and the label names one only when you wire it as you would any control with an `id` of its own, `labelProps={{ htmlFor }}` plus that control's `id`. Only the single inputs take the `htmlFor`, so once the Field's content has mounted the label keeps it only while one of them holds the id, and drops it over anything else: a group, a `Checkbox`, `Radio` or `Switch`, an `inline` picker, an inner `Field`, an input with an `id` of its own, markup of your own, or nothing at all. A server render, and the first render while hydrating, still write the `htmlFor`, which keeps hydration matching, and an input that mounts later puts it back. The label names an input with an `id` of your own only through `labelProps={{ htmlFor }}` set to that `id`, a `for` it always keeps; `labelProps={{ htmlFor: undefined }}` opts out. Skipped for `grouped`/`hasAddons` fields (multiple controls), and a nested `Field` starts its own scope, so a horizontal Field whose body holds an inner `Field` names the control there only when you wire it. Two controls in one plain labeled Field would both adopt the id, so give each an `id` of its own. */
16
16
  label?: React.ReactNode;
17
17
  /** Size for the label. */
18
18
  labelSize?: 'small' | 'normal' | 'medium' | 'large';
@@ -11,7 +11,7 @@ import { FormFieldProps } from './fieldProps.js';
11
11
  * name on that `Field`.
12
12
  */
13
13
  export interface FileProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'color' | 'type'>, Omit<BulmaClassesProps, 'color'>, FormFieldProps {
14
- /** Field label. Automatically associated with the file input via `htmlFor` — uses your `id` when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping `file-label`); assistive tech reads both. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
14
+ /** Field label. Automatically associated with the file input via `htmlFor` — uses your `id` when provided, otherwise a generated one. The input then has two labels (this one plus the wrapping `file-label`); assistive tech reads both. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
15
15
  label?: React.ReactNode;
16
16
  /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */
17
17
  labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {
@@ -18,7 +18,7 @@ import { InputBaseProps } from './InputBase.js';
18
18
  * `label`, `horizontal` and class name on that `Field`.
19
19
  */
20
20
  export interface InputProps extends InputBaseProps {
21
- /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). */
21
+ /** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. */
22
22
  label?: React.ReactNode;
23
23
  /** Size for the label. */
24
24
  labelSize?: FieldProps['labelSize'];
@@ -17,7 +17,7 @@ export type NumberinputVariant = 'plusminus' | 'stepper';
17
17
  * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the input element.
18
18
  */
19
19
  export interface NumberinputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'color' | 'size' | 'onChange' | 'value' | 'defaultValue' | 'type'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'>, FormFieldProps {
20
- /** Field label. Automatically associated with the number input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`). Not rendered either by a plusminus `bare` Numberinput outside a `Field`. */
20
+ /** Field label. Automatically associated with the number input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here. Not rendered either by a plusminus `bare` Numberinput outside a `Field`. */
21
21
  label?: React.ReactNode;
22
22
  /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). */
23
23
  labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {