SSkilltecabyclaudinhocode
Enviar skill
← Voltar para o catálogo

react-zen

Design e Frontend

Zen é uma biblioteca de componentes React orientada a props, construída para velocidade. Crie interfaces polidas sem escrever HTML, CSS ou pensar em classes Tailwind.

52estrelas
Ver no GitHub ↗Autor: umami-softwareLicença: MIT

SKILL.md - Using @umami/react-zen

This guide covers how to use the zen component library in your React applications.

Installation

pnpm add @umami/react-zen

Import the stylesheet in your app entry point:

import '@umami/react-zen/styles.css';

Setup

Wrap your app with ZenProvider:

import { ZenProvider } from '@umami/react-zen';

function App() {
  return (
    <ZenProvider theme="light" palette="neutral">
      {children}
    </ZenProvider>
  );
}

Provider Options

PropValuesDescription
theme'light' | 'dark'Color theme
colorScheme'light' | 'dark' | 'system'System preference support
palette'neutral' | 'slate' | 'gray' | 'zinc' | 'stone'Color palette
toast{ duration: number }Toast defaults

Components

Layout

Box

Universal container with styling props:

<Box padding="4" margin="2" backgroundColor="surface-raised" borderRadius="lg">
  Content
</Box>

Flexbox, Row, Column

Flex layouts with gap, alignment, and justification:

<Row gap="4" justifyContent="space-between" alignItems="center">
  <Text>Left</Text>
  <Text>Right</Text>
</Row>

<Column gap="2">
  <Text>First</Text>
  <Text>Second</Text>
</Column>

<Flexbox direction="row" wrap="wrap" gap="2">
  {items.map(item => <Item key={item.id} />)}
</Flexbox>

Grid

CSS Grid layout:

<Grid columns="3" gap="4">
  <Box>1</Box>
  <Box>2</Box>
  <Box>3</Box>
</Grid>

Responsive Props

All layout props support responsive values:

<Box
  padding={{ base: '2', md: '4', lg: '6' }}
  display={{ base: 'none', md: 'block' }}
  width={{ base: 'full', md: '1/2', lg: '1/3' }}
>
  Responsive content
</Box>

Breakpoints: base, sm, md, lg, xl, 2xl

Buttons

// Variants
<Button variant="default">Default</Button>
<Button variant="primary">Primary</Button>
<Button variant="outline">Outline</Button>
<Button variant="quiet">Quiet</Button>
<Button variant="danger">Danger</Button>

// Sizes
<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="xl">Extra Large</Button>

// With loading state
<LoadingButton isLoading={loading} variant="primary">
  Submit
</LoadingButton>

// Copy to clipboard
<CopyButton value="text to copy" />

// Theme toggle
<ThemeButton />

Typography

// Headings
<Heading size="6xl">Hero</Heading>
<Heading size="4xl">Page Title</Heading>
<Heading size="2xl">Section</Heading>
<Heading size="lg">Subsection</Heading>

// Text
<Text>Default text</Text>
<Text size="sm" color="muted">Small muted text</Text>
<Text weight="bold" color="primary">Bold primary</Text>

// Code
<Code>inline code</Code>
<CodeBlock language="typescript">{code}</CodeBlock>

Form System

The form system is built on react-hook-form:

import { Form, FormField, FormSubmitButton, TextField } from '@umami/react-zen';

function LoginForm() {
  const handleSubmit = (data) => {
    console.log(data);
  };

  return (
    <Form onSubmit={handleSubmit} defaultValues={{ email: '', password: '' }}>
      <FormField
        name="email"
        label="Email"
        description="We'll never share your email"
        rules={{ required: 'Email is required' }}
      >
        <TextField type="email" />
      </FormField>

      <FormField
        name="password"
        label="Password"
        rules={{ required: 'Password is required', minLength: 8 }}
      >
        <PasswordField />
      </FormField>

      <FormButtons>
        <FormResetButton>Reset</FormResetButton>
        <FormSubmitButton variant="primary">Login</FormSubmitButton>
      </FormButtons>
    </Form>
  );
}

Form Fields

// Text input
<TextField placeholder="Enter text" />

// Password with visibility toggle
<PasswordField />

// Search with debouncing
<SearchField onSearch={handleSearch} delay={300} />

// Checkbox
<Checkbox>Remember me</Checkbox>

