Questions around how the Select machine works and why #598
-
Hello! I'm experimenting with building out some components using Zag and have made it to form fields, namely the Select field. One of the components from Chakra-UI that I used often was the FormControl component as it made it really easy to provide an ID, name, and various states that could be consumed by the label, field, description, and error text. After trying my hand at my own
zag/packages/machines/select/src/select.dom.ts Lines 5 to 12 in 571bb18 This is clearly just my perspective and I share/question these things only as a means to better understand Zag and possibly help improve it in some way. If you have other means of solving the problems I described here I'm very much open to it! Thanks!! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Hi @lvl-mattwells, Thanks for sharing this thoughtful feedback. You no longer need Styling is another topic we can address. How do I ensure the styling stays consistent with the existing You can leverage the context of the existing form styles provided by Chakra. Here's an example: function Select({ label, options }) {
const styles = useFormControlStyles()
const [state, send] = useMachine(select.machine())
const api = select.connect(state, send, normalizeProps)
return (
<>
{label && (
<Stack>
<Box as="label" __css={styles} {...api.labelProps}>
{label}
</Box>
<button {...api.triggerProps}>
<span>{api.selectedOption?.label ?? 'Select option'}</span>
<CaretIcon />
</button>
</Stack>
)}
<Portal>
<div {...api.positionerProps}>
<ul {...api.contentProps}>
{options.map(({ label, value }) => (
<li key={value} {...api.getOptionProps({ label, value })}>
<span>{label}</span>
{value === api.selectedOption?.value && '✓'}
</li>
))}
</ul>
</div>
</Portal>
</>
)
} |
Beta Was this translation helpful? Give feedback.
-
Why does Zag.js add ids to every element part? We do this for two reasons:
Okay. I get that, but how do I override the ids? Every machine has a You can use this to compose the FormControl and FormLabel elements if needed. Here's how to update the ids: const [tooltipState, tooltipSend] = useMachine(
select.machine({
ids: { label: "form-label" },
}),
) |
Beta Was this translation helpful? Give feedback.
Why does Zag.js add ids to every element part?
We do this for two reasons:
Accessibility: As you might know, we need to assign ids to the correct elements to get the
aria-*
andhtlmFor
attributes working correctly.Finding DOM Elements: Due to the fact that Zag.js is framework agnostic, the idea of
ref
can't be used here; we rely on the good oledocument.getElementById
to locate elements in the DOM. We also ensure it works in custom window environments and ShadowDOM.Okay. I get that, but how do I override the ids?
Every machine has a
ids
property you can pass to the context to modify the id of any part to match what you want.You can use this to compose the FormControl and FormLabe…