npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ankhorage/zora

v1.0.10

Published

Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.

Downloads

7,759

Readme

ZORA

Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.

ZORA sits above Surface. Surface provides the foundation primitives, theme system, and low-level controls; ZORA adds product-facing components, app layouts, and ready-made patterns with stronger defaults.

Install

bun add @ankhorage/zora

Peer dependencies:

  • react >=18.2.0
  • react-native >=0.72.0
  • @expo/vector-icons >=14.0.0 when using icon specs
  • expo-font >=14.0.4 when using runtime font registration

Quick Start

Wrap your app in ZoraProvider, then import components from @ankhorage/zora.

import React from 'react';
import {
  AppShell,
  Button,
  Card,
  Heading,
  Page,
  PageHeader,
  Text,
  Toolbar,
  ToolbarAction,
  ZoraProvider,
} from '@ankhorage/zora';

export function App() {
  return (
    <ZoraProvider>
      <AppShell
        header={
          <Toolbar>
            <ToolbarAction icon={{ name: 'menu-outline' }} label="Menu" />
          </Toolbar>
        }
      >
        <Page header={<PageHeader title="Dashboard" description="Ready to build." />}>
          <Card
            actions={<Button>Continue</Button>}
            description="ZORA provides composed UI surfaces for apps."
            title="Welcome"
          >
            <Heading level={3}>Next steps</Heading>
            <Text tone="muted">Structured text comes from ZORA too.</Text>
          </Card>
        </Page>
      </AppShell>
    </ZoraProvider>
  );
}

Scoped themes

ZORA supports nested theme scopes. A component may set mode and, later, themeId; everything inside inherits the nearest scope.

import React from 'react';
import { Button, Heading, Panel, Text, ZoraProvider, type ZoraTheme } from '@ankhorage/zora';

export function App({ appTheme }: { appTheme: ZoraTheme }) {
  return (
    <ZoraProvider theme={appTheme} initialMode="light">
      <Panel mode="dark">
        <Heading>Studio panel</Heading>
        <Text>Text inherits dark mode.</Text>
        <Button>Also scoped.</Button>
      </Panel>
    </ZoraProvider>
  );
}

ZORA themes use a single seed primaryColor. The selected primary color is preserved identically for both light and dark mode. Color generation is handled by @ankhorage/color-theory via Surface.

<ZoraProvider
  theme={{
    id: 'studio',
    name: 'Studio',
    appCategory: 'developer_tools',
    primaryColor: '#0f766e',
    harmony: 'analogous',
  }}
>
  <App />
</ZoraProvider>

mode and themeId are available on public ZORA components through ZoraBaseProps. Use component props for local component/subtree overrides.

Use ZoraThemeScope when the scope is conceptual and does not belong to one specific component:

import React from 'react';
import { SidebarLayout, Text, ZoraProvider, ZoraThemeScope, type ZoraTheme } from '@ankhorage/zora';

export function App({ appTheme }: { appTheme: ZoraTheme }) {
  return (
    <ZoraProvider theme={appTheme} initialMode="light">
      <ZoraThemeScope mode="dark">
        <SidebarLayout sidebar={<Text>Sidebar</Text>}>
          <Text>Everything inside uses dark mode.</Text>
        </SidebarLayout>
      </ZoraThemeScope>
    </ZoraProvider>
  );
}

themeId currently accepts the inherited theme id. Full theme registries arrive in a later phase.

Foundation primitives

ZORA re-exports selected Surface foundation primitives for app-facing layout code:

import { Box, Container, Grid, Heading, Stack, Text } from '@ankhorage/zora';

Use ZORA Text and Heading for typography. Use Box, Stack, Grid, and Container for layout. Surface remains the lower-level render foundation and should not be required in normal app-facing UI code.

Navigation chrome (Expo Router)

ZORA provides product-facing navigation chrome that can be plugged into real Expo Router / React Navigation navigators. Expo Router owns navigation mechanics (state, linking, gestures); ZORA only renders the tab bar and drawer content.

routeMap is the primary source for icons, badges, disabled state, and explicit labels. Navigator descriptor options are used as a label/title fallback only.

Tabs

import { Tabs } from 'expo-router';
import { ZoraTabBar, type ZoraNavigationRouteMap } from '@ankhorage/zora';

const routeMap: ZoraNavigationRouteMap = {
  index: { label: 'Home', icon: { name: 'home-outline' } },
  settings: { label: 'Settings', icon: { name: 'settings-outline' }, badge: '3' },
};

export default function Layout() {
  return <Tabs tabBar={(props) => <ZoraTabBar {...props} routeMap={routeMap} />} />;
}

Drawer

import { Drawer } from 'expo-router/drawer';
import { ZoraDrawerContent, type ZoraNavigationRouteMap } from '@ankhorage/zora';

const routeMap: ZoraNavigationRouteMap = {
  home: { label: 'Home', icon: { name: 'home-outline' } },
  account: { label: 'Account', icon: { name: 'person-outline' }, disabled: true },
};

export default function Layout() {
  return <Drawer drawerContent={(props) => <ZoraDrawerContent {...props} routeMap={routeMap} />} />;
}

Shared Types

These unions appear across the catalogue:

  • ZoraTone comes from Surface ButtonProps['tone'].
  • ZoraEmphasis comes from Surface ButtonProps['variant'].
  • ZoraBadgeEmphasis comes from Surface BadgeProps['variant'].
  • ZoraControlSize comes from Surface ButtonProps['size'].
  • ZoraCardTone = 'default' | 'subtle' | 'outline'.
  • ZoraContentWidth = 'narrow' | 'default' | 'wide'.

