Skip to main content

design-system

Guide for using Sentry's layout and text primitives. Use when implementing UI components, layouts, or typography. Enforces use of core components over styled components.

Source facts

Repository
getsentry/sentry
Last source activity
August 7, 2026 at 15:10
Detected SKILL.md language
English
Stars
44,880
Forks
4,869

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
design-system
description
Guide for using Sentry's layout and text primitives. Use when implementing UI components, layouts, or typography. Enforces use of core components over styled components.
# Layout and Text Primitives at Sentry ## Core Principle **ALWAYS use core components from `@sentry/scraps` instead of creating styled components with Emotion.** Core components provide consistent styling, responsive design, and better maintainability across the codebase. ## Component Implementation Reference For the complete list of supported props and their types, refer to the implementation files: - **Layout Components**: `/static/app/components/core/layout/` - `container.tsx` - Base container with all layout props - `flex.tsx` - Flex layout primitive - `grid.tsx` - Grid layout primitive - `stack.tsx` - Stack layout primitive (Flex with column direction by default) - **Typography Components**: `/static/app/components/core/text/` - `text.tsx` - Text primitive - `heading.tsx` - Heading primitive ## Layout Primitives > **Important**: `Flex`, `Grid`, and `Stack` all extend `Container`. This means **every prop available on Container is also available on Flex, Grid, and Stack**. When you use `<Flex>`, you get all Container props (position, padding, border, overflow, etc.) PLUS the flex-specific props. The same applies to Grid and Stack. ### Container Base layout component that supports all common layout properties. Flex, Grid, and Stack extend Container, inheriting all of its props. **Key Props** (see `container.tsx` for complete list): - `position`: "static" | "relative" | "absolute" | "fixed" | "sticky" - `padding`, `paddingTop`, `paddingBottom`, `paddingLeft`, `paddingRight`: SpaceSize tokens - `margin`, `marginTop`, etc.: SpaceSize tokens (deprecated, prefer gap) - `width`, `height`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight` - `border`, `borderTop`, `borderBottom`, `borderLeft`, `borderRight`: BorderVariant tokens - `radius`: RadiusSize tokens - `overflow`, `overflowX`, `overflowY`: "visible" | "hidden" | "scroll" | "auto" - `background`: SurfaceVariant ("primary" | "secondary" | "tertiary") - `display`: Various display types - Flex item props: `flex`, `flexGrow`, `flexShrink`, `flexBasis`, `alignSelf`, `order` - Grid item props: `area`, `row`, `column` ```tsx import {Container} from '@sentry/scraps/layout'; // ❌ Don't create styled components const Component = styled('div')` padding: ${p => p.theme.space.md}; border: 1px solid ${p => p.theme.tokens.border.primary}; `; // ✅ Use Container primitive <Container padding="md" border="primary"> Content </Container>; ``` ### Flex Use `<Flex>` for flex layouts. Extends `Container`, inheriting all Container props plus flex-specific props. **Flex-Specific Props** (see `flex.tsx` for complete list): - `direction`: "row" | "row-reverse" | "column" | "column-reverse" - `align`: "start" | "end" | "center" | "baseline" | "stretch" - `justify`: "start" | "end" | "center" | "between" | "around" | "evenly" | "left" | "right" - `gap`: SpaceSize or `"${SpaceSize} ${SpaceSize}"` for row/column gap - `wrap`: "nowrap" | "wrap" | "wrap-reverse" - `display`: "flex" | "inline-flex" | "none" **Plus ALL Container props**: `position`, `padding`, `margin`, `width`, `height`, `border`, `radius`, `overflow`, `background`, flex/grid item props, and more (see Container section above). ```tsx import {Flex} from '@sentry/scraps/layout'; // ❌ Don't create styled components const Component = styled('div')` display: flex; flex-direction: column; position: relative; `; // ✅ Use Flex primitive with props <Flex direction="column" position="relative" gap="md"> <Child1 /> <Child2 /> </Flex>; ``` ### Grid Use `<Grid>` for grid layouts. Extends `Container`, inheriting all Container props plus grid-specific props. **Grid-Specific Props** (see `grid.tsx` for complete list): - `columns`: Grid template columns (number or CSS value) - `rows`: Grid template rows - `areas`: Named grid areas - `gap`: SpaceSize or `"${SpaceSize} ${SpaceSize}"` for row/column gap - `align`: "start" | "end" | "center" | "baseline" | "stretch" (align-items) - `alignContent`: "start" | "end" | "center" | "between" | "around" | "evenly" | "stretch" - `justify`: "start" | "end" | "center" | "between" | "around" | "evenly" | "stretch" (justify-content) - `justifyItems`: "start" | "end" | "center" | "stretch" - `flow`: "row" | "column" | "row dense" | "column dense" - `autoColumns`, `autoRows`: Size of auto-generated tracks **Plus ALL Container props**: `position`, `padding`, `margin`, `width`, `height`, `border`, `radius`, `overflow`, `background`, flex/grid item props, and more (see Container section above). ```tsx import {Grid} from '@sentry/scraps/layout'; // ❌ Don't create styled components const Component = styled('div')` display: grid; grid-template-columns: repeat(3, 1fr); gap: ${p => p.theme.space.md}; `; // ✅ Use Grid primitive <Grid columns="repeat(3, 1fr)" gap="md"> <Item1 /> <Item2 /> <Item3 /> </Grid>; ``` ### Stack Use `<Stack>` for vertical layouts. Stack is essentially `Flex` with `direction="column"` by default. It also provides `Stack.Separator` for adding separators between items. **Props** (see `stack.tsx` for complete list): - Same as Flex props (inherits all Flex and Container props) - `direction` defaults to "column" (but can be overridden) - `Stack.Separator` component for adding dividers between stack items ```tsx import {Stack} from '@sentry/scraps/layout'; // ❌ Don't create styled components for vertical layouts const Component = styled('div')` display: flex; flex-direction: column; gap: ${p => p.theme.space.md}; `; // ✅ Use Stack primitive (automatically column direction) <Stack gap="md"> <Item1 /> <Item2 /> <Item3 /> </Stack>; // ✅ With separators between items <Stack gap="md"> <Item1 /> <Stack.Separator /> <Item2 /> <Stack.Separator /> <Item3 /> </Stack>; // ✅ Stack supports all Flex and Container props <Stack gap="md" padding="lg" position="relative" border="primary"> <Item1 /> <Item2 /> </Stack>; ``` ## Typography Primitives ### Text Use `<Text>` for all text content. Never use raw `<p>`, `<span>`, or `<div>` elements with text styling. **Key Props** (see `text.tsx` for complete list): - `as`: "span" | "p" | "label" | "div" (semantic HTML element) - `size`: TextSize ("xs" | "sm" | "md" | "lg" | "xl" | "2xl") - `variant`: ContentVariant | "muted" (see Content Variant Tokens below) - `align`: "left" | "center" | "right" | "justify" - `bold`: boolean - `italic`: boolean - `uppercase`: boolean - `monospace`: boolean - `tabular`: boolean (fixed-width numbers) - `ellipsis`: boolean (truncate with ellipsis) - `wrap`: "nowrap" | "normal" | "pre" | "pre-line" | "pre-wrap" - `textWrap`: "wrap" | "nowrap" | "balance" | "pretty" | "stable" - `wordBreak`: "normal" | "break-all" | "keep-all" | "break-word" - `density`: "compressed" | "comfortable" (line-height) - `underline`: boolean | "dotted" - `strikethrough`: boolean ```tsx import {Text} from '@sentry/scraps/text'; // ❌ Don't create styled text components const Label = styled('span')` color: ${p => p.theme.tokens.content.secondary}; font-size: ${p => p.theme.font.size.sm}; `; // ❌ Don't use raw elements <p>This is a paragraph</p> <span>Status: Active</span> // ✅ Use Text primitive with semantic 'as' prop <Text as="p" variant="muted" density="comfortable"> This is a paragraph </Text> <Text as="span" bold uppercase> Status: Active </Text> ``` ### Heading Use `<Heading>` for all headings. Never use raw `<h1>`, `<h2>`, etc. elements. **Key Props** (see `heading.tsx` for complete list): - `as`: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" (REQUIRED) - `size`: HeadingSize ("xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl") - `variant`: Same as Text - `align`: Same as Text - `italic`, `monospace`, `tabular`: Same as Text - `ellipsis`, `wrap`, `textWrap`, `wordBreak`: Same as Text - `density`: Same as Text - `underline`, `strikethrough`: Same as Text Note: `bold` and `uppercase` are NOT available on Heading (headings are always bold). ```tsx import {Heading} from '@sentry/scraps/text'; // ❌ Don't style heading elements const Title = styled('h2')` font-size: ${p => p.theme.font.size.md}; font-weight: bold; `; // ❌ Don't use raw heading elements <h2>My Title</h2> // ✅ Use Heading primitive with semantic 'as' prop <Heading as="h2">My Title</Heading> // ✅ With custom size <Heading as="h3" size="xl">Large H3</Heading> ``` ## Info Components > **Important**: Always prefer `InfoTip` and `InfoText` over using raw `<Tooltip>` components. These provide consistent, accessible patterns for contextual help. ### InfoTip Use `<InfoTip>` to add an info icon with tooltip next to labels or headings. It's keyboard accessible and provides a consistent pattern for supplementary help. ```tsx import {InfoTip} from '@sentry/scraps/info'; import {Flex} from '@sentry/scraps/layout'; import {Text} from '@sentry/scraps/text'; // ❌ Don't use Tooltip with arbitrary icons <Flex gap="xs" align="center"> <Text>Retention Period</Text> <Tooltip title="The number of days..."> <IconInfo size="xs" /> </Tooltip> </Flex> // ✅ Use InfoTip for contextual help icons <Flex gap="xs" align="center"> <Text>Retention Period</Text> <InfoTip title="The number of days event data is stored before being automatically deleted." /> </Flex> ``` **Key Props**: - `title`: Tooltip content (required) - `size`: "xs" | "sm" (default) | "md" **When to Use**: - Add context to headings or section titles - Show supplementary information without inline text - Explain settings or configuration options ### InfoText Use `<InfoText>` for inline text with a tooltip. It renders text with a dotted underline that reveals a tooltip on hover/focus. ```tsx import {InfoText} from '@sentry/scraps/info'; // ❌ Don't wrap text with raw Tooltip <Tooltip title="Time to First Byte measures the time..."> <span style={{textDecoration: 'underline dotted'}}>TTFB</span>
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub