--- name: zag-compound-components description: > Use when creating or refactoring @techsio/ui-kit interactive components with Zag.js machine/connect APIs, normalizeProps, React context, compound Component.Subcomponent assignments, slots, adapter props, and data attribute state styling. metadata: type: "core" library: "@techsio/ui-kit" library_version: "0.3.2" requires: "component-authoring tailwind-token-authoring" sources: "libs/ui/AGENTS.md libs/ui/src/molecules/accordion.tsx libs/ui/src/molecules/carousel.tsx libs/ui/src/molecules/select.tsx libs/ui/src/molecules/tree-view.tsx libs/ui/src/organisms/header.tsx https://chakra-ui.com/docs/components/accordion https://chakra-ui.com/docs/components/menu https://github.com/TechsioCZ/new-engine/issues/295" --- This skill builds on `component-authoring` and `tailwind-token-authoring`. Read them first for component slice and token rules. # @techsio/ui-kit Zag Compound Components Use this for interactive components in `libs/ui`. ## Setup Minimum Zag-backed root: ```tsx import * as accordion from "@zag-js/accordion" import { normalizeProps, useMachine } from "@zag-js/react" import { createContext, useContext, useId, type ReactNode } from "react" import { tv } from "../utils" const styles = tv({ slots: { root: "rounded-accordion bg-accordion-bg", trigger: "data-disabled:cursor-not-allowed data-[state=open]:bg-accordion-bg-open", }, }) type AccordionApi = ReturnType const AccordionContext = createContext(null) function useAccordionContext() { const api = useContext(AccordionContext) if (!api) throw new Error("Accordion components must be used within Accordion.Root") return api } export function Accordion({ children }: { children: ReactNode }) { const service = useMachine(accordion.machine, { id: useId() }) const api = accordion.connect(service, normalizeProps) const { root } = styles() return (
{children}
) } ``` ## Core Patterns ### Check Chakra compound structure before naming parts ```tsx ``` Before inventing subcomponent names, compare the proposed API with Chakra UI v3 compound patterns such as Accordion and Menu. Keep the local API aligned with `Root`, `Trigger`, `Content`, `Item`, `Indicator`, `Positioner`, and similarly scoped names when they match the component anatomy. ### Spread Zag props on the matching part ```tsx Carousel.Next = function CarouselNext() { const { api } = useCarouselContext() return ``` Correct: ```tsx ``` Manual ARIA usually misses keyboard or focus behavior already encoded in the Zag machine. Source: libs/ui/AGENTS.md ### HIGH Subcomponent outside root Wrong: ```tsx ``` Correct: ```tsx ``` Compound children require the provider value created by the root. Source: libs/ui/src/molecules/carousel.tsx ### MEDIUM Local state duplicates machine state Wrong: ```tsx const [open, setOpen] = useState(false) return