Width presets:

  • Dialog widths: narrow=420, default=520, wide=560.
  • Page widths: narrow=760, default=1040, wide=1280.

Components

Heading

Structured titles with semantic levels, visual sizes, semantic tones, and responsive props. Use Heading for titles and Text for body copy.

<Heading level={1} size={{ base: 'h2', md: 'h1' }}>
  Build faster with ZORA
</Heading>

<Heading level={2} tone="primary">
  Create consistent screens
</Heading>

level expresses document hierarchy. size controls visual scale and can be responsive for mobile and web layouts.

ZORA props:

| Prop | Type | Default | Notes | | --------------- | ---------------------------------------- | ----------- | --------------------------------------------------------------- | | children | React.ReactNode | - | Primary content. | | text | string | - | Manifest-friendly content prop. | | i18nKey | string | - | Runtime-resolved fallback key when no content prop is provided. | | level | HeadingLevel | 2 | Semantic heading level from 1 through 6. | | size | Responsive<HeadingSize> | level size | Visual scale: display, h1 through h6. | | tone | Responsive<HeadingTone> | 'default' | Semantic text color. | | align | Responsive<HeadingAlign> | - | Text alignment. | | weight | Responsive<HeadingWeight> | recipe | Optional structured weight override. | | italic | boolean | false | Italic style. | | numberOfLines | number | - | Native/web truncation line count. | | ellipsizeMode | 'head' \| 'middle' \| 'tail' \| 'clip' | - | Truncation behavior. | | selectable | boolean | - | Allows text selection where supported. | | testID | string | - | Test id. |

No inherited props. HeadingProps is declared directly by ZORA to keep heading usage structured and template-safe.

Text

Structured body text with ZORA typography variants, semantic tones, and responsive props.

<Text variant="lead" tone="muted">
  Build product screens with structured, theme-aware copy.
</Text>

<Text variant={{ base: 'bodySmall', md: 'body' }} align={{ base: 'center', md: 'left' }}>
  Responsive text without raw styles.
</Text>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | ---------------------------------------- | ----------- | --------------------------------------------------------------- | | children | React.ReactNode | - | Primary content. | | text | string | - | Manifest-friendly content prop. | | i18nKey | string | - | Runtime-resolved fallback key when no content prop is provided. | | variant | Responsive<TextVariant> | 'body' | Typography recipe. | | tone | Responsive<TextTone> | 'default' | Semantic text color. | | align | Responsive<TextAlign> | - | Text alignment. | | weight | Responsive<TextWeight> | recipe | Optional structured weight override. | | italic | boolean | false | Italic style. | | numberOfLines | number | - | Native/web truncation line count. | | ellipsizeMode | 'head' \| 'middle' \| 'tail' \| 'clip' | - | Truncation behavior. | | selectable | boolean | - | Allows text selection where supported. | | testID | string | - | Test id. |

No inherited props. TextProps is declared directly by ZORA to keep text structured and template-safe.

Button

Action button with ZORA defaults for tone, emphasis, size, and icons.

<Button leadingIcon={{ name: 'checkmark-circle-outline' }}>Save</Button>

ZORA props:

| Prop | Type | Default | Notes | | -------------- | ----------------- | ----------- | ------------------------------------------ | | children | React.ReactNode | - | Button label or content. | | tone | ZoraTone | 'primary' | Passed to Surface as tone. | | emphasis | ZoraEmphasis | 'solid' | Passed to Surface as variant. | | size | ZoraControlSize | 'l' | Passed to Surface as size. | | leadingIcon | ButtonIconSpec | - | Surface icon spec rendered before content. | | trailingIcon | ButtonIconSpec | - | Surface icon spec rendered after content. |

Inherited props:

Inherits all Surface ButtonProps except children, size, tone, and variant. This includes Surface button behavior such as loading, fullWidth, pressability props, disabled state, accessibility props allowed by Surface, and testID.

IconButton

Compact icon-only button for toolbars, rows, and actions.

<IconButton icon={{ name: 'trash-outline' }} label="Delete" tone="danger" />

ZORA props:

| Prop | Type | Default | Notes | | ---------- | ----------------- | ----------- | ---------------------------------- | | icon | ButtonIconSpec | - | Required icon to render. | | label | string | - | Required for accessibilityLabel. | | tone | ZoraTone | 'neutral' | Button tone. | | emphasis | ZoraEmphasis | 'ghost' | Button emphasis. | | size | ZoraControlSize | 'm' | Button size. |

Inherited props:

Inherits behavior from Surface IconButton including disabled, loading, onPress, and testID.

Avatar

User/profile image with name-based initials and optional icon fallback.

<Avatar name="Zora Kit" />
<Avatar size="l" tone="primary" name="Fabio Gartenmann" />

ZORA props:

| Prop | Type | Default | Notes | | -------------- | --------------------- | ----------- | ----------------------------------------------- | | source | ImageSourcePropType | - | React Native Image source for the avatar. | | name | string | - | Used to derive initials when initials absent. | | initials | string | - | Explicit initials override. | | iconFallback | ButtonIconSpec | - | Optional icon spec when no source/initials. | | label | string | - | Accessibility label for the rendered content. | | size | AvatarSize | 'm' | xs..xl size preset. | | shape | AvatarShape | 'circle' | circle or rounded. | | tone | ZoraTone | 'neutral' | Drives background and fallback content tone. | | testID | string | - | Test id. |

