diff --git a/.gitignore b/.gitignore index 24a14172f..e7f19329c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ _site .cache .DS_Store +package.json +package-lock.json dist docs/assets/images/sprite.svg node_modules diff --git a/cspell.json b/cspell.json index a366d66f0..a7bc1be0a 100644 --- a/cspell.json +++ b/cspell.json @@ -170,6 +170,7 @@ "valpha", "valuenow", "valuetext", + "WCAG", "webawesome", "WEBP", "Webpacker" diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md index 9ecf06aa4..b51bcd3f2 100644 --- a/docs/pages/resources/changelog.md +++ b/docs/pages/resources/changelog.md @@ -21,9 +21,14 @@ New versions of Web Awesome are released as-needed and generally occur when a cr ## Next +- Fixed a bug [in the localize dependency](https://github.com/shoelace-style/localize/issues/20) that caused underscores in language codes to throw a `RangeError` +- Updated `@shoelace-style/localize` to 3.1.0 + +## 2.9.0 + - Added the `modal` property to `` and `` to support third-party modals [#1571] - Fixed a bug in the autoloader causing it to register non-Shoelace elements [#1563] -- Fixed a bug in `` that resulted in improper spacing between the label and the required asterisk [#1540] +- Fixed a bug in `` that resulted in improper spacing between the label and the required asterisk [#1540] - Fixed a bug in `` that caused icons to not load when the default library used a sprite sheet [#1572] - Removed error when a missing popup anchor is provided [#1548] - Updated `@ctrl/tinycolor` to 4.0.1 [#1542] diff --git a/docs/pages/tokens/more.md b/docs/pages/tokens/more.md index 1e88cfe99..11d8ade11 100644 --- a/docs/pages/tokens/more.md +++ b/docs/pages/tokens/more.md @@ -28,5 +28,4 @@ Form control tokens control the appearance of form controls such as [input](/com | `--wa-form-controls-border-color-resting` | `var(--wa-color-neutral-outline-muted-alt)` | | `--wa-form-controls-border-color-activated` | `var(--wa-color-brand-action-vivid)` | | `--wa-form-controls-value-line-height` | `var(--wa-font-height-compact)` | -| `--wa-form-controls-padding` | `var(--wa-space-square-s)` | | `--wa-form-controls-placeholder-color` | `var(--wa-color-neutral-60)` | diff --git a/package-lock.json b/package-lock.json index e55a82eea..ba433fa57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@floating-ui/dom": "^1.2.1", "@lit-labs/react": "^2.0.3", "@shoelace-style/animations": "^1.1.0", - "@shoelace-style/localize": "^3.1.1", + "@shoelace-style/localize": "^3.1.2", "composed-offset-position": "^0.0.4", "lit": "^2.7.5", "qr-creator": "^1.0.0" @@ -1825,9 +1825,9 @@ } }, "node_modules/@shoelace-style/localize": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.1.1.tgz", - "integrity": "sha512-NkM/hj3Js6yXCU9WxhsyxRUdyqUUUl/BSvIluUMptQteUWGOJaoyP1iMbOMqO544DYMzBfnoCw66ZHkGuTdKgA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.1.2.tgz", + "integrity": "sha512-Hf45HeO+vdQblabpyZOTxJ4ZeZsmIUYXXPmoYrrR4OJ5OKxL+bhMz5mK8JXgl7HsoEowfz7+e248UGi861de9Q==" }, "node_modules/@sindresorhus/is": { "version": "0.7.0", @@ -18570,9 +18570,9 @@ "integrity": "sha512-Be+cahtZyI2dPKRm8EZSx3YJQ+jLvEcn3xzRP7tM4tqBnvd/eW/64Xh0iOf0t2w5P8iJKfdBbpVNE9naCaOf2g==" }, "@shoelace-style/localize": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.1.1.tgz", - "integrity": "sha512-NkM/hj3Js6yXCU9WxhsyxRUdyqUUUl/BSvIluUMptQteUWGOJaoyP1iMbOMqO544DYMzBfnoCw66ZHkGuTdKgA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.1.2.tgz", + "integrity": "sha512-Hf45HeO+vdQblabpyZOTxJ4ZeZsmIUYXXPmoYrrR4OJ5OKxL+bhMz5mK8JXgl7HsoEowfz7+e248UGi861de9Q==" }, "@sindresorhus/is": { "version": "0.7.0", diff --git a/package.json b/package.json index e3f80170b..3c45dd21f 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,15 @@ "./dist/react/*": "./dist/react/*", "./dist/translations/*": "./dist/translations/*" }, - "files": ["dist", "cdn"], - "keywords": ["web components", "custom elements", "components"], + "files": [ + "dist", + "cdn" + ], + "keywords": [ + "web components", + "custom elements", + "components" + ], "repository": { "type": "git", "url": "git+https://github.com/shoelace-style/shoelace.git" @@ -60,7 +67,7 @@ "@floating-ui/dom": "^1.2.1", "@lit-labs/react": "^2.0.3", "@shoelace-style/animations": "^1.1.0", - "@shoelace-style/localize": "^3.1.1", + "@shoelace-style/localize": "^3.1.2", "composed-offset-position": "^0.0.4", "lit": "^2.7.5", "qr-creator": "^1.0.0" @@ -129,6 +136,9 @@ "user-agent-data-types": "^0.3.0" }, "lint-staged": { - "*.{ts,js}": ["eslint --max-warnings 0 --cache --fix", "prettier --write"] + "*.{ts,js}": [ + "eslint --max-warnings 0 --cache --fix", + "prettier --write" + ] } } diff --git a/src/themes/default.css b/src/themes/default.css index 6d0807913..637db8385 100644 --- a/src/themes/default.css +++ b/src/themes/default.css @@ -4,7 +4,12 @@ color-scheme: light; /** - * Primitives + * Primitive colors + * Each color is identified by a number that corresponds to its lightness value, where 100 is lightest (white) and 0 is darkest (black). + * Lightness on this scale is directly related to relative luminance, so each lightness value has uniform WCAG 2.1 contrast across hues. + * A difference of 40 between lightness values guarantees a minimum 3:1 contrast ratio. + * A difference of 50 between lightness values guarantees a minimum 4.5:1 contrast ratio. + * A difference of 60 between lightness values guarantees a minimum 7:1 contrast ratio. */ --wa-color-red-95: #fdeef3; --wa-color-red-90: #fcdee7; @@ -65,44 +70,68 @@ --wa-color-black: black; /** - * App + * Base theme colors */ + + /* Surfaces are background layers that UI components and other content rest on. + * Surface colors support elevation, where raised is closest to the user and lowered is farthest away. */ --wa-color-surface-raised: var(--wa-color-white); --wa-color-surface-default: var(--wa-color-white); --wa-color-surface-lowered: var(--wa-color-neutral-95); --wa-color-surface-outline: var(--wa-color-neutral-90); + /* Text colors are used for standard text elements. + * Text should have a minimum 4.5:1 contrast ratio against surfaces. + * Inverse text should support appropriate contrast against background colors with opposing lightness. */ --wa-color-text-normal: var(--wa-color-neutral-10); --wa-color-text-quiet: var(--wa-color-neutral-40); --wa-color-text-inverse: var(--wa-color-white); --wa-color-text-link: var(--wa-color-brand-text-on-surface); + /* Selection colors apply on content that is highlighted by the user. + * Selection text should have a minimum 4.5:1 contrast ratio against the selection background. */ --wa-color-selection-background: var(--wa-color-blue-80); --wa-color-selection-text: var(--wa-color-black); - --wa-color-focus: var(--wa-color-blue-60); /* semantic variants? */ + /* Focus specifies the default color of the focus ring for predictable keyboard navigation. + * Focus should have a minimum 3:1 contrast ratio against surfaces and background colors whenever possible. */ + --wa-color-focus: color-mix(in oklab, var(--wa-color-blue-60) 96%, transparent); + /* Overlays dim background elements to focus attention on modal content, such as drawers or dialogs. */ + --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); + + /* Shadow specifies the default color for box shadows that indicate elevation. */ + --wa-color-shadow: rgb(0 0 0 / 0.06); + + /* Base tints can be mixed with or overlay other colors to make them lighter or darker. */ --wa-color-tint-white: rgb(255 255 255 / 0.2); --wa-color-tint-black: rgb(0 0 0 / 0.2); - --wa-color-tint-hover: black 8%; - --wa-color-tint-active: black 16%; - - --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); - - --wa-color-shadow: rgb(0 0 0 / 0.06); + /* State tints are mixed with component colors to achieve consistent effects on interaction. */ + --wa-color-tint-hover: black 12%; + --wa-color-tint-active: black 20%; /** - * Semantic color variants - */ - /* TODO: Add comments for semantic color tokens and usage expectations */ - /* CONSIDER: Change -alt naming to -tint or -shade? */ + * Semantic theme colors + * Five semantic groups reinforce a component's message, intended usage, or expected results through meaningful hues - + * * Brand to reinforce product branding + * * Success to express validity or confirmation + * * Warning to express caution or uncertainty + * * Danger to express errors or risk + * * Neutral for elements that are innocuous or inert + * Each semantic group specifies colors to use as fills, outlines, and text content with vivid and muted variations. + * Vivid colors are the most noticeable against base theme colors, whereas muted colors draw less attention. + * Vivid colors should have a minimum 3:1 contrast ratio against surfaces when possible. + * Muted colors have no contrast requirements. + * Text colors should have a minimum 4.5:1 contrast ratio on the intended background - vivid, muted, or surface. + */ + /* TODO: Change -alt naming? */ --wa-color-brand-fill-vivid: var(--wa-color-blue-50); --wa-color-brand-fill-vivid-alt: var(--wa-color-blue-40); --wa-color-brand-fill-muted: var(--wa-color-blue-95); --wa-color-brand-fill-muted-alt: var(--wa-color-blue-90); --wa-color-brand-outline-vivid: var(--wa-color-blue-50); - --wa-color-brand-outline-vivid-alt: var(--wa-color-blue-30); + --wa-color-brand-outline-vivid-alt: var(--wa-color-blue-40); --wa-color-brand-outline-muted: var(--wa-color-blue-90); --wa-color-brand-outline-muted-alt: var(--wa-color-blue-80); --wa-color-brand-text-on-vivid: var(--wa-color-text-inverse); @@ -114,7 +143,7 @@ --wa-color-success-fill-muted: var(--wa-color-green-95); --wa-color-success-fill-muted-alt: var(--wa-color-green-90); --wa-color-success-outline-vivid: var(--wa-color-green-50); - --wa-color-success-outline-vivid-alt: var(--wa-color-green-30); + --wa-color-success-outline-vivid-alt: var(--wa-color-green-40); --wa-color-success-outline-muted: var(--wa-color-green-90); --wa-color-success-outline-muted-alt: var(--wa-color-green-80); --wa-color-success-text-on-vivid: var(--wa-color-text-inverse); @@ -126,7 +155,7 @@ --wa-color-warning-fill-muted: var(--wa-color-yellow-95); --wa-color-warning-fill-muted-alt: var(--wa-color-yellow-90); --wa-color-warning-outline-vivid: var(--wa-color-yellow-50); - --wa-color-warning-outline-vivid-alt: var(--wa-color-yellow-30); + --wa-color-warning-outline-vivid-alt: var(--wa-color-yellow-40); --wa-color-warning-outline-muted: var(--wa-color-yellow-90); --wa-color-warning-outline-muted-alt: var(--wa-color-yellow-80); --wa-color-warning-text-on-vivid: var(--wa-color-text-inverse); @@ -138,7 +167,7 @@ --wa-color-danger-fill-muted: var(--wa-color-red-95); --wa-color-danger-fill-muted-alt: var(--wa-color-red-90); --wa-color-danger-outline-vivid: var(--wa-color-red-50); - --wa-color-danger-outline-vivid-alt: var(--wa-color-red-30); + --wa-color-danger-outline-vivid-alt: var(--wa-color-red-40); --wa-color-danger-outline-muted: var(--wa-color-red-90); --wa-color-danger-outline-muted-alt: var(--wa-color-red-80); --wa-color-danger-text-on-vivid: var(--wa-color-text-inverse); @@ -150,7 +179,7 @@ --wa-color-neutral-fill-muted: var(--wa-color-neutral-95); --wa-color-neutral-fill-muted-alt: var(--wa-color-neutral-90); --wa-color-neutral-outline-vivid: var(--wa-color-neutral-50); - --wa-color-neutral-outline-vivid-alt: var(--wa-color-neutral-30); + --wa-color-neutral-outline-vivid-alt: var(--wa-color-neutral-40); --wa-color-neutral-outline-muted: var(--wa-color-neutral-90); --wa-color-neutral-outline-muted-alt: var(--wa-color-neutral-80); --wa-color-neutral-text-on-vivid: var(--wa-color-text-inverse); @@ -179,9 +208,9 @@ --wa-font-size-xs: 0.75rem; /* 12 */ --wa-font-size-s: 0.875rem; /* 14 */ --wa-font-size-m: 1rem; /* 16 */ - --wa-font-size-l: 1.375rem; /* 22 */ - --wa-font-size-xl: 1.875rem; /* 30 */ - --wa-font-size-2xl: 2.625rem; /* 42 */ + --wa-font-size-l: 1.25rem; /* 20 */ + --wa-font-size-xl: 1.75rem; /* 28 */ + --wa-font-size-2xl: 2.5rem; /* 40 */ --wa-font-line-height-compact: 1.25; --wa-font-line-height-regular: 1.625; @@ -189,7 +218,17 @@ /** * Spacing + * Used intentionally, space properties yield a predictable rhythm and support effective implementation of the proximity principle. + * Space can be organized into three groups with distinct usage - + * * Small-scale space (3xs, 2xs, and xs) is used for gaps between closely related elements, such as a dropdown button and its menu, + * and padding within small components, such as badges and tooltips + * * Normal space (s, m, and l) is used for gaps between related elements with distinct purposes or touch targets and padding within + * typical interface elements, such as buttons and inputs + * * Large-scale space (xl, 2xl, and 3xl) is used for gaps between unrelated elements and padding within larger components, + * such as cards and dialogs */ + /* Space is designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-space-base: 1rem; --wa-space-3xs: calc(var(--wa-space-base) * 0.125); /* 2 */ --wa-space-2xs: calc(var(--wa-space-base) * 0.25); /* 4 */ @@ -222,19 +261,24 @@ /** * Borders & corners */ + --wa-border-style: solid; + + /* Border widths are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-border-width-base: 0.0625rem; /* 1px */ --wa-border-width-thin: var(--wa-border-width-base); --wa-border-width-medium: calc(var(--wa-border-width-base) * 2); --wa-border-width-thick: calc(var(--wa-border-width-base) * 3); - --wa-border-style: solid; - + /* Corners are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-corners-base: 0.25rem; --wa-corners-half: calc(var(--wa-corners-base) * 0.5); --wa-corners-1x: var(--wa-corners-base); --wa-corners-2x: calc(var(--wa-corners-base) * 2); --wa-corners-3x: calc(var(--wa-corners-base) * 3); + /* Semantic corner properties create specific shapes beyond the theme's preferred corner styles. */ --wa-corners-pill: 9999px; --wa-corners-circle: 50%; --wa-corners-sharp: 0; @@ -242,17 +286,36 @@ /** * Focus */ - --wa-focus-ring: solid var(--wa-border-width-thick) var(--wa-color-focus); + --wa-focus-ring: solid 0.1875rem var(--wa-color-focus); --wa-focus-ring-offset: 0.0625rem; /* 1px */ /** * Shadows + * Shadow effects indicate elevation and, at times, interactivity. + * Elevation is defined by levels relative to the surface where the element rests - + * * Inset sits below the surface for a punched-in effect + * * Level 0 is the surface level + * * Level 1 is slightly raised above the surface and often signifies that an element is interactive, such as a card + * * Level 2 is raised above all other elements on the same surface, such as dropdown menus + * * Level 3 is raised above all elements on all surfaces, such as dialogs and drawers */ - --wa-shadow-inset: inset 0 0.0625rem 0 var(--wa-color-shadow); + /* Shadow blur is designed to scale according to a single base value to ensure consistent and realistic effects. + * The base value is intended for calculations and is not used by components directly. */ + --wa-shadow-blur-base: 0.125rem; + + /* Offset values on the y-axis are used in pre-constructed shadows and may be used when constructing custom shadows + * or transforming elements with shadows. */ + --wa-shadow-offset-y-inset: 0.0625rem; + --wa-shadow-offset-y-level-1: 0.0625rem; + --wa-shadow-offset-y-level-2: 0.125rem; + --wa-shadow-offset-y-level-3: 0.25rem; + + --wa-shadow-inset: inset 0 var(--wa-shadow-offset-y-inset) calc(var(--wa-shadow-blur-base) * 0.5) + var(--wa-color-shadow); --wa-shadow-level-0: none; - --wa-shadow-level-1: 0 0.0625rem 0.125rem var(--wa-color-shadow); - --wa-shadow-level-2: 0 0.125rem 0.25rem var(--wa-color-shadow); - --wa-shadow-level-3: 0 0.25rem 0.5rem var(--wa-color-shadow); + --wa-shadow-level-1: 0 var(--wa-shadow-offset-y-level-1) var(--wa-shadow-blur-base) var(--wa-color-shadow); + --wa-shadow-level-2: 0 var(--wa-shadow-offset-y-level-2) calc(var(--wa-shadow-blur-base) * 2) var(--wa-color-shadow); + --wa-shadow-level-3: 0 var(--wa-shadow-offset-y-level-3) calc(var(--wa-shadow-blur-base) * 4) var(--wa-color-shadow); /** * Z-index @@ -274,30 +337,42 @@ * Form controls */ --wa-form-controls-background: var(--wa-color-surface-default); - --wa-form-controls-border-style: var(--wa-border-style); - --wa-form-controls-border-width: var(--wa-border-width-thin); - --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-border-color-resting: var(--wa-color-neutral-outline-muted-alt); --wa-form-controls-border-color-activated: var(--wa-color-brand-outline-vivid); + --wa-form-controls-border-style: var(--wa-border-style); + --wa-form-controls-border-width: var(--wa-border-width-thin); + + --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-text-color: var(--wa-color-text-normal); - --wa-form-controls-value-line-height: var(--wa-font-height-compact); - --wa-form-controls-padding: var(--wa-space-square-s); + --wa-form-controls-value-line-height: var(--wa-font-line-height-compact); + --wa-form-controls-placeholder-color: var(--wa-color-neutral-60); --wa-form-controls-placeholder-color-valid: var(--wa-color-green-60); --wa-form-controls-placeholder-color-invalid: var(--wa-color-red-60); + --wa-form-controls-height-s: calc( + var(--wa-space-xs) * 2 + var(--wa-font-size-s) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-m: calc( + var(--wa-space-s) * 2 + var(--wa-font-size-m) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-l: calc( + var(--wa-space-m) * 2 + var(--wa-font-size-l) * var(--wa-form-controls-value-line-height) + ); + /** * Panels */ + --wa-panel-border-style: var(--wa-border-style); --wa-panel-border-width: var(--wa-border-width-thin); + --wa-panel-corners: var(--wa-corners-2x); /** * From 2.x */ - --wa-form-controls-height-s: 2rem; - --wa-form-controls-height-m: 2.75rem; - --wa-form-controls-height-l: 3.5rem; --wa-form-control-toggle-size-s: 0.875rem; --wa-form-control-toggle-size-m: 1.125rem; --wa-form-control-toggle-size-l: 1.375rem; @@ -314,7 +389,7 @@ color-scheme: dark; /** - * App + * Base theme colors */ --wa-color-surface-raised: var(--wa-color-neutral-10); --wa-color-surface-default: var(--wa-color-neutral-10); @@ -329,7 +404,11 @@ --wa-color-selection-background: var(--wa-color-blue-40); --wa-color-selection-text: var(--wa-color-white); - --wa-color-focus: var(--wa-color-blue-50); + --wa-color-focus: color-mix(in oklab, var(--wa-color-blue-60) 90%, transparent); + + --wa-color-overlay: color-mix(in oklab, var(--wa-color-black) 50%, transparent); + + --wa-color-shadow: rgb(0 0 0 / 0.25); --wa-color-tint-white: rgb(255 255 255 / 0.2); --wa-color-tint-black: rgb(0 0 0 / 0.2); @@ -337,12 +416,8 @@ --wa-color-tint-hover: black 8%; --wa-color-tint-active: black 16%; - --wa-color-overlay: color-mix(in oklab, var(--wa-color-black) 50%, transparent); - - --wa-color-shadow: rgb(0 0 0 / 0.25); - /** - * Semantic color variants + * Semantic theme colors */ --wa-color-brand-fill-vivid: var(--wa-color-blue-50); --wa-color-brand-fill-vivid-alt: var(--wa-color-blue-30); @@ -404,3 +479,5 @@ --wa-color-neutral-text-on-muted: var(--wa-color-neutral-70); --wa-color-neutral-text-on-surface: var(--wa-color-neutral-60); } + +/* _utility.css */ diff --git a/src/themes/glassy.css b/src/themes/glassy.css index 43ced9855..12f64de14 100644 --- a/src/themes/glassy.css +++ b/src/themes/glassy.css @@ -1,181 +1,17 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&family=Quicksand:wght@100..900&display=swap'); - -/* copied from depth.css */ -:root { - --wa-shadow-inset-highlight: inset 0 0.125rem 0 0 rgb(255 255 255 / 0.2); -} - -wa-button:not([outline]) { - --shadow: var(--wa-shadow-inset-highlight), var(--wa-shadow-level-1); - --shadow: var(--wa-shadow-inset-highlight), var(--wa-shadow-level-2); -} -wa-button:active { - --wa-shadow-inset-highlight: inset 0 -0.125rem 0 0 rgb(255 255 255 / 0.05); - --shadow: inset 0 0.125rem 0 0 rgb(0 0 0 / 0.2), var(--wa-shadow-inset-highlight); -} -wa-button[outline] { - --shadow: var(--wa-shadow-level-1); -} -wa-button[outline]:hover { - --shadow: var(--wa-shadow-level-2); -} -wa-button[outline]:active { - --shadow: inset 0 0.125rem 0 0 rgb(0 0 0 / 0.05), var(--wa-shadow-inset-highlight); -} -wa-button:not([variant='text']) { - transition: transform var(--wa-transition-faster); -} -wa-button:active:not([variant='text']) { - transform: translateY(var(--wa-shadow-offset-x-level-2)); -} - -wa-button[variant='brand'] { - --background: linear-gradient(var(--wa-color-brand-fill-vivid) 25%, var(--wa-color-brand-fill-vivid-alt)); - --background-hover: linear-gradient( - color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-hover)) 25%, - color-mix(in oklab, var(--wa-color-brand-fill-vivid-alt), var(--wa-color-tint-hover)) - ); - --background-active: linear-gradient( - var(--wa-color-brand-fill-vivid-alt), - color-mix(in oklab, var(--wa-color-brand-fill-vivid-alt), var(--wa-color-tint-active)) - ); - --border-color: var(--wa-color-brand-fill-vivid) - color-mix(in oklab, var(--wa-color-brand-fill-vivid-alt), var(--wa-color-brand-fill-vivid)) - var(--wa-color-brand-fill-vivid-alt); - --border-color-hover: var(--border-color); - --border-color-active: var(--wa-color-brand-fill-vivid-alt); -} - -wa-button[variant='success'] { - --background: linear-gradient(var(--wa-color-success-fill-vivid) 25%, var(--wa-color-success-fill-vivid-alt)); - --background-hover: linear-gradient( - color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-hover)) 25%, - color-mix(in oklab, var(--wa-color-success-fill-vivid-alt), var(--wa-color-tint-hover)) - ); - --background-active: linear-gradient( - var(--wa-color-success-fill-vivid-alt), - color-mix(in oklab, var(--wa-color-success-fill-vivid-alt), var(--wa-color-tint-active)) - ); - --border-color: var(--wa-color-success-fill-vivid) - color-mix(in oklab, var(--wa-color-success-fill-vivid-alt), var(--wa-color-success-fill-vivid)) - var(--wa-color-success-fill-vivid-alt); - --border-color-hover: var(--border-color); - --border-color-active: var(--wa-color-success-fill-vivid-alt); -} - -wa-button[variant='neutral'] { - --background: linear-gradient(var(--wa-color-neutral-fill-vivid) 25%, var(--wa-color-neutral-fill-vivid-alt)); - --background-hover: linear-gradient( - color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover)) 25%, - color-mix(in oklab, var(--wa-color-neutral-fill-vivid-alt), var(--wa-color-tint-hover)) - ); - --background-active: linear-gradient( - var(--wa-color-neutral-fill-vivid-alt), - color-mix(in oklab, var(--wa-color-neutral-fill-vivid-alt), var(--wa-color-tint-active)) - ); - --border-color: var(--wa-color-neutral-fill-vivid) - color-mix(in oklab, var(--wa-color-neutral-fill-vivid-alt), var(--wa-color-neutral-fill-vivid)) - var(--wa-color-neutral-fill-vivid-alt); - --border-color-hover: var(--border-color); - --border-color-active: var(--wa-color-neutral-fill-vivid-alt); -} - -wa-button[variant='warning'] { - --background: linear-gradient(var(--wa-color-warning-fill-vivid) 25%, var(--wa-color-warning-fill-vivid-alt)); - --background-hover: linear-gradient( - color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-hover)) 25%, - color-mix(in oklab, var(--wa-color-warning-fill-vivid-alt), var(--wa-color-tint-hover)) - ); - --background-active: linear-gradient( - var(--wa-color-warning-fill-vivid-alt), - color-mix(in oklab, var(--wa-color-warning-fill-vivid-alt), var(--wa-color-tint-active)) - ); - --border-color: var(--wa-color-warning-fill-vivid) - color-mix(in oklab, var(--wa-color-warning-fill-vivid-alt), var(--wa-color-warning-fill-vivid)) - var(--wa-color-warning-fill-vivid-alt); - --border-color-hover: var(--border-color); - --border-color-active: var(--wa-color-warning-fill-vivid-alt); -} - -wa-button[variant='danger'] { - --background: linear-gradient(var(--wa-color-danger-fill-vivid) 25%, var(--wa-color-danger-fill-vivid-alt)); - --background-hover: linear-gradient( - color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-hover)) 25%, - color-mix(in oklab, var(--wa-color-danger-fill-vivid-alt), var(--wa-color-tint-hover)) - ); - --background-active: linear-gradient( - var(--wa-color-danger-fill-vivid-alt), - color-mix(in oklab, var(--wa-color-danger-fill-vivid-alt), var(--wa-color-tint-active)) - ); - --border-color: var(--wa-color-danger-fill-vivid) - color-mix(in oklab, var(--wa-color-danger-fill-vivid-alt), var(--wa-color-danger-fill-vivid)) - var(--wa-color-danger-fill-vivid-alt); - --border-color-hover: var(--border-color); - --border-color-active: var(--wa-color-danger-fill-vivid-alt); -} - -wa-button[variant='brand'][outline] { - --background-hover: linear-gradient(var(--wa-color-brand-fill-muted) 25%, var(--wa-color-brand-fill-muted-alt)); - --background-active: linear-gradient( - color-mix(in oklab, var(--wa-color-brand-fill-muted), var(--wa-color-surface-default) 30%), - color-mix(in oklab, var(--wa-color-brand-fill-muted-alt), var(--wa-color-surface-default) 30%) - ); - --border-color: var(--wa-color-brand-outline-vivid); - --border-color-hover: var(--border-color); - --border-color-active: var(--border-color); -} - -wa-button[variant='success'][outline] { - --background-hover: linear-gradient(var(--wa-color-success-fill-muted) 25%, var(--wa-color-success-fill-muted-alt)); - --background-active: linear-gradient( - color-mix(in oklab, var(--wa-color-success-fill-muted), var(--wa-color-surface-default) 30%), - color-mix(in oklab, var(--wa-color-success-fill-muted-alt), var(--wa-color-surface-default) 30%) - ); - --border-color: var(--wa-color-success-outline-vivid); - --border-color-hover: var(--border-color); - --border-color-active: var(--border-color); -} - -wa-button[variant='neutral'][outline] { - --background-hover: linear-gradient(var(--wa-color-neutral-fill-muted) 25%, var(--wa-color-neutral-fill-muted-alt)); - --background-active: linear-gradient( - color-mix(in oklab, var(--wa-color-neutral-fill-muted), var(--wa-color-surface-default) 30%), - color-mix(in oklab, var(--wa-color-neutral-fill-muted-alt), var(--wa-color-surface-default) 30%) - ); - --border-color: var(--wa-color-neutral-outline-vivid); - --border-color-hover: var(--border-color); - --border-color-active: var(--border-color); -} - -wa-button[variant='warning'][outline] { - --background-hover: linear-gradient(var(--wa-color-warning-fill-muted) 25%, var(--wa-color-warning-fill-muted-alt)); - --background-active: linear-gradient( - color-mix(in oklab, var(--wa-color-warning-fill-muted), var(--wa-color-surface-default) 25%), - color-mix(in oklab, var(--wa-color-warning-fill-muted-alt), var(--wa-color-surface-default) 25%) - ); - --border-color: var(--wa-color-warning-outline-vivid); - --border-color-hover: var(--border-color); - --border-color-active: var(--border-color); -} - -wa-button[variant='danger'][outline] { - --background-hover: linear-gradient(var(--wa-color-danger-fill-muted) 25%, var(--wa-color-danger-fill-muted-alt)); - --background-active: linear-gradient( - color-mix(in oklab, var(--wa-color-danger-fill-muted), var(--wa-color-surface-default) 25%), - color-mix(in oklab, var(--wa-color-danger-fill-muted-alt), var(--wa-color-surface-default) 25%) - ); - --border-color: var(--wa-color-danger-outline-vivid); - --border-color-hover: var(--border-color); - --border-color-active: var(--border-color); -} +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300..700&family=Quicksand:wght@300..700&display=swap'); :root, :host, -.wa-theme-default { +.wa-theme-glassy-light { color-scheme: light; /** - * Primitives + * Primitive colors + * Each color is identified by a number that corresponds to its lightness value, where 100 is lightest (white) and 0 is darkest (black). + * Lightness on this scale is directly related to relative luminance, so each lightness value has uniform WCAG 2.1 contrast across hues. + * A difference of 40 between lightness values guarantees a minimum 3:1 contrast ratio. + * A difference of 50 between lightness values guarantees a minimum 4.5:1 contrast ratio. + * A difference of 60 between lightness values guarantees a minimum 7:1 contrast ratio. */ --wa-color-red-95: #fbeff3; --wa-color-red-90: #f6e0e7; @@ -236,38 +72,62 @@ wa-button[variant='danger'][outline] { --wa-color-black: black; /** - * App + * Base theme colors */ + + /* Surfaces are background layers that UI components and other content rest on. + * Surface colors support elevation, where raised is closest to the user and lowered is farthest away. */ --wa-color-surface-raised: var(--wa-color-white); --wa-color-surface-default: var(--wa-color-white); --wa-color-surface-lowered: var(--wa-color-neutral-95); --wa-color-surface-outline: var(--wa-color-neutral-90); + /* Text colors are used for standard text elements. + * Text should have a minimum 4.5:1 contrast ratio against surfaces. + * Inverse text should support appropriate contrast against background colors with opposing lightness. */ --wa-color-text-normal: var(--wa-color-neutral-10); --wa-color-text-quiet: var(--wa-color-neutral-40); --wa-color-text-inverse: var(--wa-color-white); --wa-color-text-link: var(--wa-color-brand-text-on-surface); + /* Selection colors apply on content that is highlighted by the user. + * Selection text should have a minimum 4.5:1 contrast ratio against the selection background. */ --wa-color-selection-background: var(--wa-color-orchid-80); --wa-color-selection-text: var(--wa-color-black); - --wa-color-focus: var(--wa-color-orchid-60); /* semantic variants? */ + /* Focus specifies the default color of the focus ring for predictable keyboard navigation. + * Focus should have a minimum 3:1 contrast ratio against surfaces and background colors whenever possible. */ + --wa-color-focus: color-mix(in oklab, var(--wa-color-orchid-60) 96%, transparent); + /* Overlays dim background elements to focus attention on modal content, such as drawers or dialogs. */ + --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); + + /* Shadow specifies the default color for box shadows that indicate elevation. */ + --wa-color-shadow: color-mix(in oklab, var(--wa-color-neutral-10) 20%, transparent); + + /* Base tints can be mixed with or overlay other colors to make them lighter or darker. */ --wa-color-tint-white: rgb(255 255 255 / 0.2); --wa-color-tint-black: rgb(0 0 0 / 0.2); - --wa-color-tint-hover: white 4%; - --wa-color-tint-active: black 16%; - - --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); - - --wa-color-shadow: color-mix(in oklab, var(--wa-color-neutral-10) 20%, transparent); + /* State tints are mixed with component colors to achieve consistent effects on interaction. */ + --wa-color-tint-hover: black 12%; + --wa-color-tint-active: black 20%; /** - * Semantic color variants - */ - /* TODO: Add comments for semantic color tokens and usage expectations */ - /* CONSIDER: Change -alt naming to -tint or -shade? */ + * Semantic theme colors + * Five semantic groups reinforce a component's message, intended usage, or expected results through meaningful hues - + * * Brand to reinforce product branding + * * Success to express validity or confirmation + * * Warning to express caution or uncertainty + * * Danger to express errors or risk + * * Neutral for elements that are innocuous or inert + * Each semantic group specifies colors to use as fills, outlines, and text content with vivid and muted variations. + * Vivid colors are the most noticeable against base theme colors, whereas muted colors draw less attention. + * Vivid colors should have a minimum 3:1 contrast ratio against surfaces when possible. + * Muted colors have no contrast requirements. + * Text colors should have a minimum 4.5:1 contrast ratio on the intended background - vivid, muted, or surface. + */ + /* TODO: Change -alt naming? */ --wa-color-brand-fill-vivid: var(--wa-color-orchid-50); --wa-color-brand-fill-vivid-alt: var(--wa-color-orchid-40); --wa-color-brand-fill-muted: var(--wa-color-orchid-95); @@ -350,9 +210,9 @@ wa-button[variant='danger'][outline] { --wa-font-size-xs: 0.75rem; /* 12 */ --wa-font-size-s: 0.875rem; /* 14 */ --wa-font-size-m: 1rem; /* 16 */ - --wa-font-size-l: 1.375rem; /* 22 */ - --wa-font-size-xl: 1.875rem; /* 30 */ - --wa-font-size-2xl: 2.625rem; /* 42 */ + --wa-font-size-l: 1.25rem; /* 20 */ + --wa-font-size-xl: 1.75rem; /* 28 */ + --wa-font-size-2xl: 2.5rem; /* 40 */ --wa-font-line-height-compact: 1.25; --wa-font-line-height-regular: 1.625; @@ -360,7 +220,17 @@ wa-button[variant='danger'][outline] { /** * Spacing + * Used intentionally, space properties yield a predictable rhythm and support effective implementation of the proximity principle. + * Space can be organized into three groups with distinct usage - + * * Small-scale space (3xs, 2xs, and xs) is used for gaps between closely related elements, such as a dropdown button and its menu, + * and padding within small components, such as badges and tooltips + * * Normal space (s, m, and l) is used for gaps between related elements with distinct purposes or touch targets and padding within + * typical interface elements, such as buttons and inputs + * * Large-scale space (xl, 2xl, and 3xl) is used for gaps between unrelated elements and padding within larger components, + * such as cards and dialogs */ + /* Space is designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-space-base: 1rem; --wa-space-3xs: calc(var(--wa-space-base) * 0.125); /* 2 */ --wa-space-2xs: calc(var(--wa-space-base) * 0.25); /* 4 */ @@ -393,19 +263,24 @@ wa-button[variant='danger'][outline] { /** * Borders & corners */ + --wa-border-style: solid; + + /* Border widths are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-border-width-base: 0.0625rem; /* 1px */ --wa-border-width-thin: var(--wa-border-width-base); --wa-border-width-medium: calc(var(--wa-border-width-base) * 2); --wa-border-width-thick: calc(var(--wa-border-width-base) * 3); - --wa-border-style: solid; - + /* Corners are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-corners-base: 0.375rem; --wa-corners-half: calc(var(--wa-corners-base) * 0.5); --wa-corners-1x: var(--wa-corners-base); --wa-corners-2x: calc(var(--wa-corners-base) * 2); --wa-corners-3x: calc(var(--wa-corners-base) * 3); + /* Semantic corner properties create specific shapes beyond the theme's preferred corner styles. */ --wa-corners-pill: 9999px; --wa-corners-circle: 50%; --wa-corners-sharp: 0; @@ -413,26 +288,37 @@ wa-button[variant='danger'][outline] { /** * Focus */ - --wa-focus-ring: solid var(--wa-border-width-thick) var(--wa-color-focus); + --wa-focus-ring: solid 0.1875rem var(--wa-color-focus); --wa-focus-ring-offset: 0.0625rem; /* 1px */ /** * Shadows + * Shadow effects indicate elevation and, at times, interactivity. + * Elevation is defined by levels relative to the surface where the element rests - + * * Inset sits below the surface for a punched-in effect + * * Level 0 is the surface level + * * Level 1 is slightly raised above the surface and often signifies that an element is interactive, such as a card + * * Level 2 is raised above all other elements on the same surface, such as dropdown menus + * * Level 3 is raised above all elements on all surfaces, such as dialogs and drawers */ - --wa-shadow-offset-x-inset: 0.0625rem; - --wa-shadow-offset-x-level-1: 0.125rem; - --wa-shadow-offset-x-level-2: 0.25rem; - --wa-shadow-offset-x-level-3: 0.5rem; - + /* Shadow blur is designed to scale according to a single base value to ensure consistent and realistic effects. + * The base value is intended for calculations and is not used by components directly. */ --wa-shadow-blur-base: 0.25rem; - --wa-shadow-inset: inset 0 var(--wa-shadow-offset-x-inset) calc(var(--wa-shadow-blur-base) * 0.5) + /* Offset values on the y-axis are used in pre-constructed shadows and may be used when constructing custom shadows + * or transforming elements with shadows. */ + --wa-shadow-offset-y-inset: 0.0625rem; + --wa-shadow-offset-y-level-1: 0.125rem; + --wa-shadow-offset-y-level-2: 0.25rem; + --wa-shadow-offset-y-level-3: 0.5rem; + + --wa-shadow-inset: inset 0 var(--wa-shadow-offset-y-inset) calc(var(--wa-shadow-blur-base) * 0.5) var(--wa-color-shadow); --wa-shadow-level-0: none; - --wa-shadow-level-1: 0 var(--wa-shadow-offset-x-level-1) var(--wa-shadow-blur-base) var(--wa-color-shadow); - --wa-shadow-level-2: 0 var(--wa-shadow-offset-x-level-2) calc(var(--wa-shadow-blur-base) * 2) + --wa-shadow-level-1: 0 var(--wa-shadow-offset-y-level-1) var(--wa-shadow-blur-base) var(--wa-color-shadow); + --wa-shadow-level-2: 0 var(--wa-shadow-offset-y-level-2) calc(var(--wa-shadow-blur-base) * 2) color-mix(in oklab, var(--wa-color-shadow), transparent 20%); - --wa-shadow-level-3: 0 var(--wa-shadow-offset-x-level-3) calc(var(--wa-shadow-blur-base) * 4) + --wa-shadow-level-3: 0 var(--wa-shadow-offset-y-level-3) calc(var(--wa-shadow-blur-base) * 4) color-mix(in oklab, var(--wa-color-shadow), transparent 40%); /** @@ -447,36 +333,50 @@ wa-button[variant='danger'][outline] { /** * Transitions */ - --wa-transition-normal: 275ms; - --wa-transition-fast: 175ms; - --wa-transition-faster: 75ms; + --wa-transition-normal: 250ms; + --wa-transition-fast: 150ms; + --wa-transition-faster: 50ms; /** * Form controls */ - --wa-form-controls-background: var(--wa-color-surface-raised); - --wa-form-controls-border-style: var(--wa-border-style); - --wa-form-controls-border-width: var(--wa-border-width-thin); - --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-background: var(--wa-color-surface-default); + --wa-form-controls-border-color-resting: var(--wa-color-neutral-outline-muted-alt); --wa-form-controls-border-color-activated: var(--wa-color-brand-outline-vivid); + --wa-form-controls-border-style: var(--wa-border-style); + --wa-form-controls-border-width: var(--wa-border-width-thin); + + --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-text-color: var(--wa-color-text-normal); - --wa-form-controls-value-line-height: var(--wa-font-height-compact); - --wa-form-controls-padding: var(--wa-space-square-s); + --wa-form-controls-value-line-height: var(--wa-font-line-height-compact); + --wa-form-controls-placeholder-color: var(--wa-color-neutral-60); + --wa-form-controls-placeholder-color-valid: var(--wa-color-green-60); + --wa-form-controls-placeholder-color-invalid: var(--wa-color-red-60); + + --wa-form-controls-height-s: calc( + var(--wa-space-xs) * 2 + var(--wa-font-size-s) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-m: calc( + var(--wa-space-s) * 2 + var(--wa-font-size-m) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-l: calc( + var(--wa-space-m) * 2 + var(--wa-font-size-l) * var(--wa-form-controls-value-line-height) + ); /** * Panels */ + --wa-panel-border-style: var(--wa-border-style); --wa-panel-border-width: var(--wa-border-width-thin); + --wa-panel-corners: var(--wa-corners-2x); /** * From 2.x */ - --wa-form-controls-height-s: 2rem; - --wa-form-controls-height-m: 2.75rem; - --wa-form-controls-height-l: 3.5rem; --wa-form-control-toggle-size-s: 0.875rem; --wa-form-control-toggle-size-m: 1.125rem; --wa-form-control-toggle-size-l: 1.375rem; @@ -484,10 +384,104 @@ wa-button[variant='danger'][outline] { --wa-form-controls-required-content-color: inherit; --wa-form-controls-required-content-offset: -0.1em; - --wa-overlay-color: hsl(240 3.8% 46.1% / 33%); - - --wa-tooltip-arrow-size: 0.375rem; --wa-flow-spacing: 1.5rem; + --wa-tooltip-arrow-size: 0.375rem; +} + +.wa-theme-glassy-dark, +.wa-theme-glassy-dark :host { + color-scheme: dark; + + /** + * Base theme colors + */ + --wa-color-surface-raised: var(--wa-color-neutral-10); + --wa-color-surface-default: var(--wa-color-neutral-10); + --wa-color-surface-lowered: var(--wa-color-black); + --wa-color-surface-outline: var(--wa-color-neutral-20); + + --wa-color-text-normal: var(--wa-color-neutral-95); + --wa-color-text-quiet: var(--wa-color-neutral-60); + --wa-color-text-inverse: var(--wa-color-neutral-10); + --wa-color-text-link: var(--wa-color-brand-text-on-surface); + + --wa-color-selection-background: var(--wa-color-orchid-40); + --wa-color-selection-text: var(--wa-color-white); + + --wa-color-focus: color-mix(in oklab, var(--wa-color-orchid-60) 90%, transparent); + + --wa-color-overlay: color-mix(in oklab, var(--wa-color-black) 50%, transparent); + + --wa-color-shadow: rgb(0 0 0 / 0.25); + + --wa-color-tint-white: rgb(255 255 255 / 0.2); + --wa-color-tint-black: rgb(0 0 0 / 0.2); + + --wa-color-tint-hover: black 8%; + --wa-color-tint-active: black 16%; + + /** + * Semantic theme colors + */ + --wa-color-brand-fill-vivid: var(--wa-color-orchid-50); + --wa-color-brand-fill-vivid-alt: var(--wa-color-orchid-30); + --wa-color-brand-fill-muted: var(--wa-color-orchid-10); + --wa-color-brand-fill-muted-alt: var(--wa-color-orchid-20); + --wa-color-brand-outline-vivid: var(--wa-color-orchid-50); + --wa-color-brand-outline-vivid-alt: var(--wa-color-orchid-40); + --wa-color-brand-outline-muted: var(--wa-color-orchid-20); + --wa-color-brand-outline-muted-alt: var(--wa-color-orchid-30); + --wa-color-brand-text-on-vivid: var(--wa-color-white); + --wa-color-brand-text-on-muted: var(--wa-color-orchid-70); + --wa-color-brand-text-on-surface: var(--wa-color-orchid-60); + + --wa-color-success-fill-vivid: var(--wa-color-green-50); + --wa-color-success-fill-vivid-alt: var(--wa-color-green-30); + --wa-color-success-fill-muted: var(--wa-color-green-10); + --wa-color-success-fill-muted-alt: var(--wa-color-green-20); + --wa-color-success-outline-vivid: var(--wa-color-green-50); + --wa-color-success-outline-vivid-alt: var(--wa-color-green-40); + --wa-color-success-outline-muted: var(--wa-color-green-20); + --wa-color-success-outline-muted-alt: var(--wa-color-green-30); + --wa-color-success-text-on-vivid: var(--wa-color-white); + --wa-color-success-text-on-muted: var(--wa-color-green-70); + --wa-color-success-text-on-surface: var(--wa-color-green-60); + + --wa-color-warning-fill-vivid: var(--wa-color-yellow-50); + --wa-color-warning-fill-vivid-alt: var(--wa-color-yellow-30); + --wa-color-warning-fill-muted: var(--wa-color-yellow-10); + --wa-color-warning-fill-muted-alt: var(--wa-color-yellow-20); + --wa-color-warning-outline-vivid: var(--wa-color-yellow-50); + --wa-color-warning-outline-vivid-alt: var(--wa-color-yellow-40); + --wa-color-warning-outline-muted: var(--wa-color-yellow-20); + --wa-color-warning-outline-muted-alt: var(--wa-color-yellow-30); + --wa-color-warning-text-on-vivid: var(--wa-color-white); + --wa-color-warning-text-on-muted: var(--wa-color-yellow-70); + --wa-color-warning-text-on-surface: var(--wa-color-yellow-60); + + --wa-color-danger-fill-vivid: var(--wa-color-red-50); + --wa-color-danger-fill-vivid-alt: var(--wa-color-red-30); + --wa-color-danger-fill-muted: var(--wa-color-red-10); + --wa-color-danger-fill-muted-alt: var(--wa-color-red-20); + --wa-color-danger-outline-vivid: var(--wa-color-red-50); + --wa-color-danger-outline-vivid-alt: var(--wa-color-red-40); + --wa-color-danger-outline-muted: var(--wa-color-red-20); + --wa-color-danger-outline-muted-alt: var(--wa-color-red-30); + --wa-color-danger-text-on-vivid: var(--wa-color-white); + --wa-color-danger-text-on-muted: var(--wa-color-red-70); + --wa-color-danger-text-on-surface: var(--wa-color-red-60); + + --wa-color-neutral-fill-vivid: var(--wa-color-neutral-50); + --wa-color-neutral-fill-vivid-alt: var(--wa-color-neutral-30); + --wa-color-neutral-fill-muted: var(--wa-color-neutral-10); + --wa-color-neutral-fill-muted-alt: var(--wa-color-neutral-20); + --wa-color-neutral-outline-vivid: var(--wa-color-neutral-50); + --wa-color-neutral-outline-vivid-alt: var(--wa-color-neutral-40); + --wa-color-neutral-outline-muted: var(--wa-color-neutral-20); + --wa-color-neutral-outline-muted-alt: var(--wa-color-neutral-30); + --wa-color-neutral-text-on-vivid: var(--wa-color-white); + --wa-color-neutral-text-on-muted: var(--wa-color-neutral-70); + --wa-color-neutral-text-on-surface: var(--wa-color-neutral-60); } /* _utility.css */ diff --git a/src/themes/mellow.css b/src/themes/mellow.css index 657f8ab34..894bd9905 100644 --- a/src/themes/mellow.css +++ b/src/themes/mellow.css @@ -1,12 +1,17 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&family=Lora:wght@100..900&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300..700&family=Lora:wght@400..700&display=swap'); :root, :host, -.wa-theme-mellow { +.wa-theme-mellow-light { color-scheme: light; /** - * Primitives + * Primitive colors + * Each color is identified by a number that corresponds to its lightness value, where 100 is lightest (white) and 0 is darkest (black). + * Lightness on this scale is directly related to relative luminance, so each lightness value has uniform WCAG 2.1 contrast across hues. + * A difference of 40 between lightness values guarantees a minimum 3:1 contrast ratio. + * A difference of 50 between lightness values guarantees a minimum 4.5:1 contrast ratio. + * A difference of 60 between lightness values guarantees a minimum 7:1 contrast ratio. */ --wa-color-red-95: #fbf0ed; --wa-color-red-90: #f7e1db; @@ -67,38 +72,62 @@ --wa-color-black: black; /** - * App + * Base theme colors */ + + /* Surfaces are background layers that UI components and other content rest on. + * Surface colors support elevation, where raised is closest to the user and lowered is farthest away. */ --wa-color-surface-raised: var(--wa-color-white); --wa-color-surface-default: var(--wa-color-white); --wa-color-surface-lowered: var(--wa-color-neutral-95); --wa-color-surface-outline: var(--wa-color-neutral-90); + /* Text colors are used for standard text elements. + * Text should have a minimum 4.5:1 contrast ratio against surfaces. + * Inverse text should support appropriate contrast against background colors with opposing lightness. */ --wa-color-text-normal: var(--wa-color-neutral-30); --wa-color-text-quiet: var(--wa-color-neutral-50); --wa-color-text-inverse: var(--wa-color-white); --wa-color-text-link: var(--wa-color-blue-50); + /* Selection colors apply on content that is highlighted by the user. + * Selection text should have a minimum 4.5:1 contrast ratio against the selection background. */ --wa-color-selection-background: var(--wa-color-green-80); --wa-color-selection-text: var(--wa-color-black); - --wa-color-focus: var(--wa-color-green-60); /* semantic variants? */ + /* Focus specifies the default color of the focus ring for predictable keyboard navigation. + * Focus should have a minimum 3:1 contrast ratio against surfaces and background colors whenever possible. */ + --wa-color-focus: color-mix(in oklab, var(--wa-color-green-60) 96%, transparent); + /* Overlays dim background elements to focus attention on modal content, such as drawers or dialogs. */ + --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); + + /* Shadow specifies the default color for box shadows that indicate elevation. */ + --wa-color-shadow: color-mix(in oklab, var(--wa-color-neutral-10) 6%, transparent); + + /* Base tints can be mixed with or overlay other colors to make them lighter or darker. */ --wa-color-tint-white: rgb(255 255 255 / 0.2); --wa-color-tint-black: rgb(0 0 0 / 0.2); - --wa-color-tint-hover: black 8%; - --wa-color-tint-active: black 16%; - - --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); - - --wa-color-shadow: color-mix(in oklab, var(--wa-color-neutral-10) 6%, transparent); + /* State tints are mixed with component colors to achieve consistent effects on interaction. */ + --wa-color-tint-hover: black 12%; + --wa-color-tint-active: black 20%; /** - * Semantic color variants - */ - /* TODO: Add comments for semantic color tokens and usage expectations */ - /* CONSIDER: Change -alt naming to -tint or -shade? */ + * Semantic theme colors + * Five semantic groups reinforce a component's message, intended usage, or expected results through meaningful hues - + * * Brand to reinforce product branding + * * Success to express validity or confirmation + * * Warning to express caution or uncertainty + * * Danger to express errors or risk + * * Neutral for elements that are innocuous or inert + * Each semantic group specifies colors to use as fills, outlines, and text content with vivid and muted variations. + * Vivid colors are the most noticeable against base theme colors, whereas muted colors draw less attention. + * Vivid colors should have a minimum 3:1 contrast ratio against surfaces when possible. + * Muted colors have no contrast requirements. + * Text colors should have a minimum 4.5:1 contrast ratio on the intended background - vivid, muted, or surface. + */ + /* TODO: Change -alt naming? */ --wa-color-brand-fill-vivid: var(--wa-color-green-50); --wa-color-brand-fill-vivid-alt: var(--wa-color-green-40); --wa-color-brand-fill-muted: var(--wa-color-green-95); @@ -181,9 +210,9 @@ --wa-font-size-xs: 0.75rem; /* 12 */ --wa-font-size-s: 0.875rem; /* 14 */ --wa-font-size-m: 1rem; /* 16 */ - --wa-font-size-l: 1.375rem; /* 22 */ - --wa-font-size-xl: 1.875rem; /* 30 */ - --wa-font-size-2xl: 2.625rem; /* 42 */ + --wa-font-size-l: 1.25rem; /* 20 */ + --wa-font-size-xl: 1.75rem; /* 28 */ + --wa-font-size-2xl: 2.5rem; /* 40 */ --wa-font-line-height-compact: 1.25; --wa-font-line-height-regular: 1.625; @@ -191,7 +220,17 @@ /** * Spacing + * Used intentionally, space properties yield a predictable rhythm and support effective implementation of the proximity principle. + * Space can be organized into three groups with distinct usage - + * * Small-scale space (3xs, 2xs, and xs) is used for gaps between closely related elements, such as a dropdown button and its menu, + * and padding within small components, such as badges and tooltips + * * Normal space (s, m, and l) is used for gaps between related elements with distinct purposes or touch targets and padding within + * typical interface elements, such as buttons and inputs + * * Large-scale space (xl, 2xl, and 3xl) is used for gaps between unrelated elements and padding within larger components, + * such as cards and dialogs */ + /* Space is designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-space-base: 1rem; --wa-space-3xs: calc(var(--wa-space-base) * 0.125); /* 2 */ --wa-space-2xs: calc(var(--wa-space-base) * 0.25); /* 4 */ @@ -224,19 +263,24 @@ /** * Borders & corners */ + --wa-border-style: solid; + + /* Border widths are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-border-width-base: 0.0625rem; /* 1px */ --wa-border-width-thin: var(--wa-border-width-base); --wa-border-width-medium: calc(var(--wa-border-width-base) * 2); --wa-border-width-thick: calc(var(--wa-border-width-base) * 3); - --wa-border-style: solid; - + /* Corners are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-corners-base: 0.125rem; --wa-corners-half: calc(var(--wa-corners-base) * 0.5); --wa-corners-1x: var(--wa-corners-base); --wa-corners-2x: calc(var(--wa-corners-base) * 2); --wa-corners-3x: calc(var(--wa-corners-base) * 3); + /* Semantic corner properties create specific shapes beyond the theme's preferred corner styles. */ --wa-corners-pill: 9999px; --wa-corners-circle: 50%; --wa-corners-sharp: 0; @@ -244,17 +288,35 @@ /** * Focus */ - --wa-focus-ring: solid var(--wa-border-width-thick) var(--wa-color-focus); + --wa-focus-ring: solid 0.1875rem var(--wa-color-focus); --wa-focus-ring-offset: 0.0625rem; /* 1px */ /** * Shadows + * Shadow effects indicate elevation and, at times, interactivity. + * Elevation is defined by levels relative to the surface where the element rests - + * * Inset sits below the surface for a punched-in effect + * * Level 0 is the surface level + * * Level 1 is slightly raised above the surface and often signifies that an element is interactive, such as a card + * * Level 2 is raised above all other elements on the same surface, such as dropdown menus + * * Level 3 is raised above all elements on all surfaces, such as dialogs and drawers */ + /* Shadow blur is designed to scale according to a single base value to ensure consistent and realistic effects. + * The base value is intended for calculations and is not used by components directly. */ + --wa-shadow-blur-base: 0.0625rem; + + /* Offset values on the y-axis are used in pre-constructed shadows and may be used when constructing custom shadows + * or transforming elements with shadows. */ + --wa-shadow-offset-y-inset: 0.0625rem; + --wa-shadow-offset-y-level-1: 0.0625rem; + --wa-shadow-offset-y-level-2: 0.125rem; + --wa-shadow-offset-y-level-3: 0.25rem; + --wa-shadow-inset: none; --wa-shadow-level-0: none; - --wa-shadow-level-1: 0 0.0625rem 0 var(--wa-color-shadow); - --wa-shadow-level-2: 0 0.125rem 0.125rem var(--wa-color-shadow); - --wa-shadow-level-3: 0 0.25rem 0.25rem var(--wa-color-shadow); + --wa-shadow-level-1: 0 var(--wa-shadow-offset-y-level-1) var(--wa-shadow-blur-base) var(--wa-color-shadow); + --wa-shadow-level-2: 0 var(--wa-shadow-offset-y-level-2) calc(var(--wa-shadow-blur-base) * 2) var(--wa-color-shadow); + --wa-shadow-level-3: 0 var(--wa-shadow-offset-y-level-3) calc(var(--wa-shadow-blur-base) * 4) var(--wa-color-shadow); /** * Z-index @@ -276,28 +338,42 @@ * Form controls */ --wa-form-controls-background: var(--wa-color-surface-default); - --wa-form-controls-border-style: var(--wa-border-style); - --wa-form-controls-border-width: var(--wa-border-width-thin); - --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-border-color-resting: var(--wa-color-neutral-outline-muted-alt); --wa-form-controls-border-color-activated: var(--wa-color-brand-outline-vivid); + --wa-form-controls-border-style: var(--wa-border-style); + --wa-form-controls-border-width: var(--wa-border-width-thin); + + --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-text-color: var(--wa-color-text-normal); - --wa-form-controls-value-line-height: var(--wa-font-height-compact); - --wa-form-controls-padding: var(--wa-space-square-s); + --wa-form-controls-value-line-height: var(--wa-font-line-height-compact); + --wa-form-controls-placeholder-color: var(--wa-color-neutral-60); + --wa-form-controls-placeholder-color-valid: var(--wa-color-green-60); + --wa-form-controls-placeholder-color-invalid: var(--wa-color-red-60); + + --wa-form-controls-height-s: calc( + var(--wa-space-xs) * 2 + var(--wa-font-size-s) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-m: calc( + var(--wa-space-s) * 2 + var(--wa-font-size-m) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-l: calc( + var(--wa-space-m) * 2 + var(--wa-font-size-l) * var(--wa-form-controls-value-line-height) + ); /** * Panels */ + --wa-panel-border-style: var(--wa-border-style); --wa-panel-border-width: var(--wa-border-width-thin); + --wa-panel-corners: var(--wa-corners-2x); /** * From 2.x */ - --wa-form-controls-height-s: 2rem; - --wa-form-controls-height-m: 2.75rem; - --wa-form-controls-height-l: 3.5rem; --wa-form-control-toggle-size-s: 0.875rem; --wa-form-control-toggle-size-m: 1.125rem; --wa-form-control-toggle-size-l: 1.375rem; @@ -305,6 +381,7 @@ --wa-form-controls-required-content-color: inherit; --wa-form-controls-required-content-offset: -0.1em; + --wa-flow-spacing: 1.5rem; --wa-tooltip-arrow-size: 0.375rem; --wa-flow-spacing: 1.5rem; } @@ -314,7 +391,7 @@ color-scheme: dark; /** - * App + * Base theme colors */ --wa-color-surface-raised: var(--wa-color-neutral-10); --wa-color-surface-default: var(--wa-color-neutral-10); @@ -329,7 +406,11 @@ --wa-color-selection-background: var(--wa-color-green-40); --wa-color-selection-text: var(--wa-color-white); - --wa-color-focus: var(--wa-color-blue-50); + --wa-color-focus: color-mix(in oklab, var(--wa-color-blue-60) 90%, transparent); + + --wa-color-overlay: color-mix(in oklab, var(--wa-color-black) 50%, transparent); + + --wa-color-shadow: color-mix(in oklab, var(--wa-color-black) 20%, transparent); --wa-color-tint-white: rgb(255 255 255 / 0.2); --wa-color-tint-black: rgb(0 0 0 / 0.2); @@ -337,12 +418,8 @@ --wa-color-tint-hover: black 8%; --wa-color-tint-active: black 16%; - --wa-color-overlay: color-mix(in oklab, var(--wa-color-black) 50%, transparent); - - --wa-color-shadow: color-mix(in oklab, var(--wa-color-black) 20%, transparent); - /** - * Semantic color variants + * Semantic theme colors */ --wa-color-brand-fill-vivid: var(--wa-color-green-50); --wa-color-brand-fill-vivid-alt: var(--wa-color-green-30); diff --git a/src/themes/playful.css b/src/themes/playful.css index ad02104ca..6b09a1a6b 100644 --- a/src/themes/playful.css +++ b/src/themes/playful.css @@ -1,45 +1,17 @@ @import url('https://fonts.googleapis.com/css2?family=Roboto+Flex:wght@300..700&family=Roboto+Slab:wght@300..700&display=swap'); -@import 'depth_flat.css'; -@import 'borders.css'; - -/* copied from depth_flat.css */ -wa-button:not([variant='text']) { - --shadow: 0 var(--wa-shadow-offset-x-level-1) var(--wa-shadow-blur-base) var(--border-color); -} -wa-button:active:not([variant='text']) { - --shadow: none; - transform: translateY(var(--wa-shadow-offset-x-level-1)); -} - -/* copied from borders.css */ -wa-button:not([outline]) { - --border-color-hover: var(--border-color); - --border-color-active: var(--border-color); - --background-active: var(--border-color); -} -wa-button[variant='brand'] { - --border-color: var(--wa-color-brand-outline-vivid); -} -wa-button[variant='success'] { - --border-color: var(--wa-color-success-outline-vivid); -} -wa-button[variant='neutral'] { - --border-color: var(--wa-color-neutral-outline-vivid); -} -wa-button[variant='warning'] { - --border-color: var(--wa-color-warning-outline-vivid); -} -wa-button[variant='danger'] { - --border-color: var(--wa-color-danger-outline-vivid); -} :root, :host, -.wa-theme-default { +.wa-theme-playful-light { color-scheme: light; /** - * Primitives + * Primitive colors + * Each color is identified by a number that corresponds to its lightness value, where 100 is lightest (white) and 0 is darkest (black). + * Lightness on this scale is directly related to relative luminance, so each lightness value has uniform WCAG 2.1 contrast across hues. + * A difference of 40 between lightness values guarantees a minimum 3:1 contrast ratio. + * A difference of 50 between lightness values guarantees a minimum 4.5:1 contrast ratio. + * A difference of 60 between lightness values guarantees a minimum 7:1 contrast ratio. */ --wa-color-red-95: #fcf0ed; --wa-color-red-90: #f8e0dc; @@ -100,42 +72,62 @@ wa-button[variant='danger'] { --wa-color-black: black; /** - * App + * Base theme colors */ + + /* Surfaces are background layers that UI components and other content rest on. + * Surface colors support elevation, where raised is closest to the user and lowered is farthest away. */ --wa-color-surface-raised: var(--wa-color-white); --wa-color-surface-default: var(--wa-color-white); - --wa-color-surface-lowered: repeating-linear-gradient( - 45deg, - var(--wa-color-neutral-95), - var(--wa-color-neutral-95) 0.5rem, - color-mix(in oklab, var(--wa-color-neutral-95), var(--wa-color-white) 40%) 0.5rem, - color-mix(in oklab, var(--wa-color-neutral-95), var(--wa-color-white) 40%) 1rem - ); + --wa-color-surface-lowered: var(--wa-color-neutral-95); --wa-color-surface-outline: var(--wa-color-neutral-90); + /* Text colors are used for standard text elements. + * Text should have a minimum 4.5:1 contrast ratio against surfaces. + * Inverse text should support appropriate contrast against background colors with opposing lightness. */ --wa-color-text-normal: var(--wa-color-neutral-10); --wa-color-text-quiet: var(--wa-color-neutral-40); --wa-color-text-inverse: var(--wa-color-white); --wa-color-text-link: var(--wa-color-brand-text-on-surface); + /* Selection colors apply on content that is highlighted by the user. + * Selection text should have a minimum 4.5:1 contrast ratio against the selection background. */ --wa-color-selection-background: var(--wa-color-rose-80); --wa-color-selection-text: var(--wa-color-black); + /* Focus specifies the default color of the focus ring for predictable keyboard navigation. + * Focus should have a minimum 3:1 contrast ratio against surfaces and background colors whenever possible. */ --wa-color-focus: color-mix(in oklab, var(--wa-color-rose-60) 96%, transparent); - --wa-color-tint-white: rgb(255 255 255 / 0.2); - --wa-color-tint-black: rgb(0 0 0 / 0.1); - - --wa-color-tint-hover: black 8%; - --wa-color-tint-active: black 16%; - + /* Overlays dim background elements to focus attention on modal content, such as drawers or dialogs. */ --wa-color-overlay: color-mix(in oklab, var(--wa-color-neutral-10) 25%, transparent); + /* Shadow specifies the default color for box shadows that indicate elevation. */ --wa-color-shadow: color-mix(in oklab, var(--wa-color-neutral-10) 8%, transparent); + /* Base tints can be mixed with or overlay other colors to make them lighter or darker. */ + --wa-color-tint-white: rgb(255 255 255 / 0.2); + --wa-color-tint-black: rgb(0 0 0 / 0.2); + + /* State tints are mixed with component colors to achieve consistent effects on interaction. */ + --wa-color-tint-hover: black 12%; + --wa-color-tint-active: black 20%; + /** - * Semantic color variants - */ + * Semantic theme colors + * Five semantic groups reinforce a component's message, intended usage, or expected results through meaningful hues - + * * Brand to reinforce product branding + * * Success to express validity or confirmation + * * Warning to express caution or uncertainty + * * Danger to express errors or risk + * * Neutral for elements that are innocuous or inert + * Each semantic group specifies colors to use as fills, outlines, and text content with vivid and muted variations. + * Vivid colors are the most noticeable against base theme colors, whereas muted colors draw less attention. + * Vivid colors should have a minimum 3:1 contrast ratio against surfaces when possible. + * Muted colors have no contrast requirements. + * Text colors should have a minimum 4.5:1 contrast ratio on the intended background - vivid, muted, or surface. + */ + /* TODO: Change -alt naming? */ --wa-color-brand-fill-vivid: var(--wa-color-rose-50); --wa-color-brand-fill-vivid-alt: var(--wa-color-rose-40); --wa-color-brand-fill-muted: var(--wa-color-rose-95); @@ -218,9 +210,9 @@ wa-button[variant='danger'] { --wa-font-size-xs: 0.75rem; /* 12 */ --wa-font-size-s: 0.875rem; /* 14 */ --wa-font-size-m: 1rem; /* 16 */ - --wa-font-size-l: 1.375rem; /* 22 */ - --wa-font-size-xl: 1.875rem; /* 30 */ - --wa-font-size-2xl: 2.625rem; /* 42 */ + --wa-font-size-l: 1.25rem; /* 20 */ + --wa-font-size-xl: 1.75rem; /* 28 */ + --wa-font-size-2xl: 2.5rem; /* 40 */ --wa-font-line-height-compact: 1.25; --wa-font-line-height-regular: 1.625; @@ -228,7 +220,17 @@ wa-button[variant='danger'] { /** * Spacing + * Used intentionally, space properties yield a predictable rhythm and support effective implementation of the proximity principle. + * Space can be organized into three groups with distinct usage - + * * Small-scale space (3xs, 2xs, and xs) is used for gaps between closely related elements, such as a dropdown button and its menu, + * and padding within small components, such as badges and tooltips + * * Normal space (s, m, and l) is used for gaps between related elements with distinct purposes or touch targets and padding within + * typical interface elements, such as buttons and inputs + * * Large-scale space (xl, 2xl, and 3xl) is used for gaps between unrelated elements and padding within larger components, + * such as cards and dialogs */ + /* Space is designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-space-base: 1rem; --wa-space-3xs: calc(var(--wa-space-base) * 0.125); /* 2 */ --wa-space-2xs: calc(var(--wa-space-base) * 0.25); /* 4 */ @@ -261,19 +263,24 @@ wa-button[variant='danger'] { /** * Borders & corners */ + --wa-border-style: solid; + + /* Border widths are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-border-width-base: 0.125rem; /* 1px */ --wa-border-width-thin: var(--wa-border-width-base); --wa-border-width-medium: calc(var(--wa-border-width-base) * 2); --wa-border-width-thick: calc(var(--wa-border-width-base) * 3); - --wa-border-style: solid; - + /* Corners are designed to scale according to a single base value. + * The base value is intended for calculations and is not used by components directly. */ --wa-corners-base: 0.375rem; --wa-corners-half: calc(var(--wa-corners-base) * 0.5); --wa-corners-1x: var(--wa-corners-base); --wa-corners-2x: calc(var(--wa-corners-base) * 2); --wa-corners-3x: calc(var(--wa-corners-base) * 3); + /* Semantic corner properties create specific shapes beyond the theme's preferred corner styles. */ --wa-corners-pill: 9999px; --wa-corners-circle: 50%; --wa-corners-sharp: 0; @@ -281,25 +288,36 @@ wa-button[variant='danger'] { /** * Focus */ - --wa-focus-ring: solid var(--wa-border-width-medium) var(--wa-color-focus); + --wa-focus-ring: solid 0.1875rem var(--wa-color-focus); --wa-focus-ring-offset: 0.0625rem; /* 1px */ /** * Shadows + * Shadow effects indicate elevation and, at times, interactivity. + * Elevation is defined by levels relative to the surface where the element rests - + * * Inset sits below the surface for a punched-in effect + * * Level 0 is the surface level + * * Level 1 is slightly raised above the surface and often signifies that an element is interactive, such as a card + * * Level 2 is raised above all other elements on the same surface, such as dropdown menus + * * Level 3 is raised above all elements on all surfaces, such as dialogs and drawers */ - --wa-shadow-offset-x-inset: 0.125rem; /* inset (optional) | offset-y | offset-x */ - --wa-shadow-offset-x-level-1: 0.25rem; - --wa-shadow-offset-x-level-2: 0.375rem; - --wa-shadow-offset-x-level-3: 0.5rem; - + /* Shadow blur is designed to scale according to a single base value to ensure consistent and realistic effects. + * The base value is intended for calculations and is not used by components directly. */ --wa-shadow-blur-base: 0rem; - --wa-shadow-inset: inset 0 var(--wa-shadow-offset-x-inset) calc(var(--wa-shadow-blur-base) * 0.5) + /* Offset values on the y-axis are used in pre-constructed shadows and may be used when constructing custom shadows + * or transforming elements with shadows. */ + --wa-shadow-offset-y-inset: 0.125rem; + --wa-shadow-offset-y-level-1: 0.25rem; + --wa-shadow-offset-y-level-2: 0.375rem; + --wa-shadow-offset-y-level-3: 0.5rem; + + --wa-shadow-inset: inset 0 var(--wa-shadow-offset-y-inset) calc(var(--wa-shadow-blur-base) * 0.5) var(--wa-color-shadow); --wa-shadow-level-0: none; - --wa-shadow-level-1: 0 var(--wa-shadow-offset-x-level-1) var(--wa-shadow-blur-base) var(--wa-color-shadow); - --wa-shadow-level-2: 0 var(--wa-shadow-offset-x-level-2) calc(var(--wa-shadow-blur-base) * 2) var(--wa-color-shadow); - --wa-shadow-level-3: 0 var(--wa-shadow-offset-x-level-3) calc(var(--wa-shadow-blur-base) * 4) var(--wa-color-shadow); + --wa-shadow-level-1: 0 var(--wa-shadow-offset-y-level-1) var(--wa-shadow-blur-base) var(--wa-color-shadow); + --wa-shadow-level-2: 0 var(--wa-shadow-offset-y-level-2) calc(var(--wa-shadow-blur-base) * 2) var(--wa-color-shadow); + --wa-shadow-level-3: 0 var(--wa-shadow-offset-y-level-3) calc(var(--wa-shadow-blur-base) * 4) var(--wa-color-shadow); /** * Z-index @@ -315,34 +333,48 @@ wa-button[variant='danger'] { */ --wa-transition-normal: 250ms; --wa-transition-fast: 150ms; - --wa-transition-faster: 0ms; + --wa-transition-faster: 50ms; /** * Form controls */ - --wa-form-controls-background: var(--wa-color-surface-raised); - --wa-form-controls-border-style: var(--wa-border-style); - --wa-form-controls-border-width: var(--wa-border-width-thin); - --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-background: var(--wa-color-surface-default); + --wa-form-controls-border-color-resting: var(--wa-color-neutral-outline-muted-alt); --wa-form-controls-border-color-activated: var(--wa-color-brand-outline-vivid); + --wa-form-controls-border-style: var(--wa-border-style); + --wa-form-controls-border-width: var(--wa-border-width-thin); + + --wa-form-controls-corners: var(--wa-corners-1x); + --wa-form-controls-text-color: var(--wa-color-text-normal); - --wa-form-controls-value-line-height: var(--wa-font-height-compact); - --wa-form-controls-padding: var(--wa-space-square-s); + --wa-form-controls-value-line-height: var(--wa-font-line-height-compact); + --wa-form-controls-placeholder-color: var(--wa-color-neutral-60); + --wa-form-controls-placeholder-color-valid: var(--wa-color-green-60); + --wa-form-controls-placeholder-color-invalid: var(--wa-color-red-60); + + --wa-form-controls-height-s: calc( + var(--wa-space-xs) * 2 + var(--wa-font-size-s) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-m: calc( + var(--wa-space-s) * 2 + var(--wa-font-size-m) * var(--wa-form-controls-value-line-height) + ); + --wa-form-controls-height-l: calc( + var(--wa-space-m) * 2 + var(--wa-font-size-l) * var(--wa-form-controls-value-line-height) + ); /** * Panels */ + --wa-panel-border-style: var(--wa-border-style); --wa-panel-border-width: var(--wa-border-width-thin); + --wa-panel-corners: var(--wa-corners-2x); /** * From 2.x */ - --wa-form-controls-height-s: 2rem; - --wa-form-controls-height-m: 2.75rem; - --wa-form-controls-height-l: 3.5rem; --wa-form-control-toggle-size-s: 0.875rem; --wa-form-control-toggle-size-m: 1.125rem; --wa-form-control-toggle-size-l: 1.375rem; @@ -350,10 +382,104 @@ wa-button[variant='danger'] { --wa-form-controls-required-content-color: inherit; --wa-form-controls-required-content-offset: -0.1em; - --wa-overlay-color: hsl(240 3.8% 46.1% / 33%); - - --wa-tooltip-arrow-size: 0.375rem; --wa-flow-spacing: 1.5rem; + --wa-tooltip-arrow-size: 0.375rem; +} + +.wa-theme-playful-dark, +.wa-theme-playful-dark :host { + color-scheme: dark; + + /** + * Base theme colors + */ + --wa-color-surface-raised: var(--wa-color-neutral-10); + --wa-color-surface-default: var(--wa-color-neutral-10); + --wa-color-surface-lowered: var(--wa-color-black); + --wa-color-surface-outline: var(--wa-color-neutral-20); + + --wa-color-text-normal: var(--wa-color-neutral-95); + --wa-color-text-quiet: var(--wa-color-neutral-60); + --wa-color-text-inverse: var(--wa-color-neutral-10); + --wa-color-text-link: var(--wa-color-brand-text-on-surface); + + --wa-color-selection-background: var(--wa-color-rose-40); + --wa-color-selection-text: var(--wa-color-white); + + --wa-color-focus: color-mix(in oklab, var(--wa-color-rose-60) 90%, transparent); + + --wa-color-overlay: color-mix(in oklab, var(--wa-color-black) 50%, transparent); + + --wa-color-shadow: rgb(0 0 0 / 0.25); + + --wa-color-tint-white: rgb(255 255 255 / 0.2); + --wa-color-tint-black: rgb(0 0 0 / 0.2); + + --wa-color-tint-hover: black 8%; + --wa-color-tint-active: black 16%; + + /** + * Semantic theme colors + */ + --wa-color-brand-fill-vivid: var(--wa-color-rose-50); + --wa-color-brand-fill-vivid-alt: var(--wa-color-rose-30); + --wa-color-brand-fill-muted: var(--wa-color-rose-10); + --wa-color-brand-fill-muted-alt: var(--wa-color-rose-20); + --wa-color-brand-outline-vivid: var(--wa-color-rose-40); + --wa-color-brand-outline-vivid-alt: var(--wa-color-rose-30); + --wa-color-brand-outline-muted: var(--wa-color-rose-20); + --wa-color-brand-outline-muted-alt: var(--wa-color-rose-30); + --wa-color-brand-text-on-vivid: var(--wa-color-white); + --wa-color-brand-text-on-muted: var(--wa-color-rose-70); + --wa-color-brand-text-on-surface: var(--wa-color-rose-60); + + --wa-color-success-fill-vivid: var(--wa-color-green-50); + --wa-color-success-fill-vivid-alt: var(--wa-color-green-30); + --wa-color-success-fill-muted: var(--wa-color-green-10); + --wa-color-success-fill-muted-alt: var(--wa-color-green-20); + --wa-color-success-outline-vivid: var(--wa-color-green-40); + --wa-color-success-outline-vivid-alt: var(--wa-color-green-30); + --wa-color-success-outline-muted: var(--wa-color-green-20); + --wa-color-success-outline-muted-alt: var(--wa-color-green-30); + --wa-color-success-text-on-vivid: var(--wa-color-white); + --wa-color-success-text-on-muted: var(--wa-color-green-70); + --wa-color-success-text-on-surface: var(--wa-color-green-60); + + --wa-color-warning-fill-vivid: var(--wa-color-yellow-50); + --wa-color-warning-fill-vivid-alt: var(--wa-color-yellow-30); + --wa-color-warning-fill-muted: var(--wa-color-yellow-10); + --wa-color-warning-fill-muted-alt: var(--wa-color-yellow-20); + --wa-color-warning-outline-vivid: var(--wa-color-yellow-40); + --wa-color-warning-outline-vivid-alt: var(--wa-color-yellow-30); + --wa-color-warning-outline-muted: var(--wa-color-yellow-20); + --wa-color-warning-outline-muted-alt: var(--wa-color-yellow-30); + --wa-color-warning-text-on-vivid: var(--wa-color-white); + --wa-color-warning-text-on-muted: var(--wa-color-yellow-70); + --wa-color-warning-text-on-surface: var(--wa-color-yellow-60); + + --wa-color-danger-fill-vivid: var(--wa-color-red-50); + --wa-color-danger-fill-vivid-alt: var(--wa-color-red-30); + --wa-color-danger-fill-muted: var(--wa-color-red-10); + --wa-color-danger-fill-muted-alt: var(--wa-color-red-20); + --wa-color-danger-outline-vivid: var(--wa-color-red-40); + --wa-color-danger-outline-vivid-alt: var(--wa-color-red-30); + --wa-color-danger-outline-muted: var(--wa-color-red-20); + --wa-color-danger-outline-muted-alt: var(--wa-color-red-30); + --wa-color-danger-text-on-vivid: var(--wa-color-white); + --wa-color-danger-text-on-muted: var(--wa-color-red-70); + --wa-color-danger-text-on-surface: var(--wa-color-red-60); + + --wa-color-neutral-fill-vivid: var(--wa-color-neutral-50); + --wa-color-neutral-fill-vivid-alt: var(--wa-color-neutral-30); + --wa-color-neutral-fill-muted: var(--wa-color-neutral-10); + --wa-color-neutral-fill-muted-alt: var(--wa-color-neutral-20); + --wa-color-neutral-outline-vivid: var(--wa-color-neutral-40); + --wa-color-neutral-outline-vivid-alt: var(--wa-color-neutral-30); + --wa-color-neutral-outline-muted: var(--wa-color-neutral-20); + --wa-color-neutral-outline-muted-alt: var(--wa-color-neutral-30); + --wa-color-neutral-text-on-vivid: var(--wa-color-white); + --wa-color-neutral-text-on-muted: var(--wa-color-neutral-70); + --wa-color-neutral-text-on-surface: var(--wa-color-neutral-60); } /* _utility.css */