Merge branch 'worktree-agent-ad8d9c4488c648d01'

This commit is contained in:
Andreas Reinhold / reini
2026-09-14 13:44:15 +02:00
24 changed files with 2201 additions and 877 deletions
@@ -88,6 +88,8 @@ Scheme::resolveProfileUsing(fn (): ?string => Setting::get('color_profile'));
## Tokens
2.0.0's vocabulary is plain CSS, without Tailwind. `resources/css/foundation.css` is the one required import, first in the entry (while an application still builds Tailwind: before `@import 'tailwindcss'`, with `resources/css/tailwind.css` after it in place of `material.css`). It declares the layer order `material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility`, so an application's unlayered CSS beats every package rule, and `hidden` or `x-cloak` hides any element. It brings the reset, every `--md-sys-*` token (spacing included: `--md-sys-measurement-space25``space900`, 272px), and `md-state-layer`, `md-focus-ring`, `md-touch-target`, `md-link`. Text on plain elements takes the fixed text classes of `resources/css/text.css` and nothing else: `md-type-{display|headline|title|body|label}-{lg|md|sm}` and `md-type-emphasized-…`; `md-ink` (on-surface), `md-ink-variant`, `md-ink-quiet`, `md-ink-primary`, `md-ink-error`, `md-ink-success`, `md-ink-warning`, `md-ink-info`, `md-ink-inverse`; `md-text-start|center|end`, `md-truncate`, `md-line-clamp-2|3`, `md-nowrap`, `md-tabular`, `md-visually-hidden`. The Tailwind names below stay for the components not yet rewritten.
Tailwind's default palette is cleared: every colour class names an M3 role. `text-red-600`, `bg-base-200` or `text-gray-500` compile to nothing. The rules behind the names below — which role, surface container, corner, type style, elevation level, motion spring, state and window size class to use, and M3's don'ts — are the `material-3` guideline (always on) and the `material-3-design` skill (the tables and Google's source pages); activate that skill before designing a screen.
- Colour roles (`bg-*`, `text-*`, `border-*`, …): `primary`, `on-primary`, `primary-container`, `on-primary-container`, `inverse-primary`, `primary-fixed`, `primary-fixed-dim`, `on-primary-fixed`, `on-primary-fixed-variant`; the same for `secondary` and `tertiary`; `error`, `on-error`, `error-container`, `on-error-container`; `success`, `warning` and `info` with their `on-`, `-container` and `on-…-container`; `inverse-error|success|warning|info`; `surface`, `surface-dim`, `surface-bright`, `surface-container-lowest|low||high|highest`, `on-surface`, `on-surface-variant`, `inverse-surface`, `inverse-on-surface`, `outline`, `outline-variant`, `scrim`, `shadow`; plus `white` and `black`.
@@ -9,7 +9,7 @@ description: Material 3 Expressive's design system as Livewire Material implemen
Use this skill when deciding how a screen, panel or control should look or behave — which colour, container, corner, type style, motion, breakpoint or spacing — in an application that requires `nonameweb/livewire-material`, and when reviewing a view against Material 3. The props and slots of each component are in the `livewire-material-development` skill; this one is the design language they implement. The rules an agent must always follow are in the `material-3` guideline; the tables here are what those rules compress.
Every table pairs the M3 name with the library's utility or attribute. The tokens are CSS variables (`--md-sys-color-*`, `--md-sys-typescale-*`, `--md-sys-shape-*`, `--md-sys-elevation-*`, `--md-sys-motion-*`, `--md-sys-state-*`, `--md-ref-typeface-*`) and the utilities read them, so a template names a utility and never a variable or a value.
Every table pairs the M3 name with the library's utility or attribute. The tokens are CSS variables (`--md-sys-color-*`, `--md-sys-typescale-*`, `--md-sys-shape-*`, `--md-sys-elevation-*`, `--md-sys-motion-*`, `--md-sys-state-*`, `--md-sys-measurement-*`, `--md-ref-typeface-*`) and the utilities read them, so a template names a utility and never a variable or a value.
## Colour
+38
View File
@@ -0,0 +1,38 @@
/*
* Livewire Material the foundation, the one stylesheet every application imports, first:
*
* @import '../../vendor/nonameweb/livewire-material/resources/css/foundation.css';
* @import './material-scheme.css';
*
* Plain CSS, no build step of its own: an application's bundler (Vite) inlines the imports, and a
* browser could read the files as they are.
*
* Every rule of the package sits in a sub-layer of `material`, in this order, lowest first:
*
* material.reset foundation/reset.css the browser's defaults taken back
* material.tokens foundation/tokens.css every `--md-sys-*` and `--md-ref-*` property
* material.base foundation/base.css, foundation/interaction.css the page, the font
* face, and md-state-layer, md-focus-ring, md-touch-target, md-link
* material.layout the layout components: scaffold, panes, the canonical layouts
* material.components the components
* material.text text.css md-type-*, md-ink-*, and the few classes for text
* material.visibility hiding an element below or from a breakpoint, over a component's display
*
* Every package stylesheet opens with the same layer statement, before its imports, so the order
* holds whichever file a bundler reaches first. An application's own CSS is unlayered and
* therefore outranks every package rule, whatever the selector an application's broad selector
* (`button { }`) restyles the components too. foundation/hidden.css keeps its two `!important`
* rules outside the layers, so `hidden` and `x-cloak` hide an element whatever sets its display.
*
* Until the components leave Tailwind, an application still building it imports this file before
* `@import 'tailwindcss'`, so the `material` layers are declared first and sit below Tailwind's.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@import './foundation/reset.css';
@import './foundation/hidden.css';
@import './foundation/tokens.css';
@import './foundation/base.css';
@import './foundation/interaction.css';
@import './text.css';
+24
View File
@@ -0,0 +1,24 @@
/*
* The page itself: M3's background and default ink, in the brand typeface.
*
* The page is `surface` and its text `on-surface`, the default typography colour
* (docs/reference/m3/styles.md § Typography, "Accessibility requirements"). `color-scheme` is
* declared with the roles in tokens/scheme.css, so native controls and scrollbars change with
* `data-theme` in the same block as the colours. The typeface is
* `--md-ref-typeface-brand` (tokens/type.css), Google Sans Flex from tokens/font.css, whose
* `@font-face` this file imports into the same layer.
*
* In `material.base`, above the reset and below every component and text class.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@import '../tokens/font.css';
@layer material.base {
html {
background-color: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
font-family: var(--md-ref-typeface-brand);
}
}
+23
View File
@@ -0,0 +1,23 @@
/*
* The two rules that hide, outside every layer.
*
* A layered rule always loses to an unlayered one, and no rule without `!important` beats one with
* it, so these two sit outside the layers and carry `!important`: whatever `display` a component
* gives its root, `hidden` on it hides it, and an application can pass `hidden` to any component.
* `hidden="until-found"` is left to the browser, which keeps such content searchable.
* `[x-cloak]` hides what Alpine has not started yet; Alpine removes the attribute when it has.
*
* Only a layered `!important` could outrank these, and the package writes none. The file is
* apart from reset.css because material.css, which stays for applications importing it after
* Tailwind, needs `[x-cloak]` without the reset.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
[hidden]:where(:not([hidden='until-found'])) {
display: none !important;
}
[x-cloak] {
display: none !important;
}
+111
View File
@@ -0,0 +1,111 @@
/*
* The interaction classes every interactive component shares, and an application's own control
* can use: M3's state layer, its focus indicator, its minimum target, and a link in running text.
*
* `md-state-layer` lays the content colour over an element at M3's state opacities
* (tokens/state.css): hover 8%, focus and press 10%, dragged 16%. Hover only where the pointer
* can hover, because a touch screen keeps the last hover after a tap; `data-md-dragged` (or the
* older `data-dragged`) on the element draws the dragged layer; a disabled element has none. The
* layer is a ::before, so the element becomes `position: relative` and `isolation: isolate`.
*
* `md-focus-ring` is M3's focus indicator 3px in secondary, 2px out, drawn only for keyboard
* focus. The site gives no thickness or offset; the values are @material/web's focus ring tokens
* (Apache-2.0, © Google LLC).
*
* `md-touch-target` extends an element's pointer target to M3's 48×48 minimum without changing
* what is drawn: a ::after centred on it, at least `space600` (48px) each way. M3 gives the web
* target as "48 × 48 CSS pixels", so the size is px and does not grow with the text. It is
* `::after`-based, so a component that already draws with ::after wraps its control in an element
* carrying it.
*
* `md-link` is a link in running text: underlined in the colour of the words around it, because
* M3 never lets colour alone mark a link (docs/reference/m3/styles.md § Typography); give it
* `md-ink-primary` where it should also read as primary.
*
* The same declarations as the `state-layer`, `focus-ring`, `touch-target` and `link` utilities
* (tokens/utilities.css) the components still written in Tailwind use; `md-touch-target` alone
* differs, in px where the utility reads 3rem. In `material.base`, so a component's own rules,
* the text classes and an application's rules all outrank them.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.base {
.md-state-layer {
position: relative;
isolation: isolate;
&::before {
content: '';
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
background-color: currentColor;
opacity: 0;
pointer-events: none;
transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);
}
@media (hover: hover) {
&:hover::before {
opacity: var(--md-sys-state-hover-state-layer-opacity);
}
}
&:focus-visible::before {
opacity: var(--md-sys-state-focus-state-layer-opacity);
}
&:active::before {
opacity: var(--md-sys-state-pressed-state-layer-opacity);
}
&:is([data-md-dragged], [data-dragged])::before {
opacity: var(--md-sys-state-dragged-state-layer-opacity);
}
&:disabled::before,
&[aria-disabled='true']::before {
display: none;
}
}
.md-focus-ring {
outline: none;
&:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
}
.md-touch-target {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
min-width: var(--md-sys-measurement-space600);
min-height: var(--md-sys-measurement-space600);
transform: translate(-50%, -50%);
}
}
.md-link {
cursor: pointer;
text-decoration-line: underline;
text-decoration-thickness: from-font;
text-underline-offset: 0.15em;
border-radius: var(--md-sys-shape-corner-xs);
&:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
}
}
+236
View File
@@ -0,0 +1,236 @@
/*
* The reset: what a browser draws before any stylesheet, taken back to a clean start.
*
* Rule for rule the reset the components were built on, Tailwind CSS 4's preflight (MIT,
* © Tailwind Labs, after modern-normalize), so a component looks the same whether an application
* still builds Tailwind or not: every box `border-box` with a `0 solid` border and no margin or
* padding, headings and lists unstyled, form controls inheriting font, colour and tracking with no
* background or radius, media as blocks that never overflow their parent. Three differences:
*
* - no typeface here: foundation/base.css sets `--md-ref-typeface-brand` on <html>;
* - a placeholder is `on-surface-variant`, the colour of M3's text field placeholder (androidx
* FilledTextFieldTokens.kt, InputPlaceholderColor), not half the text colour;
* - it sits in `material.reset`, the lowest layer, so every package rule and every application
* rule outranks it without a specificity fight.
*
* The two rules that must win everything `[hidden]` and `[x-cloak]` are foundation/hidden.css.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.reset {
/* Padding and border inside the width; no default margin, padding or border. */
*,
::after,
::before,
::backdrop,
::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
/* A readable line height and tab size, no font resizing on rotation (iOS), no tap flash. */
html,
:host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-feature-settings: normal;
font-variation-settings: normal;
-webkit-tap-highlight-color: transparent;
}
hr {
height: 0;
color: inherit;
border-top-width: 1px;
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
-webkit-text-decoration: inherit;
text-decoration: inherit;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
font-feature-settings: normal;
font-variation-settings: normal;
font-size: 1em;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
:-moz-focusring:where(:not(iframe)) {
outline: auto;
}
progress {
vertical-align: baseline;
}
summary {
display: list-item;
}
ol,
ul,
menu {
list-style: none;
}
/* Replaced elements are blocks, aligned to the middle when made inline again. */
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
vertical-align: middle;
}
img,
video {
max-width: 100%;
height: auto;
}
/* Form controls take the text around them, with no background, radius or disabled fade. */
button,
input,
select,
optgroup,
textarea,
::file-selector-button {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
border-radius: 0;
background-color: transparent;
opacity: 1;
}
:where(select:is([multiple], [size])) optgroup {
font-weight: bolder;
}
:where(select:is([multiple], [size])) optgroup option {
padding-inline-start: 20px;
}
::file-selector-button {
margin-inline-end: 4px;
}
::placeholder {
opacity: 1;
color: var(--md-sys-color-on-surface-variant);
}
textarea {
resize: vertical;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
/* Date and time inputs keep one height and follow text-align (Safari). */
::-webkit-date-and-time-value {
min-height: 1lh;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-datetime-edit,
::-webkit-datetime-edit-year-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-minute-field,
::-webkit-datetime-edit-second-field,
::-webkit-datetime-edit-millisecond-field,
::-webkit-datetime-edit-meridiem-field {
padding-block: 0;
}
::-webkit-calendar-picker-indicator {
line-height: 1;
}
:-moz-ui-invalid {
box-shadow: none;
}
button,
input:where([type='button'], [type='reset'], [type='submit']),
::file-selector-button {
appearance: button;
}
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
}
+27
View File
@@ -0,0 +1,27 @@
/*
* The tokens: every `--md-sys-*` and `--md-ref-*` custom property the package reads.
*
* Each token file wraps its own declarations in `material.tokens`, because an `@import` cannot sit
* inside a layer block and `layer()` on the import would nest the layer a second time. Being the
* lowest layer but one, a token here loses to the same property declared anywhere an application
* writes it: its generated `material-scheme.css`, unlayered, replaces the default scheme below
* whatever its selectors, and a typeface or a spacing step is overridden the same way.
*
* scheme the colour roles of M3's baseline scheme, light and dark, three contrast levels
* shape the corner scale
* elevation the five shadow levels
* motion the springs of both motion schemes and M3's legacy easings
* type the 30 type styles and the brand typeface
* state the state-layer and disabled opacities
* spacing the measurement scale, space25 space900
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@import '../tokens/scheme.css';
@import '../tokens/shape.css';
@import '../tokens/elevation.css';
@import '../tokens/motion.css';
@import '../tokens/type.css';
@import '../tokens/state.css';
@import '../tokens/spacing.css';
+11 -20
View File
@@ -1,6 +1,6 @@
/*
* Livewire Material the one stylesheet an application imports, after Tailwind, followed by
* the scheme `php artisan material:scheme` wrote for it:
* Livewire Material on 1.x-style imports the one stylesheet an application imports, after
* Tailwind, followed by the scheme `php artisan material:scheme` wrote for it:
*
* @import 'tailwindcss';
* @import '../../vendor/nonameweb/livewire-material/resources/css/material.css';
@@ -9,7 +9,13 @@
* @source '../../vendor/nonameweb/livewire-material/src';
*
* tokens/scheme.css is the package's own default (M3's baseline purple), so an application
* renders before it has a scheme; the application's file declares the same roles later and wins.
* renders before it has a scheme; the application's file declares the same roles, unlayered, and
* wins over the default in `material.tokens`.
*
* It brings the tokens, the two hiding rules and tailwind.css, but not foundation.css: imported
* after Tailwind, the foundation's reset would land in a layer above Tailwind's utilities and
* undo them. An application moving to 2.0.0's vocabulary imports foundation.css before
* `@import 'tailwindcss'` and tailwind.css after it, instead of this file.
*/
@import './tokens/scheme.css';
@@ -18,24 +24,9 @@
@import './tokens/motion.css';
@import './tokens/type.css';
@import './tokens/font.css';
@import './tokens/theme.css';
@import './tokens/state.css';
@import './components/actions.css';
@import './components/groups.css';
@import './components/list.css';
@import './components/collapse.css';
@import './components/dialog.css';
@import './components/field.css';
@import './components/menu.css';
@import './components/selection.css';
@import './components/search.css';
@import './components/datepicker.css';
@import './components/timepicker.css';
@import './components/tabs.css';
@import './components/app-bar.css';
@import './components/navigation.css';
@import './components/toolbar.css';
@import './components/table.css';
@import './foundation/hidden.css';
@import './tailwind.css';
@layer base {
html {
+34
View File
@@ -0,0 +1,34 @@
/*
* Livewire Material's Tailwind half: the theme that turns the tokens into utilities, the token
* utilities, and the component stylesheets still written for Tailwind (`@utility`, `@variant`,
* `@layer components`). It goes when the last component leaves Tailwind.
*
* It carries no tokens, so it can sit behind the foundation without declaring them twice the
* Workbench imports it that way, after Tailwind:
*
* @import '../../../resources/css/foundation.css';
* @import 'tailwindcss' source(none);
* @import '../../../resources/css/tailwind.css';
*
* An application on 1.x-style imports keeps importing material.css, which brings the tokens and
* this file together.
*/
@import './tokens/theme.css';
@import './tokens/utilities.css';
@import './components/actions.css';
@import './components/groups.css';
@import './components/list.css';
@import './components/collapse.css';
@import './components/dialog.css';
@import './components/field.css';
@import './components/menu.css';
@import './components/selection.css';
@import './components/search.css';
@import './components/datepicker.css';
@import './components/timepicker.css';
@import './components/tabs.css';
@import './components/app-bar.css';
@import './components/navigation.css';
@import './components/toolbar.css';
@import './components/table.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;
}
}
+13 -8
View File
@@ -9,13 +9,18 @@
* sheet. On a dark surface a shadow is nearly invisible, so a panel separates from the page
* by its container tone instead. As utilities: shadow-elevation-1 shadow-elevation-5.
*/
:root {
--md-sys-color-shadow: #000000;
--md-sys-color-scrim: #000000;
--md-sys-elevation-1: 0 1px 2px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 1px 3px 1px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-2: 0 1px 2px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 2px 6px 2px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-3: 0 1px 3px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 4px 8px 3px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-4: 0 2px 3px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 6px 10px 4px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-5: 0 4px 4px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 8px 12px 6px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.tokens {
:root {
--md-sys-color-shadow: #000000;
--md-sys-color-scrim: #000000;
--md-sys-elevation-1: 0 1px 2px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 1px 3px 1px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-2: 0 1px 2px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 2px 6px 2px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-3: 0 1px 3px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 4px 8px 3px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-4: 0 2px 3px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 6px 10px 4px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
--md-sys-elevation-5: 0 4px 4px 0 color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent), 0 8px 12px 6px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent);
}
}
+14 -8
View File
@@ -6,13 +6,19 @@
* size pinned 63 KB where the full font is 4 MB. Vite copies it into the application's
* build from this relative url.
*
* An application that wants another typeface overrides `--md-ref-typeface-brand` (and so
* `font-sans`) after importing material.css.
* The face sits in `material.base` (foundation/base.css imports it). An application that wants
* another typeface overrides `--md-ref-typeface-brand` in its own stylesheet, which outranks
* every package layer.
*/
@font-face {
font-family: 'Google Sans Flex';
src: url('../../fonts/google-sans-flex/GoogleSansFlex-Latin.woff2') format('woff2');
font-weight: 400 700;
font-style: normal;
font-display: swap;
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.base {
@font-face {
font-family: 'Google Sans Flex';
src: url('../../fonts/google-sans-flex/GoogleSansFlex-Latin.woff2') format('woff2');
font-weight: 400 700;
font-style: normal;
font-display: swap;
}
}
+63 -58
View File
@@ -40,73 +40,78 @@
* these tokens turns instant with no per-component check; anything that animates without them
* is a bug.
*/
:root {
/* damping 0.6, stiffness 800; settles in 360ms; peaks at 1.095 at 139ms; sampled over 350ms */
--md-sys-motion-spatial-fast: linear(0, 0.0195, 0.0716, 0.1471, 0.2381, 0.3378, 0.4404, 0.5416, 0.6378, 0.7265, 0.806, 0.8754, 0.9342, 0.9826, 1.0211, 1.0503, 1.0713, 1.0849, 1.0924, 1.0948, 1.0931, 1.0882, 1.0812, 1.0726, 1.0632, 1.0534, 1.0438, 1.0347, 1.0263, 1.0187, 1.0121, 1.0064, 1.0018, 0.9981, 0.9953, 0.9933, 0.992, 0.9913, 0.991, 0.9912, 0.9916, 0.9923, 0.9931, 0.994, 0.9949, 0.9958, 0.9967, 0.9975, 1);
--md-sys-motion-spatial-fast-duration: 350ms;
/* damping 0.8, stiffness 380; settles in 440ms; peaks at 1.015 at 269ms; sampled over 500ms */
--md-sys-motion-spatial-default: linear(0, 0.0185, 0.0663, 0.1336, 0.2126, 0.2973, 0.3832, 0.4669, 0.5461, 0.6192, 0.6854, 0.7443, 0.7958, 0.8402, 0.8779, 0.9094, 0.9354, 0.9564, 0.9731, 0.9861, 0.996, 1.0033, 1.0085, 1.0119, 1.014, 1.015, 1.0152, 1.0148, 1.014, 1.0129, 1.0117, 1.0104, 1.0091, 1.0078, 1.0066, 1.0055, 1.0046, 1.0037, 1.0029, 1.0023, 1.0017, 1.0013, 1.0009, 1.0006, 1.0004, 1.0002, 1, 0.9999, 1);
--md-sys-motion-spatial-default-duration: 500ms;
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
/* damping 0.8, stiffness 200; settles in 600ms; peaks at 1.015 at 370ms; sampled over 650ms */
--md-sys-motion-spatial-slow: linear(0, 0.0166, 0.0597, 0.1211, 0.1939, 0.273, 0.354, 0.434, 0.5107, 0.5826, 0.6487, 0.7084, 0.7615, 0.8081, 0.8484, 0.8829, 0.912, 0.9361, 0.9559, 0.9719, 0.9845, 0.9943, 1.0017, 1.0071, 1.0108, 1.0132, 1.0146, 1.0151, 1.0151, 1.0145, 1.0137, 1.0126, 1.0114, 1.0102, 1.009, 1.0078, 1.0067, 1.0057, 1.0047, 1.0039, 1.0031, 1.0025, 1.0019, 1.0015, 1.0011, 1.0008, 1.0005, 1.0003, 1);
--md-sys-motion-spatial-slow-duration: 650ms;
@layer material.tokens {
:root {
/* damping 0.6, stiffness 800; settles in 360ms; peaks at 1.095 at 139ms; sampled over 350ms */
--md-sys-motion-spatial-fast: linear(0, 0.0195, 0.0716, 0.1471, 0.2381, 0.3378, 0.4404, 0.5416, 0.6378, 0.7265, 0.806, 0.8754, 0.9342, 0.9826, 1.0211, 1.0503, 1.0713, 1.0849, 1.0924, 1.0948, 1.0931, 1.0882, 1.0812, 1.0726, 1.0632, 1.0534, 1.0438, 1.0347, 1.0263, 1.0187, 1.0121, 1.0064, 1.0018, 0.9981, 0.9953, 0.9933, 0.992, 0.9913, 0.991, 0.9912, 0.9916, 0.9923, 0.9931, 0.994, 0.9949, 0.9958, 0.9967, 0.9975, 1);
--md-sys-motion-spatial-fast-duration: 350ms;
/* damping 1.0, stiffness 3800; settles in 150ms; sampled over 150ms */
--md-sys-motion-effects-fast: linear(0, 0.0163, 0.0576, 0.1147, 0.1807, 0.2507, 0.3214, 0.3902, 0.4558, 0.5172, 0.5737, 0.6253, 0.6718, 0.7136, 0.7508, 0.7837, 0.8128, 0.8383, 0.8606, 0.8801, 0.897, 0.9117, 0.9244, 0.9353, 0.9448, 0.9529, 0.9599, 0.9658, 0.9709, 0.9753, 0.979, 0.9822, 0.9849, 0.9872, 0.9892, 0.9909, 0.9923, 0.9935, 0.9945, 0.9954, 0.9961, 0.9967, 0.9972, 0.9977, 0.998, 0.9983, 0.9986, 0.9988, 1);
--md-sys-motion-effects-fast-duration: 150ms;
/* damping 0.8, stiffness 380; settles in 440ms; peaks at 1.015 at 269ms; sampled over 500ms */
--md-sys-motion-spatial-default: linear(0, 0.0185, 0.0663, 0.1336, 0.2126, 0.2973, 0.3832, 0.4669, 0.5461, 0.6192, 0.6854, 0.7443, 0.7958, 0.8402, 0.8779, 0.9094, 0.9354, 0.9564, 0.9731, 0.9861, 0.996, 1.0033, 1.0085, 1.0119, 1.014, 1.015, 1.0152, 1.0148, 1.014, 1.0129, 1.0117, 1.0104, 1.0091, 1.0078, 1.0066, 1.0055, 1.0046, 1.0037, 1.0029, 1.0023, 1.0017, 1.0013, 1.0009, 1.0006, 1.0004, 1.0002, 1, 0.9999, 1);
--md-sys-motion-spatial-default-duration: 500ms;
/* damping 1.0, stiffness 1600; settles in 240ms; sampled over 200ms */
--md-sys-motion-effects-default: linear(0, 0.0124, 0.0446, 0.0902, 0.1443, 0.2032, 0.2642, 0.3253, 0.3849, 0.4422, 0.4963, 0.547, 0.594, 0.6372, 0.6768, 0.7127, 0.7452, 0.7745, 0.8009, 0.8244, 0.8454, 0.8641, 0.8807, 0.8954, 0.9084, 0.9199, 0.93, 0.9389, 0.9467, 0.9536, 0.9596, 0.9648, 0.9694, 0.9734, 0.9769, 0.98, 0.9826, 0.985, 0.987, 0.9887, 0.9902, 0.9916, 0.9927, 0.9937, 0.9946, 0.9953, 0.9959, 0.9965, 1);
--md-sys-motion-effects-default-duration: 200ms;
/* damping 0.8, stiffness 200; settles in 600ms; peaks at 1.015 at 370ms; sampled over 650ms */
--md-sys-motion-spatial-slow: linear(0, 0.0166, 0.0597, 0.1211, 0.1939, 0.273, 0.354, 0.434, 0.5107, 0.5826, 0.6487, 0.7084, 0.7615, 0.8081, 0.8484, 0.8829, 0.912, 0.9361, 0.9559, 0.9719, 0.9845, 0.9943, 1.0017, 1.0071, 1.0108, 1.0132, 1.0146, 1.0151, 1.0151, 1.0145, 1.0137, 1.0126, 1.0114, 1.0102, 1.009, 1.0078, 1.0067, 1.0057, 1.0047, 1.0039, 1.0031, 1.0025, 1.0019, 1.0015, 1.0011, 1.0008, 1.0005, 1.0003, 1);
--md-sys-motion-spatial-slow-duration: 650ms;
/* damping 1.0, stiffness 800; settles in 330ms; sampled over 300ms */
--md-sys-motion-effects-slow: linear(0, 0.0139, 0.0496, 0.0995, 0.1583, 0.2216, 0.2865, 0.3509, 0.4131, 0.4722, 0.5275, 0.5788, 0.6258, 0.6687, 0.7075, 0.7424, 0.7737, 0.8016, 0.8264, 0.8484, 0.8678, 0.8849, 0.8999, 0.9131, 0.9247, 0.9347, 0.9435, 0.9512, 0.9578, 0.9636, 0.9686, 0.973, 0.9767, 0.98, 0.9828, 0.9852, 0.9873, 0.9891, 0.9907, 0.992, 0.9931, 0.9941, 0.995, 0.9957, 0.9963, 0.9969, 0.9973, 0.9977, 1);
--md-sys-motion-effects-slow-duration: 300ms;
/* damping 1.0, stiffness 3800; settles in 150ms; sampled over 150ms */
--md-sys-motion-effects-fast: linear(0, 0.0163, 0.0576, 0.1147, 0.1807, 0.2507, 0.3214, 0.3902, 0.4558, 0.5172, 0.5737, 0.6253, 0.6718, 0.7136, 0.7508, 0.7837, 0.8128, 0.8383, 0.8606, 0.8801, 0.897, 0.9117, 0.9244, 0.9353, 0.9448, 0.9529, 0.9599, 0.9658, 0.9709, 0.9753, 0.979, 0.9822, 0.9849, 0.9872, 0.9892, 0.9909, 0.9923, 0.9935, 0.9945, 0.9954, 0.9961, 0.9967, 0.9972, 0.9977, 0.998, 0.9983, 0.9986, 0.9988, 1);
--md-sys-motion-effects-fast-duration: 150ms;
--md-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
--md-sys-motion-easing-standard-accelerate: cubic-bezier(0.3, 0, 1, 1);
--md-sys-motion-easing-standard-decelerate: cubic-bezier(0, 0, 0, 1);
--md-sys-motion-easing-emphasized: cubic-bezier(0.2, 0, 0, 1);
--md-sys-motion-easing-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15);
--md-sys-motion-easing-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1);
--md-sys-motion-duration-short: 150ms;
--md-sys-motion-duration-medium: 300ms;
--md-sys-motion-duration-long: 500ms;
}
/* damping 1.0, stiffness 1600; settles in 240ms; sampled over 200ms */
--md-sys-motion-effects-default: linear(0, 0.0124, 0.0446, 0.0902, 0.1443, 0.2032, 0.2642, 0.3253, 0.3849, 0.4422, 0.4963, 0.547, 0.594, 0.6372, 0.6768, 0.7127, 0.7452, 0.7745, 0.8009, 0.8244, 0.8454, 0.8641, 0.8807, 0.8954, 0.9084, 0.9199, 0.93, 0.9389, 0.9467, 0.9536, 0.9596, 0.9648, 0.9694, 0.9734, 0.9769, 0.98, 0.9826, 0.985, 0.987, 0.9887, 0.9902, 0.9916, 0.9927, 0.9937, 0.9946, 0.9953, 0.9959, 0.9965, 1);
--md-sys-motion-effects-default-duration: 200ms;
/*
* The Standard scheme: the same three spatial springs at a damping ratio of 0.9, which leaves
* a 0.2% overshoot instead of Expressive's 9% motion that eases into place rather than
* bouncing. Google's web durations for them are 350/500/750 ms; the effects springs, the
* legacy easings and every other token are the ones above.
*/
[data-motion="standard"] {
/* damping 0.9, stiffness 1400; settles in 230ms; peaks at 1.002 at 193ms; sampled over 350ms */
--md-sys-motion-spatial-fast: linear(0, 0.0316, 0.1076, 0.2062, 0.313, 0.4185, 0.517, 0.6056, 0.6828, 0.7486, 0.8036, 0.8487, 0.8852, 0.9142, 0.937, 0.9546, 0.968, 0.9781, 0.9856, 0.991, 0.9948, 0.9975, 0.9992, 1.0004, 1.001, 1.0014, 1.0015, 1.0015, 1.0014, 1.0013, 1.0011, 1.001, 1.0008, 1.0007, 1.0005, 1.0004, 1.0003, 1.0003, 1.0002, 1.0001, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1);
--md-sys-motion-spatial-fast-duration: 350ms;
/* damping 1.0, stiffness 800; settles in 330ms; sampled over 300ms */
--md-sys-motion-effects-slow: linear(0, 0.0139, 0.0496, 0.0995, 0.1583, 0.2216, 0.2865, 0.3509, 0.4131, 0.4722, 0.5275, 0.5788, 0.6258, 0.6687, 0.7075, 0.7424, 0.7737, 0.8016, 0.8264, 0.8484, 0.8678, 0.8849, 0.8999, 0.9131, 0.9247, 0.9347, 0.9435, 0.9512, 0.9578, 0.9636, 0.9686, 0.973, 0.9767, 0.98, 0.9828, 0.9852, 0.9873, 0.9891, 0.9907, 0.992, 0.9931, 0.9941, 0.995, 0.9957, 0.9963, 0.9969, 0.9973, 0.9977, 1);
--md-sys-motion-effects-slow-duration: 300ms;
/* damping 0.9, stiffness 700; settles in 320ms; peaks at 1.002 at 272ms; sampled over 500ms */
--md-sys-motion-spatial-default: linear(0, 0.0322, 0.1094, 0.2094, 0.3173, 0.4237, 0.5227, 0.6114, 0.6886, 0.7541, 0.8086, 0.8532, 0.8891, 0.9175, 0.9397, 0.9569, 0.9699, 0.9796, 0.9867, 0.9918, 0.9954, 0.9979, 0.9995, 1.0006, 1.0011, 1.0014, 1.0015, 1.0015, 1.0014, 1.0012, 1.0011, 1.0009, 1.0007, 1.0006, 1.0005, 1.0004, 1.0003, 1.0002, 1.0002, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1, 1);
--md-sys-motion-spatial-default-duration: 500ms;
--md-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
--md-sys-motion-easing-standard-accelerate: cubic-bezier(0.3, 0, 1, 1);
--md-sys-motion-easing-standard-decelerate: cubic-bezier(0, 0, 0, 1);
--md-sys-motion-easing-emphasized: cubic-bezier(0.2, 0, 0, 1);
--md-sys-motion-easing-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15);
--md-sys-motion-easing-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1);
--md-sys-motion-duration-short: 150ms;
--md-sys-motion-duration-medium: 300ms;
--md-sys-motion-duration-long: 500ms;
}
/* damping 0.9, stiffness 300; settles in 490ms; peaks at 1.002 at 416ms; sampled over 750ms */
--md-sys-motion-spatial-slow: linear(0, 0.0311, 0.1061, 0.2037, 0.3095, 0.4143, 0.5125, 0.6009, 0.6782, 0.7442, 0.7995, 0.8451, 0.882, 0.9115, 0.9347, 0.9527, 0.9665, 0.9769, 0.9846, 0.9903, 0.9943, 0.9971, 0.999, 1.0002, 1.0009, 1.0013, 1.0015, 1.0015, 1.0014, 1.0013, 1.0012, 1.001, 1.0008, 1.0007, 1.0006, 1.0005, 1.0004, 1.0003, 1.0002, 1.0002, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1);
--md-sys-motion-spatial-slow-duration: 750ms;
}
@media (prefers-reduced-motion: reduce) {
:root,
/*
* The Standard scheme: the same three spatial springs at a damping ratio of 0.9, which leaves
* a 0.2% overshoot instead of Expressive's 9% motion that eases into place rather than
* bouncing. Google's web durations for them are 350/500/750 ms; the effects springs, the
* legacy easings and every other token are the ones above.
*/
[data-motion="standard"] {
--md-sys-motion-spatial-fast-duration: 0ms;
--md-sys-motion-spatial-default-duration: 0ms;
--md-sys-motion-spatial-slow-duration: 0ms;
--md-sys-motion-effects-fast-duration: 0ms;
--md-sys-motion-effects-default-duration: 0ms;
--md-sys-motion-effects-slow-duration: 0ms;
--md-sys-motion-duration-short: 0ms;
--md-sys-motion-duration-medium: 0ms;
--md-sys-motion-duration-long: 0ms;
/* damping 0.9, stiffness 1400; settles in 230ms; peaks at 1.002 at 193ms; sampled over 350ms */
--md-sys-motion-spatial-fast: linear(0, 0.0316, 0.1076, 0.2062, 0.313, 0.4185, 0.517, 0.6056, 0.6828, 0.7486, 0.8036, 0.8487, 0.8852, 0.9142, 0.937, 0.9546, 0.968, 0.9781, 0.9856, 0.991, 0.9948, 0.9975, 0.9992, 1.0004, 1.001, 1.0014, 1.0015, 1.0015, 1.0014, 1.0013, 1.0011, 1.001, 1.0008, 1.0007, 1.0005, 1.0004, 1.0003, 1.0003, 1.0002, 1.0001, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1);
--md-sys-motion-spatial-fast-duration: 350ms;
/* damping 0.9, stiffness 700; settles in 320ms; peaks at 1.002 at 272ms; sampled over 500ms */
--md-sys-motion-spatial-default: linear(0, 0.0322, 0.1094, 0.2094, 0.3173, 0.4237, 0.5227, 0.6114, 0.6886, 0.7541, 0.8086, 0.8532, 0.8891, 0.9175, 0.9397, 0.9569, 0.9699, 0.9796, 0.9867, 0.9918, 0.9954, 0.9979, 0.9995, 1.0006, 1.0011, 1.0014, 1.0015, 1.0015, 1.0014, 1.0012, 1.0011, 1.0009, 1.0007, 1.0006, 1.0005, 1.0004, 1.0003, 1.0002, 1.0002, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1, 1);
--md-sys-motion-spatial-default-duration: 500ms;
/* damping 0.9, stiffness 300; settles in 490ms; peaks at 1.002 at 416ms; sampled over 750ms */
--md-sys-motion-spatial-slow: linear(0, 0.0311, 0.1061, 0.2037, 0.3095, 0.4143, 0.5125, 0.6009, 0.6782, 0.7442, 0.7995, 0.8451, 0.882, 0.9115, 0.9347, 0.9527, 0.9665, 0.9769, 0.9846, 0.9903, 0.9943, 0.9971, 0.999, 1.0002, 1.0009, 1.0013, 1.0015, 1.0015, 1.0014, 1.0013, 1.0012, 1.001, 1.0008, 1.0007, 1.0006, 1.0005, 1.0004, 1.0003, 1.0002, 1.0002, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1);
--md-sys-motion-spatial-slow-duration: 750ms;
}
@media (prefers-reduced-motion: reduce) {
:root,
[data-motion="standard"] {
--md-sys-motion-spatial-fast-duration: 0ms;
--md-sys-motion-spatial-default-duration: 0ms;
--md-sys-motion-spatial-slow-duration: 0ms;
--md-sys-motion-effects-fast-duration: 0ms;
--md-sys-motion-effects-default-duration: 0ms;
--md-sys-motion-effects-slow-duration: 0ms;
--md-sys-motion-duration-short: 0ms;
--md-sys-motion-duration-medium: 0ms;
--md-sys-motion-duration-long: 0ms;
}
}
}
+422 -414
View File
@@ -11,431 +11,439 @@
* data-contrast which the head script writes from the visitor's choice, or from the
* operating system's contrast setting while that choice is `system`. No media query
* decides here, as none decides the theme.
*
* This is the package's default scheme, so the generated blocks are wrapped in
* `material.tokens` behind the layer statement (keep both when regenerating into this file): an
* application's own scheme, written unlayered, outranks it whatever the selectors.
*/
:root,
[data-theme='light'] {
color-scheme: light;
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
--md-sys-color-background: #fdf7fe;
--md-sys-color-on-background: #34313a;
--md-sys-color-surface: #fdf7fe;
--md-sys-color-surface-dim: #ded8e4;
--md-sys-color-surface-bright: #fdf7fe;
--md-sys-color-surface-container-lowest: #ffffff;
--md-sys-color-surface-container-low: #f8f1fa;
--md-sys-color-surface-container: #f2ecf5;
--md-sys-color-surface-container-high: #ece6f0;
--md-sys-color-surface-container-highest: #e7e0ec;
--md-sys-color-on-surface: #34313a;
--md-sys-color-on-surface-variant: #615d68;
--md-sys-color-outline: #7d7983;
--md-sys-color-outline-variant: #b5b0bb;
--md-sys-color-inverse-surface: #0f0d12;
--md-sys-color-inverse-on-surface: #a09ba1;
--md-sys-color-primary: #655789;
--md-sys-color-primary-dim: #594b7c;
--md-sys-color-on-primary: #fdf7ff;
--md-sys-color-primary-container: #d4c3fd;
--md-sys-color-on-primary-container: #493c6c;
--md-sys-color-primary-fixed: #d4c3fd;
--md-sys-color-primary-fixed-dim: #c6b6ee;
--md-sys-color-on-primary-fixed: #352857;
--md-sys-color-on-primary-fixed-variant: #524576;
--md-sys-color-inverse-primary: #d4c3fd;
--md-sys-color-secondary: #625c71;
--md-sys-color-secondary-dim: #565065;
--md-sys-color-on-secondary: #fdf7ff;
--md-sys-color-secondary-container: #e8def8;
--md-sys-color-on-secondary-container: #554f63;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #423c50;
--md-sys-color-on-secondary-fixed-variant: #5f586e;
--md-sys-color-tertiary: #7b5270;
--md-sys-color-tertiary-dim: #6e4664;
--md-sys-color-on-tertiary: #fff7f9;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #5f3956;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #4a2642;
--md-sys-color-on-tertiary-fixed-variant: #694260;
--md-sys-color-error: #a8364b;
--md-sys-color-error-dim: #6b0221;
--md-sys-color-on-error: #fff7f7;
--md-sys-color-error-container: #f97386;
--md-sys-color-on-error-container: #6e0523;
--md-sys-color-success: #006d46;
--md-sys-color-on-success: #e7ffed;
--md-sys-color-success-container: #86f9bc;
--md-sys-color-on-success-container: #00734a;
--md-sys-color-warning: #7c5900;
--md-sys-color-on-warning: #fff8f1;
--md-sys-color-warning-container: #fab925;
--md-sys-color-on-warning-container: #6a4b00;
--md-sys-color-info: #005bc5;
--md-sys-color-on-info: #f9f8ff;
--md-sys-color-info-container: #1c7afc;
--md-sys-color-on-info-container: #001435;
--md-sys-color-inverse-error: #f97386;
--md-sys-color-inverse-success: #3bb27b;
--md-sys-color-inverse-warning: #f3b31e;
--md-sys-color-inverse-info: #699cff;
}
@layer material.tokens {
:root,
[data-theme='light'] {
color-scheme: light;
[data-theme='dark'] {
color-scheme: dark;
--md-sys-color-background: #fdf7fe;
--md-sys-color-on-background: #34313a;
--md-sys-color-surface: #fdf7fe;
--md-sys-color-surface-dim: #ded8e4;
--md-sys-color-surface-bright: #fdf7fe;
--md-sys-color-surface-container-lowest: #ffffff;
--md-sys-color-surface-container-low: #f8f1fa;
--md-sys-color-surface-container: #f2ecf5;
--md-sys-color-surface-container-high: #ece6f0;
--md-sys-color-surface-container-highest: #e7e0ec;
--md-sys-color-on-surface: #34313a;
--md-sys-color-on-surface-variant: #615d68;
--md-sys-color-outline: #7d7983;
--md-sys-color-outline-variant: #b5b0bb;
--md-sys-color-inverse-surface: #0f0d12;
--md-sys-color-inverse-on-surface: #a09ba1;
--md-sys-color-primary: #655789;
--md-sys-color-primary-dim: #594b7c;
--md-sys-color-on-primary: #fdf7ff;
--md-sys-color-primary-container: #d4c3fd;
--md-sys-color-on-primary-container: #493c6c;
--md-sys-color-primary-fixed: #d4c3fd;
--md-sys-color-primary-fixed-dim: #c6b6ee;
--md-sys-color-on-primary-fixed: #352857;
--md-sys-color-on-primary-fixed-variant: #524576;
--md-sys-color-inverse-primary: #d4c3fd;
--md-sys-color-secondary: #625c71;
--md-sys-color-secondary-dim: #565065;
--md-sys-color-on-secondary: #fdf7ff;
--md-sys-color-secondary-container: #e8def8;
--md-sys-color-on-secondary-container: #554f63;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #423c50;
--md-sys-color-on-secondary-fixed-variant: #5f586e;
--md-sys-color-tertiary: #7b5270;
--md-sys-color-tertiary-dim: #6e4664;
--md-sys-color-on-tertiary: #fff7f9;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #5f3956;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #4a2642;
--md-sys-color-on-tertiary-fixed-variant: #694260;
--md-sys-color-error: #a8364b;
--md-sys-color-error-dim: #6b0221;
--md-sys-color-on-error: #fff7f7;
--md-sys-color-error-container: #f97386;
--md-sys-color-on-error-container: #6e0523;
--md-sys-color-success: #006d46;
--md-sys-color-on-success: #e7ffed;
--md-sys-color-success-container: #86f9bc;
--md-sys-color-on-success-container: #00734a;
--md-sys-color-warning: #7c5900;
--md-sys-color-on-warning: #fff8f1;
--md-sys-color-warning-container: #fab925;
--md-sys-color-on-warning-container: #6a4b00;
--md-sys-color-info: #005bc5;
--md-sys-color-on-info: #f9f8ff;
--md-sys-color-info-container: #1c7afc;
--md-sys-color-on-info-container: #001435;
--md-sys-color-inverse-error: #f97386;
--md-sys-color-inverse-success: #3bb27b;
--md-sys-color-inverse-warning: #f3b31e;
--md-sys-color-inverse-info: #699cff;
}
--md-sys-color-background: #0f0d12;
--md-sys-color-on-background: #eae3ef;
--md-sys-color-surface: #0f0d12;
--md-sys-color-surface-dim: #0f0d12;
--md-sys-color-surface-bright: #2e2b34;
--md-sys-color-surface-container-lowest: #000000;
--md-sys-color-surface-container-low: #141218;
--md-sys-color-surface-container: #1b181f;
--md-sys-color-surface-container-high: #211e26;
--md-sys-color-surface-container-highest: #27242d;
--md-sys-color-on-surface: #eae3ef;
--md-sys-color-on-surface-variant: #aea9b4;
--md-sys-color-outline: #78737e;
--md-sys-color-outline-variant: #4a4650;
--md-sys-color-inverse-surface: #fdf7fe;
--md-sys-color-inverse-on-surface: #575459;
--md-sys-color-primary: #cdc0ec;
--md-sys-color-primary-dim: #bfb2de;
--md-sys-color-on-primary: #443a5f;
--md-sys-color-primary-container: #574d72;
--md-sys-color-on-primary-container: #e9deff;
--md-sys-color-primary-fixed: #ded0fe;
--md-sys-color-primary-fixed-dim: #d0c3ef;
--md-sys-color-on-primary-fixed: #3c3256;
--md-sys-color-on-primary-fixed-variant: #594e74;
--md-sys-color-inverse-primary: #645980;
--md-sys-color-secondary: #cbc2db;
--md-sys-color-secondary-dim: #beb5cd;
--md-sys-color-on-secondary: #433d51;
--md-sys-color-secondary-container: #3e384c;
--md-sys-color-on-secondary-container: #c4bbd4;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #423c50;
--md-sys-color-on-secondary-fixed-variant: #5f586e;
--md-sys-color-tertiary: #ffcfef;
--md-sys-color-tertiary-dim: #f4bfe3;
--md-sys-color-on-tertiary: #69415f;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #5f3956;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #4a2642;
--md-sys-color-on-tertiary-fixed-variant: #694260;
--md-sys-color-error: #f97386;
--md-sys-color-error-dim: #c44b5f;
--md-sys-color-on-error: #490013;
--md-sys-color-error-container: #871c34;
--md-sys-color-on-error-container: #ff97a3;
--md-sys-color-success: #3bb27b;
--md-sys-color-on-success: #002615;
--md-sys-color-success-container: #059460;
--md-sys-color-on-success-container: #001e10;
--md-sys-color-warning: #f3b31e;
--md-sys-color-on-warning: #4e3600;
--md-sys-color-warning-container: #e4a604;
--md-sys-color-on-warning-container: #593f00;
--md-sys-color-info: #699cff;
--md-sys-color-on-info: #001e4b;
--md-sys-color-info-container: #0c74f6;
--md-sys-color-on-info-container: #000a23;
--md-sys-color-inverse-error: #a8364b;
--md-sys-color-inverse-success: #006d46;
--md-sys-color-inverse-warning: #7c5900;
--md-sys-color-inverse-info: #005bc5;
}
[data-theme='dark'] {
color-scheme: dark;
[data-contrast='medium'],
[data-contrast='medium'][data-theme='light'],
[data-contrast='medium'] [data-theme='light'] {
color-scheme: light;
--md-sys-color-background: #0f0d12;
--md-sys-color-on-background: #eae3ef;
--md-sys-color-surface: #0f0d12;
--md-sys-color-surface-dim: #0f0d12;
--md-sys-color-surface-bright: #2e2b34;
--md-sys-color-surface-container-lowest: #000000;
--md-sys-color-surface-container-low: #141218;
--md-sys-color-surface-container: #1b181f;
--md-sys-color-surface-container-high: #211e26;
--md-sys-color-surface-container-highest: #27242d;
--md-sys-color-on-surface: #eae3ef;
--md-sys-color-on-surface-variant: #aea9b4;
--md-sys-color-outline: #78737e;
--md-sys-color-outline-variant: #4a4650;
--md-sys-color-inverse-surface: #fdf7fe;
--md-sys-color-inverse-on-surface: #575459;
--md-sys-color-primary: #cdc0ec;
--md-sys-color-primary-dim: #bfb2de;
--md-sys-color-on-primary: #443a5f;
--md-sys-color-primary-container: #574d72;
--md-sys-color-on-primary-container: #e9deff;
--md-sys-color-primary-fixed: #ded0fe;
--md-sys-color-primary-fixed-dim: #d0c3ef;
--md-sys-color-on-primary-fixed: #3c3256;
--md-sys-color-on-primary-fixed-variant: #594e74;
--md-sys-color-inverse-primary: #645980;
--md-sys-color-secondary: #cbc2db;
--md-sys-color-secondary-dim: #beb5cd;
--md-sys-color-on-secondary: #433d51;
--md-sys-color-secondary-container: #3e384c;
--md-sys-color-on-secondary-container: #c4bbd4;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #423c50;
--md-sys-color-on-secondary-fixed-variant: #5f586e;
--md-sys-color-tertiary: #ffcfef;
--md-sys-color-tertiary-dim: #f4bfe3;
--md-sys-color-on-tertiary: #69415f;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #5f3956;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #4a2642;
--md-sys-color-on-tertiary-fixed-variant: #694260;
--md-sys-color-error: #f97386;
--md-sys-color-error-dim: #c44b5f;
--md-sys-color-on-error: #490013;
--md-sys-color-error-container: #871c34;
--md-sys-color-on-error-container: #ff97a3;
--md-sys-color-success: #3bb27b;
--md-sys-color-on-success: #002615;
--md-sys-color-success-container: #059460;
--md-sys-color-on-success-container: #001e10;
--md-sys-color-warning: #f3b31e;
--md-sys-color-on-warning: #4e3600;
--md-sys-color-warning-container: #e4a604;
--md-sys-color-on-warning-container: #593f00;
--md-sys-color-info: #699cff;
--md-sys-color-on-info: #001e4b;
--md-sys-color-info-container: #0c74f6;
--md-sys-color-on-info-container: #000a23;
--md-sys-color-inverse-error: #a8364b;
--md-sys-color-inverse-success: #006d46;
--md-sys-color-inverse-warning: #7c5900;
--md-sys-color-inverse-info: #005bc5;
}
--md-sys-color-background: #fdf7fe;
--md-sys-color-on-background: #25232b;
--md-sys-color-surface: #fdf7fe;
--md-sys-color-surface-dim: #ded8e4;
--md-sys-color-surface-bright: #fdf7fe;
--md-sys-color-surface-container-lowest: #ffffff;
--md-sys-color-surface-container-low: #f8f1fa;
--md-sys-color-surface-container: #f2ecf5;
--md-sys-color-surface-container-high: #ece6f0;
--md-sys-color-surface-container-highest: #e7e0ec;
--md-sys-color-on-surface: #25232b;
--md-sys-color-on-surface-variant: #45414b;
--md-sys-color-outline: #615d68;
--md-sys-color-outline-variant: #7d7983;
--md-sys-color-inverse-surface: #0f0d12;
--md-sys-color-inverse-on-surface: #c8c3c9;
--md-sys-color-primary: #483b6b;
--md-sys-color-primary-dim: #3c305f;
--md-sys-color-on-primary: #e1d3ff;
--md-sys-color-primary-container: #7b6da0;
--md-sys-color-on-primary-container: #ffffff;
--md-sys-color-primary-fixed: #7b6da0;
--md-sys-color-primary-fixed-dim: #6e6093;
--md-sys-color-on-primary-fixed: #ffffff;
--md-sys-color-on-primary-fixed-variant: #ffffff;
--md-sys-color-inverse-primary: #d4c3fd;
--md-sys-color-secondary: #464054;
--md-sys-color-secondary-dim: #3a3548;
--md-sys-color-on-secondary: #dfd5ef;
--md-sys-color-secondary-container: #787187;
--md-sys-color-on-secondary-container: #ffffff;
--md-sys-color-secondary-fixed: #787187;
--md-sys-color-secondary-fixed-dim: #6c657b;
--md-sys-color-on-secondary-fixed: #ffffff;
--md-sys-color-on-secondary-fixed-variant: #ffffff;
--md-sys-color-tertiary: #5c3653;
--md-sys-color-tertiary-dim: #502b47;
--md-sys-color-on-tertiary: #ffcaee;
--md-sys-color-tertiary-container: #936787;
--md-sys-color-on-tertiary-container: #ffffff;
--md-sys-color-tertiary-fixed: #936787;
--md-sys-color-tertiary-fixed-dim: #855b7a;
--md-sys-color-on-tertiary-fixed: #ffffff;
--md-sys-color-on-tertiary-fixed-variant: #ffffff;
--md-sys-color-error: #821830;
--md-sys-color-error-dim: #6b0221;
--md-sys-color-on-error: #ffcdd1;
--md-sys-color-error-container: #c44b5f;
--md-sys-color-on-error-container: #ffffff;
--md-sys-color-success: #004d30;
--md-sys-color-on-success: #7df0b3;
--md-sys-color-success-container: #008656;
--md-sys-color-on-success-container: #ffffff;
--md-sys-color-warning: #593e00;
--md-sys-color-on-warning: #ffd385;
--md-sys-color-warning-container: #986d00;
--md-sys-color-on-warning-container: #ffffff;
--md-sys-color-info: #003f8e;
--md-sys-color-on-info: #cbd9ff;
--md-sys-color-info-container: #006fef;
--md-sys-color-on-info-container: #ffffff;
--md-sys-color-inverse-error: #ff9da8;
--md-sys-color-inverse-success: #5ace94;
--md-sys-color-inverse-warning: #f3b31e;
--md-sys-color-inverse-info: #98b8ff;
}
[data-contrast='medium'],
[data-contrast='medium'][data-theme='light'],
[data-contrast='medium'] [data-theme='light'] {
color-scheme: light;
[data-contrast='medium'][data-theme='dark'],
[data-contrast='medium'] [data-theme='dark'] {
color-scheme: dark;
--md-sys-color-background: #fdf7fe;
--md-sys-color-on-background: #25232b;
--md-sys-color-surface: #fdf7fe;
--md-sys-color-surface-dim: #ded8e4;
--md-sys-color-surface-bright: #fdf7fe;
--md-sys-color-surface-container-lowest: #ffffff;
--md-sys-color-surface-container-low: #f8f1fa;
--md-sys-color-surface-container: #f2ecf5;
--md-sys-color-surface-container-high: #ece6f0;
--md-sys-color-surface-container-highest: #e7e0ec;
--md-sys-color-on-surface: #25232b;
--md-sys-color-on-surface-variant: #45414b;
--md-sys-color-outline: #615d68;
--md-sys-color-outline-variant: #7d7983;
--md-sys-color-inverse-surface: #0f0d12;
--md-sys-color-inverse-on-surface: #c8c3c9;
--md-sys-color-primary: #483b6b;
--md-sys-color-primary-dim: #3c305f;
--md-sys-color-on-primary: #e1d3ff;
--md-sys-color-primary-container: #7b6da0;
--md-sys-color-on-primary-container: #ffffff;
--md-sys-color-primary-fixed: #7b6da0;
--md-sys-color-primary-fixed-dim: #6e6093;
--md-sys-color-on-primary-fixed: #ffffff;
--md-sys-color-on-primary-fixed-variant: #ffffff;
--md-sys-color-inverse-primary: #d4c3fd;
--md-sys-color-secondary: #464054;
--md-sys-color-secondary-dim: #3a3548;
--md-sys-color-on-secondary: #dfd5ef;
--md-sys-color-secondary-container: #787187;
--md-sys-color-on-secondary-container: #ffffff;
--md-sys-color-secondary-fixed: #787187;
--md-sys-color-secondary-fixed-dim: #6c657b;
--md-sys-color-on-secondary-fixed: #ffffff;
--md-sys-color-on-secondary-fixed-variant: #ffffff;
--md-sys-color-tertiary: #5c3653;
--md-sys-color-tertiary-dim: #502b47;
--md-sys-color-on-tertiary: #ffcaee;
--md-sys-color-tertiary-container: #936787;
--md-sys-color-on-tertiary-container: #ffffff;
--md-sys-color-tertiary-fixed: #936787;
--md-sys-color-tertiary-fixed-dim: #855b7a;
--md-sys-color-on-tertiary-fixed: #ffffff;
--md-sys-color-on-tertiary-fixed-variant: #ffffff;
--md-sys-color-error: #821830;
--md-sys-color-error-dim: #6b0221;
--md-sys-color-on-error: #ffcdd1;
--md-sys-color-error-container: #c44b5f;
--md-sys-color-on-error-container: #ffffff;
--md-sys-color-success: #004d30;
--md-sys-color-on-success: #7df0b3;
--md-sys-color-success-container: #008656;
--md-sys-color-on-success-container: #ffffff;
--md-sys-color-warning: #593e00;
--md-sys-color-on-warning: #ffd385;
--md-sys-color-warning-container: #986d00;
--md-sys-color-on-warning-container: #ffffff;
--md-sys-color-info: #003f8e;
--md-sys-color-on-info: #cbd9ff;
--md-sys-color-info-container: #006fef;
--md-sys-color-on-info-container: #ffffff;
--md-sys-color-inverse-error: #ff9da8;
--md-sys-color-inverse-success: #5ace94;
--md-sys-color-inverse-warning: #f3b31e;
--md-sys-color-inverse-info: #98b8ff;
}
--md-sys-color-background: #0f0d12;
--md-sys-color-on-background: #ffffff;
--md-sys-color-surface: #0f0d12;
--md-sys-color-surface-dim: #0f0d12;
--md-sys-color-surface-bright: #2e2b34;
--md-sys-color-surface-container-lowest: #000000;
--md-sys-color-surface-container-low: #141218;
--md-sys-color-surface-container: #1b181f;
--md-sys-color-surface-container-high: #211e26;
--md-sys-color-surface-container-highest: #27242d;
--md-sys-color-on-surface: #ffffff;
--md-sys-color-on-surface-variant: #bcb6c2;
--md-sys-color-outline: #96919c;
--md-sys-color-outline-variant: #78737e;
--md-sys-color-inverse-surface: #fdf7fe;
--md-sys-color-inverse-on-surface: #39373c;
--md-sys-color-primary: #cdc0ec;
--md-sys-color-primary-dim: #bfb2de;
--md-sys-color-on-primary: #3a3054;
--md-sys-color-primary-container: #7a6f96;
--md-sys-color-on-primary-container: #ffffff;
--md-sys-color-primary-fixed: #ded0fe;
--md-sys-color-primary-fixed-dim: #d0c3ef;
--md-sys-color-on-primary-fixed: #180e30;
--md-sys-color-on-primary-fixed-variant: #3c3256;
--md-sys-color-inverse-primary: #5a4f75;
--md-sys-color-secondary: #cbc2db;
--md-sys-color-secondary-dim: #beb5cd;
--md-sys-color-on-secondary: #393347;
--md-sys-color-secondary-container: #787187;
--md-sys-color-on-secondary-container: #ffffff;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #221d2f;
--md-sys-color-on-secondary-fixed-variant: #423c50;
--md-sys-color-tertiary: #ffcfef;
--md-sys-color-tertiary-dim: #f4bfe3;
--md-sys-color-on-tertiary: #5e3855;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #542f4c;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #180015;
--md-sys-color-on-tertiary-fixed-variant: #4a2642;
--md-sys-color-error: #ff9da8;
--md-sys-color-error-dim: #ff8695;
--md-sys-color-on-error: #5f001c;
--md-sys-color-error-container: #c44b5f;
--md-sys-color-on-error-container: #ffffff;
--md-sys-color-success: #5ace94;
--md-sys-color-on-success: #00341e;
--md-sys-color-success-container: #008656;
--md-sys-color-on-success-container: #ffffff;
--md-sys-color-warning: #f3b31e;
--md-sys-color-on-warning: #412d00;
--md-sys-color-warning-container: #e4a604;
--md-sys-color-on-warning-container: #332200;
--md-sys-color-info: #98b8ff;
--md-sys-color-on-info: #002a62;
--md-sys-color-info-container: #006fef;
--md-sys-color-on-info-container: #ffffff;
--md-sys-color-inverse-error: #821830;
--md-sys-color-inverse-success: #004d30;
--md-sys-color-inverse-warning: #593e00;
--md-sys-color-inverse-info: #003f8e;
}
[data-contrast='medium'][data-theme='dark'],
[data-contrast='medium'] [data-theme='dark'] {
color-scheme: dark;
[data-contrast='high'],
[data-contrast='high'][data-theme='light'],
[data-contrast='high'] [data-theme='light'] {
color-scheme: light;
--md-sys-color-background: #0f0d12;
--md-sys-color-on-background: #ffffff;
--md-sys-color-surface: #0f0d12;
--md-sys-color-surface-dim: #0f0d12;
--md-sys-color-surface-bright: #2e2b34;
--md-sys-color-surface-container-lowest: #000000;
--md-sys-color-surface-container-low: #141218;
--md-sys-color-surface-container: #1b181f;
--md-sys-color-surface-container-high: #211e26;
--md-sys-color-surface-container-highest: #27242d;
--md-sys-color-on-surface: #ffffff;
--md-sys-color-on-surface-variant: #bcb6c2;
--md-sys-color-outline: #96919c;
--md-sys-color-outline-variant: #78737e;
--md-sys-color-inverse-surface: #fdf7fe;
--md-sys-color-inverse-on-surface: #39373c;
--md-sys-color-primary: #cdc0ec;
--md-sys-color-primary-dim: #bfb2de;
--md-sys-color-on-primary: #3a3054;
--md-sys-color-primary-container: #7a6f96;
--md-sys-color-on-primary-container: #ffffff;
--md-sys-color-primary-fixed: #ded0fe;
--md-sys-color-primary-fixed-dim: #d0c3ef;
--md-sys-color-on-primary-fixed: #180e30;
--md-sys-color-on-primary-fixed-variant: #3c3256;
--md-sys-color-inverse-primary: #5a4f75;
--md-sys-color-secondary: #cbc2db;
--md-sys-color-secondary-dim: #beb5cd;
--md-sys-color-on-secondary: #393347;
--md-sys-color-secondary-container: #787187;
--md-sys-color-on-secondary-container: #ffffff;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #221d2f;
--md-sys-color-on-secondary-fixed-variant: #423c50;
--md-sys-color-tertiary: #ffcfef;
--md-sys-color-tertiary-dim: #f4bfe3;
--md-sys-color-on-tertiary: #5e3855;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #542f4c;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #180015;
--md-sys-color-on-tertiary-fixed-variant: #4a2642;
--md-sys-color-error: #ff9da8;
--md-sys-color-error-dim: #ff8695;
--md-sys-color-on-error: #5f001c;
--md-sys-color-error-container: #c44b5f;
--md-sys-color-on-error-container: #ffffff;
--md-sys-color-success: #5ace94;
--md-sys-color-on-success: #00341e;
--md-sys-color-success-container: #008656;
--md-sys-color-on-success-container: #ffffff;
--md-sys-color-warning: #f3b31e;
--md-sys-color-on-warning: #412d00;
--md-sys-color-warning-container: #e4a604;
--md-sys-color-on-warning-container: #332200;
--md-sys-color-info: #98b8ff;
--md-sys-color-on-info: #002a62;
--md-sys-color-info-container: #006fef;
--md-sys-color-on-info-container: #ffffff;
--md-sys-color-inverse-error: #821830;
--md-sys-color-inverse-success: #004d30;
--md-sys-color-inverse-warning: #593e00;
--md-sys-color-inverse-info: #003f8e;
}
--md-sys-color-background: #fdf7fe;
--md-sys-color-on-background: #000000;
--md-sys-color-surface: #fdf7fe;
--md-sys-color-surface-dim: #ded8e4;
--md-sys-color-surface-bright: #fdf7fe;
--md-sys-color-surface-container-lowest: #ffffff;
--md-sys-color-surface-container-low: #f8f1fa;
--md-sys-color-surface-container: #f2ecf5;
--md-sys-color-surface-container-high: #ece6f0;
--md-sys-color-surface-container-highest: #e7e0ec;
--md-sys-color-on-surface: #000000;
--md-sys-color-on-surface-variant: #25232b;
--md-sys-color-outline: #45414b;
--md-sys-color-outline-variant: #54505a;
--md-sys-color-inverse-surface: #0f0d12;
--md-sys-color-inverse-on-surface: #ffffff;
--md-sys-color-primary: #281b49;
--md-sys-color-primary-dim: #1e103f;
--md-sys-color-on-primary: #e1d3ff;
--md-sys-color-primary-container: #584a7b;
--md-sys-color-on-primary-container: #ffffff;
--md-sys-color-primary-fixed: #584a7b;
--md-sys-color-primary-fixed-dim: #4c3f6f;
--md-sys-color-on-primary-fixed: #ffffff;
--md-sys-color-on-primary-fixed-variant: #ffffff;
--md-sys-color-inverse-primary: #d4c3fd;
--md-sys-color-secondary: #262134;
--md-sys-color-secondary-dim: #1c1729;
--md-sys-color-on-secondary: #dfd6ef;
--md-sys-color-secondary-container: #554f64;
--md-sys-color-on-secondary-container: #ffffff;
--md-sys-color-secondary-fixed: #554f64;
--md-sys-color-secondary-fixed-dim: #494358;
--md-sys-color-on-secondary-fixed: #ffffff;
--md-sys-color-on-secondary-fixed-variant: #ffffff;
--md-sys-color-tertiary: #391733;
--md-sys-color-tertiary-dim: #2e0d28;
--md-sys-color-on-tertiary: #ffcbee;
--md-sys-color-tertiary-container: #6d4563;
--md-sys-color-on-tertiary-container: #ffffff;
--md-sys-color-tertiary-fixed: #6d4563;
--md-sys-color-tertiary-fixed-dim: #603a57;
--md-sys-color-on-tertiary-fixed: #ffffff;
--md-sys-color-on-tertiary-fixed-variant: #ffffff;
--md-sys-color-error: #500016;
--md-sys-color-error-dim: #3d000f;
--md-sys-color-on-error: #ffced2;
--md-sys-color-error-container: #97283e;
--md-sys-color-on-error-container: #ffffff;
--md-sys-color-success: #002a18;
--md-sys-color-on-success: #7df0b4;
--md-sys-color-success-container: #005f3c;
--md-sys-color-on-success-container: #ffffff;
--md-sys-color-warning: #312100;
--md-sys-color-on-warning: #ffd486;
--md-sys-color-warning-container: #6c4d00;
--md-sys-color-on-warning-container: #ffffff;
--md-sys-color-info: #002252;
--md-sys-color-on-info: #ccdaff;
--md-sys-color-info-container: #004eac;
--md-sys-color-on-info-container: #ffffff;
--md-sys-color-inverse-error: #ffdddf;
--md-sys-color-inverse-success: #89fcbf;
--md-sys-color-inverse-warning: #ffe2b1;
--md-sys-color-inverse-info: #dde5ff;
}
[data-contrast='high'],
[data-contrast='high'][data-theme='light'],
[data-contrast='high'] [data-theme='light'] {
color-scheme: light;
[data-contrast='high'][data-theme='dark'],
[data-contrast='high'] [data-theme='dark'] {
color-scheme: dark;
--md-sys-color-background: #fdf7fe;
--md-sys-color-on-background: #000000;
--md-sys-color-surface: #fdf7fe;
--md-sys-color-surface-dim: #ded8e4;
--md-sys-color-surface-bright: #fdf7fe;
--md-sys-color-surface-container-lowest: #ffffff;
--md-sys-color-surface-container-low: #f8f1fa;
--md-sys-color-surface-container: #f2ecf5;
--md-sys-color-surface-container-high: #ece6f0;
--md-sys-color-surface-container-highest: #e7e0ec;
--md-sys-color-on-surface: #000000;
--md-sys-color-on-surface-variant: #25232b;
--md-sys-color-outline: #45414b;
--md-sys-color-outline-variant: #54505a;
--md-sys-color-inverse-surface: #0f0d12;
--md-sys-color-inverse-on-surface: #ffffff;
--md-sys-color-primary: #281b49;
--md-sys-color-primary-dim: #1e103f;
--md-sys-color-on-primary: #e1d3ff;
--md-sys-color-primary-container: #584a7b;
--md-sys-color-on-primary-container: #ffffff;
--md-sys-color-primary-fixed: #584a7b;
--md-sys-color-primary-fixed-dim: #4c3f6f;
--md-sys-color-on-primary-fixed: #ffffff;
--md-sys-color-on-primary-fixed-variant: #ffffff;
--md-sys-color-inverse-primary: #d4c3fd;
--md-sys-color-secondary: #262134;
--md-sys-color-secondary-dim: #1c1729;
--md-sys-color-on-secondary: #dfd6ef;
--md-sys-color-secondary-container: #554f64;
--md-sys-color-on-secondary-container: #ffffff;
--md-sys-color-secondary-fixed: #554f64;
--md-sys-color-secondary-fixed-dim: #494358;
--md-sys-color-on-secondary-fixed: #ffffff;
--md-sys-color-on-secondary-fixed-variant: #ffffff;
--md-sys-color-tertiary: #391733;
--md-sys-color-tertiary-dim: #2e0d28;
--md-sys-color-on-tertiary: #ffcbee;
--md-sys-color-tertiary-container: #6d4563;
--md-sys-color-on-tertiary-container: #ffffff;
--md-sys-color-tertiary-fixed: #6d4563;
--md-sys-color-tertiary-fixed-dim: #603a57;
--md-sys-color-on-tertiary-fixed: #ffffff;
--md-sys-color-on-tertiary-fixed-variant: #ffffff;
--md-sys-color-error: #500016;
--md-sys-color-error-dim: #3d000f;
--md-sys-color-on-error: #ffced2;
--md-sys-color-error-container: #97283e;
--md-sys-color-on-error-container: #ffffff;
--md-sys-color-success: #002a18;
--md-sys-color-on-success: #7df0b4;
--md-sys-color-success-container: #005f3c;
--md-sys-color-on-success-container: #ffffff;
--md-sys-color-warning: #312100;
--md-sys-color-on-warning: #ffd486;
--md-sys-color-warning-container: #6c4d00;
--md-sys-color-on-warning-container: #ffffff;
--md-sys-color-info: #002252;
--md-sys-color-on-info: #ccdaff;
--md-sys-color-info-container: #004eac;
--md-sys-color-on-info-container: #ffffff;
--md-sys-color-inverse-error: #ffdddf;
--md-sys-color-inverse-success: #89fcbf;
--md-sys-color-inverse-warning: #ffe2b1;
--md-sys-color-inverse-info: #dde5ff;
}
--md-sys-color-background: #0f0d12;
--md-sys-color-on-background: #ffffff;
--md-sys-color-surface: #0f0d12;
--md-sys-color-surface-dim: #0f0d12;
--md-sys-color-surface-bright: #2e2b34;
--md-sys-color-surface-container-lowest: #000000;
--md-sys-color-surface-container-low: #141218;
--md-sys-color-surface-container: #1b181f;
--md-sys-color-surface-container-high: #211e26;
--md-sys-color-surface-container-highest: #27242d;
--md-sys-color-on-surface: #ffffff;
--md-sys-color-on-surface-variant: #eae3ef;
--md-sys-color-outline: #bcb6c2;
--md-sys-color-outline-variant: #a7a1ad;
--md-sys-color-inverse-surface: #fdf7fe;
--md-sys-color-inverse-on-surface: #000000;
--md-sys-color-primary: #ebe1ff;
--md-sys-color-primary-dim: #ded0fe;
--md-sys-color-on-primary: #302649;
--md-sys-color-primary-container: #aa9dc8;
--md-sys-color-on-primary-container: #000000;
--md-sys-color-primary-fixed: #ded0fe;
--md-sys-color-primary-fixed-dim: #d0c3ef;
--md-sys-color-on-primary-fixed: #000000;
--md-sys-color-on-primary-fixed-variant: #180e30;
--md-sys-color-inverse-primary: #3c3256;
--md-sys-color-secondary: #ebe1fb;
--md-sys-color-secondary-dim: #ddd3ed;
--md-sys-color-on-secondary: #2e293c;
--md-sys-color-secondary-container: #a8a0b8;
--md-sys-color-on-secondary-container: #000000;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #000000;
--md-sys-color-on-secondary-fixed-variant: #221d2f;
--md-sys-color-tertiary: #ffdbf2;
--md-sys-color-tertiary-dim: #fac5e9;
--md-sys-color-on-tertiary: #43203b;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #2e0e29;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #000000;
--md-sys-color-on-tertiary-fixed-variant: #180015;
--md-sys-color-error: #ffdddf;
--md-sys-color-error-dim: #ffc7cb;
--md-sys-color-on-error: #5f001c;
--md-sys-color-error-container: #ff798c;
--md-sys-color-on-error-container: #000000;
--md-sys-color-success: #89fcbf;
--md-sys-color-on-success: #00341e;
--md-sys-color-success-container: #42b880;
--md-sys-color-on-success-container: #000000;
--md-sys-color-warning: #ffe2b1;
--md-sys-color-on-warning: #3c2900;
--md-sys-color-warning-container: #e4a604;
--md-sys-color-on-warning-container: #000000;
--md-sys-color-info: #dde5ff;
--md-sys-color-on-info: #002a62;
--md-sys-color-info-container: #74a2ff;
--md-sys-color-on-info-container: #000000;
--md-sys-color-inverse-error: #500016;
--md-sys-color-inverse-success: #002a18;
--md-sys-color-inverse-warning: #312100;
--md-sys-color-inverse-info: #002252;
[data-contrast='high'][data-theme='dark'],
[data-contrast='high'] [data-theme='dark'] {
color-scheme: dark;
--md-sys-color-background: #0f0d12;
--md-sys-color-on-background: #ffffff;
--md-sys-color-surface: #0f0d12;
--md-sys-color-surface-dim: #0f0d12;
--md-sys-color-surface-bright: #2e2b34;
--md-sys-color-surface-container-lowest: #000000;
--md-sys-color-surface-container-low: #141218;
--md-sys-color-surface-container: #1b181f;
--md-sys-color-surface-container-high: #211e26;
--md-sys-color-surface-container-highest: #27242d;
--md-sys-color-on-surface: #ffffff;
--md-sys-color-on-surface-variant: #eae3ef;
--md-sys-color-outline: #bcb6c2;
--md-sys-color-outline-variant: #a7a1ad;
--md-sys-color-inverse-surface: #fdf7fe;
--md-sys-color-inverse-on-surface: #000000;
--md-sys-color-primary: #ebe1ff;
--md-sys-color-primary-dim: #ded0fe;
--md-sys-color-on-primary: #302649;
--md-sys-color-primary-container: #aa9dc8;
--md-sys-color-on-primary-container: #000000;
--md-sys-color-primary-fixed: #ded0fe;
--md-sys-color-primary-fixed-dim: #d0c3ef;
--md-sys-color-on-primary-fixed: #000000;
--md-sys-color-on-primary-fixed-variant: #180e30;
--md-sys-color-inverse-primary: #3c3256;
--md-sys-color-secondary: #ebe1fb;
--md-sys-color-secondary-dim: #ddd3ed;
--md-sys-color-on-secondary: #2e293c;
--md-sys-color-secondary-container: #a8a0b8;
--md-sys-color-on-secondary-container: #000000;
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #dad0ea;
--md-sys-color-on-secondary-fixed: #000000;
--md-sys-color-on-secondary-fixed-variant: #221d2f;
--md-sys-color-tertiary: #ffdbf2;
--md-sys-color-tertiary-dim: #fac5e9;
--md-sys-color-on-tertiary: #43203b;
--md-sys-color-tertiary-container: #f4bfe3;
--md-sys-color-on-tertiary-container: #2e0e29;
--md-sys-color-tertiary-fixed: #f4bfe3;
--md-sys-color-tertiary-fixed-dim: #e5b2d5;
--md-sys-color-on-tertiary-fixed: #000000;
--md-sys-color-on-tertiary-fixed-variant: #180015;
--md-sys-color-error: #ffdddf;
--md-sys-color-error-dim: #ffc7cb;
--md-sys-color-on-error: #5f001c;
--md-sys-color-error-container: #ff798c;
--md-sys-color-on-error-container: #000000;
--md-sys-color-success: #89fcbf;
--md-sys-color-on-success: #00341e;
--md-sys-color-success-container: #42b880;
--md-sys-color-on-success-container: #000000;
--md-sys-color-warning: #ffe2b1;
--md-sys-color-on-warning: #3c2900;
--md-sys-color-warning-container: #e4a604;
--md-sys-color-on-warning-container: #000000;
--md-sys-color-info: #dde5ff;
--md-sys-color-on-info: #002a62;
--md-sys-color-info-container: #74a2ff;
--md-sys-color-on-info-container: #000000;
--md-sys-color-inverse-error: #500016;
--md-sys-color-inverse-success: #002a18;
--md-sys-color-inverse-warning: #312100;
--md-sys-color-inverse-info: #002252;
}
}
+16 -11
View File
@@ -7,15 +7,20 @@
*
* As utilities: rounded-corner-xs rounded-corner-full.
*/
:root {
--md-sys-shape-corner-none: 0px;
--md-sys-shape-corner-xs: 4px;
--md-sys-shape-corner-sm: 8px;
--md-sys-shape-corner-md: 12px;
--md-sys-shape-corner-lg: 16px;
--md-sys-shape-corner-lg-increased: 20px;
--md-sys-shape-corner-xl: 28px;
--md-sys-shape-corner-xl-increased: 32px;
--md-sys-shape-corner-xxl: 48px;
--md-sys-shape-corner-full: 9999px;
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.tokens {
:root {
--md-sys-shape-corner-none: 0px;
--md-sys-shape-corner-xs: 4px;
--md-sys-shape-corner-sm: 8px;
--md-sys-shape-corner-md: 12px;
--md-sys-shape-corner-lg: 16px;
--md-sys-shape-corner-lg-increased: 20px;
--md-sys-shape-corner-xl: 28px;
--md-sys-shape-corner-xl-increased: 32px;
--md-sys-shape-corner-xxl: 48px;
--md-sys-shape-corner-full: 9999px;
}
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Spacing, as M3's measurement scale.
*
* An 8dp grid where space100 is the base unit, with the nested steps M3 uses below and just above
* it: 0.25×, 0.5×, 0.75× and 1.25× (docs/reference/m3/styles-supplement.md § Spacing, "Spacing
* scale"). Names are Compose's `md.sys.measurement.space*`. A dp is a CSS pixel, so the values are
* px and a larger text size leaves them alone M3 keeps spacing when text scales to 200%.
*
* Padding and gaps on the parent, margins only between layout regions. A value between two steps
* is a new token in the application's own stylesheet, named by the same multiplier convention
* (space225 = 18px), never a literal.
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@layer material.tokens {
:root {
--md-sys-measurement-space25: 2px;
--md-sys-measurement-space50: 4px;
--md-sys-measurement-space75: 6px;
--md-sys-measurement-space100: 8px;
--md-sys-measurement-space125: 10px;
--md-sys-measurement-space200: 16px;
--md-sys-measurement-space300: 24px;
--md-sys-measurement-space400: 32px;
--md-sys-measurement-space500: 40px;
--md-sys-measurement-space600: 48px;
--md-sys-measurement-space700: 56px;
--md-sys-measurement-space800: 64px;
--md-sys-measurement-space900: 72px;
}
}
+12 -100
View File
@@ -5,108 +5,20 @@
* element at 8% on hover, 10% on focus and press, 16% while dragged; disabled content at 38%
* and a disabled container at 12%.
*
* `state-layer` puts M3's state layer on an element. Hover only where the pointer can hover,
* because a touch screen keeps the last hover after a tap; `data-dragged` on the element draws
* the dragged layer. The layer is a ::before, so the element becomes `position: relative` and
* `isolation: isolate`; never pass `static` or a z-index to it.
*
* `touch-target` extends an element's pointer target to M3's 48×48px minimum without changing
* what is drawn: a ::after centred on it, at least 48px each way. It is `::after`-based, so a
* component that already draws with ::after wraps its control in an element carrying it.
*
* `focus-ring` is M3's focus indicator 3px in secondary, 2px out, drawn only for keyboard
* focus. The site gives no thickness or offset; the values are @material/web's focus ring
* tokens (Apache-2.0, © Google LLC). `link` is a link in running text: underlined in the
* colour of the words around it.
* The classes that draw them are foundation/interaction.css (`md-state-layer`, `md-focus-ring`,
* `md-touch-target`, `md-link`), and utilities.css for the components still written in Tailwind.
* The tokens sit in `material.tokens`, so an application's own unlayered declaration wins.
*/
:root {
--md-sys-state-hover-state-layer-opacity: 0.08;
--md-sys-state-focus-state-layer-opacity: 0.1;
--md-sys-state-pressed-state-layer-opacity: 0.1;
--md-sys-state-dragged-state-layer-opacity: 0.16;
--md-sys-state-disabled-content-opacity: 0.38;
--md-sys-state-disabled-container-opacity: 0.12;
}
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@utility state-layer {
position: relative;
isolation: isolate;
&::before {
content: '';
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
background-color: currentColor;
opacity: 0;
pointer-events: none;
transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);
}
@media (hover: hover) {
&:hover::before {
opacity: var(--md-sys-state-hover-state-layer-opacity);
}
}
&:focus-visible::before {
opacity: var(--md-sys-state-focus-state-layer-opacity);
}
&:active::before {
opacity: var(--md-sys-state-pressed-state-layer-opacity);
}
&[data-dragged]::before {
opacity: var(--md-sys-state-dragged-state-layer-opacity);
}
&:disabled::before,
&[aria-disabled='true']::before {
display: none;
@layer material.tokens {
:root {
--md-sys-state-hover-state-layer-opacity: 0.08;
--md-sys-state-focus-state-layer-opacity: 0.1;
--md-sys-state-pressed-state-layer-opacity: 0.1;
--md-sys-state-dragged-state-layer-opacity: 0.16;
--md-sys-state-disabled-content-opacity: 0.38;
--md-sys-state-disabled-container-opacity: 0.12;
}
}
@utility touch-target {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
min-width: 3rem;
min-height: 3rem;
transform: translate(-50%, -50%);
}
}
@utility focus-ring {
outline: none;
&:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
}
@utility link {
cursor: pointer;
text-decoration-line: underline;
text-decoration-thickness: from-font;
text-underline-offset: 0.15em;
border-radius: var(--md-sys-shape-corner-xs);
&:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
}
[x-cloak] {
display: none !important;
}
+76 -251
View File
@@ -4,265 +4,90 @@
* Sizes, line heights, weights and tracking are androidx Compose Material 3's own token values
* (tokens/TypeScaleTokens.kt, Apache-2.0, © Google LLC, androidx-main @ 1608250), converted as
* M3's units table says: rem = sp / 16, tracking in rem as well (docs/reference/m3/styles.md
* § Typography). A style is used through its utility, never by hand-assembling `text-*`,
* `leading-*` and `tracking-*`:
* § Typography). A style is used whole, through its class, never by hand-assembling a size, a
* line height and a tracking:
*
* <h2 class="type-title-lg"></h2>
* <p class="type-emphasized-headline-md tabular-nums"></p>
* <h2 class="md-type-title-lg"></h2>
* <p class="md-type-emphasized-headline-md md-tabular"></p>
*
* The `md-type-*` classes are text.css; the `type-*` utilities of the components still written in
* Tailwind are utilities.css, with the same declarations.
*
* The brand typeface is Google Sans Flex (font.css). Emphasized styles are one weight step
* heavier and fully rounded ("ROND" 100) the axis that typeface exists for, verified by
* `npm run check:font` and they carry their own tracking, because M3 widens four of them and
* takes Display Large's negative tracking back to zero.
*
* M3 asks for emphasis one element at a time, and `font-variation-settings` inherits, so every
* regular utility resets it: body copy inside an emphasized heading reads as itself again.
*/
:root {
--md-ref-typeface-brand: 'Google Sans Flex', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--md-ref-typeface-plain: var(--md-ref-typeface-brand);
--md-ref-typeface-weight-regular: 400;
--md-ref-typeface-weight-medium: 500;
--md-ref-typeface-weight-bold: 700;
--md-sys-typescale-display-lg: var(--md-ref-typeface-weight-regular) 3.5625rem/4rem var(--md-ref-typeface-brand);
--md-sys-typescale-display-lg-tracking: -0.0125rem;
--md-sys-typescale-emphasized-display-lg: var(--md-ref-typeface-weight-medium) 3.5625rem/4rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-display-lg-tracking: 0rem;
--md-sys-typescale-display-md: var(--md-ref-typeface-weight-regular) 2.8125rem/3.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-display-md-tracking: 0rem;
--md-sys-typescale-emphasized-display-md: var(--md-ref-typeface-weight-medium) 2.8125rem/3.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-display-md-tracking: 0rem;
--md-sys-typescale-display-sm: var(--md-ref-typeface-weight-regular) 2.25rem/2.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-display-sm-tracking: 0rem;
--md-sys-typescale-emphasized-display-sm: var(--md-ref-typeface-weight-medium) 2.25rem/2.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-display-sm-tracking: 0rem;
--md-sys-typescale-headline-lg: var(--md-ref-typeface-weight-regular) 2rem/2.5rem var(--md-ref-typeface-brand);
--md-sys-typescale-headline-lg-tracking: 0rem;
--md-sys-typescale-emphasized-headline-lg: var(--md-ref-typeface-weight-medium) 2rem/2.5rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-headline-lg-tracking: 0rem;
--md-sys-typescale-headline-md: var(--md-ref-typeface-weight-regular) 1.75rem/2.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-headline-md-tracking: 0rem;
--md-sys-typescale-emphasized-headline-md: var(--md-ref-typeface-weight-medium) 1.75rem/2.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-headline-md-tracking: 0rem;
--md-sys-typescale-headline-sm: var(--md-ref-typeface-weight-regular) 1.5rem/2rem var(--md-ref-typeface-brand);
--md-sys-typescale-headline-sm-tracking: 0rem;
--md-sys-typescale-emphasized-headline-sm: var(--md-ref-typeface-weight-medium) 1.5rem/2rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-headline-sm-tracking: 0rem;
--md-sys-typescale-title-lg: var(--md-ref-typeface-weight-regular) 1.375rem/1.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-title-lg-tracking: 0rem;
--md-sys-typescale-emphasized-title-lg: var(--md-ref-typeface-weight-medium) 1.375rem/1.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-title-lg-tracking: 0rem;
--md-sys-typescale-title-md: var(--md-ref-typeface-weight-medium) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-title-md-tracking: 0.0125rem;
--md-sys-typescale-emphasized-title-md: var(--md-ref-typeface-weight-bold) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-title-md-tracking: 0.009375rem;
--md-sys-typescale-title-sm: var(--md-ref-typeface-weight-medium) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-title-sm-tracking: 0.00625rem;
--md-sys-typescale-emphasized-title-sm: var(--md-ref-typeface-weight-bold) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-title-sm-tracking: 0.00625rem;
--md-sys-typescale-body-lg: var(--md-ref-typeface-weight-regular) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-body-lg-tracking: 0.03125rem;
--md-sys-typescale-emphasized-body-lg: var(--md-ref-typeface-weight-medium) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-body-lg-tracking: 0.009375rem;
--md-sys-typescale-body-md: var(--md-ref-typeface-weight-regular) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-body-md-tracking: 0.0125rem;
--md-sys-typescale-emphasized-body-md: var(--md-ref-typeface-weight-medium) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-body-md-tracking: 0.015625rem;
--md-sys-typescale-body-sm: var(--md-ref-typeface-weight-regular) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-body-sm-tracking: 0.025rem;
--md-sys-typescale-emphasized-body-sm: var(--md-ref-typeface-weight-medium) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-body-sm-tracking: 0.025rem;
--md-sys-typescale-label-lg: var(--md-ref-typeface-weight-medium) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-label-lg-tracking: 0.00625rem;
--md-sys-typescale-emphasized-label-lg: var(--md-ref-typeface-weight-bold) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-label-lg-tracking: 0.00625rem;
--md-sys-typescale-label-md: var(--md-ref-typeface-weight-medium) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-label-md-tracking: 0.03125rem;
--md-sys-typescale-emphasized-label-md: var(--md-ref-typeface-weight-bold) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-label-md-tracking: 0.03125rem;
--md-sys-typescale-label-sm: var(--md-ref-typeface-weight-medium) 0.6875rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-label-sm-tracking: 0.03125rem;
--md-sys-typescale-emphasized-label-sm: var(--md-ref-typeface-weight-bold) 0.6875rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-label-sm-tracking: 0.03125rem;
}
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@utility type-display-lg {
font: var(--md-sys-typescale-display-lg);
letter-spacing: var(--md-sys-typescale-display-lg-tracking);
font-variation-settings: normal;
}
@layer material.tokens {
:root {
--md-ref-typeface-brand: 'Google Sans Flex', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--md-ref-typeface-plain: var(--md-ref-typeface-brand);
--md-ref-typeface-weight-regular: 400;
--md-ref-typeface-weight-medium: 500;
--md-ref-typeface-weight-bold: 700;
@utility 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;
}
@utility type-display-md {
font: var(--md-sys-typescale-display-md);
letter-spacing: var(--md-sys-typescale-display-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-display-sm {
font: var(--md-sys-typescale-display-sm);
letter-spacing: var(--md-sys-typescale-display-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-headline-lg {
font: var(--md-sys-typescale-headline-lg);
letter-spacing: var(--md-sys-typescale-headline-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-headline-md {
font: var(--md-sys-typescale-headline-md);
letter-spacing: var(--md-sys-typescale-headline-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-headline-sm {
font: var(--md-sys-typescale-headline-sm);
letter-spacing: var(--md-sys-typescale-headline-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-title-lg {
font: var(--md-sys-typescale-title-lg);
letter-spacing: var(--md-sys-typescale-title-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-title-md {
font: var(--md-sys-typescale-title-md);
letter-spacing: var(--md-sys-typescale-title-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-title-sm {
font: var(--md-sys-typescale-title-sm);
letter-spacing: var(--md-sys-typescale-title-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-body-lg {
font: var(--md-sys-typescale-body-lg);
letter-spacing: var(--md-sys-typescale-body-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-body-md {
font: var(--md-sys-typescale-body-md);
letter-spacing: var(--md-sys-typescale-body-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-body-sm {
font: var(--md-sys-typescale-body-sm);
letter-spacing: var(--md-sys-typescale-body-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-label-lg {
font: var(--md-sys-typescale-label-lg);
letter-spacing: var(--md-sys-typescale-label-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-label-md {
font: var(--md-sys-typescale-label-md);
letter-spacing: var(--md-sys-typescale-label-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-label-sm {
font: var(--md-sys-typescale-label-sm);
letter-spacing: var(--md-sys-typescale-label-sm-tracking);
font-variation-settings: normal;
}
@utility 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-sys-typescale-display-lg: var(--md-ref-typeface-weight-regular) 3.5625rem/4rem var(--md-ref-typeface-brand);
--md-sys-typescale-display-lg-tracking: -0.0125rem;
--md-sys-typescale-emphasized-display-lg: var(--md-ref-typeface-weight-medium) 3.5625rem/4rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-display-lg-tracking: 0rem;
--md-sys-typescale-display-md: var(--md-ref-typeface-weight-regular) 2.8125rem/3.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-display-md-tracking: 0rem;
--md-sys-typescale-emphasized-display-md: var(--md-ref-typeface-weight-medium) 2.8125rem/3.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-display-md-tracking: 0rem;
--md-sys-typescale-display-sm: var(--md-ref-typeface-weight-regular) 2.25rem/2.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-display-sm-tracking: 0rem;
--md-sys-typescale-emphasized-display-sm: var(--md-ref-typeface-weight-medium) 2.25rem/2.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-display-sm-tracking: 0rem;
--md-sys-typescale-headline-lg: var(--md-ref-typeface-weight-regular) 2rem/2.5rem var(--md-ref-typeface-brand);
--md-sys-typescale-headline-lg-tracking: 0rem;
--md-sys-typescale-emphasized-headline-lg: var(--md-ref-typeface-weight-medium) 2rem/2.5rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-headline-lg-tracking: 0rem;
--md-sys-typescale-headline-md: var(--md-ref-typeface-weight-regular) 1.75rem/2.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-headline-md-tracking: 0rem;
--md-sys-typescale-emphasized-headline-md: var(--md-ref-typeface-weight-medium) 1.75rem/2.25rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-headline-md-tracking: 0rem;
--md-sys-typescale-headline-sm: var(--md-ref-typeface-weight-regular) 1.5rem/2rem var(--md-ref-typeface-brand);
--md-sys-typescale-headline-sm-tracking: 0rem;
--md-sys-typescale-emphasized-headline-sm: var(--md-ref-typeface-weight-medium) 1.5rem/2rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-headline-sm-tracking: 0rem;
--md-sys-typescale-title-lg: var(--md-ref-typeface-weight-regular) 1.375rem/1.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-title-lg-tracking: 0rem;
--md-sys-typescale-emphasized-title-lg: var(--md-ref-typeface-weight-medium) 1.375rem/1.75rem var(--md-ref-typeface-brand);
--md-sys-typescale-emphasized-title-lg-tracking: 0rem;
--md-sys-typescale-title-md: var(--md-ref-typeface-weight-medium) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-title-md-tracking: 0.0125rem;
--md-sys-typescale-emphasized-title-md: var(--md-ref-typeface-weight-bold) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-title-md-tracking: 0.009375rem;
--md-sys-typescale-title-sm: var(--md-ref-typeface-weight-medium) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-title-sm-tracking: 0.00625rem;
--md-sys-typescale-emphasized-title-sm: var(--md-ref-typeface-weight-bold) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-title-sm-tracking: 0.00625rem;
--md-sys-typescale-body-lg: var(--md-ref-typeface-weight-regular) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-body-lg-tracking: 0.03125rem;
--md-sys-typescale-emphasized-body-lg: var(--md-ref-typeface-weight-medium) 1rem/1.5rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-body-lg-tracking: 0.009375rem;
--md-sys-typescale-body-md: var(--md-ref-typeface-weight-regular) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-body-md-tracking: 0.0125rem;
--md-sys-typescale-emphasized-body-md: var(--md-ref-typeface-weight-medium) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-body-md-tracking: 0.015625rem;
--md-sys-typescale-body-sm: var(--md-ref-typeface-weight-regular) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-body-sm-tracking: 0.025rem;
--md-sys-typescale-emphasized-body-sm: var(--md-ref-typeface-weight-medium) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-body-sm-tracking: 0.025rem;
--md-sys-typescale-label-lg: var(--md-ref-typeface-weight-medium) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-label-lg-tracking: 0.00625rem;
--md-sys-typescale-emphasized-label-lg: var(--md-ref-typeface-weight-bold) 0.875rem/1.25rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-label-lg-tracking: 0.00625rem;
--md-sys-typescale-label-md: var(--md-ref-typeface-weight-medium) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-label-md-tracking: 0.03125rem;
--md-sys-typescale-emphasized-label-md: var(--md-ref-typeface-weight-bold) 0.75rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-label-md-tracking: 0.03125rem;
--md-sys-typescale-label-sm: var(--md-ref-typeface-weight-medium) 0.6875rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-label-sm-tracking: 0.03125rem;
--md-sys-typescale-emphasized-label-sm: var(--md-ref-typeface-weight-bold) 0.6875rem/1rem var(--md-ref-typeface-plain);
--md-sys-typescale-emphasized-label-sm-tracking: 0.03125rem;
}
}
+286
View File
@@ -0,0 +1,286 @@
/*
* The token utilities, for the components still written in Tailwind.
*
* Tailwind's side of tokens/state.css and tokens/type.css, kept apart so that the token files the
* foundation imports carry no Tailwind directive. material.css imports this file after Tailwind;
* it goes when the last component leaves Tailwind. New markup uses the plain-CSS classes instead,
* which carry the same declarations: `md-state-layer`, `md-focus-ring`, `md-touch-target` and
* `md-link` (foundation/interaction.css), and `md-type-*` (text.css).
*
* `state-layer` puts M3's state layer on an element. Hover only where the pointer can hover,
* because a touch screen keeps the last hover after a tap; `data-dragged` on the element draws
* the dragged layer. The layer is a ::before, so the element becomes `position: relative` and
* `isolation: isolate`; never pass `static` or a z-index to it.
*
* `touch-target` extends an element's pointer target to M3's 48×48px minimum without changing
* what is drawn: a ::after centred on it, at least 48px each way. It is `::after`-based, so a
* component that already draws with ::after wraps its control in an element carrying it.
*
* `focus-ring` is M3's focus indicator 3px in secondary, 2px out, drawn only for keyboard
* focus. The site gives no thickness or offset; the values are @material/web's focus ring
* tokens (Apache-2.0, © Google LLC). `link` is a link in running text: underlined in the
* colour of the words around it.
*
* `type-*` is one of M3's 30 type styles (tokens/type.css): size, line height, weight and
* tracking together. M3 asks for emphasis one element at a time, and `font-variation-settings`
* inherits, so every regular utility resets it: body copy inside an emphasized heading reads as
* itself again.
*/
@utility state-layer {
position: relative;
isolation: isolate;
&::before {
content: '';
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
background-color: currentColor;
opacity: 0;
pointer-events: none;
transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);
}
@media (hover: hover) {
&:hover::before {
opacity: var(--md-sys-state-hover-state-layer-opacity);
}
}
&:focus-visible::before {
opacity: var(--md-sys-state-focus-state-layer-opacity);
}
&:active::before {
opacity: var(--md-sys-state-pressed-state-layer-opacity);
}
&[data-dragged]::before {
opacity: var(--md-sys-state-dragged-state-layer-opacity);
}
&:disabled::before,
&[aria-disabled='true']::before {
display: none;
}
}
@utility touch-target {
position: relative;
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
min-width: 3rem;
min-height: 3rem;
transform: translate(-50%, -50%);
}
}
@utility focus-ring {
outline: none;
&:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
}
@utility link {
cursor: pointer;
text-decoration-line: underline;
text-decoration-thickness: from-font;
text-underline-offset: 0.15em;
border-radius: var(--md-sys-shape-corner-xs);
&:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
}
@utility type-display-lg {
font: var(--md-sys-typescale-display-lg);
letter-spacing: var(--md-sys-typescale-display-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-display-md {
font: var(--md-sys-typescale-display-md);
letter-spacing: var(--md-sys-typescale-display-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-display-sm {
font: var(--md-sys-typescale-display-sm);
letter-spacing: var(--md-sys-typescale-display-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-headline-lg {
font: var(--md-sys-typescale-headline-lg);
letter-spacing: var(--md-sys-typescale-headline-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-headline-md {
font: var(--md-sys-typescale-headline-md);
letter-spacing: var(--md-sys-typescale-headline-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-headline-sm {
font: var(--md-sys-typescale-headline-sm);
letter-spacing: var(--md-sys-typescale-headline-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-title-lg {
font: var(--md-sys-typescale-title-lg);
letter-spacing: var(--md-sys-typescale-title-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-title-md {
font: var(--md-sys-typescale-title-md);
letter-spacing: var(--md-sys-typescale-title-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-title-sm {
font: var(--md-sys-typescale-title-sm);
letter-spacing: var(--md-sys-typescale-title-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-body-lg {
font: var(--md-sys-typescale-body-lg);
letter-spacing: var(--md-sys-typescale-body-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-body-md {
font: var(--md-sys-typescale-body-md);
letter-spacing: var(--md-sys-typescale-body-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-body-sm {
font: var(--md-sys-typescale-body-sm);
letter-spacing: var(--md-sys-typescale-body-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-label-lg {
font: var(--md-sys-typescale-label-lg);
letter-spacing: var(--md-sys-typescale-label-lg-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-label-md {
font: var(--md-sys-typescale-label-md);
letter-spacing: var(--md-sys-typescale-label-md-tracking);
font-variation-settings: normal;
}
@utility 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;
}
@utility type-label-sm {
font: var(--md-sys-typescale-label-sm);
letter-spacing: var(--md-sys-typescale-label-sm-tracking);
font-variation-settings: normal;
}
@utility 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;
}
+1 -1
View File
@@ -88,7 +88,7 @@ it('divides a scrolling body from its header and actions only while content is h
->toContain('position: absolute;')
// A token that reduced motion sets to zero, so then the rule appears without a fade.
->toContain('transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);')
->and(File::get(__DIR__.'/../../../resources/css/material.css'))->toContain("@import './components/dialog.css';")
->and(File::get(__DIR__.'/../../../resources/css/tailwind.css'))->toContain("@import './components/dialog.css';")
->and(File::get(__DIR__.'/../../../resources/js/material.js'))->toContain("import './dialog.js'")
->and(File::get(__DIR__.'/../../../resources/js/dialog.js'))
->toContain("directive('dialog-dividers'")
+427
View File
@@ -0,0 +1,427 @@
<?php
use Illuminate\Support\Facades\File;
/**
* The package's stylesheets are plain CSS in `material.*` layers, with no Tailwind in them. Every
* one opens with the same layer statement, so the order holds whichever file a bundler reaches
* first; then plain imports (an `@import` cannot sit inside a layer block, and `layer()` on it
* would nest the layer twice); then its own `@layer material.<x>` blocks. The only rules outside
* a layer are foundation/hidden.css's two `!important` ones.
*
* Until the components leave Tailwind, the checks cover the foundation foundation.css and every
* file it imports, text.css included and material.css and tailwind.css carry the rest.
*/
const MATERIAL_LAYER_STATEMENT = '@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;';
function stylesheetPath(string $path = ''): string
{
return (string) realpath(__DIR__.'/../../resources/css'.($path === '' ? '' : '/'.$path));
}
/**
* A stylesheet without its comments; a quoted string keeps whatever it holds.
*/
function stylesheetWithoutComments(string $css): string
{
return (string) preg_replace('~("(?:\\\\.|[^"\\\\])*"|\'(?:\\\\.|[^\'\\\\])*\')|/\*.*?\*/~s', '$1', $css);
}
/**
* The top-level statements (`@layer …;`, `@import …;`) and blocks of a stylesheet, in order, with
* whitespace collapsed in statements and preludes.
*
* @return list<array{statement: string}|array{prelude: string, body: string}>
*/
function stylesheetItems(string $css): array
{
$css = stylesheetWithoutComments($css);
$items = [];
$start = 0;
$depth = 0;
$quote = null;
$opening = 0;
for ($i = 0, $length = strlen($css); $i < $length; $i++) {
$char = $css[$i];
if ($quote !== null) {
if ($char === '\\') {
$i++;
} elseif ($char === $quote) {
$quote = null;
}
continue;
}
if ($char === '"' || $char === "'") {
$quote = $char;
} elseif ($char === '{') {
if ($depth++ === 0) {
$opening = $i;
}
} elseif ($char === '}' && --$depth === 0) {
$items[] = [
'prelude' => (string) preg_replace('/\s+/', ' ', trim(substr($css, $start, $opening - $start))),
'body' => substr($css, $opening + 1, $i - $opening - 1),
];
$start = $i + 1;
} elseif ($char === ';' && $depth === 0) {
$items[] = ['statement' => preg_replace('/\s+/', ' ', trim(substr($css, $start, $i - $start))).';'];
$start = $i + 1;
}
}
expect(trim(substr($css, $start)))->toBe('', 'The stylesheet ends inside an unclosed rule.');
return $items;
}
/**
* The declarations of a flat block body, by property.
*
* @return array<string, string>
*/
function stylesheetDeclarations(string $body): array
{
return collect(explode(';', $body))
->map(fn (string $declaration): string => trim($declaration))
->filter()
->mapWithKeys(fn (string $declaration): array => [trim(strstr($declaration, ':', true)) => trim(substr(strstr($declaration, ':'), 1))])
->all();
}
/**
* The body of the first block with this prelude, at the top level or one layer block down.
*/
function stylesheetBlock(string $css, string $prelude): string
{
foreach (stylesheetItems($css) as $item) {
if (($item['prelude'] ?? null) === $prelude) {
return $item['body'];
}
if (str_starts_with($item['prelude'] ?? '', '@layer ')) {
foreach (stylesheetItems($item['body']) as $inner) {
if (($inner['prelude'] ?? null) === $prelude) {
return $inner['body'];
}
}
}
}
throw new RuntimeException("No block `{$prelude}`.");
}
/**
* The paths a stylesheet imports, as written.
*
* @return list<string>
*/
function stylesheetImports(string $file): array
{
return collect(stylesheetItems(File::get($file)))
->map(fn (array $item): ?string => preg_match('/^@import\s+([\'"])(.+?)\1/', $item['statement'] ?? '', $match) === 1 ? $match[2] : null)
->filter()
->values()
->all();
}
/**
* A stylesheet and every stylesheet it reaches through `@import`, each once, in the order a
* bundler meets them. `tailwindcss` itself is a package, not a file, and is left out.
*
* @return list<string>
*/
function stylesheetTree(string $entry): array
{
$files = [];
$visit = function (string $file) use (&$visit, &$files): void {
$file = (string) realpath($file);
if (in_array($file, $files, true)) {
return;
}
$files[] = $file;
foreach (stylesheetImports($file) as $import) {
if (str_starts_with($import, '.')) {
$visit(dirname($file).'/'.$import);
}
}
};
$visit($entry);
return $files;
}
/**
* The foundation: foundation.css and everything it imports.
*
* @return list<string>
*/
function foundationStylesheets(): array
{
return stylesheetTree(stylesheetPath('foundation.css'));
}
function stylesheetName(string $file): string
{
return substr($file, strlen(stylesheetPath()) + 1);
}
it('brings every foundation file and text.css into the foundation, and nothing of Tailwind', function () {
$foundation = array_map(stylesheetName(...), foundationStylesheets());
$parts = collect(File::files(stylesheetPath('foundation')))
->map(fn (SplFileInfo $file): string => 'foundation/'.$file->getFilename())
->push('foundation.css', 'text.css');
expect($parts->diff($foundation)->values()->all())->toBe([])
->and(array_map(fn (string $import): string => basename($import), stylesheetImports(stylesheetPath('foundation.css'))))
// In the order of their layers, the rules outside every layer beside the reset.
->toBe(['reset.css', 'hidden.css', 'tokens.css', 'base.css', 'interaction.css', 'text.css'])
->and($foundation)
->toContain('tokens/scheme.css', 'tokens/shape.css', 'tokens/elevation.css', 'tokens/motion.css', 'tokens/type.css', 'tokens/state.css', 'tokens/spacing.css', 'tokens/font.css')
// The Tailwind half: the theme, the token utilities and the components still written for it.
->and(array_values(array_intersect($foundation, ['tokens/theme.css', 'tokens/utilities.css', 'tailwind.css', 'material.css'])))->toBe([])
->and(array_values(preg_grep('/^components\//', $foundation)))->toBe([]);
});
it('opens every foundation stylesheet with a header, the layer statement and plain imports', function () {
foreach (foundationStylesheets() as $file) {
$name = stylesheetName($file);
$items = stylesheetItems(File::get($file));
expect(File::get($file))->toStartWith('/*', "{$name} has no header comment")
->and($items[0]['statement'] ?? null)->toBe(MATERIAL_LAYER_STATEMENT, "{$name} does not open with the layer statement");
$blocks = false;
foreach (array_slice($items, 1) as $item) {
if (isset($item['prelude'])) {
$blocks = true;
continue;
}
expect($blocks)->toBeFalse("{$name}: `{$item['statement']}` comes after a block")
// A plain import: a quoted path and nothing after it — no layer(), supports() or media.
->and($item['statement'])->toMatch('/^@import ([\'"])\.{1,2}\/[\w.\/-]+\.css\1;$/', "{$name}: `{$item['statement']}` is not a plain import");
}
}
});
it('keeps every foundation rule inside its material layer, but the two that hide', function () {
// Which layer each file writes into; tokens.css only imports.
$layers = [
'foundation.css' => null,
'foundation/reset.css' => 'material.reset',
'foundation/hidden.css' => null,
'foundation/tokens.css' => null,
'foundation/base.css' => 'material.base',
'foundation/interaction.css' => 'material.base',
'text.css' => 'material.text',
'tokens/font.css' => 'material.base',
];
$unlayered = [];
$important = 0;
foreach (foundationStylesheets() as $file) {
$name = stylesheetName($file);
$layer = array_key_exists($name, $layers) ? $layers[$name] : 'material.tokens';
$important += substr_count(stylesheetWithoutComments(File::get($file)), '!important');
foreach (stylesheetItems(File::get($file)) as $item) {
if (! isset($item['prelude'])) {
continue;
}
if (! str_starts_with($item['prelude'], '@layer ')) {
$unlayered["{$name}: {$item['prelude']}"] = stylesheetDeclarations($item['body']);
continue;
}
expect($item['prelude'])->toBe("@layer {$layer}", "{$name} writes into `{$item['prelude']}`")
// A layer inside the block would become material.<x>.<y>, below the rest of <x>.
->and($item['body'])->not->toContain('@layer');
}
}
expect($unlayered)->toBe([
"foundation/hidden.css: [hidden]:where(:not([hidden='until-found']))" => ['display' => 'none !important'],
'foundation/hidden.css: [x-cloak]' => ['display' => 'none !important'],
])->and($important)->toBe(2);
});
it('defines x-cloak once, where both the foundation and material.css reach it', function () {
$definitions = collect(File::allFiles(stylesheetPath()))
->filter(fn (SplFileInfo $file): bool => $file->getExtension() === 'css')
->filter(fn (SplFileInfo $file): bool => str_contains(stylesheetWithoutComments($file->getContents()), '[x-cloak]'))
->map(fn (SplFileInfo $file): string => stylesheetName((string) $file->getRealPath()))
->values()
->all();
$material = array_map(stylesheetName(...), stylesheetTree(stylesheetPath('material.css')));
expect($definitions)->toBe(['foundation/hidden.css'])
->and($material)->toContain('foundation/hidden.css', 'tailwind.css')
// Imported after Tailwind, the reset would sit in a layer above Tailwind's utilities.
->and(array_values(array_intersect($material, ['foundation.css', 'foundation/reset.css', 'foundation/base.css', 'foundation/interaction.css', 'text.css'])))->toBe([]);
});
it('writes no Tailwind directive in the foundation', function () {
foreach (foundationStylesheets() as $file) {
expect(stylesheetWithoutComments(File::get($file)))
->not->toMatch('/@(?:tailwind|theme|utility|variant|custom-variant|apply|source|config|plugin|reference)\b/', stylesheetName($file))
->not->toMatch('/--(?:theme|spacing|alpha)\(|\btheme\(|[\'"]tailwindcss[\'"]/', stylesheetName($file));
}
});
it('writes a media query in the foundation only at M3\'s breakpoints, in px', function () {
$queries = collect(foundationStylesheets())
->flatMap(function (string $file): array {
preg_match_all('/@media\b([^{]*)\{/', stylesheetWithoutComments(File::get($file)), $matches);
return array_map(fn (string $query): string => stylesheetName($file).': '.trim($query), $matches[1]);
});
// The foundation's own queries (hover, reduced motion) hold no width; the check is for what
// lands here later.
expect($queries)->not->toBeEmpty();
foreach ($queries as $query) {
preg_match_all('/(\d*\.?\d+)([a-z%]*)/i', substr($query, strpos($query, ': ') + 2), $lengths, PREG_SET_ORDER);
foreach ($lengths as [, $number, $unit]) {
expect($unit)->toBe('px', $query)
->and(in_array($number, ['600', '840', '1200', '1600'], true))->toBeTrue("{$query} is not at an M3 breakpoint");
}
}
});
it('declares M3\'s spacing scale as the reference gives it', function () {
preg_match_all(
'/^\|\s*\**space(\d+)\**\s*\|\s*\**([\d.]+)×\**\s*\|\s*\**(\d+)dp/m',
File::get(__DIR__.'/../../docs/reference/m3/styles-supplement.md'),
$rows,
PREG_SET_ORDER,
);
$reference = collect($rows)->mapWithKeys(fn (array $row): array => ["--md-sys-measurement-space{$row[1]}" => "{$row[3]}px"])->all();
$tokens = stylesheetDeclarations(stylesheetBlock(File::get(stylesheetPath('tokens/spacing.css')), ':root'));
expect($reference)->toHaveCount(13)
->and($tokens)->toBe($reference);
// space100 is the 8dp base unit and every name is its multiplier: space125 = 1.25 × 8.
foreach ($rows as [, $name, $multiplier, $value]) {
expect((float) $name / 100 * 8)->toBe((float) $value)
->and((float) $multiplier * 8)->toBe((float) $value);
}
});
it('gives every md-type class the declarations of its type utility', function () {
preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(stylesheetPath('tokens/utilities.css')), $matches, PREG_SET_ORDER);
$utilities = collect($matches)->mapWithKeys(fn (array $match): array => ["md-{$match[1]}" => stylesheetDeclarations($match[2])]);
$text = File::get(stylesheetPath('text.css'));
expect($utilities)->toHaveCount(30);
foreach ($utilities as $class => $declarations) {
expect(stylesheetDeclarations(stylesheetBlock($text, ".{$class}")))->toBe($declarations, $class)
->and(array_keys($declarations))->toBe(['font', 'letter-spacing', 'font-variation-settings']);
}
});
it('ships exactly the documented text classes, each ink an M3 role', function () {
$text = File::get(stylesheetPath('text.css'));
$styles = collect(['display', 'headline', 'title', 'body', 'label'])
->crossJoin(['lg', 'md', 'sm'])
->flatMap(fn (array $style): array => ["md-type-{$style[0]}-{$style[1]}", "md-type-emphasized-{$style[0]}-{$style[1]}"]);
$inks = [
'md-ink' => 'on-surface',
'md-ink-variant' => 'on-surface-variant',
'md-ink-quiet' => 'outline',
'md-ink-primary' => 'primary',
'md-ink-error' => 'error',
'md-ink-success' => 'success',
'md-ink-warning' => 'warning',
'md-ink-info' => 'info',
'md-ink-inverse' => 'inverse-on-surface',
];
$rest = [
'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',
],
];
$classes = collect(stylesheetItems(stylesheetBlock($text, '@layer material.text')))
->map(fn (array $item): string => $item['prelude'] ?? $item['statement'])
->all();
expect($classes)->toBe($styles->merge(array_keys($inks))->merge(array_keys($rest))->map(fn (string $class): string => ".{$class}")->all());
foreach ($inks as $class => $role) {
expect(stylesheetDeclarations(stylesheetBlock($text, ".{$class}")))->toBe(['color' => "var(--md-sys-color-{$role})"]);
}
foreach ($rest as $class => $declarations) {
expect(stylesheetDeclarations(stylesheetBlock($text, ".{$class}")))->toBe($declarations);
}
});
it('draws the interaction classes as the utilities the Tailwind components still use', function () {
$utilities = File::get(stylesheetPath('tokens/utilities.css'));
$interaction = File::get(stylesheetPath('foundation/interaction.css'));
$normalise = fn (string $body): string => trim((string) preg_replace('/\s+/', ' ', $body));
foreach (['state-layer', 'focus-ring', 'touch-target', 'link'] as $name) {
$class = stylesheetBlock($interaction, ".md-{$name}");
expect($normalise(str_replace(
// The two deliberate differences: the data-md-* hook beside the old one, and M3's 48
// CSS pixels for the target where the utility reads 3rem.
['&:is([data-md-dragged], [data-dragged])', 'var(--md-sys-measurement-space600)'],
['&[data-dragged]', '3rem'],
$class,
)))->toBe($normalise(stylesheetBlock($utilities, "@utility {$name}")), $name);
}
expect(stylesheetBlock($interaction, '.md-state-layer'))->toContain('&:is([data-md-dragged], [data-dragged])::before')
->and(stylesheetBlock($interaction, '.md-touch-target'))->toContain('min-width: var(--md-sys-measurement-space600);');
});
it('declares the material layers in the Workbench before Tailwind\'s', function () {
$app = stylesheetWithoutComments(File::get(__DIR__.'/../../workbench/resources/css/app.css'));
$foundation = strpos($app, "@import '../../../resources/css/foundation.css';");
$tailwind = strpos($app, "@import 'tailwindcss'");
$components = strpos($app, "@import '../../../resources/css/tailwind.css';");
expect($foundation)->toBeInt()
->and($tailwind)->toBeGreaterThan($foundation)
->and($components)->toBeGreaterThan($tailwind)
// material.css would declare the tokens a second time.
->and($app)->not->toContain('material.css');
});
+3 -2
View File
@@ -37,13 +37,14 @@ function typeStyles(): array
}
/**
* The body of every `@utility type-…` block of type.css, keyed by utility name.
* The body of every `@utility type-…` block, keyed by utility name. The utilities live in
* tokens/utilities.css, apart from the tokens, so the foundation imports no Tailwind directive.
*
* @return array<string, string>
*/
function typeUtilities(): array
{
preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(packageCss('tokens/type.css')), $matches, PREG_SET_ORDER);
preg_match_all('/@utility (type-[\w-]+) \{\n(.*?)\n\}/s', File::get(packageCss('tokens/utilities.css')), $matches, PREG_SET_ORDER);
return array_combine(array_column($matches, 1), array_column($matches, 2));
}
+6 -3
View File
@@ -1,7 +1,10 @@
/* The Workbench builds the package exactly as an application would, with explicit
sources so the plans in docs/ are not scanned for class names. */
/* The Workbench builds the package as an application would, with explicit sources so the plans
in docs/ are not scanned for class names. The foundation comes before Tailwind, so the
`material` layers are declared first and sit below Tailwind's; tailwind.css brings the
components still written for Tailwind, without declaring the tokens a second time. */
@import '../../../resources/css/foundation.css';
@import 'tailwindcss' source(none);
@import '../../../resources/css/material.css';
@import '../../../resources/css/tailwind.css';
@import './material-scheme.css';
@source '../../../resources/views';