Inherited props:

No inherited props. AvatarProps is declared directly by ZORA.

AvatarGroup

Overlapping avatar stack with optional overflow label.

<AvatarGroup
  items={[
    { id: '1', name: 'Ada Lovelace' },
    { id: '2', name: 'Grace Hopper', tone: 'success' },
  ]}
/>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | --------------------------- | ---------- | ------------------------------------ | | items | AvatarGroupItem[] | - | Avatar sources and fallback fields. | | max | number | 4 | Max visible avatars before overflow. | | size | AvatarSize | 's' | Avatar size preset. | | shape | AvatarShape | 'circle' | Avatar shape preset. | | overflowLabel | (overflowCount) => string | +N | Overflow label formatter. | | testID | string | - | Test id. |

AvatarGroupItem:

| Prop | Type | Notes | | -------------- | --------------------- | ------------------------------- | | id | string | Optional stable key. | | source | ImageSourcePropType | Image source for the avatar. | | name | string | Used to derive initials. | | initials | string | Explicit initials override. | | iconFallback | ButtonIconSpec | Optional icon fallback. | | label | string | Accessibility label. | | tone | ZoraTone | Overrides avatar tone per item. |

Inherited props:

No inherited props. AvatarGroupProps is declared directly by ZORA.

Badge

Small status label with ZORA tone, emphasis, and size defaults.

<Badge tone="success">Active</Badge>

ZORA props:

| Prop | Type | Default | Notes | | ---------- | ------------------- | ----------- | ------------------------------------ | | children | React.ReactNode | - | Rendered as Surface badge content. | | tone | ZoraTone | 'primary' | Passed to Surface as tone. | | emphasis | ZoraBadgeEmphasis | 'soft' | Passed to Surface as variant. | | size | ZoraControlSize | 'm' | Passed to Surface as size. |

Inherited props:

Inherits all Surface BadgeProps except content, size, tone, and variant. The remaining inherited prop is testID.

Card

Composed content surface with optional header, actions, footer, and ZORA card tones.

<Card actions={<Button>Open</Button>} description="A reusable product surface." title="Project" />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ----------- | ---------------------------------------------------------------------------------------- | | children | React.ReactNode | - | Main card body. | | title | React.ReactNode | - | Header title. | | description | React.ReactNode | - | Header description. | | eyebrow | React.ReactNode | - | Small muted text above the title. | | actions | React.ReactNode | - | Header action area. | | footer | React.ReactNode | - | Footer area below body content. | | tone | ZoraCardTone | 'default' | Maps to Surface variants: default -> raised, subtle -> subtle, outline -> outline. | | compact | boolean | false | Uses tighter padding and heading scale. |

Inherited props:

Inherits all Surface CardProps except children, p, radius, variant, and style. ZORA owns spacing, radius, and variant selection for this wrapper.

MediaCard

Media-first card surface for listings, content previews, and catalog items.

<MediaCard
  imageSource={require('./cover.png')}
  imageLabel="Cover image"
  title="MediaCard"
  description="Composes an image slot, header content, badges, actions, and footer metadata."
  badges={<Badge tone="primary">Featured</Badge>}
  footer={<Rating value={4.5} />}
  onPress={() => undefined}
/>

ZORA props:

| Prop | Type | Default | Notes | | ------------------ | --------------------- | ----------- | ---------------------------------------------------------- | | imageSource | ImageSourcePropType | - | Image source (mutually exclusive with image). | | imageLabel | string | - | Accessibility label for imageSource. | | image | React.ReactNode | - | Custom image slot (mutually exclusive with imageSource). | | imageAspectRatio | number | 16 / 9 | Aspect ratio used when rendering imageSource. | | title | React.ReactNode | - | Required title. | | description | React.ReactNode | - | Optional description under the title. | | eyebrow | React.ReactNode | - | Optional caption above the title. | | badges | React.ReactNode | - | Optional badge/tags region near the title. | | actions | React.ReactNode | - | Optional trailing action area; disables onPress. | | footer | React.ReactNode | - | Optional footer content under the body. | | children | React.ReactNode | - | Optional body content. | | tone | ZoraCardTone | 'default' | Passed to the underlying Card. | | compact | boolean | false | Uses tighter spacing. | | onPress | () => void | - | Makes the card pressable when no actions are present. | | testID | string | - | Forwarded to the underlying Card. |

Inherited props:

No inherited props. MediaCardProps is declared directly by ZORA.

MetricCard

Compact metric surface for dashboards, stats, and summary cards.

<MetricCard
  label="Monthly active users"
  value="14.2k"
  delta="+4.1%"
  deltaTone="success"
  description="Last 30 days"
/>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ----------- | ------------------------------------------------------- | | label | React.ReactNode | - | Required label above the value. | | value | React.ReactNode | - | Required metric value. | | description | React.ReactNode | - | Optional supporting copy. | | icon | ButtonIconSpec | - | Optional icon shown next to the label. | | delta | React.ReactNode | - | Optional delta badge content. | | deltaTone | ZoraTone | 'neutral' | Tone used for the delta Badge. | | actions | React.ReactNode | - | Optional trailing action area; disables onPress. | | tone | ZoraCardTone | 'default' | Passed to the underlying Card. | | compact | boolean | false | Uses tighter spacing. | | onPress | () => void | - | Makes the card pressable when no actions are present. | | testID | string | - | Forwarded to the underlying Card. |

