FR

frontend-style-guide

Apply the Lightdash frontend style guide for React and Mantine migration tasks.

Install

mkdir -p .claude/skills/frontend-style-guide && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/6557" && unzip -o skill.zip -d .claude/skills/frontend-style-guide && rm skill.zip

Installs to .claude/skills/frontend-style-guide

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Apply the Lightdash frontend style guide when working on React components, migrating Mantine v6 to v8, or styling frontend code. Use when editing TSX files, fixing styling issues, or when user mentions Mantine, styling, or CSS modules.
235 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • →Migrates components from Mantine v6 to v8
  • →Enforces CSS module usage
  • →Validates component prop counts
  • →Applies themed styling variables
  • →Enforces style guide component checklist

How it works

Applies a transformation rule-set based on the project's style guide and component migration requirements.

Inputs & outputs

You give it
React component file path
You get back
Refactored component conforming to Lightdash standards

When to use frontend-style-guide

  • →Migrate Mantine component
  • →Style React component
  • →Enforce CSS module standards
  • →Update theme values

About this skill

Lightdash Frontend Style Guide

Apply these rules when working on any frontend component in packages/frontend/.

Mantine 8

The app runs on Mantine 8 (@mantine/core), with the theme in src/theme/.

Design principles

The theme is neutral and quiet, in the spirit of shadcn, Radix and Kumo: one ink accent, flat surfaces, soft borders, a tight type scale. Most of what "looks right" comes from using the defaults. Check each rule before you add a colour, a shadow or a size.

  1. One accent, and it is ink. The primary action on a surface is the theme primary (near-black in light, near-white in dark). Never colour a Button or ActionIcon blue, dark, indigo or ldDark for emphasis. Colour on a control means state: red destructive, yellow warning, teal "copied", orange favourite, green only for the existing verify/merge actions. Indigo belongs to AI surfaces. Links are the only blue text.
  2. Hierarchy comes from variant, not colour. filled is the one primary action per card, header or modal footer. default (bordered) is secondary. light is a tertiary or toggle-like action ("Add filter"). subtle is for icon buttons and inline actions; it is the ActionIcon default. If a surface has two filled buttons, one of them is wrong.
  3. Surfaces are flat. Paper and Card are bordered with no shadow and a 12px radius by default; shadows only on floating layers (Menu and Popover md, Modal lg). Do not pass withBorder, shadow or radius to restate that. Empty or placeholder sections use <Paper variant="dotted">.
  4. Neutrals are tokens, never hand-picked pairs. --mantine-color-body (surface), --ld-color-page (canvas), default-border, default-hover, text, dimmed, placeholder. ldGray.N already resolves per scheme (0 canvas, 1 muted fill, 2 border, 3 strong border, 5 tertiary text, 6 = dimmed, 7 label, 9 text), so light-dark(ldGray-x, ldDark-y) and @mixin dark blocks for neutrals are always a smell. Secondary text is c="dimmed".
  5. Type is a scale, not a slider. Body is 14/20. Headings are 600 on Title orders 1 to 6 (28 to 14px); labels and table headers are 500; everything else 400. Use fz="xs|sm|md", never fz={13}. Card and section titles are Title order={5}; page tops use PageHeader.
  6. Space on the token grid. Card padding md, group gaps xs/sm, section gaps lg, page gutters lg/xl. No pixel margins; if a layout needs margin-top: 20px it is mt="lg".
  7. Icons are quiet. MantineIcon at stroke 1.5, 16px next to text and 14px in xs controls, coloured dimmed when they are secondary. Every icon-only button has an aria-label and a Tooltip.
  8. Inputs are calm. Default variant, soft border, focus is a darker border with no ring. size="xs" controls carry compact secondary labels automatically. Selects mark the selected option with a check; filter value pickers are the standard combobox, not a custom list.
  9. Motion is functional. Dropdowns pop from their anchor and modals fade, both from the theme. Nothing else animates unless it shows progress.
  10. Dark mode is designed, not derived. Check both schemes before you finish. Never read useMantineColorScheme to pick a colour; use a token. Editors take useEditorTheme(); only JS consumers with no CSS (ECharts, Leaflet) read useComputedColorScheme.
  11. States are shared components. EmptyStateLoader for loading, InlineErrorState for a failed section, SuboptimalState for a failed page, <Paper variant="dotted"> for "nothing here".
  12. Before writing CSS, look for the thing that already exists: a variant, a token, an ld-* utility class, or a shared control (CopyActionIcon, FavoriteActionIcon, ConfirmDeleteButton, TruncatedText, FilterFacet, NumberInput, MantineModal).

