Usage#
import { useFieldset } from '@primereact/headless/fieldset';const { rootProps, triggerProps, contentProps, indicatorProps, state } = useFieldset({ defaultOpen: true });
<fieldset {...rootProps}>
<legend>
<button {...triggerProps}>
<span {...indicatorProps} />
</button>
</legend>
{state.open && <div {...contentProps}></div>}
</fieldset>;useFieldset wraps useCollapsible and returns spread-ready prop objects for semantic fieldset/legend grouping — see Primitive for a component-based API.
Features#
- Semantic form grouping — props are tuned for native
fieldsetandlegendelements so built-in form semantics stay intact - Single-hook collapsible — built on
useCollapsible, one call returnsrootProps,triggerProps,contentProps, andindicatorProps - Controlled or uncontrolled open state — pass
open/onOpenChangeor rely ondefaultOpen - Imperative controls —
toggle(),open(), andclose()flip state from anywhere outside the legend - Full render control — use
state.opento mount, hide, or animate content on your terms
Working with callbacks#
Controlled open state#
Drive the fieldset's open state from parent state.
const [open, setOpen] = React.useState(true);
const fieldset = useFieldset({
open,
onOpenChange: (e) => setOpen(e.value ?? false)
});onOpenChange receives { originalEvent, value } where value is the new boolean state.
Collapsing groups of form fields#
Pair useFieldset with form libraries by gating validation on state.open — skip validating hidden groups.
const fieldset = useFieldset({ defaultOpen: false });
const onSubmit = (data) => {
if (fieldset.state.open) {
validateAdvancedFields(data);
}
submit(data);
};Imperative control from toolbar actions#
Use toggle, open, and close to drive the fieldset from "Expand all" / "Collapse all" buttons elsewhere on the page.
const fieldset = useFieldset({ defaultOpen: false });
<button onClick={(e) => fieldset.open(e)}>Show advanced options</button>;Animated reveal#
Gate content mounting on state.open and wrap with your motion library of choice.
const { contentProps, state } = useFieldset({ defaultOpen: true });
<AnimatePresence>
{state.open && (
<motion.div {...contentProps} initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
Advanced fields
</motion.div>
)}
</AnimatePresence>;Styling with data attributes#
Every prop object includes data-scope="fieldset" and a data-part attribute. State is reflected via data-open/data-closed/data-disabled, and triggerProps also gets data-content-open/data-content-closed.
[data-scope='fieldset'][data-part='trigger'] {
font-weight: 600;
}
[data-scope='fieldset'][data-part='content'][data-open] {
animation: slideDown 200ms ease-out;
}
[data-scope='fieldset'][data-part='content'][data-closed] {
animation: slideUp 200ms ease-out;
}
[data-scope='fieldset'][data-part='trigger'][data-content-open] {
color: blue;
}API#
useFieldset#
| Name | Type | Default |
|---|---|---|
open | boolean | false |
| Controls the open state of the collapsible. | ||
defaultOpen | boolean | false |
| Defines the initial open state of the collapsible. | ||
disabled | boolean | false |
| When disabled, the component cannot be interacted with. | ||
tabIndex | number | 0 |
| Index of the element in tabbing order. | ||
onOpen | (event?: SyntheticEvent) => void | — |
| Callback triggered when the content is opened. | ||
onClose | (event?: SyntheticEvent) => void | — |
| Callback triggered when the content is closed. | ||
onOpenChange | (event: useFieldsetOpenChangeEvent) => void | — |
| Callback triggered when the content's toggle state changes. | ||
Accessibility#
Enter or Space on the legend toggles when toggleable, otherwise standard fieldset semantics apply. See Primitive for full WAI-ARIA compliance details.