Inherited props:

No inherited props. MetricCardProps is declared directly by ZORA.

Progress

Linear progress bar with semantic tone.

<Progress value={72} />
<Progress tone="success" value={38} />

ZORA props:

| Prop | Type | Default | Notes | | -------- | ----------------- | ----------- | ----------------------------- | | value | number | - | Current progress value. | | max | number | 100 | Maximum value for completion. | | tone | ZoraTone | 'primary' | Fill tone. | | size | ZoraControlSize | 'm' | Controls bar height. | | testID | string | - | Test id. |

Inherited props:

No inherited props. ProgressProps is declared directly by ZORA.

Rating

Readonly rating display rendered as star icons.

<Rating value={4.5} />

ZORA props:

| Prop | Type | Default | Notes | | -------- | ----------------- | ----------- | ---------------------- | | value | number | - | Current rating value. | | max | number | 5 | Maximum rating value. | | tone | ZoraTone | 'warning' | Tone for filled icons. | | size | ZoraControlSize | 'm' | Icon sizing preset. | | testID | string | - | Test id. |

Inherited props:

No inherited props. RatingProps is declared directly by ZORA.

Input

Text input wrapper with ZORA sizing and optional Surface icon specs.

<Input
  autoCapitalize="none"
  keyboardType="email-address"
  leadingIcon={{ name: 'mail-outline' }}
  placeholder="[email protected]"
/>

ZORA props:

| Prop | Type | Default | Notes | | ---------------- | --------------------- | ------- | ------------------------------------------------------------------------------ | | size | ZoraControlSize | 'l' | Passed to Surface as size. | | leadingIcon | ButtonIconSpec | - | Rendered as Surface leadingAccessory. | | trailingIcon | ButtonIconSpec | - | Rendered as Surface trailingAccessory. | | trailingAction | InputTrailingAction | - | Renders an icon-only trailing action (mutually exclusive with trailingIcon). |

Inherited props:

Inherits all Surface TextInputProps except leadingAccessory, size, and trailingAccessory. Surface TextInputProps also inherit React Native TextInputProps except defaultValue, editable, onChangeText, placeholderTextColor, style, testID, and value; Surface re-exposes value, defaultValue, onChangeText, placeholder, disabled, readOnly, invalid, style, and testID.

SearchBar

Controlled search input with leading search icon and optional clear action.

<SearchBar value={query} onValueChange={setQuery} onSubmit={(value) => console.log(value)} />

ZORA props:

| Prop | Type | Default | Notes | | --------------- | ------------------------- | ---------- | --------------------------------------------- | | value | string | - | Current search query. | | onValueChange | (value: string) => void | - | Called when the query changes. | | placeholder | string | 'Search' | Placeholder text. | | onSubmit | (value: string) => void | - | Called on submit (returnKeyType="search"). | | onClear | () => void | - | Called after clearing the query. | | clearable | boolean | true | Shows clear action when value is non-empty. | | size | ZoraControlSize | 'l' | Passed to the underlying Input. | | disabled | boolean | - | Disables the underlying Input. | | readOnly | boolean | - | Makes the underlying Input read-only. | | testID | string | - | Test id. |

Inherited props:

No inherited props. SearchBarProps is declared directly by ZORA.

RadioGroup

Single-selection control built on top of Surface Radio, designed for use inside FormField.

<FormField label="Navigator type">
  <RadioGroup
    value="tabs"
    onValueChange={(value) => console.log(value)}
    options={[
      { value: 'tabs', label: 'Tabs' },
      { value: 'drawer', label: 'Drawer' },
    ]}
  />
</FormField>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | ---------------------------- | ------------ | ------------------------------ | | value | string | - | Currently selected value. | | onValueChange | (value: string) => void | - | Called when selection changes. | | options | RadioGroupOption[] | - | List of selectable options. | | orientation | 'horizontal' \| 'vertical' | 'vertical' | Layout direction. | | gap | 'xs' \| 's' \| 'm' \| 'l' | 's' | Spacing between items. |

Option shape:

type RadioGroupOption = {
  value: string;
  label: React.ReactNode;
  description?: React.ReactNode;
  disabled?: boolean;
};

Inherited props:

Passes tone, size, invalid, readOnly, disabled, and testID to underlying Surface Radio components.


CheckboxGroup

Multi-selection control built on top of Surface Checkbox, for selecting multiple values.

<FormField label="Features">
  <CheckboxGroup
    value={['a']}
    onValueChange={(value) => console.log(value)}
    options={[
      { value: 'a', label: 'Feature A' },
      { value: 'b', label: 'Feature B' },
    ]}
  />
</FormField>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | ---------------------------- | ------------ | ------------------------------ | | value | string[] | - | Array of selected values. | | onValueChange | (value: string[]) => void | - | Called when selection changes. | | options | CheckboxGroupOption[] | - | List of selectable options. | | orientation | 'horizontal' \| 'vertical' | 'vertical' | Layout direction. | | gap | 'xs' \| 's' \| 'm' \| 'l' | 's' | Spacing between items. |

Option shape:

type CheckboxGroupOption = {
  value: string;
  label: React.ReactNode;
  description?: React.ReactNode;
  disabled?: boolean;
};

Inherited props:

Passes tone, size, invalid, readOnly, disabled, and testID to underlying Surface Checkbox components.

Chip

Compact filter/action token with optional icon and selected state.

<Chip selected tone="primary" onPress={() => undefined}>
  Selected
</Chip>

ZORA props:

| Prop | Type | Default | Notes | | ---------- | ----------------- | ----------- | ------------------------------------ | | children | React.ReactNode | - | Chip label content. | | icon | ButtonIconSpec | - | Optional leading icon spec. | | selected | boolean | false | Selected styling state. | | tone | ZoraTone | 'neutral' | Selected tone. | | size | ZoraControlSize | 's' | Padding and icon sizing. | | disabled | boolean | false | Disables interaction and mutes tone. | | onPress | () => void | - | Optional press handler. | | testID | string | - | Test id. |

Inherited props:

No inherited props. ChipProps is declared directly by ZORA.

ChipGroup

Controlled single- or multi-select chip set for filters and facets.

<ChipGroup
  value="all"
  onValueChange={setValue}
  items={[
    { value: 'all', label: 'All' },
    { value: 'favorites', label: 'Favorites' },
  ]}
/>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | -------------------- | ----------- | ------------------------------ | | items | ChipGroupItem[] | - | Rendered chips. | | value | string \| string[] | - | Selected value(s). | | onValueChange | (value) => void | - | Selection change handler. | | multiple | boolean | false | Enables multi-select mode. | | tone | ZoraTone | 'neutral' | Tone for selected chips. | | size | ZoraControlSize | 's' | Chip size. | | wrap | boolean | true | Wrap chips on smaller screens. | | disabled | boolean | - | Disables all chips. | | testID | string | - | Test id. |

Inherited props:

No inherited props. ChipGroupProps is declared directly by ZORA.

Textarea

Multiline text input wrapper with ZORA sizing and optional Surface icon specs.

<Textarea leadingIcon={{ name: 'document-text-outline' }} rows={5} />

ZORA props:

| Prop | Type | Default | Notes | | -------------- | ----------------- | ------- | ---------------------------------------- | | size | ZoraControlSize | 'l' | Passed to Surface as size. | | leadingIcon | ButtonIconSpec | - | Rendered as Surface leadingAccessory. | | trailingIcon | ButtonIconSpec | - | Rendered as Surface trailingAccessory. |

Inherited props:

Inherits all Surface TextareaProps except leadingAccessory, size, and trailingAccessory. Surface TextareaProps extend Surface TextInputProps except multiline, so React Native text input props are available through Surface with the same Surface exclusions and re-exposed values listed for Input.

Tabs

Generic controlled tabs for navigation and filtering.

<Tabs
  items={[
    { value: 'all', label: 'All' },
    { value: 'active', label: 'Active' },
  ]}
  onValueChange={setValue}
  value={value}
/>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | -------------------------------------- | ------------- | --------------------- | | value | string | - | Active tab value. | | items | TabItem[] | - | Array of tab objects. | | onValueChange | (value: string) => void | - | Change handler. | | variant | 'underline' \| 'pill' \| 'segmented' | 'underline' | Visual style. | | size | ZoraControlSize | 'm' | Control size. |

Toolbar

Horizontal shell for actions and tools.

<Toolbar>
  <ToolbarAction icon={{ name: 'add-outline' }} label="Add" />
  <ToolbarAction icon={{ name: 'search-outline' }} label="Search" />
</Toolbar>

Toolbar props:

| Prop | Type | Default | Notes | | ---------- | ------------------------------- | ---------- | ----------------------------------------- | | children | React.ReactNode | - | Toolbar content. | | position | 'top' \| 'bottom' \| 'inline' | 'inline' | Layout position. | | floating | boolean | false | Whether the toolbar floats with a shadow. | | compact | boolean | true | Tighter padding. |

ToolbarAction props:

| Prop | Type | Default | Notes | | --------- | ---------------- | ------- | -------------------- | | icon | ButtonIconSpec | - | Required icon. | | label | string | - | Accessibility label. | | active | boolean | false | Highlighted state. | | onPress | () => void | - | Click handler. |

Select

Standard dropdown selector wrapping @react-native-picker/picker.

<Select
  onValueChange={setValue}
  options={[
    { value: '1', label: 'Option 1' },
    { value: '2', label: 'Option 2' },
  ]}
  value={value}
/>

ZORA props:

| Prop | Type | Default | Notes | | --------------- | ------------------------- | ------- | ------------------------ | | value | string | - | Selected value. | | options | SelectOption[] | - | Array of option objects. | | onValueChange | (value: string) => void | - | Change handler. | | invalid | boolean | false | Error state styling. | | disabled | boolean | false | Interaction state. |

Modal

Centered overlay shell with optional header, body, footer, and width preset.

<Modal footer={<Button>Done</Button>} onDismiss={close} title="Details" visible={visible} />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ------------------ | ----------- | ------------------------------------------ | | children | React.ReactNode | - | Modal body. | | title | React.ReactNode | - | Header title. | | description | React.ReactNode | - | Header description. | | footer | React.ReactNode | - | Footer area. | | width | ZoraContentWidth | 'default' | Resolves to 420, 520, or 560 pixels. |

Inherited props:

Picks these Surface ModalProps: closeOnBackdrop, onDismiss, testID, and visible.

Drawer

Side overlay shell with optional header, body, and footer.

