"use client" import * as React from "react" import { cn } from "../../lib/utils" /** * `ItemGroup` and `Item` replace `@wordpress/components`' `__experimentalItemGroup` and * `__experimentalItem` - 27 files. * * An adapter, not a rename: WP's prop names are kept so a call site converts with an import swap. * What is reproduced, read off WP's own item-group styles: * * - isBordered a border around the group * - isRounded rounded group, default true as in WP * - isSeparated a hairline between rows and none under the last * - size row padding - small 8px, medium 12px, large 16px * * `Item` keeps WP's two-element shape, a listitem wrapper around the row, and renders a button when * it is given `onClick` and a div otherwise. That is WP's rule, and `utils/renderField.tsx` already * hand-writes the same shape for its rows, which are passed to these groups directly. * * Colours use the warm ramp names (line, line-soft, surface, ink) and not the shadcn aliases * (border, accent, card). They resolve to the same variables, but only the ramp is registered in * `tailwind.config.js`, so `divide-border` and `hover:bg-accent` compile to nothing. * * Deliberately not accepted: `as`, and a per-item `size`. No call site passes either. */ export type ItemGroupSize = "small" | "medium" | "large" const itemPadding: Record = { small: "px-2 py-1", medium: "px-3 py-2", large: "px-4 py-3", } // WP hands the group's size down by context so a call site sets it once. Same here. const ItemGroupSizeContext = React.createContext("medium") export interface ItemGroupProps extends React.HTMLAttributes { isBordered?: boolean isRounded?: boolean isSeparated?: boolean size?: ItemGroupSize } function ItemGroup({ isBordered = false, isRounded = true, isSeparated = false, size = "medium", role = "list", className, children, ...props }: ItemGroupProps) { return (
{children}
) } export type ItemProps = React.HTMLAttributes function Item({ role = "listitem", className, children, onClick, ...props }: ItemProps) { const size = React.useContext(ItemGroupSizeContext) const inner = cn( "m-0 block w-full box-border text-left", itemPadding[size], onClick && "cursor-pointer appearance-none bg-transparent text-inherit hover:bg-line-soft outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ink", className ) return (
{onClick ? ( // type="button" so a row inside a form cannot submit it. ) : (
{children}
)}
) } export { ItemGroup, Item }