import type {CSSProperties} from 'react';
import {Fragment} from 'react';
import {css} from '@emotion/react';
import styled from '@emotion/styled';
import LetterSpacingGraphic from 'sentry-images/stories/typography/letter-spacing.svg';
import LineHeightGraphic from 'sentry-images/stories/typography/line-height.svg';
import WeightGraphic from 'sentry-images/stories/typography/weight.svg';
import {CodeSnippet} from 'sentry/components/codeSnippet';
import {Flex} from 'sentry/components/container/flex';
import ExternalLink from 'sentry/components/links/externalLink';
import Link from 'sentry/components/links/link';
import Panel from 'sentry/components/panels/panel';
import {PanelTable} from 'sentry/components/panels/panelTable';
import {IconCheckmark, IconCircleFill, IconClose} from 'sentry/icons';
import {space} from 'sentry/styles/space';
import type {ColorOrAlias} from 'sentry/utils/theme';
const FixedWidth = styled('div')`
max-width: 800px;
`;
interface TypeScaleItem {
fontSize: CSSProperties['fontSize'];
fontWeight: CSSProperties['fontWeight'];
letterSpacing: CSSProperties['letterSpacing'];
lineHeight: CSSProperties['lineHeight'];
name: string;
}
const TYPE_SCALE: TypeScaleItem[] = [
{
name: 'Heading 1',
fontWeight: 600,
fontSize: '2.25rem',
lineHeight: 1.2,
letterSpacing: '-0.02rem',
},
{
name: 'Heading 2',
fontWeight: 600,
fontSize: '1.875rem',
lineHeight: 1.2,
letterSpacing: '-0.016em',
},
{
name: 'Heading 3',
fontWeight: 600,
fontSize: '1.625rem',
lineHeight: 1.2,
letterSpacing: '-0.012em',
},
{
name: 'Heading 4',
fontWeight: 600,
fontSize: '1.375rem',
lineHeight: 1.2,
letterSpacing: '-0.008em',
},
{
name: 'Heading 5',
fontWeight: 600,
fontSize: '1.25rem',
lineHeight: 1.2,
letterSpacing: '-0.004em',
},
{
name: 'Heading 6',
fontWeight: 600,
fontSize: '1.125rem',
lineHeight: 1.2,
letterSpacing: 'normal',
},
{
name: 'Paragraph',
fontWeight: 400,
fontSize: '1rem',
lineHeight: 1.4,
letterSpacing: 'normal',
},
{
name: 'Button/Label',
fontWeight: 600,
fontSize: '1rem',
lineHeight: 1.2,
letterSpacing: 'normal',
},
{
name: 'Small',
fontWeight: 400,
fontSize: '0.875rem',
lineHeight: 1.4,
letterSpacing: '+0.01rem',
},
];
const InlineLinkExampleStyles = `styled('a')\`
color: \${p => p.theme.blue300};
text-decoration: underline;
text-decoration-color: ${p => p.theme.blue100};
cursor: pointer;
&:hover {
text-decoration-color: ${p => p.theme.blue200};
}
\`;
`;
const StandaloneLinkExampleStyles = `/* Link color is flexible, choose between Gray 500, 400, and 300. */
styled('a')\`
color: \${p => p.theme.gray500};
text-decoration: none;
cursor: pointer;
&:hover {
text-decoration: underline;
text-decoration-color: \${p => p.theme.gray200};
}
\`;
`;
const UnorderedListExampleStyles = `/* First-level items */
ul > li {
list-style-type: disc;
}
/* Second-level items */
ul > ul > li {
list-style-type: circle;
}
`;
const OrderedListExampleStyles = `/* First-level items */
ul > li {
list-style-type: decimal;
}
/* Second-level items */
ul > ul > li {
list-style-type: lower-alpha;
}
`;
const TabularNumsExampleStyles = `/* Add this to numeric columns */
font-variant-numeric: tabular-nums;
`;
const FontLigatureExampleStyles = `/* Add this to the root element */
font-feature-settings: 'liga';
`;
const FontFractionExampleStyles = `/* Be careful: this changes the appearance of normal,
non-fractional numbers, so only apply it to specific
text elements with fractions inside. */
font-feature-settings: 'frac';
`;
export default function TypographyStories() {
return (
We've built Sentry's type system around Rubik - a playful open-source typeface.
For code and code-like elements, we use
Type scales are hierarchical type systems consisting of style definitions for
common elements, such as Heading 1, Heading 2, Paragraph, and Button/Label.
Sentry's type scale is based on the Rubik typeface. The root font size is 16px
(1rem = 16px).
The type scale above should cover a large majority of use cases. However, if an
element requires a custom style outside of the type scale, make sure to follow the
rules below.
Use values from the type scale above. Be mindful of the type
hierarchy. If the element has low importance, use a smaller size.
Use Roboto Mono in Regular (400) for code and code-like elements, like search
tokens.
Set the line height based on the context:
External links lead users to pages outside the application. Examples include links
to Sentry's blog/marketing pages, terms of service, third-party documentation,…
The following styling rules apply to external links only. Internal links, on the
other hand, can have more flexible styles, based on their behavior and context.
When a link appears inside a longer sentence…
When a link appears on its own and the user likely knows that it's a link given
the context, like in a footer:
Use filled and hollow circles as bullets points:
Use Arabic numerals and lowercase letters as counters:
Rubik supports a few useful{' '}
By default, Rubik uses proportional figures. This works well in most cases.
However, for large tables with a lot of numbers, tabular figures would be a better
choice, thanks to their consistent width and more legible design.
Ligatures are special glyphs that replace two or more glyphs in order to better
connect them. Common ligature replacements include ff, fi, fl, and ffi.
Without ligatures, the characters are all separate. With ligatures, the characters are connected into a single glyph.
Rubik also contains special formatting for fractions. Without this formatting,
numbers in fractions are just rendered as separate characters.
Fractional formatting shrinks the numbers and connects them with a diagonal
slash, forming a proportional, condensed visual block.
Typography
Roboto Mono
.
Type scale
Styling
Size
rem
unit.
Weight
Line height
Letter spacing
Code
External Links
In a sentence
cursor: pointer
Standalone
cursor: pointer
Lists
Unordered
Ordered
OpenType features
Tabular figures
Ligatures
Fractions