diff --git a/components/card/card-content-meta.js b/components/card/card-content-meta.js index 28e8371038d..3e9a9d7ae7a 100644 --- a/components/card/card-content-meta.js +++ b/components/card/card-content-meta.js @@ -11,7 +11,7 @@ class CardContentMeta extends LitElement { return css` :host { box-sizing: border-box; - color: var(--d2l-color-tungsten); + color: var(--d2l-theme-text-color-static-subtle); display: inline-block; font-size: 0.7rem; font-weight: 400; diff --git a/components/card/card-loading-shimmer.js b/components/card/card-loading-shimmer.js index ad51cc1cdb8..3d182501c49 100644 --- a/components/card/card-loading-shimmer.js +++ b/components/card/card-loading-shimmer.js @@ -1,11 +1,12 @@ import '../colors/colors.js'; import { css, html, LitElement } from 'lit'; +import { SkeletonMixin, skeletonStyles } from '../skeleton/skeleton-mixin.js'; /** * A card layout component for when the card header is loading. * @slot - Slot for header content being loaded */ -class CardLoadingShimmer extends LitElement { +class CardLoadingShimmer extends SkeletonMixin(LitElement) { static get properties() { return { @@ -18,37 +19,25 @@ class CardLoadingShimmer extends LitElement { } static get styles() { - return css` + return [skeletonStyles, css` :host([hidden]) { display: none; } - - .d2l-card-loading-indicator { - background-color: var(--d2l-color-regolith); + .d2l-skeletize { border-radius: 7px 7px 0 0; - box-shadow: inset 0 -1px 0 0 var(--d2l-color-gypsum); height: inherit; overflow: hidden; position: relative; } - .d2l-card-loading-indicator::after { - animation: loadingShimmer 1.5s ease-in-out infinite; - background: linear-gradient(90deg, rgba(249, 250, 251, 0.1), rgba(114, 119, 122, 0.1), rgba(249, 250, 251, 0.1)); - background-color: var(--d2l-color-regolith); - content: ""; - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; + :host([skeleton]) .d2l-skeletize::before { + border-radius: 0; + box-shadow: inset 0 -1px 0 0 var(--d2l-color-gypsum); } - - @keyframes loadingShimmer { - 0% { transform: translate3d(-100%, 0, 0); } - 100% { transform: translate3d(100%, 0, 0); } + :host([skeleton]) slot { + display: none; } - `; + `]; } constructor() { @@ -58,11 +47,17 @@ class CardLoadingShimmer extends LitElement { render() { return html` -
-
+
`; } + willUpdate(changedProperties) { + super.willUpdate(changedProperties); + if (changedProperties.has('loading')) { + this.skeleton = this.loading; + } + } + } customElements.define('d2l-card-loading-shimmer', CardLoadingShimmer); diff --git a/components/card/card.js b/components/card/card.js index e83448b70f7..1324a322160 100644 --- a/components/card/card.js +++ b/components/card/card.js @@ -87,8 +87,8 @@ class Card extends LitElement { static get styles() { return [offscreenStyles, css` :host { - background-color: #ffffff; - border: 1px solid var(--d2l-color-gypsum); + background-color: var(--d2l-theme-background-color-base); + border: 1px solid var(--d2l-theme-border-color-subtle); border-radius: 6px; box-sizing: border-box; display: inline-block; @@ -191,20 +191,18 @@ class Card extends LitElement { border: none; } :host([subtle][href]) { - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.03); - } - :host([href]:not([_active]):hover) { - box-shadow: 0 2px 14px 1px rgba(0, 0, 0, 0.06); + box-shadow: var(--d2l-theme-shadow-attached); } + :host([href]:not([_active]):hover), :host([subtle][href]:not([_active]):hover) { - box-shadow: 0 4px 18px 2px rgba(0, 0, 0, 0.06); + box-shadow: var(--d2l-theme-shadow-floating); } ${getFocusRingStyles(() => ':host([_active])', { 'extraStyles': css`border-color: transparent;` })} /* .d2l-card-link-container-hover is used to only color/underline when hovering the anchor; these styles are not applied when hovering actions */ :host([href]) .d2l-card-link-container-hover, :host([href][_active]) .d2l-card-content { - color: var(--d2l-color-celestine); + color: var(--d2l-theme-text-color-interactive-default); text-decoration: underline; } /* this is needed to ensure tooltip is not be clipped by adjacent cards */ @@ -222,7 +220,7 @@ class Card extends LitElement { } @media (prefers-contrast: more) { :host([subtle]) { - border: 1px solid var(--d2l-color-gypsum); + border: 1px solid var(--d2l-theme-border-color-subtle); } } `]; diff --git a/components/card/demo/card.html b/components/card/demo/card.html index 65782dbd139..83430144b94 100644 --- a/components/card/demo/card.html +++ b/components/card/demo/card.html @@ -26,7 +26,7 @@ gap: 0.6rem; } .cards-subtle { - background-color: #f6f7f8; + background-color: var(--d2l-theme-background-color-face); padding: 20px; } d2l-card { diff --git a/components/card/test/card-content.vdiff.js b/components/card/test/card-content.vdiff.js index 66ca3e5d4f4..829f5316548 100644 --- a/components/card/test/card-content.vdiff.js +++ b/components/card/test/card-content.vdiff.js @@ -13,7 +13,7 @@ describe('card-content-meta', () => { `); - await expect(elem).to.be.golden(); + await expect(elem).to.be.golden({ allColorModes: true }); }); }); diff --git a/components/card/test/card.vdiff.js b/components/card/test/card.vdiff.js index b6159fa3f41..13f9647d093 100644 --- a/components/card/test/card.vdiff.js +++ b/components/card/test/card.vdiff.js @@ -6,7 +6,8 @@ import '../../tooltip/tooltip.js'; import '../card.js'; import '../card-loading-shimmer.js'; import { clickElem, expect, fixture, focusElem, hoverElem, html, oneEvent } from '@brightspace-ui/testing'; - +import { _registerCustomSemanticVariableValue } from '../../../helpers/internal/css.js'; +_registerCustomSemanticVariableValue('--d2l-subtle-cards-header-background', 'orange', 'darkblue'); function createCardTemplate(opts) { const { alignCenter, content, subtle } = { alignCenter: false, subtle: false, ...opts }; return html` @@ -24,7 +25,7 @@ function createLinkCardTemplate(opts) { } function createHeader(text) { return html` -
${text}
+
${text}
`; } function createMultiLinkCardTemplate(opts) { @@ -99,15 +100,15 @@ const badgeSlotContent = html` `; -const subtleLinkCardTemplate = html`
+const subtleLinkCardTemplate = html`
${createLinkCardTemplate({ content: simpleContent, subtle: true })}
`; describe('card', () => { [ { name: 'header-content', template: createCardTemplate({ content: simpleContent }) }, - { name: 'hover', template: createLinkCardTemplate({ content: simpleContent }), action: elem => hoverElem(elem) }, - { name: 'focus', template: createLinkCardTemplate({ content: simpleContent }), action: elem => focusElem(elem) }, + { name: 'hover', template: createLinkCardTemplate({ content: simpleContent }), action: elem => hoverElem(elem), allColorModes: true }, + { name: 'focus', template: createLinkCardTemplate({ content: simpleContent }), action: elem => focusElem(elem), allColorModes: true }, { name: 'footer', template: createCardTemplate({ content: simpleContentWithFooter }) }, { name: 'align-center', template: createCardTemplate({ content: simpleContentWithFooter, alignCenter: true }) }, { name: 'badge', template: createCardTemplate({ content: html`${simpleContent}${badgeSlotContent}` }) }, @@ -133,18 +134,18 @@ describe('card', () => { await oneEvent(elem, 'd2l-tooltip-show'); } }, { name: 'loading', template: createCardTemplate({ content: html`` }) }, - { name: 'subtle', template: html`
+ { name: 'subtle', template: html`
${createCardTemplate({ content: simpleContent, subtle: true })} -
`, cardOnly: true }, - { name: 'subtle-link', template: subtleLinkCardTemplate, cardOnly: true }, - { name: 'subtle-link-hover', template: subtleLinkCardTemplate, action: elem => hoverElem(elem), cardOnly: true }, - { name: 'subtle-link-focus', template: subtleLinkCardTemplate, action: elem => focusElem(elem), cardOnly: true }, - ].forEach(({ name, template, action, rtl, cardOnly }) => { +
`, cardOnly: true, allColorModes: true }, + { name: 'subtle-link', template: subtleLinkCardTemplate, cardOnly: true, allColorModes: true }, + { name: 'subtle-link-hover', template: subtleLinkCardTemplate, action: elem => hoverElem(elem), cardOnly: true, allColorModes: true }, + { name: 'subtle-link-focus', template: subtleLinkCardTemplate, action: elem => focusElem(elem), cardOnly: true, allColorModes: true }, + ].forEach(({ name, template, action, rtl, cardOnly, allColorModes }) => { it(name, async() => { let elem = await fixture(template, { rtl }); if (cardOnly) elem = elem.querySelector('d2l-card'); if (action) await action(elem); - await expect(elem).to.be.golden(); + await expect(elem).to.be.golden({ allColorModes }); }); }); }); diff --git a/components/card/test/golden/card-content-meta/chromium/default.dark.png b/components/card/test/golden/card-content-meta/chromium/default.dark.png new file mode 100644 index 00000000000..905371ff712 Binary files /dev/null and b/components/card/test/golden/card-content-meta/chromium/default.dark.png differ diff --git a/components/card/test/golden/card/chromium/focus.dark.png b/components/card/test/golden/card/chromium/focus.dark.png new file mode 100644 index 00000000000..4983fed64c0 Binary files /dev/null and b/components/card/test/golden/card/chromium/focus.dark.png differ diff --git a/components/card/test/golden/card/chromium/hover.dark.png b/components/card/test/golden/card/chromium/hover.dark.png new file mode 100644 index 00000000000..54692b1ec6f Binary files /dev/null and b/components/card/test/golden/card/chromium/hover.dark.png differ diff --git a/components/card/test/golden/card/chromium/hover.png b/components/card/test/golden/card/chromium/hover.png index 1de743a29e3..e029f64a2cd 100644 Binary files a/components/card/test/golden/card/chromium/hover.png and b/components/card/test/golden/card/chromium/hover.png differ diff --git a/components/card/test/golden/card/chromium/loading.png b/components/card/test/golden/card/chromium/loading.png index b530effc0c1..42b9692f0ea 100644 Binary files a/components/card/test/golden/card/chromium/loading.png and b/components/card/test/golden/card/chromium/loading.png differ diff --git a/components/card/test/golden/card/chromium/subtle-link-focus.dark.png b/components/card/test/golden/card/chromium/subtle-link-focus.dark.png new file mode 100644 index 00000000000..92fec853502 Binary files /dev/null and b/components/card/test/golden/card/chromium/subtle-link-focus.dark.png differ diff --git a/components/card/test/golden/card/chromium/subtle-link-focus.png b/components/card/test/golden/card/chromium/subtle-link-focus.png index ce9641ac8d2..e3edbb44c2e 100644 Binary files a/components/card/test/golden/card/chromium/subtle-link-focus.png and b/components/card/test/golden/card/chromium/subtle-link-focus.png differ diff --git a/components/card/test/golden/card/chromium/subtle-link-hover.dark.png b/components/card/test/golden/card/chromium/subtle-link-hover.dark.png new file mode 100644 index 00000000000..c1f30c11858 Binary files /dev/null and b/components/card/test/golden/card/chromium/subtle-link-hover.dark.png differ diff --git a/components/card/test/golden/card/chromium/subtle-link-hover.png b/components/card/test/golden/card/chromium/subtle-link-hover.png index 631dbbd1e40..ecd06bbf0f8 100644 Binary files a/components/card/test/golden/card/chromium/subtle-link-hover.png and b/components/card/test/golden/card/chromium/subtle-link-hover.png differ diff --git a/components/card/test/golden/card/chromium/subtle-link.dark.png b/components/card/test/golden/card/chromium/subtle-link.dark.png new file mode 100644 index 00000000000..e0de5b2a8cf Binary files /dev/null and b/components/card/test/golden/card/chromium/subtle-link.dark.png differ diff --git a/components/card/test/golden/card/chromium/subtle-link.png b/components/card/test/golden/card/chromium/subtle-link.png index 3623c0fe8e8..06410bca684 100644 Binary files a/components/card/test/golden/card/chromium/subtle-link.png and b/components/card/test/golden/card/chromium/subtle-link.png differ diff --git a/components/card/test/golden/card/chromium/subtle.dark.png b/components/card/test/golden/card/chromium/subtle.dark.png new file mode 100644 index 00000000000..9dd29a52afa Binary files /dev/null and b/components/card/test/golden/card/chromium/subtle.dark.png differ diff --git a/components/card/test/golden/card/chromium/subtle.png b/components/card/test/golden/card/chromium/subtle.png index 3a3b5cec2f4..c24890165cc 100644 Binary files a/components/card/test/golden/card/chromium/subtle.png and b/components/card/test/golden/card/chromium/subtle.png differ diff --git a/components/card/test/golden/card/chromium/with-dropdown-adjacent-hover.png b/components/card/test/golden/card/chromium/with-dropdown-adjacent-hover.png index e8e8298d3c9..93170943b62 100644 Binary files a/components/card/test/golden/card/chromium/with-dropdown-adjacent-hover.png and b/components/card/test/golden/card/chromium/with-dropdown-adjacent-hover.png differ diff --git a/components/colors/colors.js b/components/colors/colors.js index dea7734c376..188c96739b5 100644 --- a/components/colors/colors.js +++ b/components/colors/colors.js @@ -114,6 +114,7 @@ const lightVariables = new Map([ ['--d2l-theme-backdrop-background-color', '--d2l-color-regolith'], ['--d2l-theme-backdrop-opacity', '0.7'], ['--d2l-theme-backdrop-dialog-color', '#ffffff'], + ['--d2l-theme-background-color-face', 'var(--d2l-color-gypsum)'], ['--d2l-theme-background-color-interactive-faint-disabled', '#f9fbff80'], /* --d2l-theme-background-color-interactive-faint-default at 50% opacity, remove once color-mix is widely supported */ ['--d2l-theme-badge-background-color', '--d2l-color-gypsum'], ['--d2l-theme-badge-text-color', '--d2l-theme-text-color-static-standard'], @@ -194,6 +195,7 @@ const darkVariables = new Map([ ['--d2l-theme-backdrop-background-color', '--d2l-color-ferrite'], ['--d2l-theme-backdrop-opacity', '0.7'], ['--d2l-theme-backdrop-dialog-color', '#ffffff'], + ['--d2l-theme-background-color-face', '#303335'], ['--d2l-theme-background-color-interactive-faint-disabled', '#20212280'], /* --d2l-theme-background-color-interactive-faint-default at 50% opacity, remove once color-mix is widely supported */ ['--d2l-theme-badge-background-color', '#303335'], ['--d2l-theme-badge-text-color', '--d2l-theme-text-color-static-standard'], diff --git a/helpers/internal/css.js b/helpers/internal/css.js index e7231ed9cba..dcc515b0244 100644 --- a/helpers/internal/css.js +++ b/helpers/internal/css.js @@ -14,3 +14,22 @@ export function _isValidCssSelector(selector) { const allValid = parts.every(part => partIsValid(part)); return allValid; } + +export function _registerCustomSemanticVariableValue(name, lightValue, darkValue) { + const style = globalThis.document?.head.querySelector('#d2l-colors'); + if (!style) throw new Error('Colors stylesheet not found, make sure to properly import colors.js'); + if (!name || !_isValidCssValue(lightValue) || !_isValidCssValue(darkValue)) { + throw new TypeError('_registerCustomSemanticVariableValue requires a name, lightValue, and darkValue'); + } + const lightRule = style.sheet.cssRules[0]; + const darkRule = style.sheet.cssRules[1]; + const osRule = style.sheet.cssRules[2].cssRules[0]; + + lightRule.style.setProperty(name, lightValue); + darkRule.style.setProperty(name, darkValue); + osRule.style.setProperty(name, darkValue); +} + +function _isValidCssValue(value) { + return (typeof value === 'string') || typeof (value?.cssText) === 'string'; +}