Skip to main content

Component API patterns

Tosui uses three API patterns. The pattern tells you whether a component accepts Box style props, owns a focused set of props, or coordinates several subcomponents.

Polymorphic styled components​

Polymorphic styled components build on Box. They accept Box style props, responsive values, state props, and an as prop unless their reference page lists an exception.

CategoryComponents
PrimitivesBox, Text, Heading, Code
LayoutStack, HStack, VStack, Flex, Grid, Container, Divider, Spacer
FormsButton, Input, Textarea, Select, Label
OtherLink, Spinner
<Button mt={6}>Submit</Button>
<Input w="100%" />
<VStack gap={{ base: 4, md: 8 }}>
<Text>First item</Text>
<Text>Second item</Text>
</VStack>

Some components replace a Box prop with a narrower convenience prop. Text and Heading, for example, use size, weight, and align instead of fontSize, fontWeight, and textAlign.

<Text size="sm" weight="medium" align="center" />
<Heading level={2} size="2xl" />

The as prop changes the rendered element and its native TypeScript attributes:

<Box as="section">Section content</Box>
<Text as="p">Paragraph content</Text>
<Button as="a" href="/signup">Create an account</Button>

Focused components​

Focused components expose only the props needed for their visual or interaction contract. They do not accept the full Box API.

CategoryComponents
Form controlsIconButton, Checkbox, Radio, Switch
FeedbackAlert, Badge, Progress, Skeleton
Data displayAvatar, Image
NavigationPagination

Wrap a focused component in Box when you need layout that its API does not expose:

<Box mt={6} display="flex" justifyContent="end">
<Pagination totalPages={12} />
</Box>

Use each component's className prop when you need CSS that cannot be expressed by its public props.

Compound components​

Compound components coordinate state or structure across named children.

RootSubcomponents
AccordionAccordionItem
BreadcrumbBreadcrumbItem
CardCardHeader, CardBody, CardFooter
ListListItem, ListIcon
MenuMenuButton, MenuList, MenuItem
ModalModalHeader, ModalBody, ModalFooter
PopoverPopoverHeader, PopoverBody
TabsTabList, Tab, TabPanel

Pass the documented subcomponents directly to their root unless a component reference says otherwise.

<Tabs defaultIndex={0}>
<TabList>
<Tab index={0}>Profile</Tab>
<Tab index={1}>Security</Tab>
</TabList>
<TabPanel index={0}>Profile settings</TabPanel>
<TabPanel index={1}>Security settings</TabPanel>
</Tabs>

Tabs does not export a TabPanels wrapper. TabPanel elements are direct children of Tabs.

Composition through context​

FormField is a separate composition pattern. Tosui form controls read the field ID, description, required state, disabled state, and invalid state from context. The controls can remain inside layout components.

<FormField label="Email" helperText="We use this for account notices">
<Box>
<Input type="email" />
</Box>
</FormField>

For a native or custom control, use the render-function adapter so that the accessible props reach the focusable element:

<FormField label="Email" isRequired>
{(controlProps) => <input type="email" {...controlProps} />}
</FormField>

See the FormField reference for the complete adapter contract.