<Drawer onDismiss={close} title="Filters" visible={visible}>
  {content}
</Drawer>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------- | | children | React.ReactNode | - | Drawer body. | | title | React.ReactNode | - | Header title. | | description | React.ReactNode | - | Header description. | | footer | React.ReactNode | - | Footer area. |

Inherited props:

Picks these Surface DrawerProps: closeOnBackdrop, onDismiss, position, testID, and visible.

Layouts

AppShell

Theme-aware application root shell providing the structural frame for an app. It defines the top-level layout slots (header, body, footer, overlay) and ensures a full-height, flexible container.

Use it as the outer layout inside ZoraProvider. Combine it with layout primitives like SidebarLayout or Page to structure inner content.

<AppShell header={<Toolbar position="inline">{actions}</Toolbar>} footer={<BottomBar />}>
  <Page header={<PageHeader title="Dashboard" />}>{content}</Page>
</AppShell>

Example with overlay (e.g. mobile panel or drawer):

<AppShell footer={<BottomBar />} overlay={isOpen ? <MyDrawer onClose={close} /> : null}>
  {content}
</AppShell>

ZORA props:

| Prop | Type | Default | Notes | | ----------- | ---------------------- | ------- | ------------------------------------------------------------------------------------ | | children | React.ReactNode | - | Main application content. | | header | React.ReactNode | - | Optional top section (e.g. toolbar or navigation). | | footer | React.ReactNode | - | Optional bottom section (e.g. tab bar or actions). | | overlay | React.ReactNode | - | Optional overlay layer rendered above content (e.g. drawer, modal, floating panels). | | style | StyleProp<ViewStyle> | - | Style applied to the root container. | | bodyStyle | StyleProp<ViewStyle> | - | Style applied to the main content container. | | testID | string | - | Forwarded to the root Surface container. |

Inherited props:

No inherited props. AppShellProps is declared directly by ZORA.


Design notes

  • AppShell is a structural primitive, not a page layout.

  • It does not manage sidebars or content splits — use SidebarLayout for that.

  • It does not provide theming — wrap with ZoraProvider.

  • overlay is rendered using absolute positioning and should be used for drawers, mobile panels, or floating UI.

  • All inner content must support flexible layouts (flex: 1, minHeight: 0) to behave correctly inside the shell.

Page

Constrained page container with optional header and footer slots.

<Page header={<PageHeader title="Projects" />} width="wide">
  {content}
</Page>

ZORA props:

| Prop | Type | Default | Notes | | ---------- | ------------------ | ----------- | -------------------------------------------- | | children | React.ReactNode | - | Page body. | | header | React.ReactNode | - | Rendered above body content. | | footer | React.ReactNode | - | Rendered below body content. | | width | ZoraContentWidth | 'default' | Resolves to 760, 1040, or 1280 pixels. | | testID | string | - | Forwarded to the root Surface container. |

Inherited props:

No inherited props. PageProps is declared directly by ZORA.

PageHeader

Top-level page heading with optional eyebrow, metadata, and actions.

<PageHeader actions={<Button>New</Button>} title="Projects" />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------------------------ | | title | React.ReactNode | - | Required page title. | | description | React.ReactNode | - | Supporting copy below title. | | eyebrow | React.ReactNode | - | Small muted text above title. | | actions | React.ReactNode | - | Action area opposite the heading. | | meta | React.ReactNode | - | Extra content below description. | | testID | string | - | Forwarded to the root Surface stack. |

Inherited props:

No inherited props. PageHeaderProps is declared directly by ZORA.

PageSection

Section wrapper that optionally renders a SectionHeader.

<PageSection actions={<Button>Refresh</Button>} title="Recent activity">
  {content}
</PageSection>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | -------------------------------------------------- | | title | React.ReactNode | - | Section title; when absent, no header is rendered. | | description | React.ReactNode | - | Passed to the section header. | | actions | React.ReactNode | - | Passed to the section header. | | children | React.ReactNode | - | Section body. | | testID | string | - | Forwarded to the root Surface stack. |

Inherited props:

No inherited props. PageSectionProps is declared directly by ZORA.

SidebarLayout

Responsive shell with required sidebar, main content, and optional aside.

<SidebarLayout sidebar={navigation} aside={details}>
  {content}
</SidebarLayout>

ZORA props:

| Prop | Type | Default | Notes | | -------------- | ----------------- | ------- | ------------------------------------ | | sidebar | React.ReactNode | - | Required left column content. | | children | React.ReactNode | - | Main content. | | aside | React.ReactNode | - | Optional right column content. | | sidebarWidth | number | 280 | Desktop sidebar width. | | asideWidth | number | 280 | Desktop aside width. | | testID | string | - | Forwarded to the root Surface stack. |

Inherited props:

No inherited props. SidebarLayoutProps is declared directly by ZORA.

TopbarLayout

Top navigation shell with optional sidebar composition.

<TopbarLayout topbar={topbar} sidebar={sidebar}>
  {content}
</TopbarLayout>

ZORA props:

| Prop | Type | Default | Notes | | ---------- | ----------------- | ------- | ---------------------------------------------------------------------------- | | topbar | React.ReactNode | - | Required topbar content. | | children | React.ReactNode | - | Main content. | | sidebar | React.ReactNode | - | Optional sidebar; when present, content is rendered through SidebarLayout. | | testID | string | - | Forwarded to the root Surface stack. |

