Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧪 [Spike] Theming “support” in HDS and Showcase - Aggregated #2611

Draft
wants to merge 41 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f5a9427
added `build:watch` script to `tokens` package
didoo Oct 1, 2024
08fa678
updated `build` script to remove check on token category for `font-si…
didoo Oct 1, 2024
ed7feb7
enable logging
didoo Dec 6, 2024
ede6b01
renamed custom transform to avoid bug in SD
didoo Dec 10, 2024
2337a68
created folders for theming of colors
didoo Dec 11, 2024
744a698
updated build script to include by default only the light theme files
didoo Dec 10, 2024
28fc344
updated source (themed) tokens to include a `theme` attribute
didoo Dec 11, 2024
af7543f
found a scrappy but working way to generate themed CSS files
didoo Dec 11, 2024
c7c140f
generated CSS output files
didoo Dec 12, 2024
c945fc5
cherry-pick commits from `spike-showcase-theming`
didoo Nov 13, 2024
99714ac
changed `design-system-components.scss` file imports structure so the…
didoo Dec 11, 2024
3eba63d
added “themed” scss files
didoo Dec 11, 2024
8d8f68f
added `outputReferences": true` to be able to use the themed tokens
didoo Dec 11, 2024
7f946ae
replaced core palettes (“neutral” and “accents”) values with Jory’s o…
didoo Dec 12, 2024
b8bc083
regenerated design tokens output files to use dark colors from Figma
didoo Dec 12, 2024
663c644
tried to update the Rollup.js config to generate multiple CSS in outp…
didoo Dec 11, 2024
e96f274
workaround for Rollup not compiling distinct CSS in output
didoo Dec 11, 2024
5dd4754
TEMP local link to SD
didoo Dec 12, 2024
a9ceedd
removed neeed for “gap” token in Showcase
didoo Dec 12, 2024
056c125
added `hds-theming` service in HDS components
didoo Dec 16, 2024
40b4fd1
refactored generation of extra theming files to have a unified output…
didoo Dec 16, 2024
928b873
updated imported file in HDS component for tokens, to use the “unifie…
didoo Dec 16, 2024
d2ff2da
changed theming switcher logic in the showcase
didoo Dec 16, 2024
f57d360
simplified theming for showcase
didoo Dec 16, 2024
2f72cc8
fixed showcase theming page
didoo Dec 16, 2024
8c00e50
removed unused CSS variables for Showcase
didoo Dec 16, 2024
0c5f694
implemented basic HDS switcher for testing
didoo Dec 16, 2024
2b0550b
added `build:watch` command to scripts for `components` package
didoo Dec 17, 2024
37e782c
fixed Sass warnings in Showcase
didoo Dec 19, 2024
4172633
fixed declarations sorting
didoo Dec 19, 2024
d9f0075
added “demo” frameless page for theming testing
didoo Dec 17, 2024
0d41df4
renamed component file
didoo Dec 19, 2024
1e84660
showcase “theming” page improvements
didoo Dec 19, 2024
51625ca
reworked logic for HDS theming service and switcher
didoo Dec 19, 2024
6fb07bc
reworked logic for Showcase theming service and switcher
didoo Dec 19, 2024
f66abea
added missing color style in showcase `body` element
didoo Dec 19, 2024
0c44e04
added status bar in showcase theming page
didoo Dec 19, 2024
5d0b983
added section with “themed” HDS components in theming showcase page
didoo Dec 20, 2024
3c6016e
HACK workardound to support nested theming
didoo Dec 20, 2024
46e5a6a
refactored HDS theme switcher to be more similar to the one in use on…
didoo Dec 20, 2024
db5fe26
HACK fixed issue with color inheritance for the `<dialog>` component
didoo Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"packageManager": "[email protected]",
"resolutions": {
"broccoli-asset-rewrite@^2.0.0": "patch:broccoli-asset-rewrite@npm%3A2.0.0#./.yarn/patches/broccoli-asset-rewrite-npm-2.0.0-c4ce42084a.patch",
"@glint/environment-ember-loose": "patch:@glint/environment-ember-loose@npm%3A1.4.0#~/.yarn/patches/@glint-environment-ember-loose-npm-1.4.0-31c2f31bcb.patch"
"@glint/environment-ember-loose": "patch:@glint/environment-ember-loose@npm%3A1.4.0#~/.yarn/patches/@glint-environment-ember-loose-npm-1.4.0-31c2f31bcb.patch",
"style-dictionary": "portal:/Users/cristianorastelli/src/github/style-dictionary-didoo"
}
}
6 changes: 5 additions & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
"license": "MPL-2.0",
"author": "HashiCorp Design Systems <[email protected]>",
"scripts": {
"build": "concurrently 'npm:build:*'",
"build": "concurrently 'npm:build:js' 'npm:build:types'",
"build:js": "rollup --config",
"build:types": "glint --declaration",
"build:watch": "nodemon --watch '../tokens/dist/*' --ext 'css' --exec 'yarn build'",
"prepublishOnly": "yarn build && test -f 'dist/styles/@hashicorp/design-system-components.css' || (echo 'The pre-compiled CSS file was not found' && exit 1)",
"start": "concurrently 'yarn:start:*'",
"start:js": "rollup --config --watch --environment development",
Expand Down Expand Up @@ -99,6 +100,7 @@
"eslint-plugin-n": "^17.7.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-qunit": "^8.1.1",
"nodemon": "^3.1.7",
"postcss": "^8.4.47",
"prettier": "^3.3.2",
"rollup": "^4.22.4",
Expand Down Expand Up @@ -288,6 +290,7 @@
"./components/hds/text/code.js": "./dist/_app_/components/hds/text/code.js",
"./components/hds/text/display.js": "./dist/_app_/components/hds/text/display.js",
"./components/hds/text/index.js": "./dist/_app_/components/hds/text/index.js",
"./components/hds/theme-switcher/index.js": "./dist/_app_/components/hds/theme-switcher/index.js",
"./components/hds/time/index.js": "./dist/_app_/components/hds/time/index.js",
"./components/hds/time/range.js": "./dist/_app_/components/hds/time/range.js",
"./components/hds/time/single.js": "./dist/_app_/components/hds/time/single.js",
Expand All @@ -303,6 +306,7 @@
"./modifiers/hds-clipboard.js": "./dist/_app_/modifiers/hds-clipboard.js",
"./modifiers/hds-register-event.js": "./dist/_app_/modifiers/hds-register-event.js",
"./modifiers/hds-tooltip.js": "./dist/_app_/modifiers/hds-tooltip.js",
"./services/hds-theming.js": "./dist/_app_/services/hds-theming.js",
"./services/hds-time.js": "./dist/_app_/services/hds-time.js"
}
},
Expand Down
28 changes: 28 additions & 0 deletions packages/components/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const plugins = [
'index.js',
'template-registry.js',
'styles/@hashicorp/design-system-components.scss',
// TODO they're added to the main CSS file, unfortunately → discuss with Alex what we can do
// 'styles/@hashicorp/design-system-components--themed-with-prefers-color-scheme.scss',
// 'styles/@hashicorp/design-system-components--themed-with-css-selectors.scss',
]),

