material-plus-ui 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -28
- package/dist/components/accordion/MPAccordion.d.ts +115 -0
- package/dist/components/accordion/MPAccordion.js +1 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +1 -0
- package/dist/components/alert/MPAlert.d.ts +91 -0
- package/dist/components/alert/MPAlert.js +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/animate-appear/MPAnimateAppear.d.ts +56 -0
- package/dist/components/animate-appear/MPAnimateAppear.js +1 -0
- package/dist/components/animate-appear/index.d.ts +2 -0
- package/dist/components/animate-appear/index.js +1 -0
- package/dist/components/animate-blink/MPAnimateBlink.d.ts +41 -0
- package/dist/components/animate-blink/MPAnimateBlink.js +1 -0
- package/dist/components/animate-blink/index.d.ts +2 -0
- package/dist/components/animate-blink/index.js +1 -0
- package/dist/components/animate-fade/MPAnimateFade.d.ts +38 -0
- package/dist/components/animate-fade/MPAnimateFade.js +1 -0
- package/dist/components/animate-fade/index.d.ts +2 -0
- package/dist/components/animate-fade/index.js +1 -0
- package/dist/components/animate-grow/MPAnimateGrow.d.ts +52 -0
- package/dist/components/animate-grow/MPAnimateGrow.js +1 -0
- package/dist/components/animate-grow/index.d.ts +2 -0
- package/dist/components/animate-grow/index.js +1 -0
- package/dist/components/animate-headline/MPAnimateHeadline.d.ts +63 -0
- package/dist/components/animate-headline/MPAnimateHeadline.js +1 -0
- package/dist/components/animate-headline/index.d.ts +2 -0
- package/dist/components/animate-headline/index.js +1 -0
- package/dist/components/animate-lighting/MPAnimateLighting.d.ts +68 -0
- package/dist/components/animate-lighting/MPAnimateLighting.js +1 -0
- package/dist/components/animate-lighting/index.d.ts +2 -0
- package/dist/components/animate-lighting/index.js +1 -0
- package/dist/components/animate-marquee/MPAnimateMarquee.d.ts +66 -0
- package/dist/components/animate-marquee/MPAnimateMarquee.js +1 -0
- package/dist/components/animate-marquee/index.d.ts +2 -0
- package/dist/components/animate-marquee/index.js +1 -0
- package/dist/components/animate-rotate/MPAnimateRotate.d.ts +56 -0
- package/dist/components/animate-rotate/MPAnimateRotate.js +1 -0
- package/dist/components/animate-rotate/index.d.ts +2 -0
- package/dist/components/animate-rotate/index.js +1 -0
- package/dist/components/animate-slide/MPAnimateSlide.d.ts +53 -0
- package/dist/components/animate-slide/MPAnimateSlide.js +1 -0
- package/dist/components/animate-slide/index.d.ts +2 -0
- package/dist/components/animate-slide/index.js +1 -0
- package/dist/components/animate-typing/MPAnimateTyping.d.ts +59 -0
- package/dist/components/animate-typing/MPAnimateTyping.js +1 -0
- package/dist/components/animate-typing/index.d.ts +2 -0
- package/dist/components/animate-typing/index.js +1 -0
- package/dist/components/animate-zoom/MPAnimateZoom.d.ts +44 -0
- package/dist/components/animate-zoom/MPAnimateZoom.js +1 -0
- package/dist/components/animate-zoom/index.d.ts +2 -0
- package/dist/components/animate-zoom/index.js +1 -0
- package/dist/components/aspect-ratio/MPAspectRatio.d.ts +69 -0
- package/dist/components/aspect-ratio/MPAspectRatio.js +1 -0
- package/dist/components/aspect-ratio/index.d.ts +2 -0
- package/dist/components/aspect-ratio/index.js +1 -0
- package/dist/components/avatar/MPAvatar.d.ts +104 -0
- package/dist/components/avatar/MPAvatar.js +1 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +1 -0
- package/dist/components/badge/MPBadge.d.ts +104 -0
- package/dist/components/badge/MPBadge.js +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/blockquote/MPBlockquote.d.ts +73 -0
- package/dist/components/blockquote/MPBlockquote.js +1 -0
- package/dist/components/blockquote/index.d.ts +2 -0
- package/dist/components/blockquote/index.js +1 -0
- package/dist/components/bottom-navigation/MPBottomNavigation.d.ts +144 -0
- package/dist/components/bottom-navigation/MPBottomNavigation.js +1 -0
- package/dist/components/bottom-navigation/index.d.ts +2 -0
- package/dist/components/bottom-navigation/index.js +1 -0
- package/dist/components/box/MPBox.d.ts +78 -0
- package/dist/components/box/MPBox.js +1 -0
- package/dist/components/box/index.d.ts +2 -0
- package/dist/components/box/index.js +1 -0
- package/dist/components/breadcrumb/MPBreadcrumb.d.ts +127 -0
- package/dist/components/breadcrumb/MPBreadcrumb.js +1 -0
- package/dist/components/breadcrumb/index.d.ts +2 -0
- package/dist/components/breadcrumb/index.js +1 -0
- package/dist/components/button/MPButton.d.ts +75 -0
- package/dist/components/button/MPButton.js +1 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/button-group/MPButtonGroup.d.ts +31 -0
- package/dist/components/button-group/MPButtonGroup.js +1 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.js +1 -0
- package/dist/components/card/MPCard.d.ts +73 -0
- package/dist/components/card/MPCard.js +1 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/carousel/MPCarousel.d.ts +116 -0
- package/dist/components/carousel/MPCarousel.js +1 -0
- package/dist/components/carousel/index.d.ts +2 -0
- package/dist/components/carousel/index.js +1 -0
- package/dist/components/chat-bubble/MPChatBubble.d.ts +132 -0
- package/dist/components/chat-bubble/MPChatBubble.js +1 -0
- package/dist/components/chat-bubble/index.d.ts +2 -0
- package/dist/components/chat-bubble/index.js +1 -0
- package/dist/components/checkbox/MPCheckbox.d.ts +76 -0
- package/dist/components/checkbox/MPCheckbox.js +1 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/chip/MPChip.d.ts +74 -0
- package/dist/components/chip/MPChip.js +1 -0
- package/dist/components/chip/index.d.ts +2 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/collapsible/MPCollapsible.d.ts +97 -0
- package/dist/components/collapsible/MPCollapsible.js +1 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/color-picker/MPColorPicker.d.ts +131 -0
- package/dist/components/color-picker/MPColorPicker.js +1 -0
- package/dist/components/color-picker/index.d.ts +2 -0
- package/dist/components/color-picker/index.js +1 -0
- package/dist/components/combobox/MPCombobox.d.ts +175 -0
- package/dist/components/combobox/MPCombobox.js +1 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/container/MPContainer.d.ts +75 -0
- package/dist/components/container/MPContainer.js +1 -0
- package/dist/components/container/index.d.ts +2 -0
- package/dist/components/container/index.js +1 -0
- package/dist/components/date-picker/MPDatePicker.d.ts +98 -0
- package/dist/components/date-picker/MPDatePicker.js +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-range-picker/MPDateRangePicker.d.ts +98 -0
- package/dist/components/date-range-picker/MPDateRangePicker.js +1 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/date-time-picker/MPDateTimePicker.d.ts +78 -0
- package/dist/components/date-time-picker/MPDateTimePicker.js +1 -0
- package/dist/components/date-time-picker/index.d.ts +2 -0
- package/dist/components/date-time-picker/index.js +1 -0
- package/dist/components/dialog/MPDialog.d.ts +150 -0
- package/dist/components/dialog/MPDialog.js +1 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +1 -0
- package/dist/components/divider/MPDivider.d.ts +80 -0
- package/dist/components/divider/MPDivider.js +1 -0
- package/dist/components/divider/index.d.ts +2 -0
- package/dist/components/divider/index.js +1 -0
- package/dist/components/drawer/MPDrawer.d.ts +168 -0
- package/dist/components/drawer/MPDrawer.js +1 -0
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/drawer/index.js +1 -0
- package/dist/components/empty/MPEmpty.d.ts +74 -0
- package/dist/components/empty/MPEmpty.js +1 -0
- package/dist/components/empty/index.d.ts +2 -0
- package/dist/components/empty/index.js +1 -0
- package/dist/components/file-picker/MPFilePicker.d.ts +113 -0
- package/dist/components/file-picker/MPFilePicker.js +1 -0
- package/dist/components/file-picker/index.d.ts +2 -0
- package/dist/components/file-picker/index.js +1 -0
- package/dist/components/floating-action-button/MPFloatingActionButton.d.ts +126 -0
- package/dist/components/floating-action-button/MPFloatingActionButton.js +1 -0
- package/dist/components/floating-action-button/index.d.ts +2 -0
- package/dist/components/floating-action-button/index.js +1 -0
- package/dist/components/grid/MPGrid.d.ts +155 -0
- package/dist/components/grid/MPGrid.js +1 -0
- package/dist/components/grid/index.d.ts +2 -0
- package/dist/components/grid/index.js +1 -0
- package/dist/components/highlight/MPHighlight.d.ts +95 -0
- package/dist/components/highlight/MPHighlight.js +1 -0
- package/dist/components/highlight/index.d.ts +2 -0
- package/dist/components/highlight/index.js +1 -0
- package/dist/components/icon-button/MPIconButton.d.ts +59 -0
- package/dist/components/icon-button/MPIconButton.js +1 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/icon-button/index.js +1 -0
- package/dist/components/list/MPList.d.ts +96 -0
- package/dist/components/list/MPList.js +1 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.js +1 -0
- package/dist/components/locale/MPLocaleProvider.d.ts +63 -0
- package/dist/components/locale/MPLocaleProvider.js +1 -0
- package/dist/components/locale/index.d.ts +2 -0
- package/dist/components/locale/index.js +1 -0
- package/dist/components/menu/MPMenu.d.ts +232 -0
- package/dist/components/menu/MPMenu.js +1 -0
- package/dist/components/menu/index.d.ts +2 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/number-field/MPNumberField.d.ts +117 -0
- package/dist/components/number-field/MPNumberField.js +1 -0
- package/dist/components/number-field/index.d.ts +2 -0
- package/dist/components/number-field/index.js +1 -0
- package/dist/components/otp-field/MPOtpField.d.ts +89 -0
- package/dist/components/otp-field/MPOtpField.js +1 -0
- package/dist/components/otp-field/index.d.ts +2 -0
- package/dist/components/otp-field/index.js +1 -0
- package/dist/components/overlay/MPOverlay.d.ts +96 -0
- package/dist/components/overlay/MPOverlay.js +1 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.js +1 -0
- package/dist/components/pagination/MPPagination.d.ts +106 -0
- package/dist/components/pagination/MPPagination.js +1 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/panes/MPPanes.d.ts +100 -0
- package/dist/components/panes/MPPanes.js +1 -0
- package/dist/components/panes/index.d.ts +2 -0
- package/dist/components/panes/index.js +1 -0
- package/dist/components/pill/MPPill.d.ts +117 -0
- package/dist/components/pill/MPPill.js +1 -0
- package/dist/components/pill/index.d.ts +2 -0
- package/dist/components/pill/index.js +1 -0
- package/dist/components/popover/MPPopover.d.ts +143 -0
- package/dist/components/popover/MPPopover.js +1 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +1 -0
- package/dist/components/progress-box/MPProgressBox.d.ts +40 -0
- package/dist/components/progress-box/MPProgressBox.js +1 -0
- package/dist/components/progress-box/index.d.ts +2 -0
- package/dist/components/progress-box/index.js +1 -0
- package/dist/components/progress-circular/MPProgressCircular.d.ts +32 -0
- package/dist/components/progress-circular/MPProgressCircular.js +1 -0
- package/dist/components/progress-circular/index.d.ts +2 -0
- package/dist/components/progress-circular/index.js +1 -0
- package/dist/components/progress-linear/MPProgressLinear.d.ts +32 -0
- package/dist/components/progress-linear/MPProgressLinear.js +1 -0
- package/dist/components/progress-linear/index.d.ts +2 -0
- package/dist/components/progress-linear/index.js +1 -0
- package/dist/components/radio-group/MPRadioGroup.d.ts +81 -0
- package/dist/components/radio-group/MPRadioGroup.js +1 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +1 -0
- package/dist/components/rating/MPRating.d.ts +135 -0
- package/dist/components/rating/MPRating.js +1 -0
- package/dist/components/rating/index.d.ts +2 -0
- package/dist/components/rating/index.js +1 -0
- package/dist/components/segmented-button/MPSegmentedButton.d.ts +75 -0
- package/dist/components/segmented-button/MPSegmentedButton.js +1 -0
- package/dist/components/segmented-button/index.d.ts +2 -0
- package/dist/components/segmented-button/index.js +1 -0
- package/dist/components/select/MPSelect.d.ts +103 -0
- package/dist/components/select/MPSelect.js +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/shortcut/MPShortcut.d.ts +67 -0
- package/dist/components/shortcut/MPShortcut.js +1 -0
- package/dist/components/shortcut/index.d.ts +2 -0
- package/dist/components/shortcut/index.js +1 -0
- package/dist/components/skeleton/MPSkeleton.d.ts +76 -0
- package/dist/components/skeleton/MPSkeleton.js +1 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/slider/MPSlider.d.ts +77 -0
- package/dist/components/slider/MPSlider.js +1 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +1 -0
- package/dist/components/snackbar/MPSnackbar.d.ts +175 -0
- package/dist/components/snackbar/MPSnackbar.js +1 -0
- package/dist/components/snackbar/index.d.ts +2 -0
- package/dist/components/snackbar/index.js +1 -0
- package/dist/components/spoiler/MPSpoiler.d.ts +106 -0
- package/dist/components/spoiler/MPSpoiler.js +1 -0
- package/dist/components/spoiler/index.d.ts +2 -0
- package/dist/components/spoiler/index.js +1 -0
- package/dist/components/switch/MPSwitch.d.ts +75 -0
- package/dist/components/switch/MPSwitch.js +1 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/MPTable.d.ts +120 -0
- package/dist/components/table/MPTable.js +1 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/tabs/MPTabs.d.ts +145 -0
- package/dist/components/tabs/MPTabs.js +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/text-field/MPTextField.d.ts +51 -22
- package/dist/components/text-field/MPTextField.js +1 -1
- package/dist/components/text-link/MPTextLink.d.ts +88 -0
- package/dist/components/text-link/MPTextLink.js +1 -0
- package/dist/components/text-link/index.d.ts +2 -0
- package/dist/components/text-link/index.js +1 -0
- package/dist/components/time-picker/MPTimePicker.d.ts +108 -0
- package/dist/components/time-picker/MPTimePicker.js +1 -0
- package/dist/components/time-picker/index.d.ts +2 -0
- package/dist/components/time-picker/index.js +1 -0
- package/dist/components/timeline/MPTimeline.d.ts +96 -0
- package/dist/components/timeline/MPTimeline.js +1 -0
- package/dist/components/timeline/index.d.ts +2 -0
- package/dist/components/timeline/index.js +1 -0
- package/dist/components/tooltip/MPTooltip.d.ts +117 -0
- package/dist/components/tooltip/MPTooltip.js +1 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/typography/MPTypography.d.ts +94 -0
- package/dist/components/typography/MPTypography.js +1 -0
- package/dist/components/typography/index.d.ts +2 -0
- package/dist/components/typography/index.js +1 -0
- package/dist/constants/icons.d.ts +49 -0
- package/dist/constants/icons.js +1 -1
- package/dist/index.d.ts +73 -0
- package/dist/index.js +1 -1
- package/dist/internal/Calendar.d.ts +118 -0
- package/dist/internal/Calendar.js +1 -0
- package/dist/internal/FieldOutline.d.ts +109 -0
- package/dist/internal/FieldOutline.js +1 -0
- package/dist/internal/Picker.d.ts +153 -0
- package/dist/internal/Picker.js +1 -0
- package/dist/internal/StateLayer.d.ts +45 -0
- package/dist/internal/StateLayer.js +1 -0
- package/dist/internal/SupportingText.d.ts +23 -0
- package/dist/internal/SupportingText.js +1 -0
- package/dist/internal/WidthSizer.d.ts +31 -0
- package/dist/internal/WidthSizer.js +1 -0
- package/dist/internal/accent.d.ts +39 -0
- package/dist/internal/accent.js +1 -0
- package/dist/internal/animate.d.ts +179 -0
- package/dist/internal/animate.js +1 -0
- package/dist/internal/button-group.d.ts +21 -0
- package/dist/internal/button-group.js +1 -0
- package/dist/internal/color.d.ts +125 -0
- package/dist/internal/color.js +1 -0
- package/dist/internal/date.d.ts +179 -0
- package/dist/internal/date.js +1 -0
- package/dist/internal/i18n.d.ts +241 -0
- package/dist/internal/i18n.js +1 -0
- package/dist/internal/inert.d.ts +11 -0
- package/dist/internal/inert.js +1 -0
- package/dist/internal/locale.d.ts +43 -0
- package/dist/internal/locale.js +1 -0
- package/dist/internal/menu.d.ts +23 -0
- package/dist/internal/menu.js +1 -0
- package/dist/internal/progress.d.ts +126 -0
- package/dist/internal/progress.js +1 -0
- package/dist/internal/scale.d.ts +127 -0
- package/dist/internal/scale.js +1 -0
- package/dist/internal/surface.d.ts +76 -0
- package/dist/internal/surface.js +1 -0
- package/dist/internal/visually-hidden.d.ts +23 -0
- package/dist/internal/visually-hidden.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +1871 -20
- package/dist/types.d.ts +262 -16
- package/package.json +16 -21
package/dist/tailwind.css
CHANGED
|
@@ -12,20 +12,31 @@
|
|
|
12
12
|
* is this file plus the compiled utilities, built by `scripts/build-styles.mjs`
|
|
13
13
|
* from `src/standalone.css`. The tokens below are the same in both.
|
|
14
14
|
*
|
|
15
|
-
* ##
|
|
15
|
+
* ## The vocabulary is Material Design 3's, not Material UI's
|
|
16
|
+
*
|
|
17
|
+
* This library implements the Material Design specification rather than wrapping
|
|
18
|
+
* an implementation of it, so the token names here are the ones the spec uses —
|
|
19
|
+
* `primary`, `on-surface-variant`, `outline`, `corner-extra-small`,
|
|
20
|
+
* `body-large`. They are not `main`/`light`/`dark`/`contrastText`, which is
|
|
21
|
+
* Material UI's own palette model and a different (earlier) colour system.
|
|
22
|
+
*
|
|
23
|
+
* ## Only what a component reads
|
|
16
24
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
25
|
+
* A token nobody uses is a promise to keep supporting a name, so the roles below
|
|
26
|
+
* are exactly the ones the components actually resolve, and nothing else. MD3
|
|
27
|
+
* defines around fifty colour roles; an outlined text field reads five of them,
|
|
28
|
+
* and the components in this library between them read twenty-nine. The rest
|
|
29
|
+
* are absent on purpose and get added as components need them.
|
|
22
30
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
31
|
+
* This is also why the library does not try to reproduce MD3 completely. It has
|
|
32
|
+
* to *coexist* with whatever Material implementation a page already runs, not
|
|
33
|
+
* replace it — so the surface it claims stays as small as the components make
|
|
34
|
+
* necessary.
|
|
35
|
+
*
|
|
36
|
+
* ## What is deliberately not here
|
|
25
37
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* stay to that job, and the file is short on purpose.
|
|
38
|
+
* **A reset.** Material Plus adds no page-level styling of any kind. See
|
|
39
|
+
* `src/standalone.css` for why Tailwind's Preflight is left out too.
|
|
29
40
|
*/
|
|
30
41
|
|
|
31
42
|
/*
|
|
@@ -48,16 +59,1856 @@
|
|
|
48
59
|
@source '.';
|
|
49
60
|
|
|
50
61
|
/* ---------------------------------------------------------------------------
|
|
51
|
-
*
|
|
62
|
+
* System tokens
|
|
63
|
+
*
|
|
64
|
+
* Everything in this block is layered. A cascade layer loses to every unlayered
|
|
65
|
+
* rule, so a consumer's plain `:root { --mp-source-color: … }` wins over these
|
|
66
|
+
* defaults *regardless of source order* — they do not have to reason about
|
|
67
|
+
* whether their override sits before or after the `@import`.
|
|
68
|
+
*
|
|
69
|
+
* Note that the *public* names are `--mp-sys-*`, not `--md-sys-*`. The spec's
|
|
70
|
+
* names are what a role is *called*, but the `--md-sys-*` namespace belongs to
|
|
71
|
+
* the page: a project running Material Web Components already defines those, and
|
|
72
|
+
* writing to them would overwrite a theme this library has no business touching.
|
|
73
|
+
* So each role *reads* `--md-sys-color-*` and falls back to its own derivation,
|
|
74
|
+
* which gives three levels of control without a single conflict:
|
|
75
|
+
*
|
|
76
|
+
* --mp-sys-color-primary set by the consumer → wins outright
|
|
77
|
+
* --md-sys-color-primary already on the page → picked up, zero config
|
|
78
|
+
* neither → derived from the source colour
|
|
79
|
+
*
|
|
80
|
+
* ## Why the derived colours are declared on `*` and not on `:root`
|
|
81
|
+
*
|
|
82
|
+
* A custom property's value is not *parsed* until it is used, but its `var()`
|
|
83
|
+
* references are substituted at the element the property is **declared on**, and
|
|
84
|
+
* descendants inherit the already-substituted result. A role declared once on
|
|
85
|
+
* `:root` therefore freezes there: setting `--mp-source-color` further down the
|
|
86
|
+
* tree — on a section, on a wrapper, from an inline style at runtime — could not
|
|
87
|
+
* reach back and change it, and neither could a `.dark` on `<body>` rather than
|
|
88
|
+
* on `<html>`.
|
|
89
|
+
*
|
|
90
|
+
* Declaring them on every element instead makes each one re-substitute against
|
|
91
|
+
* whatever is in scope where it sits, which is what actually makes scoped and
|
|
92
|
+
* runtime theming work. This is the same technique Tailwind uses for its own
|
|
93
|
+
* composed variables.
|
|
94
|
+
*
|
|
95
|
+
* Only the *derived* colours need it. Everything else here is a literal value
|
|
96
|
+
* with no `var()` to freeze, so plain inheritance from `:root` is enough.
|
|
97
|
+
*
|
|
98
|
+
* The computed results are `--_mp-*`: private, read by the components, and not
|
|
99
|
+
* a name to set. Material Web marks its own internal tokens the same way. The
|
|
100
|
+
* indirection is load-bearing — it is what keeps a consumer's
|
|
101
|
+
* `--mp-sys-color-primary` on a wrapper from being clobbered by the `*` rule on
|
|
102
|
+
* the wrapper's own children.
|
|
103
|
+
* ------------------------------------------------------------------------- */
|
|
104
|
+
|
|
105
|
+
@layer theme {
|
|
106
|
+
:root {
|
|
107
|
+
/*
|
|
108
|
+
* The one value most consumers ever set. MD3 calls it the source colour: a
|
|
109
|
+
* single seed that the tonal palettes — and therefore every role below —
|
|
110
|
+
* are generated from.
|
|
111
|
+
*
|
|
112
|
+
* ## Why this blue rather than MD3's baseline purple
|
|
113
|
+
*
|
|
114
|
+
* The specification's own baseline source is `#6750a4`, and a library that
|
|
115
|
+
* defaults to it is making a louder statement than it looks: purple is the
|
|
116
|
+
* one hue nobody arrives at by accident, so an application that has not
|
|
117
|
+
* chosen a colour yet ends up looking like it chose that one.
|
|
118
|
+
*
|
|
119
|
+
* A deep azure is the quieter default. It is also picked for its *chroma*
|
|
120
|
+
* rather than only its hue — 0.118, close to the baseline's 0.130 — because
|
|
121
|
+
* every role derives its saturation from here. A more vivid blue (Google's
|
|
122
|
+
* `#0b57d0` sits at 0.199) pulls the whole scheme brighter than any
|
|
123
|
+
* reference Material palette, which reads as a brand rather than as
|
|
124
|
+
* Material.
|
|
125
|
+
*
|
|
126
|
+
* The one thing a source colour must not be is near-grey. At a chroma below
|
|
127
|
+
* roughly 0.05 the derived `primary` stops being distinguishable from
|
|
128
|
+
* `outline`, and a focus ring then reads as no change at all.
|
|
129
|
+
*/
|
|
130
|
+
--mp-source-color: #00639b;
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* Tone stops.
|
|
134
|
+
*
|
|
135
|
+
* MD3's light and dark schemes are not two palettes. They are the *same*
|
|
136
|
+
* tonal palettes read at different tones — light `primary` is tone 40, dark
|
|
137
|
+
* `primary` is tone 80, light `outline` is neutral-variant 50, dark is 60.
|
|
138
|
+
* Keeping them in variables is what lets the dark scheme below be a
|
|
139
|
+
* reassignment rather than a second copy of every colour, and it is why
|
|
140
|
+
* overriding `--mp-source-color` moves both schemes at once.
|
|
141
|
+
*
|
|
142
|
+
* These are private. The supported way to disagree with a colour is to set
|
|
143
|
+
* the role — `--mp-sys-color-outline` — not to retune the ramp. They are also
|
|
144
|
+
* specific to *this* approximation of MD3's palette generation, and would go
|
|
145
|
+
* away if that were ever replaced with real HCT.
|
|
146
|
+
*
|
|
147
|
+
* ## Where the numbers come from
|
|
148
|
+
*
|
|
149
|
+
* Read off MD3's own baseline ref palette, converted to OKLCh, rather than
|
|
150
|
+
* chosen by eye: light is (primary40, neutral10, neutral-variant30,
|
|
151
|
+
* neutral-variant50, error40) and dark is (primary80, neutral90,
|
|
152
|
+
* neutral-variant80, neutral-variant60, error80).
|
|
153
|
+
*
|
|
154
|
+
* The check that fixed these numbers is therefore run against `#6750a4`, not
|
|
155
|
+
* against the default above: fed the baseline source, the derivation lands on
|
|
156
|
+
* the baseline scheme — `primary` and `error` on its exact hex in both
|
|
157
|
+
* schemes, the near-grey roles within a ΔE of 0.008. What the default source
|
|
158
|
+
* changes is the hue and chroma the ramp is applied *to*, never the ramp.
|
|
159
|
+
*
|
|
160
|
+
* The lightnesses are OKLCh L, not MD3 tone numbers — tone is CIE L*, which
|
|
161
|
+
* OKLCh's L does not equal. Chroma is absolute for the near-grey roles, which
|
|
162
|
+
* are near-grey whatever the source is, and a multiplier of the source's own
|
|
163
|
+
* chroma for `primary`, so a deliberately muted brand colour stays muted.
|
|
164
|
+
*
|
|
165
|
+
* One known and accepted divergence: every derived role keeps the source
|
|
166
|
+
* colour's hue, while MD3's neutral palettes sit 10–20° off it. At a chroma
|
|
167
|
+
* of 0.01–0.02 that is a difference of a couple of thousandths in a/b — below
|
|
168
|
+
* anything visible, and chasing it would be fitting to noise, since hue is
|
|
169
|
+
* barely determined at all that close to grey.
|
|
170
|
+
*
|
|
171
|
+
* ## The accent tones are shared, the chroma is not
|
|
172
|
+
*
|
|
173
|
+
* `primary`, `secondary` and `tertiary` are one palette generation read three
|
|
174
|
+
* times: MD3 takes all three at the *same* tones and differs only in how much
|
|
175
|
+
* chroma the palette carries and, for `tertiary`, in its hue. So there is one
|
|
176
|
+
* `--_mp-tone-accent` rather than three, and a `--_mp-chroma-*` per family.
|
|
177
|
+
*/
|
|
178
|
+
--_mp-tone-accent: 0.496;
|
|
179
|
+
--_mp-tone-on-accent: 1;
|
|
180
|
+
--_mp-tone-accent-container: 0.918;
|
|
181
|
+
--_mp-tone-on-accent-container: 0.242;
|
|
182
|
+
|
|
183
|
+
--_mp-chroma-primary: 1;
|
|
184
|
+
--_mp-chroma-secondary: 0.274;
|
|
185
|
+
--_mp-chroma-tertiary: 0.464;
|
|
186
|
+
/* MD3 puts `tertiary` 60° round the wheel in HCT, which lands at about 65°
|
|
187
|
+
in OKLCh near the default source. Measured rather than converted, because
|
|
188
|
+
the two spaces do not agree on where a hue is by a constant. */
|
|
189
|
+
--_mp-hue-tertiary: 64.7;
|
|
190
|
+
|
|
191
|
+
--_mp-tone-on-surface: 0.227;
|
|
192
|
+
--_mp-chroma-on-surface: 0.01;
|
|
193
|
+
--_mp-tone-on-surface-variant: 0.398;
|
|
194
|
+
--_mp-chroma-on-surface-variant: 0.0174;
|
|
195
|
+
--_mp-tone-outline: 0.567;
|
|
196
|
+
--_mp-chroma-outline: 0.0163;
|
|
197
|
+
--_mp-tone-outline-variant: 0.829;
|
|
198
|
+
--_mp-chroma-outline-variant: 0.0178;
|
|
199
|
+
|
|
200
|
+
/* The page's own surface — neutral 98 in the light scheme and neutral 6 in
|
|
201
|
+
the dark one. Read by exactly one thing, `MPOverlay`'s `solid` tone,
|
|
202
|
+
whose job is to put the page's own background over the page. */
|
|
203
|
+
--_mp-tone-surface: 0.984;
|
|
204
|
+
--_mp-chroma-surface: 0.0128;
|
|
205
|
+
|
|
206
|
+
/* The four surface containers, which are one neutral palette read at four
|
|
207
|
+
tones. MD3 has five; a menu (`surface-container`), an elevated button
|
|
208
|
+
(`-low`), a dialog (`-high`) and a switch's track (`-highest`) are the
|
|
209
|
+
four anything here actually asks for. */
|
|
210
|
+
--_mp-tone-surface-container-low: 0.967;
|
|
211
|
+
--_mp-chroma-surface-container-low: 0.0118;
|
|
212
|
+
--_mp-tone-surface-container: 0.954;
|
|
213
|
+
--_mp-chroma-surface-container: 0.0147;
|
|
214
|
+
--_mp-tone-surface-container-high: 0.933;
|
|
215
|
+
--_mp-chroma-surface-container-high: 0.0148;
|
|
216
|
+
--_mp-tone-surface-container-highest: 0.914;
|
|
217
|
+
--_mp-chroma-surface-container-highest: 0.0137;
|
|
218
|
+
|
|
219
|
+
/* `inverse-primary`, which is the accent palette read at the *other*
|
|
220
|
+
scheme's tone — light takes the dark scheme's stop and vice versa. That
|
|
221
|
+
is not an approximation of MD3's role, it is the definition of it, which
|
|
222
|
+
is why these two numbers are the accent stops above and below swapped.
|
|
223
|
+
One thing reads it: a snackbar's action label, which sits on the inverse
|
|
224
|
+
surface and would be unreadable in the accent proper. */
|
|
225
|
+
--_mp-tone-inverse-accent: 0.835;
|
|
226
|
+
--_mp-chroma-inverse-primary: 0.725;
|
|
227
|
+
|
|
228
|
+
/* The inverted pair, which is the same neutral palette read at the *other*
|
|
229
|
+
end: neutral 20 under neutral 95 in the light scheme, and the two swapped
|
|
230
|
+
in the dark one. MD3 gives it to exactly one thing, and so does this
|
|
231
|
+
library — a plain tooltip, whose whole job is to be legible over content
|
|
232
|
+
it was not designed against. A surface that inverts with the scheme is
|
|
233
|
+
readable on either. */
|
|
234
|
+
--_mp-tone-inverse-surface: 0.313;
|
|
235
|
+
--_mp-chroma-inverse-surface: 0.0118;
|
|
236
|
+
--_mp-tone-inverse-on-surface: 0.96;
|
|
237
|
+
--_mp-chroma-inverse-on-surface: 0.0118;
|
|
238
|
+
|
|
239
|
+
/* `error` carries its own hue as well, because it is not derived from the
|
|
240
|
+
source colour at all — see the role below. */
|
|
241
|
+
--_mp-tone-error: 0.501;
|
|
242
|
+
--_mp-chroma-error: 0.1783;
|
|
243
|
+
--_mp-hue-error: 28.7;
|
|
244
|
+
|
|
245
|
+
/*
|
|
246
|
+
* The chroma a whole palette carries, as opposed to the chroma one role of it
|
|
247
|
+
* came out at. Deliberately *not* reassigned for the dark scheme below, and
|
|
248
|
+
* the only stops here that are not.
|
|
249
|
+
*
|
|
250
|
+
* MD3 holds a palette's chroma constant across its tones and lets the sRGB
|
|
251
|
+
* boundary take back whatever will not fit — which is why `primary` at tone 40
|
|
252
|
+
* is vivid and `primary-container` at tone 90 is a pale wash, from one number.
|
|
253
|
+
* The container and `on-` roles are written the same way: the palette's chroma
|
|
254
|
+
* goes in unmodified and the browser's own gamut mapping does the clipping, at
|
|
255
|
+
* constant lightness and hue, exactly as HCT's does.
|
|
256
|
+
*
|
|
257
|
+
* Fed the baseline source, that lands the twelve container and `on-` roles
|
|
258
|
+
* within 0.01 of MD3's own — bar the two `error` containers, which come out up
|
|
259
|
+
* to 0.025 more chromatic because sRGB's boundary is a blunter clip than HCT's
|
|
260
|
+
* and the error palette is the only one saturated enough to notice.
|
|
261
|
+
*
|
|
262
|
+
* `error` is an absolute chroma rather than a multiplier, because it is not
|
|
263
|
+
* derived from the source colour at all.
|
|
264
|
+
*/
|
|
265
|
+
--_mp-palette-primary: 1;
|
|
266
|
+
--_mp-palette-secondary: 0.274;
|
|
267
|
+
--_mp-palette-tertiary: 0.464;
|
|
268
|
+
--_mp-palette-error: 0.1783;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* The dark scheme, by tone reassignment. Two ways in: the page's own signal
|
|
272
|
+
(`prefers-color-scheme`), and an explicit attribute or class for a project
|
|
273
|
+
that switches schemes itself. `.dark` is included because it is what
|
|
274
|
+
Tailwind's own `dark:` variant keys on by default.
|
|
275
|
+
Declared twice rather than pulled into a shared rule: a media query and a
|
|
276
|
+
selector cannot be combined without either nesting the selector list twice
|
|
277
|
+
over or inventing a third indirection for values that are read off a table
|
|
278
|
+
anyway. */
|
|
279
|
+
@media (prefers-color-scheme: dark) {
|
|
280
|
+
:root:not([data-mp-scheme='light']) {
|
|
281
|
+
--_mp-tone-accent: 0.835;
|
|
282
|
+
--_mp-tone-on-accent: 0.325;
|
|
283
|
+
--_mp-tone-accent-container: 0.41;
|
|
284
|
+
--_mp-tone-on-accent-container: 0.918;
|
|
285
|
+
--_mp-chroma-primary: 0.725;
|
|
286
|
+
--_mp-chroma-secondary: 0.287;
|
|
287
|
+
--_mp-chroma-tertiary: 0.51;
|
|
288
|
+
--_mp-hue-tertiary: 65.7;
|
|
289
|
+
--_mp-tone-on-surface: 0.914;
|
|
290
|
+
--_mp-chroma-on-surface: 0.0137;
|
|
291
|
+
--_mp-tone-on-surface-variant: 0.829;
|
|
292
|
+
--_mp-chroma-on-surface-variant: 0.0178;
|
|
293
|
+
--_mp-tone-outline: 0.657;
|
|
294
|
+
--_mp-chroma-outline: 0.0153;
|
|
295
|
+
--_mp-tone-outline-variant: 0.398;
|
|
296
|
+
--_mp-chroma-outline-variant: 0.0174;
|
|
297
|
+
--_mp-tone-surface: 0.187;
|
|
298
|
+
--_mp-chroma-surface: 0.0124;
|
|
299
|
+
--_mp-tone-surface-container-low: 0.227;
|
|
300
|
+
--_mp-chroma-surface-container-low: 0.01;
|
|
301
|
+
--_mp-tone-surface-container: 0.245;
|
|
302
|
+
--_mp-chroma-surface-container: 0.0134;
|
|
303
|
+
--_mp-tone-surface-container-high: 0.286;
|
|
304
|
+
--_mp-chroma-surface-container-high: 0.0129;
|
|
305
|
+
--_mp-tone-surface-container-highest: 0.33;
|
|
306
|
+
--_mp-chroma-surface-container-highest: 0.0125;
|
|
307
|
+
--_mp-tone-inverse-accent: 0.496;
|
|
308
|
+
--_mp-chroma-inverse-primary: 1;
|
|
309
|
+
--_mp-tone-inverse-surface: 0.914;
|
|
310
|
+
--_mp-chroma-inverse-surface: 0.0137;
|
|
311
|
+
--_mp-tone-inverse-on-surface: 0.313;
|
|
312
|
+
--_mp-chroma-inverse-on-surface: 0.0118;
|
|
313
|
+
--_mp-tone-error: 0.834;
|
|
314
|
+
--_mp-chroma-error: 0.0677;
|
|
315
|
+
--_mp-hue-error: 22;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
[data-mp-scheme='dark'],
|
|
320
|
+
.dark {
|
|
321
|
+
--_mp-tone-accent: 0.835;
|
|
322
|
+
--_mp-tone-on-accent: 0.325;
|
|
323
|
+
--_mp-tone-accent-container: 0.41;
|
|
324
|
+
--_mp-tone-on-accent-container: 0.918;
|
|
325
|
+
--_mp-chroma-primary: 0.725;
|
|
326
|
+
--_mp-chroma-secondary: 0.287;
|
|
327
|
+
--_mp-chroma-tertiary: 0.51;
|
|
328
|
+
--_mp-hue-tertiary: 65.7;
|
|
329
|
+
--_mp-tone-on-surface: 0.914;
|
|
330
|
+
--_mp-chroma-on-surface: 0.0137;
|
|
331
|
+
--_mp-tone-on-surface-variant: 0.829;
|
|
332
|
+
--_mp-chroma-on-surface-variant: 0.0178;
|
|
333
|
+
--_mp-tone-outline: 0.657;
|
|
334
|
+
--_mp-chroma-outline: 0.0153;
|
|
335
|
+
--_mp-tone-outline-variant: 0.398;
|
|
336
|
+
--_mp-chroma-outline-variant: 0.0174;
|
|
337
|
+
--_mp-tone-surface: 0.187;
|
|
338
|
+
--_mp-chroma-surface: 0.0124;
|
|
339
|
+
--_mp-tone-surface-container-low: 0.227;
|
|
340
|
+
--_mp-chroma-surface-container-low: 0.01;
|
|
341
|
+
--_mp-tone-surface-container: 0.245;
|
|
342
|
+
--_mp-chroma-surface-container: 0.0134;
|
|
343
|
+
--_mp-tone-surface-container-high: 0.286;
|
|
344
|
+
--_mp-chroma-surface-container-high: 0.0129;
|
|
345
|
+
--_mp-tone-surface-container-highest: 0.33;
|
|
346
|
+
--_mp-chroma-surface-container-highest: 0.0125;
|
|
347
|
+
--_mp-tone-inverse-accent: 0.496;
|
|
348
|
+
--_mp-chroma-inverse-primary: 1;
|
|
349
|
+
--_mp-tone-inverse-surface: 0.914;
|
|
350
|
+
--_mp-chroma-inverse-surface: 0.0137;
|
|
351
|
+
--_mp-tone-inverse-on-surface: 0.313;
|
|
352
|
+
--_mp-chroma-inverse-on-surface: 0.0118;
|
|
353
|
+
--_mp-tone-error: 0.834;
|
|
354
|
+
--_mp-chroma-error: 0.0677;
|
|
355
|
+
--_mp-hue-error: 22;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/*
|
|
359
|
+
* Colour roles.
|
|
360
|
+
*
|
|
361
|
+
* Twenty-five, and every one of them is resolved by a component in this
|
|
362
|
+
* library. Checked against the spec's own component token maps rather than
|
|
363
|
+
* assumed — an outlined text field reads five, a filled button four, a switch
|
|
364
|
+
* six, a plain tooltip two nothing else touches.
|
|
365
|
+
*
|
|
366
|
+
* The three source-derived families are written out rather than generated. CSS
|
|
367
|
+
* has no way to build a custom property's *name* from another one, so a family
|
|
368
|
+
* is four declarations wherever it appears; what is shared between them lives
|
|
369
|
+
* in the tone stops above, which is the part that would otherwise drift.
|
|
370
|
+
*
|
|
371
|
+
* `oklch(from … h)` keeps the source colour's hue and replaces lightness and
|
|
372
|
+
* chroma. See the note above for why this is on `*` rather than `:root`.
|
|
373
|
+
*/
|
|
374
|
+
*,
|
|
375
|
+
::before,
|
|
376
|
+
::after,
|
|
377
|
+
::backdrop {
|
|
378
|
+
--_mp-color-primary: var(
|
|
379
|
+
--mp-sys-color-primary,
|
|
380
|
+
var(
|
|
381
|
+
--md-sys-color-primary,
|
|
382
|
+
oklch(
|
|
383
|
+
from var(--mp-source-color) var(--_mp-tone-accent) calc(c * var(--_mp-chroma-primary)) h
|
|
384
|
+
)
|
|
385
|
+
)
|
|
386
|
+
);
|
|
387
|
+
--_mp-color-on-primary: var(
|
|
388
|
+
--mp-sys-color-on-primary,
|
|
389
|
+
var(
|
|
390
|
+
--md-sys-color-on-primary,
|
|
391
|
+
oklch(
|
|
392
|
+
from var(--mp-source-color) var(--_mp-tone-on-accent) calc(c * var(--_mp-palette-primary))
|
|
393
|
+
h
|
|
394
|
+
)
|
|
395
|
+
)
|
|
396
|
+
);
|
|
397
|
+
--_mp-color-primary-container: var(
|
|
398
|
+
--mp-sys-color-primary-container,
|
|
399
|
+
var(
|
|
400
|
+
--md-sys-color-primary-container,
|
|
401
|
+
oklch(
|
|
402
|
+
from var(--mp-source-color) var(--_mp-tone-accent-container)
|
|
403
|
+
calc(c * var(--_mp-palette-primary)) h
|
|
404
|
+
)
|
|
405
|
+
)
|
|
406
|
+
);
|
|
407
|
+
--_mp-color-on-primary-container: var(
|
|
408
|
+
--mp-sys-color-on-primary-container,
|
|
409
|
+
var(
|
|
410
|
+
--md-sys-color-on-primary-container,
|
|
411
|
+
oklch(
|
|
412
|
+
from var(--mp-source-color) var(--_mp-tone-on-accent-container)
|
|
413
|
+
calc(c * var(--_mp-palette-primary)) h
|
|
414
|
+
)
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
--_mp-color-secondary: var(
|
|
419
|
+
--mp-sys-color-secondary,
|
|
420
|
+
var(
|
|
421
|
+
--md-sys-color-secondary,
|
|
422
|
+
oklch(
|
|
423
|
+
from var(--mp-source-color) var(--_mp-tone-accent) calc(c * var(--_mp-chroma-secondary)) h
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
);
|
|
427
|
+
--_mp-color-on-secondary: var(
|
|
428
|
+
--mp-sys-color-on-secondary,
|
|
429
|
+
var(
|
|
430
|
+
--md-sys-color-on-secondary,
|
|
431
|
+
oklch(
|
|
432
|
+
from var(--mp-source-color) var(--_mp-tone-on-accent)
|
|
433
|
+
calc(c * var(--_mp-palette-secondary)) h
|
|
434
|
+
)
|
|
435
|
+
)
|
|
436
|
+
);
|
|
437
|
+
--_mp-color-secondary-container: var(
|
|
438
|
+
--mp-sys-color-secondary-container,
|
|
439
|
+
var(
|
|
440
|
+
--md-sys-color-secondary-container,
|
|
441
|
+
oklch(
|
|
442
|
+
from var(--mp-source-color) var(--_mp-tone-accent-container)
|
|
443
|
+
calc(c * var(--_mp-palette-secondary)) h
|
|
444
|
+
)
|
|
445
|
+
)
|
|
446
|
+
);
|
|
447
|
+
--_mp-color-on-secondary-container: var(
|
|
448
|
+
--mp-sys-color-on-secondary-container,
|
|
449
|
+
var(
|
|
450
|
+
--md-sys-color-on-secondary-container,
|
|
451
|
+
oklch(
|
|
452
|
+
from var(--mp-source-color) var(--_mp-tone-on-accent-container)
|
|
453
|
+
calc(c * var(--_mp-palette-secondary)) h
|
|
454
|
+
)
|
|
455
|
+
)
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
/* The one family that moves off the source colour's hue. */
|
|
459
|
+
--_mp-color-tertiary: var(
|
|
460
|
+
--mp-sys-color-tertiary,
|
|
461
|
+
var(
|
|
462
|
+
--md-sys-color-tertiary,
|
|
463
|
+
oklch(
|
|
464
|
+
from var(--mp-source-color) var(--_mp-tone-accent) calc(c * var(--_mp-chroma-tertiary))
|
|
465
|
+
calc(h + var(--_mp-hue-tertiary))
|
|
466
|
+
)
|
|
467
|
+
)
|
|
468
|
+
);
|
|
469
|
+
--_mp-color-on-tertiary: var(
|
|
470
|
+
--mp-sys-color-on-tertiary,
|
|
471
|
+
var(
|
|
472
|
+
--md-sys-color-on-tertiary,
|
|
473
|
+
oklch(
|
|
474
|
+
from var(--mp-source-color) var(--_mp-tone-on-accent)
|
|
475
|
+
calc(c * var(--_mp-palette-tertiary)) calc(h + var(--_mp-hue-tertiary))
|
|
476
|
+
)
|
|
477
|
+
)
|
|
478
|
+
);
|
|
479
|
+
--_mp-color-tertiary-container: var(
|
|
480
|
+
--mp-sys-color-tertiary-container,
|
|
481
|
+
var(
|
|
482
|
+
--md-sys-color-tertiary-container,
|
|
483
|
+
oklch(
|
|
484
|
+
from var(--mp-source-color) var(--_mp-tone-accent-container)
|
|
485
|
+
calc(c * var(--_mp-palette-tertiary)) calc(h + var(--_mp-hue-tertiary))
|
|
486
|
+
)
|
|
487
|
+
)
|
|
488
|
+
);
|
|
489
|
+
--_mp-color-on-tertiary-container: var(
|
|
490
|
+
--mp-sys-color-on-tertiary-container,
|
|
491
|
+
var(
|
|
492
|
+
--md-sys-color-on-tertiary-container,
|
|
493
|
+
oklch(
|
|
494
|
+
from var(--mp-source-color) var(--_mp-tone-on-accent-container)
|
|
495
|
+
calc(c * var(--_mp-palette-tertiary)) calc(h + var(--_mp-hue-tertiary))
|
|
496
|
+
)
|
|
497
|
+
)
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
/* The page's own surface. Only `MPOverlay`'s `solid` tone reads it — a sheet
|
|
501
|
+
that hides the page by being the page. */
|
|
502
|
+
--_mp-color-surface: var(
|
|
503
|
+
--mp-sys-color-surface,
|
|
504
|
+
var(
|
|
505
|
+
--md-sys-color-surface,
|
|
506
|
+
oklch(from var(--mp-source-color) var(--_mp-tone-surface) var(--_mp-chroma-surface) h)
|
|
507
|
+
)
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
--_mp-color-surface-container-low: var(
|
|
511
|
+
--mp-sys-color-surface-container-low,
|
|
512
|
+
var(
|
|
513
|
+
--md-sys-color-surface-container-low,
|
|
514
|
+
oklch(
|
|
515
|
+
from var(--mp-source-color) var(--_mp-tone-surface-container-low)
|
|
516
|
+
var(--_mp-chroma-surface-container-low) h
|
|
517
|
+
)
|
|
518
|
+
)
|
|
519
|
+
);
|
|
520
|
+
--_mp-color-surface-container: var(
|
|
521
|
+
--mp-sys-color-surface-container,
|
|
522
|
+
var(
|
|
523
|
+
--md-sys-color-surface-container,
|
|
524
|
+
oklch(
|
|
525
|
+
from var(--mp-source-color) var(--_mp-tone-surface-container)
|
|
526
|
+
var(--_mp-chroma-surface-container) h
|
|
527
|
+
)
|
|
528
|
+
)
|
|
529
|
+
);
|
|
530
|
+
/* One step above `surface-container`, and the tone MD3 puts a dialog on: a
|
|
531
|
+
sheet that has taken the page has to sit above the menus that did not. */
|
|
532
|
+
--_mp-color-surface-container-high: var(
|
|
533
|
+
--mp-sys-color-surface-container-high,
|
|
534
|
+
var(
|
|
535
|
+
--md-sys-color-surface-container-high,
|
|
536
|
+
oklch(
|
|
537
|
+
from var(--mp-source-color) var(--_mp-tone-surface-container-high)
|
|
538
|
+
var(--_mp-chroma-surface-container-high) h
|
|
539
|
+
)
|
|
540
|
+
)
|
|
541
|
+
);
|
|
542
|
+
--_mp-color-surface-container-highest: var(
|
|
543
|
+
--mp-sys-color-surface-container-highest,
|
|
544
|
+
var(
|
|
545
|
+
--md-sys-color-surface-container-highest,
|
|
546
|
+
oklch(
|
|
547
|
+
from var(--mp-source-color) var(--_mp-tone-surface-container-highest)
|
|
548
|
+
var(--_mp-chroma-surface-container-highest) h
|
|
549
|
+
)
|
|
550
|
+
)
|
|
551
|
+
);
|
|
552
|
+
|
|
553
|
+
/* The two inverted roles, read by a plain tooltip and by nothing else. */
|
|
554
|
+
--_mp-color-inverse-surface: var(
|
|
555
|
+
--mp-sys-color-inverse-surface,
|
|
556
|
+
var(
|
|
557
|
+
--md-sys-color-inverse-surface,
|
|
558
|
+
oklch(
|
|
559
|
+
from var(--mp-source-color) var(--_mp-tone-inverse-surface)
|
|
560
|
+
var(--_mp-chroma-inverse-surface) h
|
|
561
|
+
)
|
|
562
|
+
)
|
|
563
|
+
);
|
|
564
|
+
--_mp-color-inverse-on-surface: var(
|
|
565
|
+
--mp-sys-color-inverse-on-surface,
|
|
566
|
+
var(
|
|
567
|
+
--md-sys-color-inverse-on-surface,
|
|
568
|
+
oklch(
|
|
569
|
+
from var(--mp-source-color) var(--_mp-tone-inverse-on-surface)
|
|
570
|
+
var(--_mp-chroma-inverse-on-surface) h
|
|
571
|
+
)
|
|
572
|
+
)
|
|
573
|
+
);
|
|
574
|
+
/* The accent read at the other scheme's tone, for the one label that sits on
|
|
575
|
+
the inverse surface: a snackbar's action. `primary` proper is derived to
|
|
576
|
+
contrast with the *page*, so on a plate that inverts the page it is the
|
|
577
|
+
one colour guaranteed not to read. */
|
|
578
|
+
--_mp-color-inverse-primary: var(
|
|
579
|
+
--mp-sys-color-inverse-primary,
|
|
580
|
+
var(
|
|
581
|
+
--md-sys-color-inverse-primary,
|
|
582
|
+
oklch(
|
|
583
|
+
from var(--mp-source-color) var(--_mp-tone-inverse-accent)
|
|
584
|
+
calc(c * var(--_mp-chroma-inverse-primary)) h
|
|
585
|
+
)
|
|
586
|
+
)
|
|
587
|
+
);
|
|
588
|
+
|
|
589
|
+
--_mp-color-on-surface: var(
|
|
590
|
+
--mp-sys-color-on-surface,
|
|
591
|
+
var(
|
|
592
|
+
--md-sys-color-on-surface,
|
|
593
|
+
oklch(from var(--mp-source-color) var(--_mp-tone-on-surface) var(--_mp-chroma-on-surface) h)
|
|
594
|
+
)
|
|
595
|
+
);
|
|
596
|
+
--_mp-color-on-surface-variant: var(
|
|
597
|
+
--mp-sys-color-on-surface-variant,
|
|
598
|
+
var(
|
|
599
|
+
--md-sys-color-on-surface-variant,
|
|
600
|
+
oklch(
|
|
601
|
+
from var(--mp-source-color) var(--_mp-tone-on-surface-variant)
|
|
602
|
+
var(--_mp-chroma-on-surface-variant) h
|
|
603
|
+
)
|
|
604
|
+
)
|
|
605
|
+
);
|
|
606
|
+
--_mp-color-outline: var(
|
|
607
|
+
--mp-sys-color-outline,
|
|
608
|
+
var(
|
|
609
|
+
--md-sys-color-outline,
|
|
610
|
+
oklch(from var(--mp-source-color) var(--_mp-tone-outline) var(--_mp-chroma-outline) h)
|
|
611
|
+
)
|
|
612
|
+
);
|
|
613
|
+
/* The quieter of the two outlines: a divider, or a line that is not the edge
|
|
614
|
+
of a control. A slider's inactive track and a dropzone's dashed rectangle
|
|
615
|
+
are both this rather than `outline`. */
|
|
616
|
+
--_mp-color-outline-variant: var(
|
|
617
|
+
--mp-sys-color-outline-variant,
|
|
618
|
+
var(
|
|
619
|
+
--md-sys-color-outline-variant,
|
|
620
|
+
oklch(
|
|
621
|
+
from var(--mp-source-color) var(--_mp-tone-outline-variant)
|
|
622
|
+
var(--_mp-chroma-outline-variant) h
|
|
623
|
+
)
|
|
624
|
+
)
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
/*
|
|
628
|
+
* The scrim, and the one colour in the sheet that is the same in both
|
|
629
|
+
* schemes.
|
|
630
|
+
*
|
|
631
|
+
* MD3 puts it at neutral tone 0 — black — and it stays black in the dark
|
|
632
|
+
* scheme, because a scrim is not a surface that has to be legible against
|
|
633
|
+
* the page: it is the absence of the page. A scrim that lightened with the
|
|
634
|
+
* scheme would fail to dim anything on the theme that needs dimming most.
|
|
635
|
+
* The alpha is the component's, not the token's: MD3 draws it at 32%.
|
|
636
|
+
*/
|
|
637
|
+
--_mp-color-scrim: var(--mp-sys-color-scrim, var(--md-sys-color-scrim, #000000));
|
|
638
|
+
|
|
639
|
+
/* Not derived from the source colour. MD3's error palette is a fixed red
|
|
640
|
+
regardless of the seed — an error that shifted hue with the brand would
|
|
641
|
+
stop reading as an error. It still tracks the scheme, so it belongs here
|
|
642
|
+
rather than with the literals below. */
|
|
643
|
+
--_mp-color-error: var(
|
|
644
|
+
--mp-sys-color-error,
|
|
645
|
+
var(
|
|
646
|
+
--md-sys-color-error,
|
|
647
|
+
oklch(var(--_mp-tone-error) var(--_mp-chroma-error) var(--_mp-hue-error))
|
|
648
|
+
)
|
|
649
|
+
);
|
|
650
|
+
--_mp-color-on-error: var(
|
|
651
|
+
--mp-sys-color-on-error,
|
|
652
|
+
var(
|
|
653
|
+
--md-sys-color-on-error,
|
|
654
|
+
oklch(var(--_mp-tone-on-accent) var(--_mp-palette-error) var(--_mp-hue-error))
|
|
655
|
+
)
|
|
656
|
+
);
|
|
657
|
+
--_mp-color-error-container: var(
|
|
658
|
+
--mp-sys-color-error-container,
|
|
659
|
+
var(
|
|
660
|
+
--md-sys-color-error-container,
|
|
661
|
+
oklch(var(--_mp-tone-accent-container) var(--_mp-palette-error) var(--_mp-hue-error))
|
|
662
|
+
)
|
|
663
|
+
);
|
|
664
|
+
--_mp-color-on-error-container: var(
|
|
665
|
+
--mp-sys-color-on-error-container,
|
|
666
|
+
var(
|
|
667
|
+
--md-sys-color-on-error-container,
|
|
668
|
+
oklch(var(--_mp-tone-on-accent-container) var(--_mp-palette-error) var(--_mp-hue-error))
|
|
669
|
+
)
|
|
670
|
+
);
|
|
671
|
+
|
|
672
|
+
/*
|
|
673
|
+
* The names Tailwind's utilities actually read, aliased here as well as in
|
|
674
|
+
* the `@theme` block at the end of the file.
|
|
675
|
+
*
|
|
676
|
+
* Both are needed, and for different reasons. `@theme` is the *registration*:
|
|
677
|
+
* Tailwind only emits `border-mp-outline` for a name declared there. But what
|
|
678
|
+
* it emits alongside is a `:root` declaration, and a `:root` declaration
|
|
679
|
+
* freezes its `var()` references at the document root — which would put the
|
|
680
|
+
* whole cascade back where it started, one level up. A field inside a section
|
|
681
|
+
* with its own source colour would read the root's colour and quietly ignore
|
|
682
|
+
* its own.
|
|
683
|
+
*
|
|
684
|
+
* So the aliases are repeated here, where `*` re-resolves them per element.
|
|
685
|
+
* Only the alias is duplicated: the derivation above it lives in one place.
|
|
686
|
+
*/
|
|
687
|
+
--color-mp-primary: var(--_mp-color-primary);
|
|
688
|
+
--color-mp-on-primary: var(--_mp-color-on-primary);
|
|
689
|
+
--color-mp-primary-container: var(--_mp-color-primary-container);
|
|
690
|
+
--color-mp-on-primary-container: var(--_mp-color-on-primary-container);
|
|
691
|
+
--color-mp-secondary: var(--_mp-color-secondary);
|
|
692
|
+
--color-mp-on-secondary: var(--_mp-color-on-secondary);
|
|
693
|
+
--color-mp-secondary-container: var(--_mp-color-secondary-container);
|
|
694
|
+
--color-mp-on-secondary-container: var(--_mp-color-on-secondary-container);
|
|
695
|
+
--color-mp-tertiary: var(--_mp-color-tertiary);
|
|
696
|
+
--color-mp-on-tertiary: var(--_mp-color-on-tertiary);
|
|
697
|
+
--color-mp-tertiary-container: var(--_mp-color-tertiary-container);
|
|
698
|
+
--color-mp-on-tertiary-container: var(--_mp-color-on-tertiary-container);
|
|
699
|
+
--color-mp-surface: var(--_mp-color-surface);
|
|
700
|
+
--color-mp-surface-container-low: var(--_mp-color-surface-container-low);
|
|
701
|
+
--color-mp-surface-container: var(--_mp-color-surface-container);
|
|
702
|
+
--color-mp-surface-container-high: var(--_mp-color-surface-container-high);
|
|
703
|
+
--color-mp-surface-container-highest: var(--_mp-color-surface-container-highest);
|
|
704
|
+
--color-mp-inverse-surface: var(--_mp-color-inverse-surface);
|
|
705
|
+
--color-mp-inverse-on-surface: var(--_mp-color-inverse-on-surface);
|
|
706
|
+
--color-mp-inverse-primary: var(--_mp-color-inverse-primary);
|
|
707
|
+
--color-mp-scrim: var(--_mp-color-scrim);
|
|
708
|
+
--color-mp-on-surface: var(--_mp-color-on-surface);
|
|
709
|
+
--color-mp-on-surface-variant: var(--_mp-color-on-surface-variant);
|
|
710
|
+
--color-mp-outline: var(--_mp-color-outline);
|
|
711
|
+
--color-mp-outline-variant: var(--_mp-color-outline-variant);
|
|
712
|
+
--color-mp-error: var(--_mp-color-error);
|
|
713
|
+
--color-mp-on-error: var(--_mp-color-on-error);
|
|
714
|
+
--color-mp-error-container: var(--_mp-color-error-container);
|
|
715
|
+
--color-mp-on-error-container: var(--_mp-color-on-error-container);
|
|
716
|
+
|
|
717
|
+
/* Literals rather than derivations, but resolved through a variable all the
|
|
718
|
+
same, so they freeze at `:root` in exactly the same way. A consumer setting
|
|
719
|
+
a typescale on a wrapper should see it apply inside that wrapper. */
|
|
720
|
+
--text-mp-display-small: var(--mp-sys-typescale-display-small-size);
|
|
721
|
+
--text-mp-display-small--line-height: var(--mp-sys-typescale-display-small-line-height);
|
|
722
|
+
--text-mp-display-small--letter-spacing: var(--mp-sys-typescale-display-small-tracking);
|
|
723
|
+
--text-mp-display-small--font-weight: var(--mp-sys-typescale-display-small-weight);
|
|
724
|
+
|
|
725
|
+
--text-mp-headline-large: var(--mp-sys-typescale-headline-large-size);
|
|
726
|
+
--text-mp-headline-large--line-height: var(--mp-sys-typescale-headline-large-line-height);
|
|
727
|
+
--text-mp-headline-large--letter-spacing: var(--mp-sys-typescale-headline-large-tracking);
|
|
728
|
+
--text-mp-headline-large--font-weight: var(--mp-sys-typescale-headline-large-weight);
|
|
729
|
+
|
|
730
|
+
--text-mp-headline-medium: var(--mp-sys-typescale-headline-medium-size);
|
|
731
|
+
--text-mp-headline-medium--line-height: var(--mp-sys-typescale-headline-medium-line-height);
|
|
732
|
+
--text-mp-headline-medium--letter-spacing: var(--mp-sys-typescale-headline-medium-tracking);
|
|
733
|
+
--text-mp-headline-medium--font-weight: var(--mp-sys-typescale-headline-medium-weight);
|
|
734
|
+
|
|
735
|
+
--text-mp-headline-small: var(--mp-sys-typescale-headline-small-size);
|
|
736
|
+
--text-mp-headline-small--line-height: var(--mp-sys-typescale-headline-small-line-height);
|
|
737
|
+
--text-mp-headline-small--letter-spacing: var(--mp-sys-typescale-headline-small-tracking);
|
|
738
|
+
--text-mp-headline-small--font-weight: var(--mp-sys-typescale-headline-small-weight);
|
|
739
|
+
|
|
740
|
+
--text-mp-title-large: var(--mp-sys-typescale-title-large-size);
|
|
741
|
+
--text-mp-title-large--line-height: var(--mp-sys-typescale-title-large-line-height);
|
|
742
|
+
--text-mp-title-large--letter-spacing: var(--mp-sys-typescale-title-large-tracking);
|
|
743
|
+
--text-mp-title-large--font-weight: var(--mp-sys-typescale-title-large-weight);
|
|
744
|
+
|
|
745
|
+
--text-mp-title-small: var(--mp-sys-typescale-title-small-size);
|
|
746
|
+
--text-mp-title-small--line-height: var(--mp-sys-typescale-title-small-line-height);
|
|
747
|
+
--text-mp-title-small--letter-spacing: var(--mp-sys-typescale-title-small-tracking);
|
|
748
|
+
--text-mp-title-small--font-weight: var(--mp-sys-typescale-title-small-weight);
|
|
749
|
+
|
|
750
|
+
--text-mp-label-medium: var(--mp-sys-typescale-label-medium-size);
|
|
751
|
+
--text-mp-label-medium--line-height: var(--mp-sys-typescale-label-medium-line-height);
|
|
752
|
+
--text-mp-label-medium--letter-spacing: var(--mp-sys-typescale-label-medium-tracking);
|
|
753
|
+
--text-mp-label-medium--font-weight: var(--mp-sys-typescale-label-medium-weight);
|
|
754
|
+
|
|
755
|
+
--text-mp-label-small: var(--mp-sys-typescale-label-small-size);
|
|
756
|
+
--text-mp-label-small--line-height: var(--mp-sys-typescale-label-small-line-height);
|
|
757
|
+
--text-mp-label-small--letter-spacing: var(--mp-sys-typescale-label-small-tracking);
|
|
758
|
+
--text-mp-label-small--font-weight: var(--mp-sys-typescale-label-small-weight);
|
|
759
|
+
|
|
760
|
+
--text-mp-body-large: var(--mp-sys-typescale-body-large-size);
|
|
761
|
+
--text-mp-body-large--line-height: var(--mp-sys-typescale-body-large-line-height);
|
|
762
|
+
--text-mp-body-large--letter-spacing: var(--mp-sys-typescale-body-large-tracking);
|
|
763
|
+
--text-mp-body-large--font-weight: var(--mp-sys-typescale-body-large-weight);
|
|
764
|
+
|
|
765
|
+
--text-mp-body-medium: var(--mp-sys-typescale-body-medium-size);
|
|
766
|
+
--text-mp-body-medium--line-height: var(--mp-sys-typescale-body-medium-line-height);
|
|
767
|
+
--text-mp-body-medium--letter-spacing: var(--mp-sys-typescale-body-medium-tracking);
|
|
768
|
+
--text-mp-body-medium--font-weight: var(--mp-sys-typescale-body-medium-weight);
|
|
769
|
+
|
|
770
|
+
--text-mp-body-small: var(--mp-sys-typescale-body-small-size);
|
|
771
|
+
--text-mp-body-small--line-height: var(--mp-sys-typescale-body-small-line-height);
|
|
772
|
+
--text-mp-body-small--letter-spacing: var(--mp-sys-typescale-body-small-tracking);
|
|
773
|
+
--text-mp-body-small--font-weight: var(--mp-sys-typescale-body-small-weight);
|
|
774
|
+
|
|
775
|
+
--text-mp-label-large: var(--mp-sys-typescale-label-large-size);
|
|
776
|
+
--text-mp-label-large--line-height: var(--mp-sys-typescale-label-large-line-height);
|
|
777
|
+
--text-mp-label-large--letter-spacing: var(--mp-sys-typescale-label-large-tracking);
|
|
778
|
+
--text-mp-label-large--font-weight: var(--mp-sys-typescale-label-large-weight);
|
|
779
|
+
|
|
780
|
+
--text-mp-title-medium: var(--mp-sys-typescale-title-medium-size);
|
|
781
|
+
--text-mp-title-medium--line-height: var(--mp-sys-typescale-title-medium-line-height);
|
|
782
|
+
--text-mp-title-medium--letter-spacing: var(--mp-sys-typescale-title-medium-tracking);
|
|
783
|
+
--text-mp-title-medium--font-weight: var(--mp-sys-typescale-title-medium-weight);
|
|
784
|
+
|
|
785
|
+
--radius-mp-xs: var(--mp-sys-shape-corner-extra-small);
|
|
786
|
+
--radius-mp-sm: var(--mp-sys-shape-corner-small);
|
|
787
|
+
--radius-mp-md: var(--mp-sys-shape-corner-medium);
|
|
788
|
+
--radius-mp-lg: var(--mp-sys-shape-corner-large);
|
|
789
|
+
--radius-mp-xl: var(--mp-sys-shape-corner-extra-large);
|
|
790
|
+
--radius-mp-full: var(--mp-sys-shape-corner-full);
|
|
791
|
+
|
|
792
|
+
--shadow-mp-1: var(--mp-sys-elevation-level1);
|
|
793
|
+
--shadow-mp-2: var(--mp-sys-elevation-level2);
|
|
794
|
+
--shadow-mp-3: var(--mp-sys-elevation-level3);
|
|
795
|
+
|
|
796
|
+
--ease-mp-standard: var(--mp-sys-motion-easing-standard);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
:root {
|
|
800
|
+
/*
|
|
801
|
+
* No state opacities here. The spec's disabled treatment — content at 38%,
|
|
802
|
+
* an outline at 12% — is expressed where it is used, as `/38` and `/12` on
|
|
803
|
+
* the colour a component was already naming. A token would be a third name
|
|
804
|
+
* for a number nothing would read.
|
|
805
|
+
*/
|
|
806
|
+
|
|
807
|
+
/*
|
|
808
|
+
* Typescale. Thirteen of MD3's fifteen roles, and each one is read by
|
|
809
|
+
* something: a text field's input is `body-large` at `md` and above and
|
|
810
|
+
* `body-medium` at `sm` and `xs`, its notched label and supporting text are
|
|
811
|
+
* `body-small`. A button's label is `label-large` at `xs` and `sm` and
|
|
812
|
+
* `title-medium` from `md` up, which is what MD3 sets its own small and
|
|
813
|
+
* medium buttons in.
|
|
814
|
+
*
|
|
815
|
+
* The display and headline half of the scale arrived with `MPTypography`,
|
|
816
|
+
* which is the component whose whole subject is the ladder — before it, a
|
|
817
|
+
* heading role was a token nothing read. `display-large` and
|
|
818
|
+
* `display-medium` are still absent for exactly that reason: at 57px and
|
|
819
|
+
* 45px they are hero type, and nothing in the library sets any.
|
|
820
|
+
*
|
|
821
|
+
* All three values are the spec's. The size ladder is ours — see `MPSize` in
|
|
822
|
+
* `src/types.ts` — but what it selects between is not: a smaller control
|
|
823
|
+
* moves *down the Material type scale* rather than to some interpolated size
|
|
824
|
+
* of the library's own invention.
|
|
825
|
+
*
|
|
826
|
+
* `--mp-sys-typescale-*-font` is left pointing at whatever the page uses
|
|
827
|
+
* rather than naming a typeface. Shipping a font stack would be a page-level
|
|
828
|
+
* decision, and this library does not make those.
|
|
829
|
+
*/
|
|
830
|
+
/* The five roles above body, at MD3's own sizes and — this is the part that
|
|
831
|
+
looks like a mistake and is not — at MD3's own **weight 400**. Material
|
|
832
|
+
headings are not bold. A 32px line at regular weight is what the
|
|
833
|
+
specification draws, and the single fastest way to make a Material page
|
|
834
|
+
look like a Bootstrap one is to set its headings in 600. */
|
|
835
|
+
--mp-sys-typescale-display-small-font: inherit;
|
|
836
|
+
--mp-sys-typescale-display-small-size: 2.25rem;
|
|
837
|
+
--mp-sys-typescale-display-small-line-height: 2.75rem;
|
|
838
|
+
--mp-sys-typescale-display-small-tracking: 0rem;
|
|
839
|
+
--mp-sys-typescale-display-small-weight: 400;
|
|
840
|
+
|
|
841
|
+
--mp-sys-typescale-headline-large-font: inherit;
|
|
842
|
+
--mp-sys-typescale-headline-large-size: 2rem;
|
|
843
|
+
--mp-sys-typescale-headline-large-line-height: 2.5rem;
|
|
844
|
+
--mp-sys-typescale-headline-large-tracking: 0rem;
|
|
845
|
+
--mp-sys-typescale-headline-large-weight: 400;
|
|
846
|
+
|
|
847
|
+
--mp-sys-typescale-headline-medium-font: inherit;
|
|
848
|
+
--mp-sys-typescale-headline-medium-size: 1.75rem;
|
|
849
|
+
--mp-sys-typescale-headline-medium-line-height: 2.25rem;
|
|
850
|
+
--mp-sys-typescale-headline-medium-tracking: 0rem;
|
|
851
|
+
--mp-sys-typescale-headline-medium-weight: 400;
|
|
852
|
+
|
|
853
|
+
--mp-sys-typescale-headline-small-font: inherit;
|
|
854
|
+
--mp-sys-typescale-headline-small-size: 1.5rem;
|
|
855
|
+
--mp-sys-typescale-headline-small-line-height: 2rem;
|
|
856
|
+
--mp-sys-typescale-headline-small-tracking: 0rem;
|
|
857
|
+
--mp-sys-typescale-headline-small-weight: 400;
|
|
858
|
+
|
|
859
|
+
--mp-sys-typescale-title-large-font: inherit;
|
|
860
|
+
--mp-sys-typescale-title-large-size: 1.375rem;
|
|
861
|
+
--mp-sys-typescale-title-large-line-height: 1.75rem;
|
|
862
|
+
--mp-sys-typescale-title-large-tracking: 0rem;
|
|
863
|
+
--mp-sys-typescale-title-large-weight: 400;
|
|
864
|
+
|
|
865
|
+
--mp-sys-typescale-body-large-font: inherit;
|
|
866
|
+
--mp-sys-typescale-body-large-size: 1rem;
|
|
867
|
+
--mp-sys-typescale-body-large-line-height: 1.5rem;
|
|
868
|
+
--mp-sys-typescale-body-large-tracking: 0.03125rem;
|
|
869
|
+
--mp-sys-typescale-body-large-weight: 400;
|
|
870
|
+
|
|
871
|
+
--mp-sys-typescale-body-medium-font: inherit;
|
|
872
|
+
--mp-sys-typescale-body-medium-size: 0.875rem;
|
|
873
|
+
--mp-sys-typescale-body-medium-line-height: 1.25rem;
|
|
874
|
+
--mp-sys-typescale-body-medium-tracking: 0.015625rem;
|
|
875
|
+
--mp-sys-typescale-body-medium-weight: 400;
|
|
876
|
+
|
|
877
|
+
--mp-sys-typescale-body-small-font: inherit;
|
|
878
|
+
--mp-sys-typescale-body-small-size: 0.75rem;
|
|
879
|
+
--mp-sys-typescale-body-small-line-height: 1rem;
|
|
880
|
+
--mp-sys-typescale-body-small-tracking: 0.025rem;
|
|
881
|
+
--mp-sys-typescale-body-small-weight: 400;
|
|
882
|
+
|
|
883
|
+
/* The label and small-title roles. All of them are 500 rather than 400: MD3
|
|
884
|
+
sets a control's own text one weight up from prose, which is what keeps a
|
|
885
|
+
button's label from reading as a paragraph that happens to be inside a
|
|
886
|
+
box. `label-small` at 11px is the smallest type in the specification and
|
|
887
|
+
is why a badge's count is legible at all. */
|
|
888
|
+
--mp-sys-typescale-label-large-font: inherit;
|
|
889
|
+
--mp-sys-typescale-label-large-size: 0.875rem;
|
|
890
|
+
--mp-sys-typescale-label-large-line-height: 1.25rem;
|
|
891
|
+
--mp-sys-typescale-label-large-tracking: 0.00625rem;
|
|
892
|
+
--mp-sys-typescale-label-large-weight: 500;
|
|
893
|
+
|
|
894
|
+
--mp-sys-typescale-label-medium-font: inherit;
|
|
895
|
+
--mp-sys-typescale-label-medium-size: 0.75rem;
|
|
896
|
+
--mp-sys-typescale-label-medium-line-height: 1rem;
|
|
897
|
+
--mp-sys-typescale-label-medium-tracking: 0.03125rem;
|
|
898
|
+
--mp-sys-typescale-label-medium-weight: 500;
|
|
899
|
+
|
|
900
|
+
--mp-sys-typescale-label-small-font: inherit;
|
|
901
|
+
--mp-sys-typescale-label-small-size: 0.6875rem;
|
|
902
|
+
--mp-sys-typescale-label-small-line-height: 1rem;
|
|
903
|
+
--mp-sys-typescale-label-small-tracking: 0.03125rem;
|
|
904
|
+
--mp-sys-typescale-label-small-weight: 500;
|
|
905
|
+
|
|
906
|
+
--mp-sys-typescale-title-small-font: inherit;
|
|
907
|
+
--mp-sys-typescale-title-small-size: 0.875rem;
|
|
908
|
+
--mp-sys-typescale-title-small-line-height: 1.25rem;
|
|
909
|
+
--mp-sys-typescale-title-small-tracking: 0.00625rem;
|
|
910
|
+
--mp-sys-typescale-title-small-weight: 500;
|
|
911
|
+
|
|
912
|
+
--mp-sys-typescale-title-medium-font: inherit;
|
|
913
|
+
--mp-sys-typescale-title-medium-size: 1rem;
|
|
914
|
+
--mp-sys-typescale-title-medium-line-height: 1.5rem;
|
|
915
|
+
--mp-sys-typescale-title-medium-tracking: 0.009375rem;
|
|
916
|
+
--mp-sys-typescale-title-medium-weight: 500;
|
|
917
|
+
|
|
918
|
+
/*
|
|
919
|
+
* Shape. Four corner sizes, and which one a component takes is a statement
|
|
920
|
+
* about what kind of object it is rather than a size to taste: a text field
|
|
921
|
+
* is a well (`extra-small`), a button is a pill (`full`), a dropzone is a
|
|
922
|
+
* sheet (`medium`), and the tiles inside one are `small`.
|
|
923
|
+
*
|
|
924
|
+
* `full` is a length rather than `50%` deliberately. A percentage radius on a
|
|
925
|
+
* box whose width and height differ draws an ellipse, so a wide button would
|
|
926
|
+
* bow along its top edge instead of ending in two half-circles.
|
|
927
|
+
*/
|
|
928
|
+
--mp-sys-shape-corner-extra-small: 4px;
|
|
929
|
+
--mp-sys-shape-corner-small: 8px;
|
|
930
|
+
--mp-sys-shape-corner-medium: 12px;
|
|
931
|
+
/* `large` is read by exactly one thing, and it arrived with it: a drawer's
|
|
932
|
+
free edge. MD3 gives the navigation drawer `corner-large` on the side that
|
|
933
|
+
faces the page and leaves the side against the window square, and neither
|
|
934
|
+
neighbour is a substitute — 12px on a 360dp panel is barely a corner, and
|
|
935
|
+
28px is the bottom sheet's, which is a different object. */
|
|
936
|
+
--mp-sys-shape-corner-large: 16px;
|
|
937
|
+
/* `extra-large` is here for the dialog, which is the spec's own corner for
|
|
938
|
+
it and the loudest radius in the system: a sheet that has taken the page
|
|
939
|
+
is allowed to look like an object rather than like a panel. It is also the
|
|
940
|
+
bottom sheet's, which is the same claim made along one edge. */
|
|
941
|
+
--mp-sys-shape-corner-extra-large: 28px;
|
|
942
|
+
--mp-sys-shape-corner-full: 9999px;
|
|
943
|
+
|
|
944
|
+
/*
|
|
945
|
+
* Elevation. Three of MD3's six levels, because three are what gets read: an
|
|
946
|
+
* elevated button rests at level 1 and rises to 2 under the pointer, a menu
|
|
947
|
+
* floats at level 2, and a dialog — which has taken the page rather than
|
|
948
|
+
* merely covered part of it — sits at level 3.
|
|
949
|
+
*
|
|
950
|
+
* Both are the spec's own two-shadow recipe — a tight key shadow plus a wider
|
|
951
|
+
* ambient one — rather than one blurred box shadow. The pair is what makes a
|
|
952
|
+
* raised surface read as lit from above instead of as a sticker with a halo.
|
|
953
|
+
*/
|
|
954
|
+
--mp-sys-elevation-level1: 0 1px 2px 0 rgb(0 0 0 / 0.3), 0 1px 3px 1px rgb(0 0 0 / 0.15);
|
|
955
|
+
--mp-sys-elevation-level2: 0 1px 2px 0 rgb(0 0 0 / 0.3), 0 2px 6px 2px rgb(0 0 0 / 0.15);
|
|
956
|
+
--mp-sys-elevation-level3: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 4px 8px 3px rgb(0 0 0 / 0.15);
|
|
957
|
+
|
|
958
|
+
/*
|
|
959
|
+
* Motion.
|
|
960
|
+
*
|
|
961
|
+
* Six of MD3's sixteen duration tokens and six of its seven easing curves —
|
|
962
|
+
* the ones something in the library actually reads, on the rule every other
|
|
963
|
+
* token here follows. `short4` is what a text field's label and outline
|
|
964
|
+
* transition on; the rest arrived with the `MPAnimate*` components, which
|
|
965
|
+
* take these as their defaults rather than numbers of their own.
|
|
966
|
+
*
|
|
967
|
+
* Worth knowing if these controls sit beside another library's: 250ms is a
|
|
968
|
+
* common default elsewhere, and a field from here will settle slightly
|
|
969
|
+
* sooner unless `short4` is set to match.
|
|
970
|
+
*/
|
|
971
|
+
--mp-sys-motion-duration-short4: 200ms;
|
|
972
|
+
--mp-sys-motion-duration-medium2: 300ms;
|
|
973
|
+
--mp-sys-motion-duration-medium4: 400ms;
|
|
974
|
+
--mp-sys-motion-duration-long2: 500ms;
|
|
975
|
+
--mp-sys-motion-duration-extra-long4: 1000ms;
|
|
976
|
+
|
|
977
|
+
/* The spec's `standard` curve: quick to leave, slow to arrive. Read by the
|
|
978
|
+
one thing in the library that actually travels, a switch's thumb. */
|
|
979
|
+
--mp-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
|
|
980
|
+
--mp-sys-motion-easing-standard-decelerate: cubic-bezier(0, 0, 0, 1);
|
|
981
|
+
--mp-sys-motion-easing-standard-accelerate: cubic-bezier(0.3, 0, 1, 1);
|
|
982
|
+
/*
|
|
983
|
+
* The emphasized set, which is what MD3 asks a *transition* to use — a
|
|
984
|
+
* standard curve is for a control changing state, an emphasized one for
|
|
985
|
+
* something arriving on or leaving the screen.
|
|
986
|
+
*
|
|
987
|
+
* `emphasized` itself is two curves joined in the middle in the
|
|
988
|
+
* specification, and CSS has no single value that is both. This is the
|
|
989
|
+
* one-curve stand-in MD3's own web implementation publishes. Where the
|
|
990
|
+
* halves genuinely matter — a line rising as another leaves — the two below
|
|
991
|
+
* are the halves, and they are what the components reach for.
|
|
992
|
+
*/
|
|
993
|
+
--mp-sys-motion-easing-emphasized: cubic-bezier(0.2, 0, 0, 1);
|
|
994
|
+
--mp-sys-motion-easing-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1);
|
|
995
|
+
--mp-sys-motion-easing-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15);
|
|
996
|
+
/* CSS's own `linear` is a keyword rather than a curve, and a token that
|
|
997
|
+
cannot be interpolated with the other six is a token that breaks the one
|
|
998
|
+
place they are swapped. The identity bezier is the same line. */
|
|
999
|
+
--mp-sys-motion-easing-linear: cubic-bezier(0, 0, 1, 1);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/*
|
|
1003
|
+
* Two shape presets, on the same model as `data-mp-scheme`: say nothing and
|
|
1004
|
+
* you get the specification's corners, name one and the whole subtree moves.
|
|
1005
|
+
*
|
|
1006
|
+
* <html data-mp-shape="rounded">
|
|
1007
|
+
* <section data-mp-shape="sharp"> <!-- a subtree, same as the scheme -->
|
|
1008
|
+
*
|
|
1009
|
+
* These only set the four tokens above, so anything a consumer sets themselves
|
|
1010
|
+
* still wins: the block is inside `@layer theme`, and unlayered CSS beats a
|
|
1011
|
+
* layered rule whatever order the two are imported in.
|
|
1012
|
+
*
|
|
1013
|
+
* Named presets rather than a `--mp-shape-scale` multiplier, because the corner
|
|
1014
|
+
* ladder is not linear and should not be scaled as if it were. Going rounder,
|
|
1015
|
+
* `extra-small` wants to double and `extra-large` wants to move by a sixth — a
|
|
1016
|
+
* dialog whose corner has doubled to 56px is not a rounder dialog, it is a
|
|
1017
|
+
* lozenge. The numbers below are chosen per rung for that reason.
|
|
1018
|
+
*/
|
|
1019
|
+
[data-mp-shape='rounded'] {
|
|
1020
|
+
--mp-sys-shape-corner-extra-small: 8px;
|
|
1021
|
+
--mp-sys-shape-corner-small: 12px;
|
|
1022
|
+
--mp-sys-shape-corner-medium: 20px;
|
|
1023
|
+
--mp-sys-shape-corner-large: 24px;
|
|
1024
|
+
--mp-sys-shape-corner-extra-large: 32px;
|
|
1025
|
+
/* `full` is not here, and cannot be: a button is already a pill at 9999px,
|
|
1026
|
+
so there is no rounder to go. This preset moves the four rungs that have
|
|
1027
|
+
somewhere to move, which is why it reads on fields, chips, sheets and
|
|
1028
|
+
dialogs and is invisible on buttons and sliders. */
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
[data-mp-shape='sharp'] {
|
|
1032
|
+
--mp-sys-shape-corner-extra-small: 0;
|
|
1033
|
+
--mp-sys-shape-corner-small: 0;
|
|
1034
|
+
--mp-sys-shape-corner-medium: 0;
|
|
1035
|
+
--mp-sys-shape-corner-large: 0;
|
|
1036
|
+
--mp-sys-shape-corner-extra-large: 0;
|
|
1037
|
+
/* `full` *is* here, unlike above, and for the same reason: this is the one
|
|
1038
|
+
direction a pill can travel. Leaving it round would make `sharp` a theme
|
|
1039
|
+
where every corner is square except the buttons, which is not a theme. */
|
|
1040
|
+
--mp-sys-shape-corner-full: 0;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/* ---------------------------------------------------------------------------
|
|
1045
|
+
* Utility generation
|
|
1046
|
+
*
|
|
1047
|
+
* The block above is the input side: values a consumer sets, in a plain `:root`,
|
|
1048
|
+
* where Tailwind will not touch them. This block is the output side — Tailwind
|
|
1049
|
+
* only generates `bg-mp-primary`, `text-mp-body-large` and friends for names
|
|
1050
|
+
* declared in `@theme`, and it prunes the ones no utility ends up using.
|
|
1051
|
+
*
|
|
1052
|
+
* The split is what keeps the input side safe from that pruning: a variable only
|
|
1053
|
+
* ever referenced from inside another custom property's value has no utility
|
|
1054
|
+
* pointing at it, and would be a candidate for removal if it lived here.
|
|
1055
|
+
*
|
|
1056
|
+
* Every name is prefixed. `@theme` registers globally, so an unprefixed
|
|
1057
|
+
* `--color-primary` would generate a `bg-primary` that collides with the
|
|
1058
|
+
* consumer's own.
|
|
1059
|
+
*
|
|
1060
|
+
* What this block does *not* do is supply the values the utilities end up using.
|
|
1061
|
+
* It registers the names; the `*` rule above resolves them, and has to, because a
|
|
1062
|
+
* `:root` declaration would freeze the cascade at the document root. Every name
|
|
1063
|
+
* here is therefore also declared there — deliberately, not by oversight.
|
|
1064
|
+
* ------------------------------------------------------------------------- */
|
|
1065
|
+
|
|
1066
|
+
@theme {
|
|
1067
|
+
--color-mp-primary: var(--_mp-color-primary);
|
|
1068
|
+
--color-mp-on-primary: var(--_mp-color-on-primary);
|
|
1069
|
+
--color-mp-primary-container: var(--_mp-color-primary-container);
|
|
1070
|
+
--color-mp-on-primary-container: var(--_mp-color-on-primary-container);
|
|
1071
|
+
--color-mp-secondary: var(--_mp-color-secondary);
|
|
1072
|
+
--color-mp-on-secondary: var(--_mp-color-on-secondary);
|
|
1073
|
+
--color-mp-secondary-container: var(--_mp-color-secondary-container);
|
|
1074
|
+
--color-mp-on-secondary-container: var(--_mp-color-on-secondary-container);
|
|
1075
|
+
--color-mp-tertiary: var(--_mp-color-tertiary);
|
|
1076
|
+
--color-mp-on-tertiary: var(--_mp-color-on-tertiary);
|
|
1077
|
+
--color-mp-tertiary-container: var(--_mp-color-tertiary-container);
|
|
1078
|
+
--color-mp-on-tertiary-container: var(--_mp-color-on-tertiary-container);
|
|
1079
|
+
--color-mp-surface: var(--_mp-color-surface);
|
|
1080
|
+
--color-mp-surface-container-low: var(--_mp-color-surface-container-low);
|
|
1081
|
+
--color-mp-surface-container: var(--_mp-color-surface-container);
|
|
1082
|
+
--color-mp-surface-container-high: var(--_mp-color-surface-container-high);
|
|
1083
|
+
--color-mp-surface-container-highest: var(--_mp-color-surface-container-highest);
|
|
1084
|
+
--color-mp-inverse-surface: var(--_mp-color-inverse-surface);
|
|
1085
|
+
--color-mp-inverse-on-surface: var(--_mp-color-inverse-on-surface);
|
|
1086
|
+
--color-mp-inverse-primary: var(--_mp-color-inverse-primary);
|
|
1087
|
+
--color-mp-scrim: var(--_mp-color-scrim);
|
|
1088
|
+
--color-mp-on-surface: var(--_mp-color-on-surface);
|
|
1089
|
+
--color-mp-on-surface-variant: var(--_mp-color-on-surface-variant);
|
|
1090
|
+
--color-mp-outline: var(--_mp-color-outline);
|
|
1091
|
+
--color-mp-outline-variant: var(--_mp-color-outline-variant);
|
|
1092
|
+
--color-mp-error: var(--_mp-color-error);
|
|
1093
|
+
--color-mp-on-error: var(--_mp-color-on-error);
|
|
1094
|
+
--color-mp-error-container: var(--_mp-color-error-container);
|
|
1095
|
+
--color-mp-on-error-container: var(--_mp-color-on-error-container);
|
|
1096
|
+
|
|
1097
|
+
--text-mp-display-small: var(--mp-sys-typescale-display-small-size);
|
|
1098
|
+
--text-mp-display-small--line-height: var(--mp-sys-typescale-display-small-line-height);
|
|
1099
|
+
--text-mp-display-small--letter-spacing: var(--mp-sys-typescale-display-small-tracking);
|
|
1100
|
+
--text-mp-display-small--font-weight: var(--mp-sys-typescale-display-small-weight);
|
|
1101
|
+
|
|
1102
|
+
--text-mp-headline-large: var(--mp-sys-typescale-headline-large-size);
|
|
1103
|
+
--text-mp-headline-large--line-height: var(--mp-sys-typescale-headline-large-line-height);
|
|
1104
|
+
--text-mp-headline-large--letter-spacing: var(--mp-sys-typescale-headline-large-tracking);
|
|
1105
|
+
--text-mp-headline-large--font-weight: var(--mp-sys-typescale-headline-large-weight);
|
|
1106
|
+
|
|
1107
|
+
--text-mp-headline-medium: var(--mp-sys-typescale-headline-medium-size);
|
|
1108
|
+
--text-mp-headline-medium--line-height: var(--mp-sys-typescale-headline-medium-line-height);
|
|
1109
|
+
--text-mp-headline-medium--letter-spacing: var(--mp-sys-typescale-headline-medium-tracking);
|
|
1110
|
+
--text-mp-headline-medium--font-weight: var(--mp-sys-typescale-headline-medium-weight);
|
|
1111
|
+
|
|
1112
|
+
--text-mp-headline-small: var(--mp-sys-typescale-headline-small-size);
|
|
1113
|
+
--text-mp-headline-small--line-height: var(--mp-sys-typescale-headline-small-line-height);
|
|
1114
|
+
--text-mp-headline-small--letter-spacing: var(--mp-sys-typescale-headline-small-tracking);
|
|
1115
|
+
--text-mp-headline-small--font-weight: var(--mp-sys-typescale-headline-small-weight);
|
|
1116
|
+
|
|
1117
|
+
--text-mp-title-large: var(--mp-sys-typescale-title-large-size);
|
|
1118
|
+
--text-mp-title-large--line-height: var(--mp-sys-typescale-title-large-line-height);
|
|
1119
|
+
--text-mp-title-large--letter-spacing: var(--mp-sys-typescale-title-large-tracking);
|
|
1120
|
+
--text-mp-title-large--font-weight: var(--mp-sys-typescale-title-large-weight);
|
|
1121
|
+
|
|
1122
|
+
--text-mp-title-small: var(--mp-sys-typescale-title-small-size);
|
|
1123
|
+
--text-mp-title-small--line-height: var(--mp-sys-typescale-title-small-line-height);
|
|
1124
|
+
--text-mp-title-small--letter-spacing: var(--mp-sys-typescale-title-small-tracking);
|
|
1125
|
+
--text-mp-title-small--font-weight: var(--mp-sys-typescale-title-small-weight);
|
|
1126
|
+
|
|
1127
|
+
--text-mp-label-medium: var(--mp-sys-typescale-label-medium-size);
|
|
1128
|
+
--text-mp-label-medium--line-height: var(--mp-sys-typescale-label-medium-line-height);
|
|
1129
|
+
--text-mp-label-medium--letter-spacing: var(--mp-sys-typescale-label-medium-tracking);
|
|
1130
|
+
--text-mp-label-medium--font-weight: var(--mp-sys-typescale-label-medium-weight);
|
|
1131
|
+
|
|
1132
|
+
--text-mp-label-small: var(--mp-sys-typescale-label-small-size);
|
|
1133
|
+
--text-mp-label-small--line-height: var(--mp-sys-typescale-label-small-line-height);
|
|
1134
|
+
--text-mp-label-small--letter-spacing: var(--mp-sys-typescale-label-small-tracking);
|
|
1135
|
+
--text-mp-label-small--font-weight: var(--mp-sys-typescale-label-small-weight);
|
|
1136
|
+
|
|
1137
|
+
--text-mp-body-large: var(--mp-sys-typescale-body-large-size);
|
|
1138
|
+
--text-mp-body-large--line-height: var(--mp-sys-typescale-body-large-line-height);
|
|
1139
|
+
--text-mp-body-large--letter-spacing: var(--mp-sys-typescale-body-large-tracking);
|
|
1140
|
+
--text-mp-body-large--font-weight: var(--mp-sys-typescale-body-large-weight);
|
|
1141
|
+
|
|
1142
|
+
--text-mp-body-medium: var(--mp-sys-typescale-body-medium-size);
|
|
1143
|
+
--text-mp-body-medium--line-height: var(--mp-sys-typescale-body-medium-line-height);
|
|
1144
|
+
--text-mp-body-medium--letter-spacing: var(--mp-sys-typescale-body-medium-tracking);
|
|
1145
|
+
--text-mp-body-medium--font-weight: var(--mp-sys-typescale-body-medium-weight);
|
|
1146
|
+
|
|
1147
|
+
--text-mp-body-small: var(--mp-sys-typescale-body-small-size);
|
|
1148
|
+
--text-mp-body-small--line-height: var(--mp-sys-typescale-body-small-line-height);
|
|
1149
|
+
--text-mp-body-small--letter-spacing: var(--mp-sys-typescale-body-small-tracking);
|
|
1150
|
+
--text-mp-body-small--font-weight: var(--mp-sys-typescale-body-small-weight);
|
|
1151
|
+
|
|
1152
|
+
--text-mp-label-large: var(--mp-sys-typescale-label-large-size);
|
|
1153
|
+
--text-mp-label-large--line-height: var(--mp-sys-typescale-label-large-line-height);
|
|
1154
|
+
--text-mp-label-large--letter-spacing: var(--mp-sys-typescale-label-large-tracking);
|
|
1155
|
+
--text-mp-label-large--font-weight: var(--mp-sys-typescale-label-large-weight);
|
|
1156
|
+
|
|
1157
|
+
--text-mp-title-medium: var(--mp-sys-typescale-title-medium-size);
|
|
1158
|
+
--text-mp-title-medium--line-height: var(--mp-sys-typescale-title-medium-line-height);
|
|
1159
|
+
--text-mp-title-medium--letter-spacing: var(--mp-sys-typescale-title-medium-tracking);
|
|
1160
|
+
--text-mp-title-medium--font-weight: var(--mp-sys-typescale-title-medium-weight);
|
|
1161
|
+
|
|
1162
|
+
--radius-mp-xs: var(--mp-sys-shape-corner-extra-small);
|
|
1163
|
+
--radius-mp-sm: var(--mp-sys-shape-corner-small);
|
|
1164
|
+
--radius-mp-md: var(--mp-sys-shape-corner-medium);
|
|
1165
|
+
--radius-mp-lg: var(--mp-sys-shape-corner-large);
|
|
1166
|
+
--radius-mp-xl: var(--mp-sys-shape-corner-extra-large);
|
|
1167
|
+
--radius-mp-full: var(--mp-sys-shape-corner-full);
|
|
1168
|
+
|
|
1169
|
+
--shadow-mp-1: var(--mp-sys-elevation-level1);
|
|
1170
|
+
--shadow-mp-2: var(--mp-sys-elevation-level2);
|
|
1171
|
+
--shadow-mp-3: var(--mp-sys-elevation-level3);
|
|
1172
|
+
|
|
1173
|
+
--ease-mp-standard: var(--mp-sys-motion-easing-standard);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
/* ---------------------------------------------------------------------------
|
|
1177
|
+
* The layout grid
|
|
1178
|
+
*
|
|
1179
|
+
* A column is `(100% + gutter) * span / columns - gutter`, and the arithmetic
|
|
1180
|
+
* lives here for the reason the keyframes below do: Tailwind finds classes by
|
|
1181
|
+
* scanning source text, and `columns` is a number the caller picks at runtime.
|
|
1182
|
+
* A class name assembled in JavaScript is a class name Tailwind never sees, so
|
|
1183
|
+
* the per-instance numbers arrive as inline `--_mp-*` slots — exactly as a
|
|
1184
|
+
* `color` reaches a background — and the rules that read them are written once,
|
|
1185
|
+
* here.
|
|
1186
|
+
*
|
|
1187
|
+
* `min(span, columns)` is the clamp: `span={99}` fills its row instead of
|
|
1188
|
+
* running off the page, which is what the caller meant.
|
|
1189
|
+
*
|
|
1190
|
+
* Every slot cascades upward — each window size class falls back through the
|
|
1191
|
+
* ones below it — so `span={{ expanded: 6 }}` sets one custom property and not
|
|
1192
|
+
* five. The chains get long at `extra-large`; that is the cost of keeping the
|
|
1193
|
+
* DOM lean, and it is paid once here rather than on every grid item in a
|
|
1194
|
+
* consumer's application.
|
|
1195
|
+
*
|
|
1196
|
+
* The widths are **MD3's window size classes** — 600, 840, 1200 and 1600dp —
|
|
1197
|
+
* and not Tailwind's breakpoints. See `MPWindowClass` in `src/types.ts`.
|
|
1198
|
+
*
|
|
1199
|
+
* Unlayered, like the two animation classes below and for the same reason: a
|
|
1200
|
+
* layered rule loses to every unlayered one, and a consumer's own page styling
|
|
1201
|
+
* is unlayered. A grid whose widths could be cancelled by a stray `div { }` in
|
|
1202
|
+
* an application's stylesheet is not a grid.
|
|
1203
|
+
* ------------------------------------------------------------------------- */
|
|
1204
|
+
|
|
1205
|
+
.mp-grid {
|
|
1206
|
+
--_mp-cols: var(--_mp-cols-compact, 12);
|
|
1207
|
+
--_mp-gap-x: var(--_mp-gap-x-compact, 0px);
|
|
1208
|
+
--_mp-gap-y: var(--_mp-gap-y-compact, 0px);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
.mp-grid-item {
|
|
1212
|
+
--_mp-span: var(--_mp-span-compact, var(--_mp-cols, 12));
|
|
1213
|
+
--_mp-offset: var(--_mp-offset-compact, 0);
|
|
1214
|
+
|
|
1215
|
+
/* One column plus one gutter. `--_mp-cols` and `--_mp-gap-x` are inherited
|
|
1216
|
+
from the grid, so this re-resolves on its own at every window class. */
|
|
1217
|
+
--_mp-track: calc((100% + var(--_mp-gap-x, 0px)) / var(--_mp-cols, 12));
|
|
1218
|
+
|
|
1219
|
+
/* Inseparable from the width under them: `flex` stops the row resizing the
|
|
1220
|
+
item, `min-width` stops a long unbroken word doing the same, and
|
|
1221
|
+
`box-sizing` is what makes the percentage mean the whole item. */
|
|
1222
|
+
box-sizing: border-box;
|
|
1223
|
+
flex: 0 0 auto;
|
|
1224
|
+
min-width: 0;
|
|
1225
|
+
width: calc(var(--_mp-track) * min(var(--_mp-span), var(--_mp-cols, 12)) - var(--_mp-gap-x, 0px));
|
|
1226
|
+
margin-inline-start: calc(var(--_mp-track) * min(var(--_mp-offset), var(--_mp-cols, 12)));
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
@media (width >= 600px) {
|
|
1230
|
+
.mp-grid {
|
|
1231
|
+
--_mp-cols: var(--_mp-cols-medium, var(--_mp-cols-compact, 12));
|
|
1232
|
+
--_mp-gap-x: var(--_mp-gap-x-medium, var(--_mp-gap-x-compact, 0px));
|
|
1233
|
+
--_mp-gap-y: var(--_mp-gap-y-medium, var(--_mp-gap-y-compact, 0px));
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
.mp-grid-item {
|
|
1237
|
+
--_mp-span: var(--_mp-span-medium, var(--_mp-span-compact, var(--_mp-cols, 12)));
|
|
1238
|
+
--_mp-offset: var(--_mp-offset-medium, var(--_mp-offset-compact, 0));
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
@media (width >= 840px) {
|
|
1243
|
+
.mp-grid {
|
|
1244
|
+
--_mp-cols: var(--_mp-cols-expanded, var(--_mp-cols-medium, var(--_mp-cols-compact, 12)));
|
|
1245
|
+
--_mp-gap-x: var(--_mp-gap-x-expanded, var(--_mp-gap-x-medium, var(--_mp-gap-x-compact, 0px)));
|
|
1246
|
+
--_mp-gap-y: var(--_mp-gap-y-expanded, var(--_mp-gap-y-medium, var(--_mp-gap-y-compact, 0px)));
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
.mp-grid-item {
|
|
1250
|
+
--_mp-span: var(
|
|
1251
|
+
--_mp-span-expanded,
|
|
1252
|
+
var(--_mp-span-medium, var(--_mp-span-compact, var(--_mp-cols, 12)))
|
|
1253
|
+
);
|
|
1254
|
+
--_mp-offset: var(
|
|
1255
|
+
--_mp-offset-expanded,
|
|
1256
|
+
var(--_mp-offset-medium, var(--_mp-offset-compact, 0))
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
@media (width >= 1200px) {
|
|
1262
|
+
.mp-grid {
|
|
1263
|
+
--_mp-cols: var(
|
|
1264
|
+
--_mp-cols-large,
|
|
1265
|
+
var(--_mp-cols-expanded, var(--_mp-cols-medium, var(--_mp-cols-compact, 12)))
|
|
1266
|
+
);
|
|
1267
|
+
--_mp-gap-x: var(
|
|
1268
|
+
--_mp-gap-x-large,
|
|
1269
|
+
var(--_mp-gap-x-expanded, var(--_mp-gap-x-medium, var(--_mp-gap-x-compact, 0px)))
|
|
1270
|
+
);
|
|
1271
|
+
--_mp-gap-y: var(
|
|
1272
|
+
--_mp-gap-y-large,
|
|
1273
|
+
var(--_mp-gap-y-expanded, var(--_mp-gap-y-medium, var(--_mp-gap-y-compact, 0px)))
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
.mp-grid-item {
|
|
1278
|
+
--_mp-span: var(
|
|
1279
|
+
--_mp-span-large,
|
|
1280
|
+
var(--_mp-span-expanded, var(--_mp-span-medium, var(--_mp-span-compact, var(--_mp-cols, 12))))
|
|
1281
|
+
);
|
|
1282
|
+
--_mp-offset: var(
|
|
1283
|
+
--_mp-offset-large,
|
|
1284
|
+
var(--_mp-offset-expanded, var(--_mp-offset-medium, var(--_mp-offset-compact, 0)))
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
@media (width >= 1600px) {
|
|
1290
|
+
.mp-grid {
|
|
1291
|
+
--_mp-cols: var(
|
|
1292
|
+
--_mp-cols-extra-large,
|
|
1293
|
+
var(
|
|
1294
|
+
--_mp-cols-large,
|
|
1295
|
+
var(--_mp-cols-expanded, var(--_mp-cols-medium, var(--_mp-cols-compact, 12)))
|
|
1296
|
+
)
|
|
1297
|
+
);
|
|
1298
|
+
--_mp-gap-x: var(
|
|
1299
|
+
--_mp-gap-x-extra-large,
|
|
1300
|
+
var(
|
|
1301
|
+
--_mp-gap-x-large,
|
|
1302
|
+
var(--_mp-gap-x-expanded, var(--_mp-gap-x-medium, var(--_mp-gap-x-compact, 0px)))
|
|
1303
|
+
)
|
|
1304
|
+
);
|
|
1305
|
+
--_mp-gap-y: var(
|
|
1306
|
+
--_mp-gap-y-extra-large,
|
|
1307
|
+
var(
|
|
1308
|
+
--_mp-gap-y-large,
|
|
1309
|
+
var(--_mp-gap-y-expanded, var(--_mp-gap-y-medium, var(--_mp-gap-y-compact, 0px)))
|
|
1310
|
+
)
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
.mp-grid-item {
|
|
1315
|
+
--_mp-span: var(
|
|
1316
|
+
--_mp-span-extra-large,
|
|
1317
|
+
var(
|
|
1318
|
+
--_mp-span-large,
|
|
1319
|
+
var(
|
|
1320
|
+
--_mp-span-expanded,
|
|
1321
|
+
var(--_mp-span-medium, var(--_mp-span-compact, var(--_mp-cols, 12)))
|
|
1322
|
+
)
|
|
1323
|
+
)
|
|
1324
|
+
);
|
|
1325
|
+
--_mp-offset: var(
|
|
1326
|
+
--_mp-offset-extra-large,
|
|
1327
|
+
var(
|
|
1328
|
+
--_mp-offset-large,
|
|
1329
|
+
var(--_mp-offset-expanded, var(--_mp-offset-medium, var(--_mp-offset-compact, 0)))
|
|
1330
|
+
)
|
|
1331
|
+
);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
/* ---------------------------------------------------------------------------
|
|
1336
|
+
* Keyframes
|
|
1337
|
+
*
|
|
1338
|
+
* The one part of the library that cannot be written as a utility, and the only
|
|
1339
|
+
* CSS here that draws rather than declares.
|
|
1340
|
+
*
|
|
1341
|
+
* Four of them belong to the progress indicators and the fifth is shared with
|
|
1342
|
+
* `MPChatBubble`'s typing dots, and they exist for a reason Tailwind cannot
|
|
1343
|
+
* answer: an indeterminate indicator is a *loop*, and a loop is a `@keyframes`
|
|
1344
|
+
* rule. Everything else about those components — their colours, their ladders,
|
|
1345
|
+
* their shapes — is classes and inline slots, exactly as it is everywhere else.
|
|
52
1346
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
1347
|
+
* Unlayered on purpose. `@keyframes` does not take part in the cascade, but the
|
|
1348
|
+
* two classes below do, and a layered class would lose to any unlayered rule a
|
|
1349
|
+
* consumer's own stylesheet happens to have.
|
|
1350
|
+
*
|
|
1351
|
+
* `prefers-reduced-motion` stops all of them. An indeterminate indicator that has
|
|
1352
|
+
* stopped moving still says "something is happening" — it is on screen, and it
|
|
1353
|
+
* was not before — and for a reader who asked for less motion that is the whole
|
|
1354
|
+
* of the message. The determinate transitions are left alone: they are a value
|
|
1355
|
+
* changing, not decoration.
|
|
56
1356
|
* ------------------------------------------------------------------------- */
|
|
57
1357
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
1358
|
+
/*
|
|
1359
|
+
* The linear indicator, which is two bars rather than one.
|
|
1360
|
+
*
|
|
1361
|
+
* MD3's indeterminate bar is a long sweep followed by a short one that catches
|
|
1362
|
+
* up — the second is what keeps the track from being empty for most of the
|
|
1363
|
+
* cycle. Both are written as `inset-inline-*` rather than as a translate so
|
|
1364
|
+
* that the whole thing runs the other way under RTL without a second rule.
|
|
1365
|
+
*/
|
|
1366
|
+
@keyframes mp-progress-linear-lead {
|
|
1367
|
+
0% {
|
|
1368
|
+
inset-inline-start: -35%;
|
|
1369
|
+
inset-inline-end: 100%;
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
60% {
|
|
1373
|
+
inset-inline-start: 100%;
|
|
1374
|
+
inset-inline-end: -90%;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
100% {
|
|
1378
|
+
inset-inline-start: 100%;
|
|
1379
|
+
inset-inline-end: -90%;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
@keyframes mp-progress-linear-trail {
|
|
1384
|
+
0% {
|
|
1385
|
+
inset-inline-start: -200%;
|
|
1386
|
+
inset-inline-end: 100%;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
60% {
|
|
1390
|
+
inset-inline-start: 107%;
|
|
1391
|
+
inset-inline-end: -8%;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
100% {
|
|
1395
|
+
inset-inline-start: 107%;
|
|
1396
|
+
inset-inline-end: -8%;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
/*
|
|
1401
|
+
* The circular indicator: the ring turns while the arc it draws grows and
|
|
1402
|
+
* shrinks. Two animations rather than one, on two elements, because the turn is
|
|
1403
|
+
* linear and the arc is eased — a single timing function cannot be both, and a
|
|
1404
|
+
* spinner whose arc pulses on the same curve it rotates on reads as a stutter.
|
|
1405
|
+
*
|
|
1406
|
+
* The dash values are in the circle's own `pathLength` units, which the
|
|
1407
|
+
* component pins to 100. That is what lets one keyframe rule serve every
|
|
1408
|
+
* diameter on the size ladder: without it each rung would need its own
|
|
1409
|
+
* arithmetic in a stylesheet that cannot do arithmetic.
|
|
1410
|
+
*/
|
|
1411
|
+
@keyframes mp-progress-circular-turn {
|
|
1412
|
+
to {
|
|
1413
|
+
transform: rotate(360deg);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
@keyframes mp-progress-circular-arc {
|
|
1418
|
+
0% {
|
|
1419
|
+
stroke-dasharray: 1 100;
|
|
1420
|
+
stroke-dashoffset: 0;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
50% {
|
|
1424
|
+
stroke-dasharray: 70 100;
|
|
1425
|
+
stroke-dashoffset: -8;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
100% {
|
|
1429
|
+
stroke-dasharray: 1 100;
|
|
1430
|
+
stroke-dashoffset: -70;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/*
|
|
1435
|
+
* A wave of light running along a row of marks, and the one loop two components
|
|
1436
|
+
* turned out to want.
|
|
1437
|
+
*
|
|
1438
|
+
* `MPProgressBox` runs it along its segments and `MPChatBubble` runs it along
|
|
1439
|
+
* the three dots that say somebody is writing. The two differ only in how fast
|
|
1440
|
+
* and how far apart, which is what the classes below set — a second keyframe
|
|
1441
|
+
* saying the same thing is a second chance for the two to drift apart.
|
|
1442
|
+
*
|
|
1443
|
+
* Opacity rather than colour, so one rule covers all four accent families, and
|
|
1444
|
+
* each mark reads its own index out of `--_mp-index` for its delay — which is
|
|
1445
|
+
* what makes a row one class and one custom property instead of N generated
|
|
1446
|
+
* keyframe names.
|
|
1447
|
+
*/
|
|
1448
|
+
@keyframes mp-wave {
|
|
1449
|
+
0%,
|
|
1450
|
+
100% {
|
|
1451
|
+
opacity: 0.24;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
40% {
|
|
1455
|
+
opacity: 1;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
.mp-progress-linear-lead {
|
|
1460
|
+
animation: mp-progress-linear-lead 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
.mp-progress-linear-trail {
|
|
1464
|
+
animation: mp-progress-linear-trail 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
|
1465
|
+
animation-delay: 1.15s;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
.mp-progress-circular-turn {
|
|
1469
|
+
animation: mp-progress-circular-turn 1.4s linear infinite;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
.mp-progress-circular-arc {
|
|
1473
|
+
animation: mp-progress-circular-arc 1.4s ease-in-out infinite;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
.mp-progress-segment-wave {
|
|
1477
|
+
animation: mp-wave 1.2s ease-in-out infinite;
|
|
1478
|
+
animation-delay: calc(var(--_mp-index, 0) * 120ms);
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
/* Faster and tighter than the progress row: three dots at conversational pace,
|
|
1482
|
+
which is roughly a beat a second. The dots never move — a bubble that bounced
|
|
1483
|
+
while somebody typed would bounce in a thread another reader is scrolling. */
|
|
1484
|
+
.mp-chat-typing {
|
|
1485
|
+
animation: mp-wave 1s ease-in-out infinite;
|
|
1486
|
+
animation-delay: calc(var(--_mp-index, 0) * 160ms);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1490
|
+
.mp-progress-linear-lead,
|
|
1491
|
+
.mp-progress-linear-trail,
|
|
1492
|
+
.mp-progress-circular-turn,
|
|
1493
|
+
.mp-progress-circular-arc,
|
|
1494
|
+
.mp-progress-segment-wave,
|
|
1495
|
+
.mp-chat-typing {
|
|
1496
|
+
animation: none;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
/* Stopping the animation is not enough on its own: three of the five draw
|
|
1500
|
+
nothing at all outside a keyframe, so each is given the frame it should
|
|
1501
|
+
rest on. A partial bar and a partial arc, never a full one — an indicator
|
|
1502
|
+
that has stopped must not read as an indicator that has finished. */
|
|
1503
|
+
.mp-progress-linear-lead {
|
|
1504
|
+
inset-inline-start: 0;
|
|
1505
|
+
inset-inline-end: 65%;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
.mp-progress-linear-trail {
|
|
1509
|
+
display: none;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
.mp-progress-circular-arc {
|
|
1513
|
+
stroke-dasharray: 25 100;
|
|
1514
|
+
stroke-dashoffset: 0;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
.mp-progress-segment-wave,
|
|
1518
|
+
.mp-chat-typing {
|
|
1519
|
+
opacity: 0.6;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/* ---------------------------------------------------------------------------
|
|
1524
|
+
* Animation
|
|
1525
|
+
*
|
|
1526
|
+
* The `MPAnimate*` components. Real CSS for the reason the loading indicators
|
|
1527
|
+
* above are: a keyframe is not a Tailwind variant, so there is nothing to
|
|
1528
|
+
* express one with.
|
|
1529
|
+
*
|
|
1530
|
+
* The whole set is built on one idea. An effect is a single `@keyframes` that
|
|
1531
|
+
* runs from a state written entirely in `--_mp-anim-*` custom properties to the
|
|
1532
|
+
* element's natural one — so `src/internal/animate.ts` never generates CSS, it
|
|
1533
|
+
* only fills slots, and running an effect backwards is `animation-direction:
|
|
1534
|
+
* reverse` rather than a second keyframe. That is what makes `mode="out"` cost
|
|
1535
|
+
* nothing, and it is also what makes it *correct*: CSS mirrors the timing
|
|
1536
|
+
* function along with the keyframes, so an entrance eased on
|
|
1537
|
+
* `emphasized-decelerate` comes back accelerating. MD3 asks for exactly that
|
|
1538
|
+
* pair; the browser supplies the second half of it.
|
|
1539
|
+
*
|
|
1540
|
+
* `fill-mode` is `both` throughout, which is what lets an animation that has
|
|
1541
|
+
* not been triggered yet sit paused on its own first frame. Without it, an
|
|
1542
|
+
* element waiting to be scrolled into view would be fully drawn and then blink
|
|
1543
|
+
* out the moment it arrived.
|
|
1544
|
+
*
|
|
1545
|
+
* This is also where the library's rule against transforms is at its narrowest.
|
|
1546
|
+
* A *control* never moves — that rule is about a button resampling its own
|
|
1547
|
+
* label under the pointer, and it holds without exception. An `MPAnimate*`
|
|
1548
|
+
* moves content the caller asked to have moved, and it moves it with the
|
|
1549
|
+
* independent `translate`, `scale` and `rotate` properties rather than the
|
|
1550
|
+
* `transform` shorthand, so a caller's own transform on the same element
|
|
1551
|
+
* survives.
|
|
1552
|
+
*
|
|
1553
|
+
* Unlayered, like the keyframes above: `@keyframes` takes no part in the
|
|
1554
|
+
* cascade, but the classes do, and a layered class would lose to any unlayered
|
|
1555
|
+
* rule a consumer's own stylesheet happens to have.
|
|
1556
|
+
* ------------------------------------------------------------------------- */
|
|
1557
|
+
|
|
1558
|
+
.mp-anim {
|
|
1559
|
+
animation-duration: var(--_mp-anim-duration, var(--mp-sys-motion-duration-medium4));
|
|
1560
|
+
animation-delay: var(--_mp-anim-delay, 0ms);
|
|
1561
|
+
animation-timing-function: var(
|
|
1562
|
+
--_mp-anim-ease,
|
|
1563
|
+
var(--mp-sys-motion-easing-emphasized-decelerate)
|
|
1564
|
+
);
|
|
1565
|
+
animation-iteration-count: var(--_mp-anim-repeat, 1);
|
|
1566
|
+
animation-direction: var(--_mp-anim-direction, normal);
|
|
1567
|
+
animation-fill-mode: both;
|
|
1568
|
+
animation-play-state: var(--_mp-anim-state, running);
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
@keyframes mp-anim-fade {
|
|
1572
|
+
from {
|
|
1573
|
+
opacity: var(--_mp-anim-opacity, 0);
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
to {
|
|
1577
|
+
opacity: 1;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
.mp-anim-fade {
|
|
1582
|
+
animation-name: mp-anim-fade;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/* Grow and Zoom share this one: they are the same arithmetic at two strengths,
|
|
1586
|
+
separated by their defaults and by their origin rather than by their maths. */
|
|
1587
|
+
@keyframes mp-anim-scale {
|
|
1588
|
+
from {
|
|
1589
|
+
opacity: var(--_mp-anim-opacity, 0);
|
|
1590
|
+
scale: var(--_mp-anim-scale, 0.8);
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
to {
|
|
1594
|
+
opacity: 1;
|
|
1595
|
+
scale: 1;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
.mp-anim-scale {
|
|
1600
|
+
animation-name: mp-anim-scale;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
@keyframes mp-anim-slide {
|
|
1604
|
+
from {
|
|
1605
|
+
opacity: var(--_mp-anim-opacity, 0);
|
|
1606
|
+
translate: var(--_mp-anim-x, 0px) var(--_mp-anim-y, 0px);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
to {
|
|
1610
|
+
opacity: 1;
|
|
1611
|
+
translate: 0 0;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
.mp-anim-slide {
|
|
1616
|
+
animation-name: mp-anim-slide;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
/* Two angles rather than one, so the same keyframe covers both the quarter turn
|
|
1620
|
+
something arrives on and the endless one a decorative mark spins through. */
|
|
1621
|
+
@keyframes mp-anim-rotate {
|
|
1622
|
+
from {
|
|
1623
|
+
opacity: var(--_mp-anim-opacity, 0);
|
|
1624
|
+
rotate: var(--_mp-anim-angle, -180deg);
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
to {
|
|
1628
|
+
opacity: 1;
|
|
1629
|
+
rotate: var(--_mp-anim-angle-to, 0deg);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
.mp-anim-rotate {
|
|
1634
|
+
animation-name: mp-anim-rotate;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
/* Symmetric on purpose: a blink that ended anywhere but where it started would
|
|
1638
|
+
leave the element half drawn whenever the count ran out. */
|
|
1639
|
+
@keyframes mp-anim-blink {
|
|
1640
|
+
0%,
|
|
1641
|
+
100% {
|
|
1642
|
+
opacity: 1;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
50% {
|
|
1646
|
+
opacity: var(--_mp-anim-opacity, 0);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
.mp-anim-blink {
|
|
1651
|
+
animation-name: mp-anim-blink;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1655
|
+
/*
|
|
1656
|
+
* The Animate components go the other way from the indicators above, and the
|
|
1657
|
+
* difference is what each of them is saying. A spinner that stops is lying
|
|
1658
|
+
* about whether anything is happening; an entrance that does not play has
|
|
1659
|
+
* still delivered its content, which is the only thing it was ever carrying.
|
|
1660
|
+
*
|
|
1661
|
+
* `animation: none` rather than a zero duration, because the shorthand also
|
|
1662
|
+
* clears `fill-mode` — and it is the fill that was holding an untriggered
|
|
1663
|
+
* element on its own first frame at `opacity: 0`. Left in place, respecting a
|
|
1664
|
+
* reader's preference would blank the page.
|
|
1665
|
+
*/
|
|
1666
|
+
.mp-anim {
|
|
1667
|
+
animation: none;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
/*
|
|
1672
|
+
* Lighting: a light travelling around the outside of something.
|
|
1673
|
+
*
|
|
1674
|
+
* The arc is a conic gradient and what moves is its `from` angle, which is only
|
|
1675
|
+
* animatable because the angle is a registered custom property with a type. The
|
|
1676
|
+
* alternative — rotating the pseudo-element itself — swings its corners out
|
|
1677
|
+
* past the element on every quarter turn.
|
|
1678
|
+
*
|
|
1679
|
+
* `z-index: -1` inside an isolated stacking context puts the glow behind the
|
|
1680
|
+
* content but still inside the component, so it reads as light escaping from
|
|
1681
|
+
* under a sheet rather than as a border drawn around one. Nothing inside is
|
|
1682
|
+
* overlaid and nothing is tinted, which is what lets it go around a card or a
|
|
1683
|
+
* button without touching how either is drawn.
|
|
1684
|
+
*/
|
|
1685
|
+
@property --mp-glow-angle {
|
|
1686
|
+
syntax: '<angle>';
|
|
1687
|
+
initial-value: 0deg;
|
|
1688
|
+
inherits: false;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
@keyframes mp-anim-lighting {
|
|
1692
|
+
to {
|
|
1693
|
+
--mp-glow-angle: 360deg;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
.mp-anim-lighting {
|
|
1698
|
+
position: relative;
|
|
1699
|
+
isolation: isolate;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
.mp-anim-lighting::before {
|
|
1703
|
+
content: '';
|
|
1704
|
+
position: absolute;
|
|
1705
|
+
z-index: -1;
|
|
1706
|
+
inset: calc(-1 * var(--_mp-anim-glow-width, 3px));
|
|
1707
|
+
border-radius: inherit;
|
|
1708
|
+
background: conic-gradient(
|
|
1709
|
+
from var(--mp-glow-angle),
|
|
1710
|
+
transparent 0deg,
|
|
1711
|
+
var(--_mp-anim-glow, var(--_mp-accent)) var(--_mp-anim-glow-arc, 50deg),
|
|
1712
|
+
transparent calc(var(--_mp-anim-glow-arc, 50deg) * 2),
|
|
1713
|
+
transparent 360deg
|
|
1714
|
+
);
|
|
1715
|
+
filter: blur(var(--_mp-anim-glow-blur, 4px));
|
|
1716
|
+
animation-name: mp-anim-lighting;
|
|
1717
|
+
animation-duration: var(--_mp-anim-duration, 3s);
|
|
1718
|
+
animation-delay: var(--_mp-anim-delay, 0ms);
|
|
1719
|
+
/* Linear, and not a token: a loop with no beginning has nothing to
|
|
1720
|
+
decelerate into, and an eased revolution reads as the light hesitating at
|
|
1721
|
+
an arbitrary point on a circle that has no arbitrary points. */
|
|
1722
|
+
animation-timing-function: linear;
|
|
1723
|
+
animation-iteration-count: var(--_mp-anim-repeat, infinite);
|
|
1724
|
+
animation-direction: var(--_mp-anim-direction, normal);
|
|
1725
|
+
animation-fill-mode: both;
|
|
1726
|
+
animation-play-state: var(--_mp-anim-state, running);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1730
|
+
/* The arc stops travelling and becomes an even glow. The same trade the
|
|
1731
|
+
skeleton makes: the decoration survives, the motion does not — a light
|
|
1732
|
+
that marked the live row still marks it while holding still. */
|
|
1733
|
+
.mp-anim-lighting::before {
|
|
1734
|
+
background: var(--_mp-anim-glow, var(--_mp-accent));
|
|
1735
|
+
animation: none;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
/*
|
|
1740
|
+
* Marquee: two identical copies, both moving by exactly one copy plus the gap.
|
|
1741
|
+
*
|
|
1742
|
+
* Which is the whole trick — when the first copy has travelled its own width,
|
|
1743
|
+
* the second is standing precisely where the first began, so there is no seam
|
|
1744
|
+
* and no frame where the strip is empty. A percentage `translate` resolves
|
|
1745
|
+
* against the element's own box, so neither copy has to be measured for this to
|
|
1746
|
+
* hold; measuring only ever decides how *fast* it goes.
|
|
1747
|
+
*/
|
|
1748
|
+
@keyframes mp-anim-marquee-x {
|
|
1749
|
+
from {
|
|
1750
|
+
translate: 0 0;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
to {
|
|
1754
|
+
translate: calc(-100% - var(--_mp-anim-gap, 0px)) 0;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
@keyframes mp-anim-marquee-y {
|
|
1759
|
+
from {
|
|
1760
|
+
translate: 0 0;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
to {
|
|
1764
|
+
translate: 0 calc(-100% - var(--_mp-anim-gap, 0px));
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
.mp-marquee {
|
|
1769
|
+
display: flex;
|
|
1770
|
+
overflow: hidden;
|
|
1771
|
+
gap: var(--_mp-anim-gap, 0px);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
.mp-marquee-vertical {
|
|
1775
|
+
flex-direction: column;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
.mp-marquee-track {
|
|
1779
|
+
display: flex;
|
|
1780
|
+
flex: 0 0 auto;
|
|
1781
|
+
align-items: center;
|
|
1782
|
+
gap: var(--_mp-anim-gap, 0px);
|
|
1783
|
+
animation-name: mp-anim-marquee-x;
|
|
1784
|
+
animation-duration: var(--_mp-anim-duration, 12s);
|
|
1785
|
+
animation-delay: var(--_mp-anim-delay, 0ms);
|
|
1786
|
+
/* Linear unless a caller insists otherwise. An eased marquee slows at both
|
|
1787
|
+
ends of a loop that has no ends, which reads as the page stuttering. */
|
|
1788
|
+
animation-timing-function: var(--_mp-anim-ease, linear);
|
|
1789
|
+
animation-iteration-count: var(--_mp-anim-repeat, infinite);
|
|
1790
|
+
animation-direction: var(--_mp-anim-direction, normal);
|
|
1791
|
+
animation-fill-mode: both;
|
|
1792
|
+
animation-play-state: var(--_mp-anim-state, running);
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
.mp-marquee-vertical .mp-marquee-track {
|
|
1796
|
+
flex-direction: column;
|
|
1797
|
+
animation-name: mp-anim-marquee-y;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
.mp-marquee[data-mp-pause-on-hover]:hover .mp-marquee-track {
|
|
1801
|
+
animation-play-state: paused;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1805
|
+
/* Stopped, not slowed. A strip of logos that has stopped scrolling is a strip
|
|
1806
|
+
of logos, and the first copy is fully in frame — which is more than the
|
|
1807
|
+
moving version guarantees at any given moment. */
|
|
1808
|
+
.mp-marquee-track {
|
|
1809
|
+
animation: none;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
/*
|
|
1814
|
+
* Headline: one line replacing another from below.
|
|
1815
|
+
*
|
|
1816
|
+
* Every item is in the same grid cell, so the box is as tall as the tallest of
|
|
1817
|
+
* them from the first frame and never resizes as the reel turns. The ones not
|
|
1818
|
+
* on screen keep their space with `visibility` rather than `display`, which is
|
|
1819
|
+
* what makes that true.
|
|
1820
|
+
*
|
|
1821
|
+
* The two halves take the two halves of MD3's emphasized curve — the line
|
|
1822
|
+
* arriving decelerates into place, the line leaving accelerates away — which is
|
|
1823
|
+
* the one place in the library where both are written out rather than one being
|
|
1824
|
+
* a reversed run of the other. Here they genuinely are two animations on two
|
|
1825
|
+
* elements at the same moment.
|
|
1826
|
+
*/
|
|
1827
|
+
@keyframes mp-anim-headline-in {
|
|
1828
|
+
from {
|
|
1829
|
+
translate: 0 var(--_mp-anim-rise, 100%);
|
|
1830
|
+
opacity: 0;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
to {
|
|
1834
|
+
translate: 0 0;
|
|
1835
|
+
opacity: 1;
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
@keyframes mp-anim-headline-out {
|
|
1840
|
+
from {
|
|
1841
|
+
translate: 0 0;
|
|
1842
|
+
opacity: 1;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
to {
|
|
1846
|
+
translate: 0 calc(-1 * var(--_mp-anim-rise, 100%));
|
|
1847
|
+
opacity: 0;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
.mp-headline {
|
|
1852
|
+
display: grid;
|
|
1853
|
+
overflow: hidden;
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
.mp-headline-item {
|
|
1857
|
+
grid-area: 1 / 1;
|
|
1858
|
+
visibility: hidden;
|
|
1859
|
+
animation-duration: var(--_mp-anim-duration, var(--mp-sys-motion-duration-long2));
|
|
1860
|
+
animation-fill-mode: both;
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
.mp-headline-item[data-mp-state='active'] {
|
|
1864
|
+
visibility: visible;
|
|
1865
|
+
animation-name: mp-anim-headline-in;
|
|
1866
|
+
animation-timing-function: var(
|
|
1867
|
+
--_mp-anim-ease,
|
|
1868
|
+
var(--mp-sys-motion-easing-emphasized-decelerate)
|
|
1869
|
+
);
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
.mp-headline-item[data-mp-state='leaving'] {
|
|
1873
|
+
visibility: visible;
|
|
1874
|
+
animation-name: mp-anim-headline-out;
|
|
1875
|
+
animation-timing-function: var(
|
|
1876
|
+
--_mp-anim-ease,
|
|
1877
|
+
var(--mp-sys-motion-easing-emphasized-accelerate)
|
|
1878
|
+
);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1882
|
+
/* The reel still turns — it is a set of phrases and stopping on the first
|
|
1883
|
+
would be a different message — but the lines swap rather than travel. */
|
|
1884
|
+
.mp-headline-item {
|
|
1885
|
+
animation: none;
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
/* The block after a typewriter. `step-end` rather than a fade, because a caret
|
|
1890
|
+
that eases is a caret that looks like it is being rendered slowly. */
|
|
1891
|
+
@keyframes mp-anim-caret {
|
|
1892
|
+
0%,
|
|
1893
|
+
45% {
|
|
1894
|
+
opacity: 1;
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
55%,
|
|
1898
|
+
100% {
|
|
1899
|
+
opacity: 0;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
.mp-typing-caret {
|
|
1904
|
+
display: inline-block;
|
|
1905
|
+
animation: mp-anim-caret 1s step-end infinite;
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1909
|
+
/* The whole string is already there under this preference — the caret would
|
|
1910
|
+
be a cursor blinking after text nobody is typing. */
|
|
1911
|
+
.mp-typing-caret {
|
|
1912
|
+
animation: none;
|
|
1913
|
+
}
|
|
63
1914
|
}
|