Navigated to /docs/ui/composition-and-imports

Composition and imports

Choose import paths by ownership and use compound components when a component owns structured child roles.

Choose an import style

All documented entry points are public. Root imports optimize convenience, focused imports make ownership explicit, and grouped imports collect components by product area.

TS
tsimport { Button, Card } from "@tavojs/ui";
import { SearchInput } from "@tavojs/ui/search-input";
import { Page, Shell } from "@tavojs/ui/layout";
import { Field, TextInput } from "@tavojs/ui/forms";
import { Table, Toolbar } from "@tavojs/ui/data";

Use compound APIs for owned structure

Compound members make structural roles visible and keep behavior inside the owning component. Use them for cards, tables, tabs, collapsibles, dialogs, and similar APIs instead of reconstructing their internal semantics with generic primitives.

TSX
tsximport { Card, Table } from "@tavojs/ui";

export const Report = () => {
  return (
    <Card.Root title="Delivery report">
      <Card.Content>Current project status</Card.Content>
      <Card.Actions>Export report</Card.Actions>
      <Table.Root>
        <Table.Head>Column definitions</Table.Head>
        <Table.Body>Project rows</Table.Body>
      </Table.Root>
    </Card.Root>
  );
};

Keep composition predictable

  • Use layout primitives for spacing and alignment instead of margin conventions between child components.

  • Keep stateful behavior controlled by application state when the component API exposes value and change handlers.

  • Do not depend on internal class names or DOM nesting.

  • Use component metadata and the reference page to find related components and required compound members.

  • Prefer one public import style within a feature so refactors remain mechanical.

Shared component props

Most single-root Tavo.js UI components extend BaseProps. A component can narrow that contract when it owns a native control or a structured composition, so its component page remains the final authority.

PropTypeBehavior
childrenChild

Content rendered by the component.

classNamestring

A class added to the public root element.

sxSx

Token-aware local styles compiled into the overrides layer.

styleRecord<string, unknown>

Inline styles forwarded to the public root.

id, role, tabIndexnative values

Identity, semantics, and keyboard order for the root.

hidden, disabledboolean

Native state where the rendered element supports it.

eventsevent handlers

Click, change, input, keyboard, focus, and blur handlers.

aria-* and data-*unknown

Accessible state and application-owned data attributes.

Sizes, tones, spacing, and responsive values

  • Size is sm, md, or lg. Interactive controls normally default to md.

  • Shared semantic tones are primary, secondary, neutral, success, warning, danger, and info. Individual components intentionally expose only the tones they can represent.

  • Spacing is sm, md, or lg. Gap additionally accepts none; layout gaps may also accept numbers or CSS strings.

  • ResponsiveValue<T> accepts one static value or an object keyed by base, sm, md, and lg.

  • Numeric responsive gaps become pixel values. Named gaps resolve through theme spacing tokens; CSS strings pass through unchanged.

TSX
tsximport { Flex, Grid, Stack } from "@tavojs/ui";

export const ResultsLayout = () => {
  return (
    <Stack gap={{ base: "sm", lg: "lg" }}>
      <Flex direction={{ base: "column", md: "row" }} gap="md" />
      <Grid columns={{ base: 1, sm: 2, lg: 4 }} spacing="md" />
    </Stack>
  );
};