// These are the modules that should get reexported into the traditional
Expand Down Expand Up @@ -55,6 +58,31 @@ const plugins = [
],
}),

// TODO they're added to the main CSS file, unfortunately → discuss with Alex what we can do
// scss({
// fileName:
// 'styles/@hashicorp/design-system-components--themed-with-prefers-color-scheme.css',
// includePaths: [
// '../../node_modules/@hashicorp/design-system-tokens/dist/products/css',
// ],
// }),
// scss({
// fileName:
// 'styles/@hashicorp/design-system-components--themed-with-css-selectors.css',
// includePaths: [
// '../../node_modules/@hashicorp/design-system-tokens/dist/products/css',
// ],
// }),
// TODO let's try this workaround...
scss({
fileName:
'styles/@hashicorp/design-system-components--themed-with-prefers-color-scheme.css',
}),
scss({
fileName:
'styles/@hashicorp/design-system-components--themed-with-css-selectors.css',
}),

scss({
fileName: 'styles/@hashicorp/design-system-power-select-overrides.css',
}),
Expand Down
11 changes: 11 additions & 0 deletions packages/components/src/components/hds/theme-switcher/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}

<Hds::Dropdown @enableCollisionDetection={{true}} @matchToggleWidth={{@toggleIsFullWidth}} class="hds-theme-switcher-control" ...attributes as |D|>
<D.ToggleButton @color="secondary" @size={{this.toggleSize}} @isFullWidth={{@toggleIsFullWidth}} @text={{this.toggleContent.label}} @icon={{this.toggleContent.icon}} />
{{#each-in this._options as |key data|}}
<D.Interactive @icon={{data.icon}} {{on "click" (fn this.setTheme data.theme)}}>{{data.label}}</D.Interactive>
{{/each-in}}
</Hds::Dropdown>
63 changes: 63 additions & 0 deletions packages/components/src/components/hds/theme-switcher/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

import type { HdsDropdownSignature } from '../dropdown/index.ts';
import type { HdsDropdownToggleButtonSignature } from '../dropdown/toggle/button.ts';
import type HdsThemingService from '../../../services/hds-theming.ts';
import { type HdsThemes } from '../../../services/hds-theming.ts';

export const OPTIONS = {
none: { theme: undefined, icon: 'minus', label: 'None' },
system: { theme: 'system', icon: 'monitor', label: 'System' },
light: { theme: 'light', icon: 'sun', label: 'Light' },
dark: { theme: 'dark', icon: 'moon', label: 'Dark' },
} as const;

export interface HdsThemeSwitcherSignature {
Args: {
toggleSize?: HdsDropdownToggleButtonSignature['Args']['size'];
toggleIsFullWidth?: boolean;
};
Element: HdsDropdownSignature['Element'];
}

export default class HdsThemeSwitcher extends Component<HdsThemeSwitcherSignature> {
@service declare readonly hdsTheming: HdsThemingService;

_options = OPTIONS;

get toggleSize() {
return this.args.toggleSize ?? 'small';
}

get toggleContent() {
switch (this.currentTheme) {
case 'system':
case 'light':
case 'dark':
return {
label: OPTIONS[this.currentTheme].label,
icon: OPTIONS[this.currentTheme].icon,
};
case undefined:
default:
return { label: 'Theme', icon: undefined };
}
}

get currentTheme() {
return this.hdsTheming.currentTheme;
}

@action
setTheme(theme: HdsThemes): void {
// we set the theme in the global service
this.hdsTheming.setTheme(theme);
}
}
2 changes: 2 additions & 0 deletions packages/components/src/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
*/

// This file is used to expose public services

export * from './services/hds-theming.ts';
61 changes: 61 additions & 0 deletions packages/components/src/services/hds-theming.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';

export const LOCALSTORAGE_KEY = 'hds-current-theme';

export enum HdsThemeValues {
System = 'system',
Light = 'light',
Dark = 'dark',
}

export type HdsThemes = `${HdsThemeValues}` | undefined;

export const THEMES: string[] = Object.values(HdsThemeValues);

export default class HdsThemingService extends Service {
@tracked currentTheme: HdsThemes = undefined;

constructor(owner: object | undefined) {
super(owner);
this.initializeTheme();
}

initializeTheme() {
const _initialTheme = localStorage.getItem(LOCALSTORAGE_KEY);
if (
_initialTheme === 'system' ||
_initialTheme === 'light' ||
_initialTheme === 'dark'
) {
this.setTheme(_initialTheme);
}
}

getTheme(): HdsThemes {
return this.currentTheme;
}

setTheme(theme: HdsThemes) {
// console.log('setting HDS theme', theme);

if (theme === undefined) {
localStorage.removeItem(LOCALSTORAGE_KEY);
} else {
localStorage.setItem(LOCALSTORAGE_KEY, theme);
}

// IMPORTANT: for this to work, it needs to be the HTML tag (it's the `:root` in CSS)
const rootElement = document.querySelector('html');

if (rootElement) {
if (theme === undefined) {
rootElement.removeAttribute('data-hds-theme');
this.currentTheme = undefined;
} else {
rootElement.setAttribute('data-hds-theme', theme);
this.currentTheme = theme;
}
}
}
}
Loading
Loading