Self-review before you hand a screen over: open it in light and dark; count filled buttons per surface (max one); look for blue that is not a link; look for a shadow on a card; look for a font size or grey that is not a token; look for an icon button without a tooltip. The Explorer page is the reference surface when in doubt.

Component Checklist

When creating/updating components:

  • Use @mantine/core imports
  • No style or styles props
  • Check Mantine docs/types for available component props
  • Use inline-style component props for styling when available (and follow <=3 props rule)
  • Use CSS modules when component props aren't available or when more than 3 inline-style props are needed
  • No Lightdash branding or docs links in embeds: gate them with useIsEmbedded() (see "Embeds are white-label" in packages/frontend/CLAUDE.md)
  • Theme values ('md', 'lg', 'xl', or 'ldGray.1', 'ldGray.2', 'ldDark.1', 'ldDark.2', etc) instead of magic numbers
  • When using mantine colors in css modules, always use the theme awared variables:
    • --mantine-color-${color}-text: for text on filled background
    • --mantine-color-${color}-filled: for filled background (strong color)
    • --mantine-color-${color}-filled-hover: for filled background on hover
    • --mantine-color-${color}-light: for light background
    • --mantine-color-${color}-light-hover: for light background on hover (light color)
    • --mantine-color-${color}-light-color: for text on light background
    • --mantine-color-${color}-outline: for outlines
    • --mantine-color-${color}-outline-hover: for outlines on hover

Styling Best Practices

Core Principle: Theme First

The goal is to use theme defaults whenever possible. Style overrides should be the exception, not the rule.

Styling Hierarchy

  1. Best: No custom styles (use theme defaults and variants)
  2. Theme extension: For repeated patterns, add a variant or rule in src/theme/components/<Component>.module.css (registered in src/theme/components/index.ts)
  3. Component props: Simple overrides (1-3 props like mt="xl" w={240})
  4. CSS modules: Complex styling, more than 3 props, or a single rule Mantine has no prop for (align-self, overflow, cursor, white-space) as a role-named class in the file's module. flex-shrink/flex-grow are the flex style prop. No global utility classes.

NEVER Use

  • styles prop (always use CSS modules instead)
  • style prop (inline styles)

Theme Extensions (For Repeated Patterns)

If you find yourself applying the same style override multiple times, put it in the theme. Each component has a CSS module in src/theme/components/ and an entry in src/theme/components/index.ts:

/* src/theme/components/Badge.module.css */
.root[data-variant='light'] {
    text-transform: none;
    font-weight: 500;
}
// src/theme/components/index.ts
Badge: Badge.extend({
    defaultProps: { variant: 'light', color: 'gray' },
    classNames: badgeClasses,
}),

Reach for the vars callback only when Mantine writes the value inline (button and badge colours, NavLink fill, input font size), because CSS cannot override an inline custom property.

Context-Specific Overrides

Inline-style Component Props (1-3 simple props)

// ✅ Good
<Button mt="xl" w={240} c="blue.6">Submit</Button>

// ❌ Bad - Too many props, use CSS modules instead
<Button mt={20} mb={20} ml={10} mr={10} w={240} c="blue.6" bg="white">Submit</Button>

Common inline-style props:

  • Layout: mt, mb, ml, mr, m, p, pt, pb, pl, pr
  • Sizing: w, h, maw, mah, miw, mih
  • Colors: c (color), bg (background)
  • Font: ff, fs, fw
  • Text: ta, lh

CSS Modules (complex styles or >3 props)

Create a .module.css file in the same folder as the component:

/* Component.module.css */
.customCard {
    transition: transform 0.2s ease;
    cursor: pointer;
}

.customCard:hover {
    transform: translateY(-2px);
    box-shadow: var(--mantine-shadow-lg);
}
import styles from './Component.module.css';

<Card className={styles.customCard}>{/* content */}</Card>;

Do NOT include .css.d.ts files - Vite handles this automatically.

Color Guidelines

Prefer default component colors. Buttons, ActionIcons and Badges get the right neutral or ink from the theme; a color prop on a control should only ever name a state (see Design principles).

// ❌ Bad - restates the theme, and is a near-black button in dark mode
<Button color="dark">Apply</Button>
<ActionIcon color="ldGray.6" variant="subtle" />

// ✅ Good - the theme already renders these
<Button>Apply</Button>
<ActionIcon />

// ❌ Bad - hand-picked grey
<Text c="ldGray.6">Secondary text</Text>

// ✅ Good - semantic token
<Text c="dimmed">Secondary text</Text>

Neutral tokens

TokenPurpose
--mantine-color-bodySurface (cards, inputs, menus)
--ld-color-pagePage canvas behind surfaces
--mantine-color-default-border / default-hoverBorders and hover fills of neutral controls
--mantine-color-text / dimmed / placeholderPrimary, secondary and tertiary text
ldGray.0-9Same role in both schemes: 0 canvas, 1 muted fill, 2 border, 3 strong border, 4 faint icon, 5 tertiary text, 6 dimmed, 7 label, 9 text

Dark Mode in CSS Modules

Neutrals need no dark-mode branch: the tokens and ldGray.N already resolve per scheme.

/* ❌ Bad */
.row:hover {
    background-color: var(--mantine-color-ldGray-0);

    @mixin dark {
        background-color: var(--mantine-color-ldDark-5);
    }
}

/* ✅ Good */
.row:hover {
    background-color: var(--mantine-color-default-hover);
}

Use light-dark() only for a non-neutral pair that has no token, such as an accent tint:

.highlight {
    background-color: light-dark(
        var(--mantine-color-indigo-0),
        var(--mantine-color-indigo-9)
    );
}

Always Use Theme Tokens

// ❌ Bad - Magic numbers
<Box p={16} mt={24}>

// ✅ Good - Theme tokens
<Box p="md" mt="lg">

Rem


Content truncated.

When not to use it

  • →Legacy projects not using Mantine
  • →Simple scripts where styling isn't required

Prerequisites

React project structureMantine core library

Limitations

  • →Hard constraint on v8 migration
  • →Strict limit on inline styling props

How it compares

It performs specific version-based code migration and styling enforcement rather than generic code styling.

Compared to similar skills

frontend-style-guide side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
frontend-style-guide (this skill)14moNo flagsIntermediate
web-artifacts-builder495moReviewIntermediate
accessibility-compliance454moNo flagsIntermediate
radix-ui-design-system334moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

web-artifacts-builder

anthropics

Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.

49162

accessibility-compliance

wshobson

Implement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.

45132

radix-ui-design-system

sickn33

Build accessible design systems with Radix UI primitives. Headless component customization, theming strategies, and compound component patterns for production-grade UI libraries.

33130

figma-integration

duongdev

Guides design-to-code workflow using Figma integration. Helps extract designs, analyze components, and generate implementation specs. Auto-activates when users mention Figma URLs, design implementation, component conversion, or design-to-code workflows. Works with /ccpm:planning:design-ui, design-approve, design-refine, and /ccpm:utils:figma-refresh commands.

23129

frontend-code-review

langgenius

Trigger when the user requests a review of frontend files (e.g., `.tsx`, `.ts`, `.js`). Support both pending-change reviews and focused file reviews while applying the checklist rules.

1174

figma-implement-design

openai

Translate Figma nodes into production-ready code with 1:1 visual fidelity using the Figma MCP workflow (design context, screenshots, assets, and project-convention translation). Trigger when the user provides Figma URLs or node IDs, or asks to implement designs or components that must match Figma specs. Requires a working Figma MCP server connection.

2460

Search skills

Search the agent skills registry