// Radio group
<RadioGroup label="Size">
  <Radio value="sm">Small</Radio>
  <Radio value="md">Medium</Radio>
  <Radio value="lg">Large</Radio>
</RadioGroup>

// Switch
<Switch>Enable notifications</Switch>

// Toggle buttons
<ToggleGroup>
  <Toggle id="bold">Bold</Toggle>
  <Toggle id="italic">Italic</Toggle>
</ToggleGroup>

Dynamic Field Arrays

<FormFieldArray name="items" label="Items">
  {({ fields, append, remove }) => (
    <>
      {fields.map((field, index) => (
        <Row key={field.id} gap="2">
          <FormField name={`items.${index}.name`}>
            <TextField />
          </FormField>
          <Button onClick={() => remove(index)}>Remove</Button>
        </Row>
      ))}
      <Button onClick={() => append({ name: '' })}>Add Item</Button>
    </>
  )}
</FormFieldArray>

Select & ComboBox

// Basic select
<Select label="Country">
  <ListItem id="us">United States</ListItem>
  <ListItem id="uk">United Kingdom</ListItem>
  <ListItem id="ca">Canada</ListItem>
</Select>

// Searchable select
<Select label="Country" allowSearch onSearch={handleSearch}>
  <ListItem id="us">United States</ListItem>
  <ListItem id="uk">United Kingdom</ListItem>
</Select>

// With sections
<Select label="Location">
  <ListSection title="North America">
    <ListItem id="us">United States</ListItem>
    <ListItem id="ca">Canada</ListItem>
  </ListSection>
  <ListSection title="Europe">
    <ListItem id="uk">United Kingdom</ListItem>
    <ListItem id="de">Germany</ListItem>
  </ListSection>
</Select>

// ComboBox (allows custom input)
<ComboBox label="Fruit" allowsCustomValue>
  <ListItem id="apple">Apple</ListItem>
  <ListItem id="banana">Banana</ListItem>
</ComboBox>

List

<List selectionMode="single" onSelectionChange={handleSelect}>
  <ListItem id="1">Option 1</ListItem>
  <ListItem id="2">Option 2</ListItem>
  <ListSeparator />
  <ListItem id="3">Option 3</ListItem>
</List>

Dialogs & Modals

// Confirmation dialog
<ConfirmationDialog
  title="Delete item?"
  message="This action cannot be undone."
  confirmLabel="Delete"
  cancelLabel="Cancel"
  onConfirm={handleDelete}
>
  <Button variant="danger">Delete</Button>
</ConfirmationDialog>

// Alert dialog
<AlertDialog title="Error" message="Something went wrong">
  <Button>Show Error</Button>
</AlertDialog>

// Custom dialog
<DialogTrigger>
  <Button>Open</Button>
  <Modal position="center">
    <Dialog>
      <Heading slot="title">Dialog Title</Heading>
      <Text>Dialog content</Text>
    </Dialog>
  </Modal>
</DialogTrigger>

Modal positions: center, left, right, top, bottom, fullscreen

Feedback Components

// Alert banner
<AlertBanner variant="info">Informational message</AlertBanner>
<AlertBanner variant="success">Success message</AlertBanner>
<AlertBanner variant="warning">Warning message</AlertBanner>
<AlertBanner variant="error">Error message</AlertBanner>

// Loading indicators
<Loading />
<Spinner size="lg" />
<ProgressBar value={75} />
<ProgressCircle value={50} />

// Status light
<StatusLight variant="success">Active</StatusLight>
<StatusLight variant="error">Failed</StatusLight>

Toast Notifications

import { useToast } from '@umami/react-zen';

function MyComponent() {
  const { toast } = useToast();

  const showToast = () => {
    toast('Operation successful', {
      variant: 'success',
      duration: 3000,
    });
  };

  const showToastWithActions = () => {
    toast('File deleted', {
      title: 'Deleted',
      variant: 'info',
      actions: ['Undo', 'Dismiss'],
      onClose: (action) => {
        if (action === 'Undo') {
          // Handle undo
        }
      },
    });
  };

  return <Button onClick={showToast}>Show Toast</Button>;
}

Tooltips & Popovers

// Tooltip
<Tooltip content="Helpful information">
  <Button>Hover me</Button>
</Tool

Como adicionar

/plugin marketplace add umami-software/react-zen

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Comentários · Nenhum comentário

Entre para comentar. Entrar

  • Ainda não há comentários. Seja o primeiro.