Add the md text classes

Plan step 34. text.css (material.text, imported by the foundation) is
the fixed set for text on plain elements: md-type-* and
md-type-emphasized-* with the type utilities' declarations, the role
inks md-ink to md-ink-inverse, md-text-start|center|end, md-truncate,
md-line-clamp-2|3, md-nowrap, md-tabular and md-visually-hidden. Its
header says when to use each, from the material-3 guideline and
docs/reference/m3/styles.md § Typography.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 13:43:11 +02:00
co-authored by Claude Opus 5
parent c545fb69ef
commit 0ab3bd861d
2 changed files with 324 additions and 0 deletions
+1
View File
@@ -35,3 +35,4 @@
@import './foundation/tokens.css';
@import './foundation/base.css';
@import './foundation/interaction.css';
@import './text.css';
+323
View File
@@ -0,0 +1,323 @@
/*
* The text classes: a fixed, documented set for text on plain elements. A component sets its own
* type and ink; these are for the headings, paragraphs and captions an application writes around
* them, and the set the package's own views use for text once they leave Tailwind.
*
* Type — one per text element, the whole style at once (size, line height, weight, tracking;
* tokens/type.css), never assembled by hand. Roles from docs/reference/m3/styles.md § Typography:
*
* md-type-display-{lg|md|sm} the largest text on a screen: short, important text or numerals,
* best on large screens
* md-type-headline-{lg|md|sm} short, high-emphasis text: page and section titles
* md-type-title-{lg|md|sm} medium-emphasis, relatively short text: card, dialog and
* list-section titles
* md-type-body-{lg|md|sm} longer passages and paragraphs; body-lg for reading
* md-type-label-{lg|md|sm} small, utilitarian text inside components, and captions
*
* `md-type-emphasized-*` is the same style one weight step heavier and fully rounded, with its own
* tracking. M3's components do not use it by default: it is a deliberate choice for a selected
* item, a primary action, a headline or a badge, not decoration. `font-variation-settings`
* inherits, so every regular class resets it and body copy inside an emphasized heading reads as
* itself again. The heading level is structure; the class is appearance.
*
* Ink — an M3 role, never an opacity (38% means disabled):
*
* md-ink on-surface: default text
* md-ink-variant on-surface-variant: lower emphasis — secondary text, metadata
* md-ink-quiet outline: decoration only, never text that must be read
* md-ink-primary primary: a link, together with `md-link`
* md-ink-error error: the text of an error
* md-ink-success, md-ink-warning, md-ink-info: the text of that state, and nothing else
* md-ink-inverse inverse-on-surface: text on an inverse surface (a snackbar)
*
* On a container, the ink is the container's `on-` role, which the component sets; these inks are
* for the surface roles.
*
* Layout of text:
*
* md-text-start|center|end logical alignment, so it turns with the writing direction
* md-truncate one line with an ellipsis — only where the whole text can be read
* elsewhere, because M3's text must scale to 200% without loss
* md-line-clamp-2|3 at most two or three lines, the same caveat
* md-nowrap never wraps: a figure with its unit, a short label
* md-tabular tabular figures, where digits change often (tables, clocks,
* counters), so the layout does not shift
* md-visually-hidden read by assistive technology, not drawn: a label a picture already
* gives the eye
*
* In `material.text`, above every component: a text class on a component's root or on an element
* inside it wins over the component's own type and ink. The `md-type-*` declarations are the
* `type-*` utilities' (tokens/utilities.css), which the components still written in Tailwind use.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.text {
.md-type-display-lg {
font: var(--md-sys-typescale-display-lg);
letter-spacing: var(--md-sys-typescale-display-lg-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-display-lg {
font: var(--md-sys-typescale-emphasized-display-lg);
letter-spacing: var(--md-sys-typescale-emphasized-display-lg-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-display-md {
font: var(--md-sys-typescale-display-md);
letter-spacing: var(--md-sys-typescale-display-md-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-display-md {
font: var(--md-sys-typescale-emphasized-display-md);
letter-spacing: var(--md-sys-typescale-emphasized-display-md-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-display-sm {
font: var(--md-sys-typescale-display-sm);
letter-spacing: var(--md-sys-typescale-display-sm-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-display-sm {
font: var(--md-sys-typescale-emphasized-display-sm);
letter-spacing: var(--md-sys-typescale-emphasized-display-sm-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-headline-lg {
font: var(--md-sys-typescale-headline-lg);
letter-spacing: var(--md-sys-typescale-headline-lg-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-headline-lg {
font: var(--md-sys-typescale-emphasized-headline-lg);
letter-spacing: var(--md-sys-typescale-emphasized-headline-lg-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-headline-md {
font: var(--md-sys-typescale-headline-md);
letter-spacing: var(--md-sys-typescale-headline-md-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-headline-md {
font: var(--md-sys-typescale-emphasized-headline-md);
letter-spacing: var(--md-sys-typescale-emphasized-headline-md-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-headline-sm {
font: var(--md-sys-typescale-headline-sm);
letter-spacing: var(--md-sys-typescale-headline-sm-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-headline-sm {
font: var(--md-sys-typescale-emphasized-headline-sm);
letter-spacing: var(--md-sys-typescale-emphasized-headline-sm-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-title-lg {
font: var(--md-sys-typescale-title-lg);
letter-spacing: var(--md-sys-typescale-title-lg-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-title-lg {
font: var(--md-sys-typescale-emphasized-title-lg);
letter-spacing: var(--md-sys-typescale-emphasized-title-lg-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-title-md {
font: var(--md-sys-typescale-title-md);
letter-spacing: var(--md-sys-typescale-title-md-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-title-md {
font: var(--md-sys-typescale-emphasized-title-md);
letter-spacing: var(--md-sys-typescale-emphasized-title-md-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-title-sm {
font: var(--md-sys-typescale-title-sm);
letter-spacing: var(--md-sys-typescale-title-sm-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-title-sm {
font: var(--md-sys-typescale-emphasized-title-sm);
letter-spacing: var(--md-sys-typescale-emphasized-title-sm-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-body-lg {
font: var(--md-sys-typescale-body-lg);
letter-spacing: var(--md-sys-typescale-body-lg-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-body-lg {
font: var(--md-sys-typescale-emphasized-body-lg);
letter-spacing: var(--md-sys-typescale-emphasized-body-lg-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-body-md {
font: var(--md-sys-typescale-body-md);
letter-spacing: var(--md-sys-typescale-body-md-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-body-md {
font: var(--md-sys-typescale-emphasized-body-md);
letter-spacing: var(--md-sys-typescale-emphasized-body-md-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-body-sm {
font: var(--md-sys-typescale-body-sm);
letter-spacing: var(--md-sys-typescale-body-sm-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-body-sm {
font: var(--md-sys-typescale-emphasized-body-sm);
letter-spacing: var(--md-sys-typescale-emphasized-body-sm-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-label-lg {
font: var(--md-sys-typescale-label-lg);
letter-spacing: var(--md-sys-typescale-label-lg-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-label-lg {
font: var(--md-sys-typescale-emphasized-label-lg);
letter-spacing: var(--md-sys-typescale-emphasized-label-lg-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-label-md {
font: var(--md-sys-typescale-label-md);
letter-spacing: var(--md-sys-typescale-label-md-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-label-md {
font: var(--md-sys-typescale-emphasized-label-md);
letter-spacing: var(--md-sys-typescale-emphasized-label-md-tracking);
font-variation-settings: "ROND" 100;
}
.md-type-label-sm {
font: var(--md-sys-typescale-label-sm);
letter-spacing: var(--md-sys-typescale-label-sm-tracking);
font-variation-settings: normal;
}
.md-type-emphasized-label-sm {
font: var(--md-sys-typescale-emphasized-label-sm);
letter-spacing: var(--md-sys-typescale-emphasized-label-sm-tracking);
font-variation-settings: "ROND" 100;
}
.md-ink {
color: var(--md-sys-color-on-surface);
}
.md-ink-variant {
color: var(--md-sys-color-on-surface-variant);
}
.md-ink-quiet {
color: var(--md-sys-color-outline);
}
.md-ink-primary {
color: var(--md-sys-color-primary);
}
.md-ink-error {
color: var(--md-sys-color-error);
}
.md-ink-success {
color: var(--md-sys-color-success);
}
.md-ink-warning {
color: var(--md-sys-color-warning);
}
.md-ink-info {
color: var(--md-sys-color-info);
}
.md-ink-inverse {
color: var(--md-sys-color-inverse-on-surface);
}
.md-text-start {
text-align: start;
}
.md-text-center {
text-align: center;
}
.md-text-end {
text-align: end;
}
.md-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.md-line-clamp-2 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.md-line-clamp-3 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.md-nowrap {
white-space: nowrap;
}
.md-tabular {
font-variant-numeric: tabular-nums;
}
.md-visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border-width: 0;
}
}