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-composite-components/

name:
building-composite-components
description:
Implement frontend designs from Figma using Chakra UI v3 and Storybook. Use when implementing UI from Figma files, when user mentions "implement design", "generate code", "implement component", "build Figma design", provides Figma URLs, or asks to build components matching Figma specs. Requires Figma MCP server connection.
metadata:
{"mcp-server":"figma, figma-desktop, chrome-devtools"}

Building Composite Components

Translate Figma designs into Chakra UI v3 components with pixel-perfect fidelity. Validate with Storybook, Playwright CLI, and Chrome DevTools MCP. Every color, spacing value, font size, and border radius must come from design tokens, not hardcoded values.

Step 1: Gather Design Context from Figma

  1. Parse the Figma URL to get fileKey and nodeId (format: https://figma.com/design/:fileKey/:fileName?node-id=1-2). With figma-desktop MCP, only nodeId is needed.
  2. Fetch design data: get_design_context(fileKey, nodeId) — returns layout, typography, colors, spacing, and component structure. If truncated, use get_metadata first, then fetch child nodes individually.
  3. Capture a screenshot: get_screenshot(fileKey, nodeId) — this is the visual source of truth throughout implementation.
  4. Download assets returned by the Figma MCP server. Use localhost asset URLs directly; do not substitute icon packages or placeholders.

Extract every specific value from the design data: exact colors, font sizes, font weights, line heights, letter spacing, padding, margin, gap, border radius, and opacity. These values must map to Chakra tokens in your implementation.

Step 2: Implement with Chakra UI v3

The Figma MCP output is typically React + Tailwind — treat it as a design spec, not final code.

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 Tailwind utility classes into Chakra style props. Never mix Tailwind and Chakra. Common mappings:

TailwindChakra v3
className="flex"<Flex> / <HStack> / <VStack>
className="space-y-4"<Stack gap="4">
className="text-sm text-gray-500"<Text fontSize="sm" color="fg.muted">
Padding/margin classesStyle props: p, px, py, m, mx, my

See 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. See TOKENS.md for the complete token reference covering colors, spacing, typography, and border radius.

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 Figma 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. Use fontFamily="mono" for code — never specify font names directly.
  • Border radius: Use Chakra tokens including the project's custom l1 (4px) and l2 (6px).
  • Theme: Built with createSystem(defaultConfig, customConfig) via ChakraProvider. Dark mode by default.

Reuse Existing Components

Before creating anything new:

  • Check src/components/ui/ for shared primitives (Provider, ColorMode, Prose, Toaster).
  • Check src/components/form/ for form components.
  • Check src/components/ for feature-level components that may already exist.
  • Extend existing components rather than creating new ones.

Step 3: Create Storybook Stories

All new or modified components require a .stories.tsx file, co-located next to the component. Use satisfies Meta<typeof Component> for type safety and the Components/ title prefix matching the folder structure.

Story Template

import { Box } from '@chakra-ui/react';
import type { Meta, StoryObj } from '@storybook/react-vite';

import { MyComponent } from './MyComponent';

const meta = {
  title: 'Components/Category/MyComponent',
  component: MyComponent,
  parameters: {
    layout: 'centered',
    backgrounds: { default: 'dark' },
  },
  decorators: [
    (Story) => (
      <Box padding="40px">
        <Story />
      </Box>
    ),
  ],
} satisfies Meta<typeof MyComponent>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    // representative default props
  },
};

export const Loading: Story = {
  args: {
    // loading state props
  },
};

export const Empty: Story = {
  args: {
    // empty/null data props
  },
};

Story Requirements

  • Default story with representative props.
  • Visual variants — one per meaningful state: Loading, Error, Empty, WithData, Disabled, etc.
  • Edge cases — long text, missing/null data, boundary values.
  • Interactive states — hover, active, disabled when applicable.
  • Use args for prop variations. Use render only when custom JSX wrapping is needed.
  • Use Chakra Box in decorators — do NOT use raw HTML elements.
  • Set parameters.backgrounds to { default: 'dark' }.

Running Storybook

  • Start: bun run storybook -- -p 6XXX from apps/frontend, where 6XXX is a random port in the 6000–6999 range (e.g., 6042). Use a random port because multiple agents may be running Storybook in parallel.
  • Build: bun run build-storybook

Step 4: Validate with Browser Tools

Playwright CLI

Use @playwright/cli for browser-based verification. It saves snapshots and screenshots to disk rather than streaming into context.

Setup: npx @playwright/cli@latest if not already available.

Key commands:

  • playwright-cli snapshot <url> — accessibility snapshot of the page.
  • playwright-cli screenshot <url> — screenshot saved to disk.
  • playwright-cli click <selector> — click an element to test interactions.

Workflow:

  1. Start Storybook on a random port if not already running.
  2. playwright-cli snapshot on specific story URLs to verify rendered structure.
  3. playwright-cli screenshot to capture visual output and compare against the Figma screenshot.
  4. playwright-cli click and other interaction commands to test interactive states.

Chrome DevTools MCP

Use Chrome DevTools MCP to inspect live rendered output and verify design token accuracy.

Capabilities:

  • Inspect computed styles — verify rendered colors, font sizes, spacing, and border radii against the Figma spec.
  • Check CSS custom properties — confirm Chakra tokens (e.g., var(--chakra-colors-fg-muted)) are used, not hardcoded values.
  • Debug layout — inspect box models to verify padding, margin, and gap.
  • Verify responsive behavior — device emulation for different viewport sizes.
  • Check accessibility — inspect the accessibility tree and ARIA attributes.

Workflow:

  1. Open the component in Storybook or the running app in Chrome.
  2. Use getStyles to inspect computed styles — verify against Figma design data.
  3. Use evaluate to read CSS custom property values and confirm tokens are used.
  4. Fix any hardcoded values found.

Step 5: Final Validation Checklist

Design Token Compliance:

  • All colors use Chakra semantic tokens — no hex codes in component files
  • All spacing uses Chakra scale tokens — no raw pixel values in style props
  • All typography uses Chakra font size/weight/line-height tokens
  • All border radii use Chakra radius tokens
  • New tokens added to Provider.tsx theme if needed (not hardcoded)

Visual Fidelity:

  • Layout matches Figma (spacing, alignment, sizing)
  • Typography matches Figma (font, size, weight, line height)
  • Colors match Figma exactly
  • Interactive states work as designed (hover, active, disabled)
  • Responsive behavior follows Figma constraints
  • Assets render correctly

Testing:

  • Storybook stories exist for all meaningful variants
  • Stories render correctly in Storybook
  • Playwright CLI verification confirms component structure
  • Chrome DevTools confirms tokens are used (no hardcoded values in computed styles)
  • Accessibility standards met (WCAG)

Component Organization

  • Reusable components shared across multiple routes live in src/components/ with individual PascalCase folders: src/components/MyComponent/MyComponent.tsx.
  • Route-specific components used by only one route live in a -components/ directory next to the route file that uses them, inside src/routes/. For example, a component only used by src/routes/$workspace/$tile/index.tsx would go in src/routes/$workspace/$tile/-components/TileHeader.tsx.
  • Co-locate stories with the component in either location: MyComponent.stories.tsx next to MyComponent.tsx.
  • Use .tsx for files with React code, .ts for everything else.

Common Issues

  • Storybook stories don't render: The preview already wraps with the Chakra Provider and a StorybookRouter (TanStack Router context via createMemoryHistory). This means components that use useNavigate, Link, or other TanStack Router hooks will work in stories without additional setup. @tanstack/react-start is also mocked — components that use ClientOnly, createServerFn, createMiddleware, createIsomorphicFn, or useServerFn will work in stories without extra setup. Use Box in decorators for layout. Check component dependencies are available.
  • Design doesn't match: Use Chrome DevTools MCP to inspect computed styles. Common culprits: wrong token mapped, missing gap/padding, incorrect font weight.

Additional Resources

  • Chakra UI v3 Documentation
  • Storybook Documentation
  • Playwright CLI
  • Chrome DevTools MCP
  • Figma MCP Server Documentation

skills

building-composite-components

README.md

tile.json