Inherited props:

No inherited props. TopbarLayoutProps is declared directly by ZORA.

SettingsLayout

Reusable settings shell with page header, sidebar, and content region.

<SettingsLayout actions={<Button>Save</Button>} sidebar={nav} title="Settings">
  {content}
</SettingsLayout>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------------------------------------------------- | | title | React.ReactNode | - | Optional page title; when absent, no page header is rendered. | | description | React.ReactNode | - | Header description. | | sidebar | React.ReactNode | - | Required settings navigation or context sidebar. | | children | React.ReactNode | - | Settings content. | | actions | React.ReactNode | - | Header action area. | | testID | string | - | Forwarded to Page. |

Inherited props:

No inherited props. SettingsLayoutProps is declared directly by ZORA.

AuthLayout

Centered authentication-style shell for sign-in, onboarding, and recovery screens.

<AuthLayout description="Sign in to continue" title="Welcome back">
  {form}
</AuthLayout>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------------------------- | | title | React.ReactNode | - | Card title. | | description | React.ReactNode | - | Card description. | | eyebrow | React.ReactNode | - | Card eyebrow. | | children | React.ReactNode | - | Form or auth content. | | footer | React.ReactNode | - | Card footer. | | testID | string | - | Forwarded to the root Surface center. |

Inherited props:

No inherited props. AuthLayoutProps is declared directly by ZORA.

Patterns

FormField

Form field wrapper with rich label composition, description, helper text, and Surface field state.

<FormField helperText="We only use this for sign-in." label="Email">
  <Input keyboardType="email-address" />
</FormField>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------------------------------ | | label | React.ReactNode | - | Required field label. | | description | React.ReactNode | - | Rendered under the label. | | helperText | React.ReactNode | - | Passed to Surface Field as helperText. |

Inherited props:

Picks these Surface FieldProps: children, disabled, errorText, invalid, readOnly, required, and testID.

Notice

Semantic notice surface with badge eyebrow, optional body, and actions.

<Notice actions={<Button>Review</Button>} title="Publish pipeline ready" tone="success" />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ----------- | ----------------------------------- | | title | React.ReactNode | - | Required notice title. | | description | React.ReactNode | - | Notice description. | | children | React.ReactNode | - | Optional body content. | | actions | React.ReactNode | - | Optional action area. | | tone | ZoraTone | 'primary' | Drives the badge eyebrow tone. | | testID | string | - | Forwarded to the underlying Card. |

Inherited props:

No inherited props. NoticeProps is declared directly by ZORA.

Panel

Named composition surface that currently forwards to Card.

<Panel description="Release details" title="Release Candidate">
  {content}
</Panel>

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ----------- | --------------------------------- | | title | React.ReactNode | - | Header title. | | description | React.ReactNode | - | Header description. | | eyebrow | React.ReactNode | - | Small muted text above the title. | | actions | React.ReactNode | - | Header action area. | | footer | React.ReactNode | - | Footer area below body content. | | children | React.ReactNode | - | Panel body. | | tone | ZoraCardTone | 'default' | Same tone behavior as Card. | | compact | boolean | false | Same compact behavior as Card. | | testID | string | - | Forwarded through Card. |

Inherited props:

No inherited props. PanelProps is declared directly by ZORA.

SectionHeader

Reusable section heading with optional eyebrow, description, and actions.

<SectionHeader actions={<Badge>Live</Badge>} title="Activity" />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------------------------ | | title | React.ReactNode | - | Required heading title. | | description | React.ReactNode | - | Supporting copy. | | eyebrow | React.ReactNode | - | Small muted text above the title. | | actions | React.ReactNode | - | Action area opposite the heading. | | testID | string | - | Forwarded to the root Surface stack. |

Inherited props:

No inherited props. SectionHeaderProps is declared directly by ZORA.

FilterBar

Composable row for search + chips + trailing actions.

<FilterBar leading={<SearchBar value={query} onValueChange={setQuery} />}>
  <ChipGroup value="all" onValueChange={setFilter} items={[{ value: 'all', label: 'All' }]} />
</FilterBar>

ZORA props:

| Prop | Type | Default | Notes | | ---------- | ----------------- | ------- | ------------------------------ | | leading | React.ReactNode | - | Optional leading content. | | children | React.ReactNode | - | Main filter controls. | | trailing | React.ReactNode | - | Optional trailing content. | | wrap | boolean | true | Wraps content on small widths. | | testID | string | - | Test id. |

Inherited props:

No inherited props. FilterBarProps is declared directly by ZORA.

List

List wrapper that renders ListRow items with dividers or spacing, or accepts custom children.

<List
  items={[
    { title: 'Account', description: 'Profile and security', onPress: () => undefined },
    { title: 'Notifications', trailing: <Badge>On</Badge> },
  ]}
/>

ZORA props:

| Prop | Type | Default | Notes | | ------------ | ----------------- | ----------- | ----------------------------------------------------- | | items | ListRowProps[] | - | Items mode. Mutually exclusive with children. | | children | React.ReactNode | - | Custom children mode. | | rowVariant | ListRowVariant | 'divider' | Default variant applied when an item omits variant. | | compact | boolean | false | Default compact value applied to rows. | | testID | string | - | Test id. |

Behavior notes:

  • In items mode, ZORA inserts Divider between variant="divider" rows and Spacer between variant="card" rows.

Inherited props:

No inherited props. ListProps is declared directly by ZORA.

ListRow

Single list row with leading/trailing slots, optional metadata, and a structured action model.

<ListRow title="Profile" description="Update your details" onPress={() => undefined} />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ----------- | ---------------------------------------------------------------- | | title | React.ReactNode | - | Required row title. | | description | React.ReactNode | - | Supporting description. | | meta | React.ReactNode | - | Small secondary metadata below description. | | leading | React.ReactNode | - | Leading slot (icon/avatar/media). | | trailing | React.ReactNode | - | Trailing slot (badges/meta). | | variant | ListRowVariant | 'divider' | divider or card. | | compact | boolean | false | Uses tighter padding and typography spacing. | | selected | boolean | false | Selected styling state. | | disabled | boolean | false | Disables interaction and mutes presentation. | | onPress | () => void | - | Makes the row pressable. Mutually exclusive with action. | | action | React.ReactNode | - | Trailing interactive content. Mutually exclusive with onPress. | | testID | string | - | Test id. |

Inherited props:

No inherited props. ListRowProps is declared directly by ZORA.

ListSection

Section wrapper for list content with an optional SectionHeader.

<ListSection title="Settings" items={[{ title: 'Account' }]} />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ----------- | ----------------------------------------------------- | | title | React.ReactNode | - | Optional section title (renders SectionHeader). | | description | React.ReactNode | - | Optional section description. | | eyebrow | React.ReactNode | - | Optional eyebrow above the title. | | actions | React.ReactNode | - | Optional trailing header actions. | | items | ListRowProps[] | - | Items mode list content. | | children | React.ReactNode | - | Custom children mode list content. | | rowVariant | ListRowVariant | 'divider' | Default variant applied when an item omits variant. | | compact | boolean | false | Default compact value applied to rows. | | testID | string | - | Test id. |

Inherited props:

No inherited props. ListSectionProps is declared directly by ZORA.

Timeline

Vertical-only timeline pattern for onboarding steps, order tracking, and activity sequences.

<Timeline
  items={[
    { id: '1', title: 'Order placed', meta: '09:15', status: 'success' },
    { id: '2', title: 'In transit', meta: '11:42', status: 'primary' },
    { id: '3', title: 'Requires attention', meta: 'Today', status: 'warning' },
  ]}
/>

ZORA props:

| Prop | Type | Default | Notes | | --------- | ---------------- | ------- | --------------------------------------------- | | items | TimelineItem[] | - | Ordered timeline items (vertical-only in v1). | | compact | boolean | false | Uses tighter spacing between items. | | testID | string | - | Test id. |

Item shape:

type TimelineItem = {
  id: string;
  title: React.ReactNode;
  description?: React.ReactNode;
  meta?: React.ReactNode;
  status?: ZoraTone;
  icon?: ButtonIconSpec;
};

Inherited props:

No inherited props. TimelineProps is declared directly by ZORA.

SettingsRow

Compact settings row with optional metadata, control, and press handling.

<SettingsRow control={<Switch value={enabled} />} title="Notifications" />

ZORA props:

| Prop | Type | Default | Notes | | ------------- | ----------------- | ------- | ------------------------------------------- | | title | React.ReactNode | - | Required row title. | | description | React.ReactNode | - | Row description. | | meta | React.ReactNode | - | Small muted metadata below the row content. | | control | React.ReactNode | - | Trailing control or action content. | | onPress | () => void | - | Makes the underlying card pressable. | | disabled | boolean | false | Forwarded to the underlying card. | | testID | string | - | Forwarded to the underlying card. |

Inherited props:

No inherited props. SettingsRowProps is declared directly by ZORA.

EmptyState

No-data surface with title, optional supporting text, actions, and footer.

<EmptyState
  primaryAction={{ label: 'Create project', onPress: createProject }}
  title="Nothing here yet"
/>

ZORA props:

| Prop | Type | Default | Notes | | ----------------- | ------------------ | ------- | ------------------------------------------------------------------------------------------------------- | | title | React.ReactNode | - | Required empty-state title. | | description | React.ReactNode | - | Supporting copy. | | eyebrow | React.ReactNode | - | Card eyebrow. | | primaryAction | EmptyStateAction | - | Primary action button. | | secondaryAction | EmptyStateAction | - | Secondary action button; defaults to tone="neutral" and emphasis="soft" when omitted on the action. | | footer | React.ReactNode | - | Footer content below actions. | | testID | string | - | Forwarded to the underlying card. |

EmptyStateAction:

| Prop | Type | Default | Notes | | ---------- | ----------------- | ------- | ---------------- | | label | React.ReactNode | - | Button label. | | onPress | () => void | - | Button handler. | | tone | ZoraTone | - | Button tone. | | emphasis | ZoraEmphasis | - | Button emphasis. |

Inherited props:

No inherited props. EmptyStateProps and EmptyStateAction are declared directly by ZORA.

ConfirmDialog

Narrow confirmation modal for destructive or high-signal decisions.

<ConfirmDialog
  confirmLabel="Archive"
  confirmTone="danger"
  onCancel={close}
  onConfirm={archive}
  title="Archive project?"
  visible={visible}
/>

ZORA props:

| Prop | Type | Default | Notes | | ----------------- | ----------------- | ----------- | ------------------------------------------ | | visible | boolean | - | Required modal visibility. | | title | React.ReactNode | - | Required dialog title. | | description | React.ReactNode | - | D