frontend-style-guide
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.
Install
mkdir -p .claude/skills/frontend-style-guide && curl -L -o skill.zip "https://mcp.directory/api/skills/download/6557" && unzip -o skill.zip -d .claude/skills/frontend-style-guide && rm skill.zipInstalls to .claude/skills/frontend-style-guide
About this skill
Lightdash Frontend Style Guide
Apply these rules when working on any frontend component in packages/frontend/.
Mantine 8 Migration
CRITICAL: We are migrating from Mantine 6 to 8. Always upgrade v6 components when you encounter them.
Component Checklist
When creating/updating components:
- Use
@mantine-8/coreimports - No
styleorstylesorsxprops - 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
- 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
Quick Migration Guide
// ❌ Mantine 6
import { Button, Group } from '@mantine/core';
<Group spacing="xs" noWrap>
<Button sx={{ mt: 20 }}>Click</Button>
</Group>;
// ✅ Mantine 8
import { Button, Group } from '@mantine-8/core';
<Group gap="xs" wrap="nowrap">
<Button mt={20}>Click</Button>
</Group>;
Key Prop Changes
spacing→gapnoWrap→wrap="nowrap"sx→ Component props (e.g.,mt,w,c) or CSS modulesleftIcon→leftSectionrightIcon→rightSection
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
- Best: No custom styles (use theme defaults)
- Theme extension: For repeated patterns, add to
mantine8Theme.ts - Component props: Simple overrides (1-3 props like
mt="xl" w={240}) - CSS modules: Complex styling or more than 3 props
NEVER Use
stylesprop (always use CSS modules instead)sxprop (it's a v6 prop)styleprop (inline styles)
Theme Extensions (For Repeated Patterns)
If you find yourself applying the same style override multiple times, add it to the theme in mantine8Theme.ts:
// In src/mantine8Theme.ts - inside the components object
components: {
Button: Button.extend({
styles: {
root: {
minWidth: '120px',
fontWeight: 600,
}
}
}),
}
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 - Mantine handles theme switching automatically.
When you need custom colors, use our custom scales for dark mode compatibility:
// ❌ Bad - Standard Mantine colors (poor dark mode support)
<Text c="gray.6">Secondary text</Text>
// ✅ Good - ldGray for borders and neutral elements
<Text c="ldGray.6">Secondary text</Text>
// ✅ Good - ldDark for elements that appear dark in light mode
<Button bg="ldDark.8" c="ldDark.0">Dark button</Button>
// ✅ Good - Foreground/background variables
<Text c="foreground">Primary text</Text>
<Box bg="background">Main background</Box>
Custom Color Scales
| Token | Purpose |
|---|---|
ldGray.0-9 | Borders, subtle text, neutral UI elements |
ldDark.0-9 | Buttons/badges with dark backgrounds in light mode |
background | Page/card backgrounds |
foreground | Primary text color |
Dark Mode in CSS Modules
Use @mixin dark for theme-specific overrides:
.clickableRow {
&:hover {
background-color: var(--mantine-color-ldGray-0);
@mixin dark {
background-color: var(--mantine-color-ldDark-5);
}
}
}
Alternative: use CSS light-dark() function for single-line theme switching:
.clickableRow:hover {
background-color: light-dark(
var(--mantine-color-ldGray-0),
var(--mantine-color-ldDark-5)
);
}
Always Use Theme Tokens
// ❌ Bad - Magic numbers
<Box p={16} mt={24}>
// ✅ Good - Theme tokens
<Box p="md" mt="lg">
Beware of dependencies
If a component is migrated to use Mantine 8 Menu.Item, ensure its parent also uses Mantine 8 Menu
Remove Dead Styles
Before moving styles to CSS modules, check if they're actually needed:
// ❌ Unnecessary - display: block has no effect on flex children
<Flex justify="flex-end">
<Button style={{display: 'block'}}>Submit</Button>
</Flex>
// ✅ Better - Remove the style entirely
<Flex justify="flex-end">
<Button>Submit</Button>
</Flex>
Theme-Aware Component Logic
For JavaScript logic that needs to know the current theme:
import { useMantineColorScheme } from '@mantine/core';
const MyComponent = () => {
const { colorScheme } = useMantineColorScheme();
const iconColor = colorScheme === 'dark' ? 'blue.4' : 'blue.6';
// ...
};
Keep using mantine/core's clsx utility until we migrate to Mantine 8 fully
import { clsx } from '@mantine/core';
const MyComponent = () => {
return (
<div className={clsx('my-class', 'my-other-class')}>My Component</div>
);
};
Select/MultiSelect grouping has a different structure on Mantine 8
<Select
label="Your favorite library"
placeholder="Pick value"
data={[
{ group: 'Frontend', items: ['React', 'Angular'] },
{ group: 'Backend', items: ['Express', 'Django'] },
]}
/>
Reusable Components
Modals
- Always use
MantineModalfromcomponents/common/MantineModal- never use Mantine's Modal directly - See
stories/Modal.stories.tsxfor usage examples - For forms inside modals: use
idon the form andform="form-id"on the submit button - For alerts inside modals: use
Calloutwith variantsdanger,warning,info
Callouts
- Use
Calloutfromcomponents/common/Callout - Variants:
danger,warning,info
Polymorphic Clickable Containers
Use these when you need a layout container that is also clickable — avoids the native <button> background/border reset problem.
PolymorphicGroupButtonfromcomponents/common/PolymorphicGroupButton— aGroup(flex row) that is polymorphic and setscursor: pointer. Use for horizontal groups of elements that act as a single button.PolymorphicPaperButtonfromcomponents/common/PolymorphicPaperButton— aPaper(card surface) that is polymorphic and setscursor: pointer. Use for card-like clickable surfaces.
Both accept all props of their base component (GroupProps / PaperProps) plus a component prop for the underlying element.
// ✅ Clickable row without native button style bleed
<PolymorphicGroupButton component="div" gap="sm" onClick={handleClick}>
<MantineIcon icon={IconFolder} />
<Text>Label</Text>
</PolymorphicGroupButton>
// ✅ Clickable card surface
<PolymorphicPaperButton component="div" p="md" onClick={handleClick}>
Card content
</PolymorphicPaperButton>
// ❌ Avoid - native <button> brings unwanted background/border in menus and panels
<UnstyledButton>
<Group>...</Group>
</UnstyledButton>
EmptyStateLoader
- Use
EmptyStateLoaderfromcomponents/common/EmptyStateLoaderfor any centered loading state: page-level guards, panels, tables, empty containers - Built on
SuboptimalState(Mantine v8) — renders a spinner with an optional title, fully centered in its parent
TruncatedText
- Use
TruncatedTextfromcomponents/common/TruncatedTextwhenever text may overflow a constrained width - Pass
maxWidth(number or string) to control the truncation boundary - Automatically shows a tooltip with the full text only when the text is actually truncated (no tooltip spam for short names)
- Defaults to
fz="sm"; override via standardTextprops
// ✅ Good - truncates long names, tooltip only appears when needed
<TruncatedText maxWidth={200}>{item.name}</TruncatedText>
// ✅ Accepts any Text prop
<TruncatedText maxWidth="100%" fw={500}>{space.name}</TruncatedText>
Mantine Documentation
List of all components and links to their documentation in LLM-friendly format: https://mantine.dev/llms.txt
More by lightdash
View all skills by lightdash →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversRecraft AI is an ai image generator for creating, editing, and upscaling raster or vector images with advanced artificia
FindMine Shopping Stylist offers AI-powered fashion recommendations, outfit creation, and style guides for e-commerce pl
Optimize your codebase for AI with Repomix—transform, compress, and secure repos for easier analysis with modern AI tool
Unlock seamless Figma to code: streamline Figma to HTML with Framelink MCP Server for fast, accurate design-to-code work
Uno Platform — Documentation and prompts for building cross-platform .NET apps with a single codebase. Get guides, sampl
Create modern React UI components instantly with Magic AI Agent. Integrates with top IDEs for fast, stunning design and
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.