CtrlK
BlogDocsLog inGet started
Tessl Logo

tessleng/ui

Implement frontend designs from figma using Chakra UI v3 and Storybook

92

1.64x
Quality

92%

Does it follow best practices?

Impact

92%

1.64x

Average score across 6 eval scenarios

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

SKILL.mdskills/building-low-level-components/

name:
building-low-level-components
description:
Build generic, reusable low-level UI components that extend or complement Chakra UI v3, including form field components. Use when building primitives not tied to a specific page — custom inputs, display elements, layout helpers, form fields, or interactive widgets that Chakra doesn't provide out of the box. Use when user mentions "build a component", "create a reusable component", "extend Chakra", "low-level component", "UI primitive", "form component", "form field", "custom input", or asks to build something generic that could be used anywhere. Requires Figma MCP server connection if building from a design.
metadata:
{"mcp-server":"figma, figma-desktop, chrome-devtools"}

Building Low-Level Components

Build generic, reusable UI components that extend Chakra UI v3 or fill gaps where Chakra has no built-in solution. These are Tier 1 components — they have no page-specific logic, no business logic, and can be dropped into any page. For form field components, see FORM_FIELDS.md.

Step 1: Check What Exists

Before building anything:

  1. Check src/components/ui/ for existing low-level primitives (Provider, ColorMode, Prose, Toaster).
  2. Check src/components/ for shared components that may already solve the problem.
  3. Check src/components/form/ for existing form field components (TextField, TextareaField, CheckboxField, ComboboxField, etc.).
  4. Check Chakra UI docs — Chakra may have a component or recipe you can use directly.
  5. Search the codebase for similar patterns — another component may already do 80% of what you need.

If something close exists, extend it with new props or variants rather than building from scratch.

Step 2: Design the Component API

Before writing code, define:

  • Name — PascalCase, descriptive of what it is, not how it looks. StatusBadge not GreenPill.
  • Props — keep the API minimal. Only expose what's needed. Accept Chakra style props via HTMLChakraProps or BoxProps for flexibility.
  • Variants — if the component has visual variants, define them upfront (e.g., variant="outline" | "solid").
  • Composition — decide if it should be a single component or a compound component (e.g., Card + Card.Header + Card.Body).

Project-Specific API Conventions

  • Forward Chakra props — consumers must be able to pass standard style props (p, bg, color, etc.) via ...rest spread.
  • Use as or asChild patterns — allow consumers to change the rendered element when appropriate.

Step 3: Implement the Component

File Structure

Create the component in src/components/ in its own PascalCase folder:

src/components/MyComponent/
├── MyComponent.tsx
└── MyComponent.stories.tsx

Import Rules

  • Import ALL Chakra components from @chakra-ui/react.
  • Use the ~/* alias for project-internal imports (e.g., import { MyComponent } from '~/components/MyComponent').
  • DO NOT use file extensions in local imports.

DO NOT Use Tailwind

Translate all styles into Chakra style props. Never mix Tailwind and Chakra. See ../building-composite-components/TOKENS.md for the full Tailwind-to-Chakra mapping and all available tokens.

Design Token Fidelity

Every visual property must use design tokens — never hardcode hex codes, pixel values, or font names.

Key rules:

  • Colors: Use semantic tokens (fg, fg.muted, bg.muted, border.muted, etc.). When a Figma color has no matching token, add a new semantic token to src/components/ui/Provider.tsx.
  • Spacing: Map pixel values to Chakra's spacing scale ("1" = 4px, "2" = 8px, "4" = 16px, etc.).
  • Typography: Use Chakra's fontSize, fontWeight, and lineHeight props with named scale values.
  • Border radius: Use Chakra tokens including the project's custom l1 (4px) and l2 (6px).

Implementation Pattern

import { Box, type BoxProps } from '@chakra-ui/react';

export interface MyComponentProps extends BoxProps {
  /** Brief description of what this prop controls */
  variant?: 'default' | 'outline';
}

export function MyComponent({
  variant = 'default',
  children,
  ...rest
}: MyComponentProps) {
  return (
    <Box
      borderRadius="l2"
      bg={variant === 'outline' ? 'transparent' : 'bg.muted'}
      borderWidth={variant === 'outline' ? '1px' : undefined}
      borderColor="border.muted"
      {...rest}
    >
      {children}
    </Box>
  );
}

Step 4: Create Storybook Stories

Every low-level component must have a .stories.tsx file co-located next to it. Stories are the primary way to verify and document these components.

See STORY_TEMPLATES.md for full story templates (UI components and form fields) and the list of required story variants.

Running Storybook

  • Start: bun run storybook -- -p 6XXX from apps/frontend, where 6XXX is a random port in the 6000–6999 range.
  • Build: bun run build-storybook

Step 5: Validate

Playwright CLI

Use playwright-cli for browser-based verification:

  1. Start Storybook on a random port if not already running.
  2. playwright-cli snapshot <storybook-url> — verify rendered structure.
  3. playwright-cli screenshot <storybook-url> — capture visual output. If building from a Figma design, compare against the Figma screenshot.

Chrome DevTools MCP

Use Chrome DevTools MCP to inspect live rendered output:

  1. Use getStyles to verify computed styles use Chakra tokens, not hardcoded values.
  2. Use evaluate to read CSS custom property values.
  3. Fix any hardcoded values found.

Step 6: Final Checklist

API Quality:

  • Props are minimal — no unnecessary configuration surface
  • Chakra style props are forwarded via ...rest
  • Component name describes what it is, not how it looks
  • TypeScript types are exported for consumers

Design Token Compliance:

  • All colors use Chakra semantic tokens — no hex codes
  • All spacing uses Chakra scale tokens — no raw pixel values
  • All typography uses Chakra font tokens
  • All border radii use Chakra radius tokens

Stories:

  • Stories file exists and is co-located with the component
  • Default story renders correctly
  • All variants and sizes have stories
  • Edge cases are covered (long text, empty, disabled)
  • parameters.backgrounds set to { default: 'dark' }

Form Fields (if applicable):

  • Uses useFieldContext and FormFieldWrapper
  • Wired to field.handleChange and field.handleBlur
  • Registered in ~/lib/form/form-hooks
  • Stories wrap component in a Form context
  • Stories use Components/Form/ title prefix
  • Required, disabled, error, and helper states have stories

Visual Verification:

  • Component renders correctly in Storybook
  • Playwright screenshot matches expectations
  • If built from Figma: visual output matches design

skills

building-low-level-components

README.md

tile.json