From 1b654c7c85f966253554cada347b0d7fdb77972c Mon Sep 17 00:00:00 2001 From: Lindsay M <126139086+lindsaym-fa@users.noreply.github.com> Date: Fri, 3 Nov 2023 13:46:00 -0400 Subject: [PATCH] Support theme customizations for depth and borders * Move custom properties related to shadows and borders to separate stylesheets * Change base values and themer calculations related to shadows and borders to be unitless * Add low-level custom properties for alert, button, card, input, select, switch, and textarea * Add generic guidance for authoring custom properties to the Contributing docs --- cspell.json | 1 + docs/_includes/sidebar.njk | 1 + docs/pages/components/button.md | 2 +- docs/pages/experimental/sandbox.md | 168 +++++++ docs/pages/experimental/themer.md | 2 +- docs/pages/resources/contributing.md | 8 +- src/components/alert/alert.component.ts | 9 + src/components/alert/alert.styles.ts | 81 ++-- src/components/button/button.component.ts | 15 + src/components/button/button.styles.ts | 426 ++++++++---------- src/components/card/card.component.ts | 9 +- src/components/card/card.styles.ts | 20 +- src/components/input/input.component.ts | 7 + src/components/input/input.styles.ts | 49 +- src/components/select/select.component.ts | 7 + src/components/select/select.styles.ts | 60 +-- src/components/switch/switch.component.ts | 12 +- src/components/switch/switch.styles.ts | 50 +- src/components/tag/tag.styles.ts | 2 +- src/components/textarea/textarea.component.ts | 7 + src/components/textarea/textarea.styles.ts | 39 +- src/styles/form-control.styles.ts | 1 + src/themes/borders_0_minimal.css | 45 ++ src/themes/borders_1_feather.css | 45 ++ src/themes/borders_2_light.css | 21 + src/themes/borders_3_medium.css | 21 + src/themes/borders_4_heavy.css | 73 +++ src/themes/default.css | 95 ++-- src/themes/depth_0_flat.css | 43 ++ src/themes/depth_1_semiflat.css | 43 ++ src/themes/depth_2_chunky.css | 71 +++ src/themes/depth_3_punchy.css | 83 ++++ src/themes/depth_4_glossy.css | 273 +++++++++++ src/themes/glassy.css | 86 ++-- src/themes/mellow.css | 91 ++-- src/themes/playful.css | 105 ++--- 36 files changed, 1427 insertions(+), 644 deletions(-) create mode 100644 docs/pages/experimental/sandbox.md create mode 100644 src/themes/borders_0_minimal.css create mode 100644 src/themes/borders_1_feather.css create mode 100644 src/themes/borders_2_light.css create mode 100644 src/themes/borders_3_medium.css create mode 100644 src/themes/borders_4_heavy.css create mode 100644 src/themes/depth_0_flat.css create mode 100644 src/themes/depth_1_semiflat.css create mode 100644 src/themes/depth_2_chunky.css create mode 100644 src/themes/depth_3_punchy.css create mode 100644 src/themes/depth_4_glossy.css diff --git a/cspell.json b/cspell.json index 8b66531e1..2fe43af29 100644 --- a/cspell.json +++ b/cspell.json @@ -47,6 +47,7 @@ "dropdowns", "easings", "endraw", + "endregion", "enterkeyhint", "eqeqeq", "erroneou", diff --git a/docs/_includes/sidebar.njk b/docs/_includes/sidebar.njk index b272c5240..121c033e8 100644 --- a/docs/_includes/sidebar.njk +++ b/docs/_includes/sidebar.njk @@ -16,6 +16,7 @@ localStorage.setItem('theme', toggle.checked ? 'dark' : 'light'); }); +
  • Sandbox
  • diff --git a/docs/pages/components/button.md b/docs/pages/components/button.md index 8c2c5f6e7..7ade3885e 100644 --- a/docs/pages/components/button.md +++ b/docs/pages/components/button.md @@ -459,7 +459,7 @@ This example demonstrates how to style buttons using a custom class. This is the wa-button.pink::part(base) { border-radius: 6px; border: solid 2px; - background-color: #ff1493; + background: #ff1493; border-top-color: #ff7ac1; border-left-color: #ff7ac1; border-bottom-color: #ad005c; diff --git a/docs/pages/experimental/sandbox.md b/docs/pages/experimental/sandbox.md new file mode 100644 index 000000000..fcddab5da --- /dev/null +++ b/docs/pages/experimental/sandbox.md @@ -0,0 +1,168 @@ +--- +meta: + title: Theming Sandbox + description: TODO +--- + +# Theming Sandbox + +#### Card + +```html:preview + + A kitten sits patiently between a terracotta pot and decorative grasses. + + Mittens
    + This kitten is as cute as he is playful. Bring him home today!
    + 6 weeks old + +
    + More Info + +
    +
    + + +``` + +#### Alerts + +```html:preview + + + This is super informative
    + You can tell by how pretty the alert is. +
    +
    + + + Your changes have been saved
    + You can safely exit the app now. +
    +
    + + + Your settings have been updated
    + Settings will take affect on next login. +
    +
    + + + Your session has ended
    + Please login again to continue. +
    +
    + + + Your account has been deleted
    + We're very sorry to see you go! +
    +``` + +#### Badges and Tags + +```html:preview +Brand +Success +Neutral +Warning +Danger +
    +Brand +Success +Neutral +Warning +Danger +``` + +#### Buttons + +```html:preview +Brand +Success +Neutral +Warning +Danger +

    +Brand +Success +Neutral +Warning +Danger +

    +Brand +``` + +#### Form controls + +```html:preview +Unchecked +
    +Checked +

    + + Option 1 + Option 2 + Option 3 + +
    +Switch off +
    +Switch on +

    + +
    + + Option 1 + Option 2 + Option 3 + Option 4 + Option 5 + Option 6 + +``` + +#### Progress + +```html:preview + + + +``` + +#### Shadows + +```html:preview + +
    +
    +
    +
    +``` diff --git a/docs/pages/experimental/themer.md b/docs/pages/experimental/themer.md index 01da40f36..09e790549 100644 --- a/docs/pages/experimental/themer.md +++ b/docs/pages/experimental/themer.md @@ -67,7 +67,7 @@ toc: false // Border width container.querySelector('[name="border-width"]').addEventListener('wa-input', event => { - document.documentElement.style.setProperty('--wa-border-width-base', `${event.target.value / 16}rem`); + document.documentElement.style.setProperty('--wa-border-width-base', `${event.target.value / 16}`); }); // Border style diff --git a/docs/pages/resources/contributing.md b/docs/pages/resources/contributing.md index 4b64ee785..a22de4e1c 100644 --- a/docs/pages/resources/contributing.md +++ b/docs/pages/resources/contributing.md @@ -348,16 +348,18 @@ When change events are emitted by Web Awesome components, they should be named ` ### CSS Custom Properties +Custom properties allow users to customize Web Awesome components by exposing specific styles across a component's shadow boundary. Use custom properties to expose key characteristics of a component for low-level theming. Avoid using custom properties for styles that may interfere with proper rendering. + To expose custom properties as part of a component's API, scope them to the `:host` block. ```css :host { - --color: var(--sl-color-primary-500); - --background-color: var(--sl-color-neutral-100); + --color: var(--wa-color-brand-text-on-vivid); + --background-color: var(--wa-color-brand-fill-vivid); } ``` -Then use the following syntax for comments so they appear in the generated docs. Do not use the `--sl-` prefix, as that is reserved for design tokens that live in the global scope. +Then use the following syntax for comments so they appear in the generated docs. Do not use the `--wa-` prefix, as that is reserved for design tokens that live in the global scope. ```js /** diff --git a/src/components/alert/alert.component.ts b/src/components/alert/alert.component.ts index 57f12565b..77b1ebce9 100644 --- a/src/components/alert/alert.component.ts +++ b/src/components/alert/alert.component.ts @@ -36,6 +36,15 @@ const toastStack = Object.assign(document.createElement('div'), { className: 'wa * @csspart close-button - The close button, an ``. * @csspart close-button__base - The close button's exported `base` part. * + * @cssproperty --background - The alert's background styles. + * @cssproperty --border-color - The color of the alert's border. + * @cssproperty --border-radius - The border radius of the alert's corners. + * @cssproperty --border-style - The style of the alert's borders. + * @cssproperty --border-width - The width of the alert's borders. + * @cssproperty --content-color - The color of the alert's content. + * @cssproperty --icon-size - The size of the icon. + * @cssproperty --padding - The padding within the alert. Expects a single value. + * * @animation alert.show - The animation to use when showing the alert. * @animation alert.hide - The animation to use when hiding the alert. */ diff --git a/src/components/alert/alert.styles.ts b/src/components/alert/alert.styles.ts index 6211edcec..b38774cae 100644 --- a/src/components/alert/alert.styles.ts +++ b/src/components/alert/alert.styles.ts @@ -5,17 +5,58 @@ export default css` ${componentStyles} :host { + --border-radius: var(--wa-panel-corners); + --border-style: var(--wa-panel-border-style); + --border-width: var(--wa-panel-border-width); + --icon-size: var(--wa-font-size-l); + --padding: var(--wa-space-m); + display: contents; /* For better DX, we'll reset the margin here so the base part can inherit it */ margin: 0; } + :host([variant='brand']) { + --background: var(--wa-color-brand-fill-muted); + --border-color: var(--wa-color-brand-outline-muted); + --content-color: var(--wa-color-brand-text-on-muted); + } + + :host([variant='success']) { + --background: var(--wa-color-success-fill-muted); + --border-color: var(--wa-color-success-outline-muted); + --content-color: var(--wa-color-success-text-on-muted); + } + + :host([variant='neutral']) { + --background: var(--wa-color-neutral-fill-muted); + --border-color: var(--wa-color-neutral-outline-muted); + --content-color: var(--wa-color-neutral-text-on-muted); + } + + :host([variant='warning']) { + --background: var(--wa-color-warning-fill-muted); + --border-color: var(--wa-color-warning-outline-muted); + --content-color: var(--wa-color-warning-text-on-muted); + } + + :host([variant='danger']) { + --background: var(--wa-color-danger-fill-muted); + --border-color: var(--wa-color-danger-outline-muted); + --content-color: var(--wa-color-danger-text-on-muted); + } + .alert { position: relative; display: flex; align-items: stretch; - border-radius: var(--wa-panel-corners); + background: var(--background); + border-color: var(--border-color); + border-radius: var(--border-radius); + border-style: var(--border-style); + border-width: var(--border-width); + color: var(--content-color); font: inherit; margin: inherit; } @@ -29,44 +70,14 @@ export default css` flex: 0 0 auto; display: flex; align-items: center; - font-size: var(--wa-font-size-l); - padding-inline-start: var(--wa-space-l); - } - - .alert--brand { - background-color: var(--wa-color-brand-fill-muted); - border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-brand-outline-muted); - color: var(--wa-color-brand-text-on-muted); - } - - .alert--success { - background-color: var(--wa-color-success-fill-muted); - border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-success-outline-muted); - color: var(--wa-color-success-text-on-muted); - } - - .alert--neutral { - background-color: var(--wa-color-neutral-fill-muted); - border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-neutral-outline-muted); - color: var(--wa-color-neutral-text-on-muted); - } - - .alert--warning { - background-color: var(--wa-color-warning-fill-muted); - border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-warning-outline-muted); - color: var(--wa-color-warning-text-on-muted); - } - - .alert--danger { - background-color: var(--wa-color-danger-fill-muted); - border: var(--wa-border-style) var(--wa-panel-border-width) var(--wa-color-danger-outline-muted); - color: var(--wa-color-danger-text-on-muted); + font-size: var(--icon-size); + padding-inline-start: var(--padding); } .alert__message { flex: 1 1 auto; display: block; - padding: var(--wa-space-m); + padding: var(--padding); overflow: hidden; } @@ -76,7 +87,7 @@ export default css` align-items: center; color: currentColor; font-size: var(--wa-font-size-m); - padding-inline-end: var(--wa-space-m); + padding-inline-end: var(--padding); } .alert__close-button:hover::part(base) { diff --git a/src/components/button/button.component.ts b/src/components/button/button.component.ts index ad05d4184..7753116d2 100644 --- a/src/components/button/button.component.ts +++ b/src/components/button/button.component.ts @@ -36,6 +36,21 @@ import type { WebAwesomeFormControl } from '../../internal/webawesome-element.js * @csspart suffix - The container that wraps the suffix. * @csspart caret - The button's caret icon, an `` element. * @csspart spinner - The spinner that shows when the button is in the loading state. + * + * @cssproperty --background - The button's background styles. + * @cssproperty --background-active - The color of the button's background when active. + * @cssproperty --background-hover - The color of the button's background on hover. + * @cssproperty --border-color - The color of the button's border. + * @cssproperty --border-color-active - The color of the button's border when active. + * @cssproperty --border-color-hover - The color of the button's border on hover. + * @cssproperty --border-radius - The radius of the button's corners. + * @cssproperty --border-style - The style of the button's border. + * @cssproperty --border-width - The width of the button's border. Expects a single value. + * @cssproperty --box-shadow - The shadow effects around the edges of the button. + * @cssproperty --box-shadow-color - A bespoke shadow color for the button. + * @cssproperty --label-color - The color of the button's label. + * @cssproperty --label-color-active - The color of the button's label when active. + * @cssproperty --label-color-hover - The color of the button's label on hover. */ export default class WaButton extends WebAwesomeElement implements WebAwesomeFormControl { static styles: CSSResultGroup = styles; diff --git a/src/components/button/button.styles.ts b/src/components/button/button.styles.ts index 9b30a322c..a04438aef 100644 --- a/src/components/button/button.styles.ts +++ b/src/components/button/button.styles.ts @@ -5,18 +5,143 @@ export default css` ${componentStyles} :host { + --border-radius: var(--wa-form-controls-corners); + --border-style: var(--wa-border-style); + --border-width: var(--wa-form-controls-border-width); + --box-shadow: var(--wa-shadow-level-0); + --box-shadow-color: var(--wa-color-shadow); + display: inline-block; position: relative; width: auto; cursor: pointer; } + /* + * Standard buttons + */ + + :host([variant='brand']) { + --background: var(--wa-color-brand-fill-vivid); + --label-color: var(--wa-color-brand-text-on-vivid); + } + + :host([variant='success']) { + --background: var(--wa-color-success-fill-vivid); + --label-color: var(--wa-color-success-text-on-vivid); + } + + :host([variant='warning']) { + --background: var(--wa-color-warning-fill-vivid); + --label-color: var(--wa-color-warning-text-on-vivid); + } + + :host([variant='neutral']) { + --background: var(--wa-color-neutral-fill-vivid); + --label-color: var(--wa-color-neutral-text-on-vivid); + } + + :host([variant='danger']) { + --background: var(--wa-color-danger-fill-vivid); + --label-color: var(--wa-color-danger-text-on-vivid); + } + + :host(:not([variant='text'])) { + --background-hover: color-mix(in oklab, var(--background), var(--wa-color-tint-hover)); + --background-active: color-mix(in oklab, var(--background), var(--wa-color-tint-active)); + --border-color: var(--background); + --border-color-hover: var(--background-hover); + --border-color-active: var(--background-active); + --label-color-hover: var(--label-color); + --label-color-active: var(--label-color); + } + + /* + * Outline buttons + */ + + :host([variant='brand'][outline]) { + --background-hover: var(--wa-color-brand-fill-muted); + --border-color: var(--wa-color-brand-outline-vivid); + --label-color: var(--wa-color-brand-text-on-surface); + --label-color-hover: var(--wa-color-brand-text-on-muted); + } + + :host([variant='success'][outline]) { + --background-hover: var(--wa-color-success-fill-muted); + --border-color: var(--wa-color-success-outline-vivid); + --label-color: var(--wa-color-success-text-on-surface); + --label-color-hover: var(--wa-color-success-text-on-muted); + } + + :host([variant='neutral'][outline]), + :host(.wa-button-group__button--radio:not([checked])) { + --background-hover: var(--wa-color-neutral-fill-muted); + --border-color: var(--wa-color-neutral-outline-vivid); + --label-color: var(--wa-color-neutral-text-on-surface); + --label-color-hover: var(--wa-color-neutral-text-on-muted); + } + + :host([variant='warning'][outline]) { + --background-hover: var(--wa-color-warning-fill-muted); + --border-color: var(--wa-color-warning-outline-vivid); + --label-color: var(--wa-color-warning-text-on-surface); + --label-color-hover: var(--wa-color-warning-text-on-muted); + } + + :host([variant='danger'][outline]) { + --background-hover: var(--wa-color-danger-fill-muted); + --border-color: var(--wa-color-danger-outline-vivid); + --label-color: var(--wa-color-danger-text-on-surface); + --label-color-hover: var(--wa-color-danger-text-on-muted); + } + + :host([outline]), + :host(.wa-button-group__button--radio:not([checked])) { + --background-active: color-mix(in oklab, var(--background-hover), var(--wa-color-surface-default) 30%); + --border-color-hover: var(--border-color); + --border-color-active: var(--border-color); + --label-color-active: var(--label-color-hover); + } + + /* + * Text buttons + */ + + :host([variant='text']) { + --background: none; + --background-active: none; + --background-hover: none; + --border-color: transparent; + --border-color-active: transparent; + --border-color-hover: transparent; + --label-color: var(--wa-color-text-link); + --label-color-active: var(--wa-color-text-link); + --label-color-hover: color-mix(in oklab, var(--wa-color-text-link), var(--wa-color-tint-hover)); + } + + /* + * Checked buttons + */ + + :host([checked]) { + --background: var(--wa-color-brand-fill-vivid); + --label-color: var(--wa-color-brand-text-on-vivid); + } + + /* + * Internal + */ + .button { + border-radius: var(--border-radius); + border-style: var(--border-style); + border-width: max(1px, var(--border-width)); + color: var(--label-color); display: inline-flex; align-items: stretch; justify-content: center; width: 100%; - border: none; font: inherit; font-weight: var(--wa-font-weight-action); text-decoration: none; @@ -26,13 +151,36 @@ export default css` vertical-align: middle; padding: 0; transition: - var(--wa-transition-faster) background-color, - var(--wa-transition-faster) color, + var(--wa-transition-faster) background, var(--wa-transition-faster) border, - var(--wa-transition-faster) box-shadow; + var(--wa-transition-faster) box-shadow, + var(--wa-transition-faster) color; cursor: inherit; } + .button--standard, + .button--checked { + background: var(--background); + border-color: var(--border-color); + box-shadow: var(--box-shadow); + } + + .button--outline:not(.button--checked) { + background: none; + border-color: var(--border-color); + box-shadow: var(--box-shadow); + } + + .button--text { + background: none; + border-color: transparent; + box-shadow: none; + } + + /* + * States + */ + .button::-moz-focus-inner { border: 0; } @@ -46,26 +194,6 @@ export default css` outline-offset: var(--wa-focus-ring-offset); } - .button--brand:focus-visible { - outline-color: var(--wa-color-brand-fill-vivid); - } - - .button--success:focus-visible { - outline-color: var(--wa-color-success-fill-vivid); - } - - .button--neutral:focus-visible { - outline-color: var(--wa-color-neutral-fill-vivid); - } - - .button--warning:focus-visible { - outline-color: var(--wa-color-warning-fill-vivid); - } - - .button--danger:focus-visible { - outline-color: var(--wa-color-danger-fill-vivid); - } - .button--disabled { opacity: 0.5; cursor: not-allowed; @@ -76,6 +204,28 @@ export default css` pointer-events: none; } + .button:hover:not(.button--disabled) { + background: var(--background-hover, var(--background, none)); + border-color: var(--border-color-hover, var(--border-color, transparent)); + color: var(--label-color-hover, var(--label-color)); + } + + .button:active:not(.button--disabled) { + background: var(--background-active, var(--background, none)); + border-color: var(--border-color-active, var(--border-color, transparent)); + color: var(--label-color-active, var(--label-color)); + } + + @media (forced-colors: active) { + .button.button--outline.button--checked:not(.button--disabled) { + outline: solid 2px transparent; + } + } + + /* + * Label + */ + .button__prefix, .button__suffix { flex: 0 0 auto; @@ -92,215 +242,6 @@ export default css` vertical-align: -2px; } - /* - * Standard buttons - */ - - /* Brand */ - .button--standard.button--brand { - background-color: var(--wa-color-brand-fill-vivid); - color: var(--wa-color-brand-text-on-vivid); - } - - .button--standard.button--brand:hover:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-hover)); - } - - .button--standard.button--brand:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-active)); - } - - /* Success */ - .button--standard.button--success { - background-color: var(--wa-color-success-fill-vivid); - color: var(--wa-color-success-text-on-vivid); - } - - .button--standard.button--success:hover:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-hover)); - } - - .button--standard.button--success:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-active)); - } - - /* Neutral */ - .button--standard.button--neutral { - background-color: var(--wa-color-neutral-fill-vivid); - color: var(--wa-color-neutral-text-on-vivid); - } - - .button--standard.button--neutral:hover:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover)); - } - - .button--standard.button--neutral:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-active)); - } - - /* Warning */ - .button--standard.button--warning { - background-color: var(--wa-color-warning-fill-vivid); - color: var(--wa-color-warning-text-on-vivid); - } - .button--standard.button--warning:hover:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-hover)); - } - - .button--standard.button--warning:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-active)); - } - - /* Danger */ - .button--standard.button--danger { - background-color: var(--wa-color-danger-fill-vivid); - color: var(--wa-color-danger-text-on-vivid); - } - - .button--standard.button--danger:hover:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-hover)); - } - - .button--standard.button--danger:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-active)); - } - - /* - * Outline buttons - */ - - .button--outline { - background: none; - border: solid max(1px, var(--wa-form-controls-border-width)); - } - - /* Brand */ - .button--outline.button--brand { - border-color: var(--wa-color-brand-outline-vivid); - color: var(--wa-color-brand-text-on-surface); - } - - .button--outline.button--brand:hover:not(.button--disabled), - .button--outline.button--brand.button--checked:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-hover)); - border-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-hover)); - color: var(--wa-color-brand-text-on-vivid); - } - - .button--outline.button--brand:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-active)); - border-color: color-mix(in oklab, var(--wa-color-brand-fill-vivid), var(--wa-color-tint-active)); - } - - /* Success */ - .button--outline.button--success { - border-color: var(--wa-color-success-outline-vivid); - color: var(--wa-color-success-text-on-surface); - } - - .button--outline.button--success:hover:not(.button--disabled), - .button--outline.button--success.button--checked:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-hover)); - border-color: color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-hover)); - color: var(--wa-color-success-text-on-vivid); - } - - .button--outline.button--success:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-active)); - border-color: color-mix(in oklab, var(--wa-color-success-fill-vivid), var(--wa-color-tint-active)); - } - - .button--outline.button--small { - line-height: calc(var(--wa-form-controls-height-s) - max(1px, var(--wa-form-controls-border-width)) * 2); - } - - .button--outline.button--medium { - line-height: calc(var(--wa-form-controls-height-m) - max(1px, var(--wa-form-controls-border-width)) * 2); - } - - .button--outline.button--large { - line-height: calc(var(--wa-form-controls-height-l) - max(1px, var(--wa-form-controls-border-width)) * 2); - } - - /* Neutral */ - .button--outline.button--neutral { - border-color: var(--wa-color-neutral-outline-vivid); - color: var(--wa-color-neutral-text-on-surface); - } - - .button--outline.button--neutral:hover:not(.button--disabled), - .button--outline.button--neutral.button--checked:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover)); - border-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-hover)); - color: var(--wa-color-neutral-text-on-vivid); - } - - .button--outline.button--neutral:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-active)); - border-color: color-mix(in oklab, var(--wa-color-neutral-fill-vivid), var(--wa-color-tint-active)); - } - - /* Warning */ - .button--outline.button--warning { - border-color: var(--wa-color-warning-outline-vivid); - color: var(--wa-color-warning-text-on-surface); - } - - .button--outline.button--warning:hover:not(.button--disabled), - .button--outline.button--warning.button--checked:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-hover)); - border-color: color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-hover)); - color: var(--wa-color-warning-text-on-vivid); - } - - .button--outline.button--warning:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-active)); - border-color: color-mix(in oklab, var(--wa-color-warning-fill-vivid), var(--wa-color-tint-active)); - } - - /* Danger */ - .button--outline.button--danger { - border-color: var(--wa-color-danger-outline-vivid); - color: var(--wa-color-danger-text-on-surface); - } - - .button--outline.button--danger:hover:not(.button--disabled), - .button--outline.button--danger.button--checked:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-hover)); - border-color: color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-hover)); - color: var(--wa-color-danger-text-on-vivid); - } - - .button--outline.button--danger:active:not(.button--disabled) { - background-color: color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-active)); - border-color: color-mix(in oklab, var(--wa-color-danger-fill-vivid), var(--wa-color-tint-active)); - } - - @media (forced-colors: active) { - .button.button--outline.button--checked:not(.button--disabled) { - outline: solid 2px transparent; - } - } - - /* - * Text buttons - */ - - .button--text { - background-color: transparent; - border-color: transparent; - color: var(--wa-color-text-link); - } - - .button--text:hover:not(.button--disabled) { - color: color-mix(in oklab, var(--wa-color-text-link), var(--wa-color-tint-hover)); - } - - .button--text:focus-visible:not(.button--disabled), - .button--text:active:not(.button--disabled) { - color: var(--wa-color-text-link); - } - /* * Size modifiers */ @@ -308,22 +249,19 @@ export default css` .button--small { height: var(--wa-form-controls-height-s); font-size: var(--wa-font-size-s); - line-height: var(--wa-form-controls-height-s); - border-radius: var(--wa-form-controls-corners); + line-height: calc(var(--wa-form-controls-height-s) - var(--border-width) * 2); } .button--medium { height: var(--wa-form-controls-height-m); font-size: var(--wa-font-size-m); - line-height: var(--wa-form-controls-height-m); - border-radius: var(--wa-form-controls-corners); + line-height: calc(var(--wa-form-controls-height-m) - var(--border-width) * 2); } .button--large { height: var(--wa-form-controls-height-l); font-size: var(--wa-font-size-l); - line-height: var(--wa-form-controls-height-l); - border-radius: var(--wa-form-controls-corners); + line-height: calc(var(--wa-form-controls-height-l) - var(--border-width) * 2); } /* @@ -432,11 +370,11 @@ export default css` } .button--has-prefix.button--large { - padding-inline-start: var(--wa-space-s); + padding-inline-start: var(--wa-space-m); } .button--has-prefix.button--large .button__label { - padding-inline-start: var(--wa-space-s); + padding-inline-start: var(--wa-space-m); } .button--has-suffix.button--small, @@ -461,12 +399,12 @@ export default css` .button--has-suffix.button--large, .button--caret.button--large { - padding-inline-end: var(--wa-space-s); + padding-inline-end: var(--wa-space-m); } .button--has-suffix.button--large .button__label, .button--caret.button--large .button__label { - padding-inline-end: var(--wa-space-s); + padding-inline-end: var(--wa-space-m); } /* @@ -503,7 +441,7 @@ export default css` top: 0; inset-inline-start: 0; bottom: 0; - border-left: solid 1px rgb(128 128 128 / 33%); + border-left: solid 1px var(--wa-color-tint-black); mix-blend-mode: multiply; } diff --git a/src/components/card/card.component.ts b/src/components/card/card.component.ts index 617a76e6c..151887df3 100644 --- a/src/components/card/card.component.ts +++ b/src/components/card/card.component.ts @@ -22,10 +22,13 @@ import type { CSSResultGroup } from 'lit'; * @csspart body - The container that wraps the card's main content. * @csspart footer - The container that wraps the card's footer. * + * @cssproperty --background - The card's background styles. * @cssproperty --border-color - The card's border color, including borders that occur inside the card. - * @cssproperty --border-radius - The border radius for the card's edges. - * @cssproperty --border-width - The width of the card's borders. - * @cssproperty --padding - The padding to use for the card's sections. + * @cssproperty --border-radius - The border radius for the card's corners. Expects a single value. + * @cssproperty --border-style - The style of the card's borders. + * @cssproperty --border-width - The width of the card's borders. Expects a single value. + * @cssproperty --box-shadow - The shadow effects around the edges of the card. + * @cssproperty --padding - The padding for each section in the card. Expects a single value. */ export default class WaCard extends WebAwesomeElement { static styles: CSSResultGroup = styles; diff --git a/src/components/card/card.styles.ts b/src/components/card/card.styles.ts index 5cc2bc001..57ded3faf 100644 --- a/src/components/card/card.styles.ts +++ b/src/components/card/card.styles.ts @@ -5,11 +5,13 @@ export default css` ${componentStyles} :host { + --background: var(--wa-color-surface-raised); --border-color: var(--wa-color-surface-outline); --border-radius: var(--wa-panel-corners); - --border-style: var(--wa-border-style); + --border-style: var(--wa-panel-border-style); --border-width: var(--wa-panel-border-width); - --padding: var(--wa-space-l); + --box-shadow: var(--wa-shadow-level-1); + --padding: var(--wa-space-xl); display: inline-block; } @@ -17,10 +19,14 @@ export default css` .card { display: flex; flex-direction: column; - background-color: var(--wa-color-surface-raised); - box-shadow: var(--wa-shadow-level-1); - border: var(--border-style) var(--border-width) var(--border-color); + background: var(--background); + border-color: var(--border-color); border-radius: var(--border-radius); + border-style: var(--border-style); + border-width: var(--border-width); + box-shadow: var(--box-shadow); + color: var(--wa-color-text-normal); + font: inherit; } .card__image { @@ -42,7 +48,7 @@ export default css` .card__header { display: block; - border-bottom: var(--border-style) var(--border-width) var(--border-color); + border-bottom: inherit; padding: calc(var(--padding) / 2) var(--padding); } @@ -62,7 +68,7 @@ export default css` .card--has-footer .card__footer { display: block; - border-top: var(--border-style) var(--border-width) var(--border-color); + border-top: inherit; padding: var(--padding); } diff --git a/src/components/input/input.component.ts b/src/components/input/input.component.ts index 2db584fa0..d0524da86 100644 --- a/src/components/input/input.component.ts +++ b/src/components/input/input.component.ts @@ -47,6 +47,13 @@ import type { WebAwesomeFormControl } from '../../internal/webawesome-element.js * @csspart clear-button - The clear button. * @csspart password-toggle-button - The password toggle button. * @csspart suffix - The container that wraps the suffix. + * + * @cssproperty --background - The input's background styles. + * @cssproperty --border-color - The color of the input's borders. + * @cssproperty --border-radius - The border radius of the input's corners. + * @cssproperty --border-style - The style of the input's borders. + * @cssproperty --border-width - The width of the input's borders. Expects a single value. + * @cssproperty --box-shadow - The shadow effects around the edges of the input. */ export default class WaInput extends WebAwesomeElement implements WebAwesomeFormControl { static styles: CSSResultGroup = styles; diff --git a/src/components/input/input.styles.ts b/src/components/input/input.styles.ts index 8b136f150..21e1934d7 100644 --- a/src/components/input/input.styles.ts +++ b/src/components/input/input.styles.ts @@ -7,10 +7,28 @@ export default css` ${formControlStyles} :host { + --background: var(--wa-form-controls-background); + --border-color: var(--wa-form-controls-border-color-resting); + --border-radius: var(--wa-form-controls-corners); + --border-style: var(--wa-form-controls-border-style); + --border-width: var(--wa-form-controls-border-width); + --box-shadow: var(--wa-shadow-level-0); + display: block; } + :host([filled]) { + --background: var(--wa-color-neutral-fill-muted); + --border-color: var(--background); + } + .input { + background: var(--background); + border-color: var(--border-color); + border-radius: var(--border-radius); + border-style: var(--border-style); + border-width: var(--border-width); + box-shadow: var(--box-shadow); flex: 1 1 auto; display: inline-flex; align-items: stretch; @@ -22,17 +40,12 @@ export default css` overflow: hidden; cursor: text; transition: + var(--wa-transition-fast) background, var(--wa-transition-fast) border, - var(--wa-transition-fast) background-color; + var(--wa-transition-faster) outline; } /* Standard inputs */ - .input--standard { - background-color: var(--wa-form-controls-background); - border: var(--wa-form-controls-border-style) var(--wa-form-controls-border-width) - var(--wa-form-controls-border-color-resting); - } - .input--standard.input--focused:not(.input--disabled) { outline: var(--wa-focus-ring); outline-offset: var(--wa-focus-ring-offset); @@ -45,15 +58,9 @@ export default css` } /* Filled inputs */ - .input--filled { - border: none; - background-color: var(--wa-color-neutral-fill-muted); - color: var(--wa-color-neutral-text-on-muted); - } - .input--filled.input--focused:not(.input--disabled) { outline: var(--wa-focus-ring); - outline-offset: 0; + outline-offset: var(--wa-focus-ring-offset); } .input--filled.input--disabled { @@ -69,7 +76,8 @@ export default css` line-height: var(--wa-form-controls-value-line-height); color: var(--wa-form-controls-text-color); border: none; - background: inherit; + /* prettier-ignore */ + background: rgb(118 118 118 / 0); /* ensures proper placeholder styles in webkit's date input */ box-shadow: none; padding: 0; margin: 0; @@ -120,7 +128,7 @@ export default css` .input__prefix ::slotted(wa-icon), .input__suffix ::slotted(wa-icon) { - color: var(--wa-color-neutral-text-on-surface); + color: var(--wa-color-neutral-fill-vivid); } /* @@ -128,13 +136,12 @@ export default css` */ .input--small { - border-radius: var(--wa-form-controls-corners); font-size: var(--wa-font-size-s); height: var(--wa-form-controls-height-s); } .input--small .input__control { - height: calc(var(--wa-form-controls-height-s) - var(--wa-form-controls-border-width) * 2); + height: calc(var(--wa-form-controls-height-s) - var(--border-width) * 2); padding: 0 var(--wa-space-s); } @@ -152,13 +159,12 @@ export default css` } .input--medium { - border-radius: var(--wa-form-controls-corners); font-size: var(--wa-font-size-m); height: var(--wa-form-controls-height-m); } .input--medium .input__control { - height: calc(var(--wa-form-controls-height-m) - var(--wa-form-controls-border-width) * 2); + height: calc(var(--wa-form-controls-height-m) - var(--border-width) * 2); padding: 0 var(--wa-space-m); } @@ -176,13 +182,12 @@ export default css` } .input--large { - border-radius: var(--wa-form-controls-corners); font-size: var(--wa-font-size-l); height: var(--wa-form-controls-height-l); } .input--large .input__control { - height: calc(var(--wa-form-controls-height-l) - var(--wa-form-controls-border-width) * 2); + height: calc(var(--wa-form-controls-height-l) - var(--border-width) * 2); padding: 0 var(--wa-space-l); } diff --git a/src/components/select/select.component.ts b/src/components/select/select.component.ts index d247ac893..e5bbf329a 100644 --- a/src/components/select/select.component.ts +++ b/src/components/select/select.component.ts @@ -65,6 +65,13 @@ import type WaOption from '../option/option.component.js'; * @csspart tag__remove-button__base - The tag's remove button base part. * @csspart clear-button - The clear button. * @csspart expand-icon - The container that wraps the expand icon. + * + * @cssproperty --background - The background styles of the select's combobox. + * @cssproperty --border-color - The color of the select's borders, including the listbox. + * @cssproperty --border-radius - The border radius of the select's combobox. + * @cssproperty --border-style - The style of the select's borders, including the listbox. + * @cssproperty --border-width - The width of the select's borders, including the listbox. + * @cssproperty --box-shadow - The shadow effects around the edges of the select's combobox. */ export default class WaSelect extends WebAwesomeElement implements WebAwesomeFormControl { static styles: CSSResultGroup = styles; diff --git a/src/components/select/select.styles.ts b/src/components/select/select.styles.ts index c6d8bac2a..71298607b 100644 --- a/src/components/select/select.styles.ts +++ b/src/components/select/select.styles.ts @@ -7,9 +7,21 @@ export default css` ${formControlStyles} :host { + --background: var(--wa-form-controls-background); + --border-color: var(--wa-form-controls-border-color-resting); + --border-radius: var(--wa-form-controls-corners); + --border-style: var(--wa-form-controls-border-style); + --border-width: var(--wa-form-controls-border-width); + --box-shadow: var(--wa-shadow-level-0); + display: block; } + :host([filled]) { + --background: var(--wa-color-neutral-fill-muted); + --border-color: var(--background); + } + /** The popup */ .select { flex: 1 1 auto; @@ -33,6 +45,12 @@ export default css` /* Combobox */ .select__combobox { + background: var(--background); + border-color: var(--border-color); + border-radius: var(--border-radius); + border-style: var(--border-style); + border-width: var(--border-width); + box-shadow: var(--box-shadow); flex: 1; display: flex; width: 100%; @@ -45,10 +63,11 @@ export default css` overflow: hidden; cursor: pointer; transition: - var(--wa-transition-fast) color, + var(--wa-transition-fast) background, var(--wa-transition-fast) border, var(--wa-transition-fast) box-shadow, - var(--wa-transition-fast) background-color; + var(--wa-transition-fast) color, + var(--wa-transition-faster) outline; } .select__display-input { @@ -115,12 +134,6 @@ export default css` } /* Standard selects */ - .select--standard .select__combobox { - background-color: var(--wa-form-controls-background); - border: var(--wa-form-controls-border-style) var(--wa-form-controls-border-width) - var(--wa-form-controls-border-color-resting); - } - .select--standard.select--disabled .select__combobox { opacity: 0.5; cursor: not-allowed; @@ -134,26 +147,13 @@ export default css` } /* Filled selects */ - .select--filled .select__combobox { - border: none; - background-color: var(--wa-color-neutral-fill-muted); - color: var(--wa-color-neutral-text-on-muted); - } - .select--filled.select--disabled .select__combobox { opacity: 0.5; cursor: not-allowed; } - .select--filled:not(.select--disabled).select--open .select__combobox, - .select--filled:not(.select--disabled).select--focused .select__combobox { - background-color: var(--wa-color-neutral-fill-muted); - color: var(--wa-color-neutral-text-on-muted); - } - /* Sizes */ .select--small .select__combobox { - border-radius: var(--wa-form-controls-corners); font-size: var(--wa-font-size-s); min-height: var(--wa-form-controls-height-s); padding-block: 0; @@ -178,7 +178,6 @@ export default css` } .select--medium .select__combobox { - border-radius: var(--wa-form-controls-corners); font-size: var(--wa-font-size-m); min-height: var(--wa-form-controls-height-m); padding-block: 0; @@ -203,7 +202,6 @@ export default css` } .select--large .select__combobox { - border-radius: var(--wa-form-controls-corners); font-size: var(--wa-font-size-l); min-height: var(--wa-form-controls-height-l); padding-block: 0; @@ -229,15 +227,15 @@ export default css` /* Pills */ .select--pill.select--small .select__combobox { - border-radius: var(--wa-form-controls-height-s); + border-radius: var(--wa-corners-pill); } .select--pill.select--medium .select__combobox { - border-radius: var(--wa-form-controls-height-m); + border-radius: var(--wa-corners-pill); } .select--pill.select--large .select__combobox { - border-radius: var(--wa-form-controls-height-l); + border-radius: var(--wa-corners-pill); } /* Prefix */ @@ -245,7 +243,7 @@ export default css` flex: 0; display: inline-flex; align-items: center; - color: var(--wa-form-controls-border-color-activated); + color: var(--wa-color-neutral-fill-vivid); } /* Clear button */ @@ -258,7 +256,7 @@ export default css` border: none; background: none; padding: 0; - transition: var(--wa-transition-fast) color; + transition: color var(--wa-transition-fast); cursor: pointer; } @@ -275,7 +273,7 @@ export default css` flex: 0 0 auto; display: flex; align-items: center; - transition: var(--wa-transition-normal) rotate ease; + transition: rotate var(--wa-transition-normal) ease; rotate: 0; margin-inline-start: var(--wa-space-s); } @@ -291,8 +289,10 @@ export default css` font: inherit; box-shadow: var(--wa-shadow-level-2); background: var(--wa-color-surface-raised); - border: var(--wa-border-style) var(--wa-border-width-thin) var(--wa-color-surface-outline); + border-color: var(--border-color); border-radius: var(--wa-corners-1x); + border-style: var(--border-style); + border-width: var(--border-width); padding-block: var(--wa-space-xs); padding-inline: 0; overflow: auto; diff --git a/src/components/switch/switch.component.ts b/src/components/switch/switch.component.ts index a66e29729..bd18a7517 100644 --- a/src/components/switch/switch.component.ts +++ b/src/components/switch/switch.component.ts @@ -30,9 +30,19 @@ import type { WebAwesomeFormControl } from '../../internal/webawesome-element.js * @csspart thumb - The switch's thumb. * @csspart label - The switch's label. * - * @cssproperty --width - The width of the switch. + * @cssproperty --background - The switch's background styles. + * @cssproperty --background-checked - The switch's background styles when checked. + * @cssproperty --border-color - The color of the switch's borders. + * @cssproperty --border-color-checked - The color of the switch's borders when checked. + * @cssproperty --border-style - The style of the switch's borders. + * @cssproperty --border-width - The width of the switch's borders. Expects a single value. + * @cssproperty --box-shadow - The shadow effects around the edges of the switch. * @cssproperty --height - The height of the switch. + * @cssproperty --thumb-color - The color of the thumb. + * @cssproperty --thumb-color-checked - The color of the thumb when checked. + * @cssproperty --thumb-shadow - The shadow effects around the edges of the thumb. * @cssproperty --thumb-size - The size of the thumb. + * @cssproperty --width - The width of the switch. */ export default class WaSwitch extends WebAwesomeElement implements WebAwesomeFormControl { static styles: CSSResultGroup = styles; diff --git a/src/components/switch/switch.styles.ts b/src/components/switch/switch.styles.ts index 05d360dd3..8a40ad144 100644 --- a/src/components/switch/switch.styles.ts +++ b/src/components/switch/switch.styles.ts @@ -5,30 +5,32 @@ export default css` ${componentStyles} :host { + --background: var(--wa-color-neutral-fill-vivid); + --background-checked: var(--wa-color-brand-fill-vivid); + --border-color: var(--background); + --border-color-checked: var(--background-checked); + --border-style: var(--wa-form-controls-border-style); + --border-width: var(--wa-form-controls-border-width); + --box-shadow: none; + --height: calc(1em * var(--wa-font-line-height-compact)); + --thumb-color: var(--wa-form-controls-background); + --thumb-color-checked: var(--wa-form-controls-background); + --thumb-shadow: none; + --thumb-size: calc(var(--height) - var(--border-width) * 2); + --width: calc(var(--height) * 2); + display: inline-block; } :host([size='small']) { - --height: var(--wa-form-control-toggle-size-s); - --thumb-size: calc(var(--wa-form-control-toggle-size-s) + 4px); - --width: calc(var(--height) * 2); - font-size: var(--wa-font-size-s); } :host([size='medium']) { - --height: var(--wa-form-control-toggle-size-m); - --thumb-size: calc(var(--wa-form-control-toggle-size-m) + 4px); - --width: calc(var(--height) * 2); - font-size: var(--wa-font-size-m); } :host([size='large']) { - --height: var(--wa-form-control-toggle-size-l); - --thumb-size: calc(var(--wa-form-control-toggle-size-l) + 4px); - --width: calc(var(--height) * 2); - font-size: var(--wa-font-size-l); } @@ -50,21 +52,24 @@ export default css` justify-content: center; width: var(--width); height: var(--height); - background-color: var(--wa-color-neutral-fill-vivid); - border: solid var(--wa-border-width-thin) var(--wa-color-neutral-fill-muted); + background: var(--background); + border-color: var(--border-color); border-radius: var(--height); + border-style: var(--border-style); + border-width: var(--border-width); + box-shadow: var(--box-shadow); transition: - var(--wa-transition-fast) border-color, - var(--wa-transition-fast) background-color; + var(--wa-transition-fast) background, + var(--wa-transition-fast) border-color; } .switch__control .switch__thumb { width: var(--thumb-size); height: var(--thumb-size); - background-color: var(--wa-form-controls-background); + background-color: var(--thumb-color); border-radius: 50%; - border: var(--wa-form-controls-border-style) var(--wa-form-controls-border-width) - var(--wa-color-neutral-outline-vivid); + border: solid var(--border-width) var(--thumb-color); + box-shadow: var(--thumb-shadow); translate: calc((var(--width) - var(--height)) / -2); transition: var(--wa-transition-fast) translate ease, @@ -89,12 +94,13 @@ export default css` /* Checked */ .switch--checked .switch__control { - background-color: var(--wa-color-brand-fill-vivid); - border-color: var(--wa-color-brand-fill-vivid); + background: var(--background-checked); + border-color: var(--border-color-checked); } .switch--checked .switch__control .switch__thumb { - border-color: var(--wa-color-brand-outline-vivid); + background: var(--thumb-color-checked); + border-color: var(--thumb-color-checked); translate: calc((var(--width) - var(--height)) / 2); } diff --git a/src/components/tag/tag.styles.ts b/src/components/tag/tag.styles.ts index eb22abccd..7892c0612 100644 --- a/src/components/tag/tag.styles.ts +++ b/src/components/tag/tag.styles.ts @@ -11,7 +11,7 @@ export default css` .tag { display: flex; align-items: center; - border: solid 1px; + border: solid var(--wa-border-width-thin); line-height: 1; white-space: nowrap; user-select: none; diff --git a/src/components/textarea/textarea.component.ts b/src/components/textarea/textarea.component.ts index 221fb750c..1016e8ad8 100644 --- a/src/components/textarea/textarea.component.ts +++ b/src/components/textarea/textarea.component.ts @@ -33,6 +33,13 @@ import type { WebAwesomeFormControl } from '../../internal/webawesome-element.js * @csspart form-control-help-text - The help text's wrapper. * @csspart base - The component's base wrapper. * @csspart textarea - The internal `