Skip to content

Commit b73dbf9

Browse files
committed
PORTING OF SHOWCASE THEMING SQUASHED
1 parent 519a6a6 commit b73dbf9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+20576
-120
lines changed

packages/components/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@
367367
"./components/hds/text/code.js": "./dist/_app_/components/hds/text/code.js",
368368
"./components/hds/text/display.js": "./dist/_app_/components/hds/text/display.js",
369369
"./components/hds/text.js": "./dist/_app_/components/hds/text.js",
370+
"./components/hds/theme-switcher.js": "./dist/_app_/components/hds/theme-switcher.js",
370371
"./components/hds/time.js": "./dist/_app_/components/hds/time.js",
371372
"./components/hds/time/range.js": "./dist/_app_/components/hds/time/range.js",
372373
"./components/hds/time/single.js": "./dist/_app_/components/hds/time/single.js",
@@ -395,6 +396,7 @@
395396
"./modifiers/hds-register-event.js": "./dist/_app_/modifiers/hds-register-event.js",
396397
"./modifiers/hds-tooltip.js": "./dist/_app_/modifiers/hds-tooltip.js",
397398
"./services/hds-intl.js": "./dist/_app_/services/hds-intl.js",
399+
"./services/hds-theming.js": "./dist/_app_/services/hds-theming.js",
398400
"./services/hds-time.js": "./dist/_app_/services/hds-time.js"
399401
}
400402
},
@@ -425,4 +427,4 @@
425427
"engines": {
426428
"node": ">= 18"
427429
}
428-
}
430+
}

packages/components/rollup.config.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ const plugins = [
2323
'index.js',
2424
'template-registry.js',
2525
'styles/@hashicorp/design-system-components.scss',
26+
// TODO they're added to the main CSS file, unfortunately → discuss with Alex what we can do
27+
// 'styles/@hashicorp/design-system-components--themed-with-prefers-color-scheme.scss',
28+
// 'styles/@hashicorp/design-system-components--themed-with-css-selectors.scss',
2629
]),
2730

2831
// These are the modules that should get reexported into the traditional
@@ -57,6 +60,31 @@ const plugins = [
5760
],
5861
}),
5962

63+
// TODO they're added to the main CSS file, unfortunately → discuss with Alex what we can do
64+
// scss({
65+
// fileName:
66+
// 'styles/@hashicorp/design-system-components--themed-with-prefers-color-scheme.css',
67+
// includePaths: [
68+
// '../../node_modules/@hashicorp/design-system-tokens/dist/products/css',
69+
// ],
70+
// }),
71+
// scss({
72+
// fileName:
73+
// 'styles/@hashicorp/design-system-components--themed-with-css-selectors.css',
74+
// includePaths: [
75+
// '../../node_modules/@hashicorp/design-system-tokens/dist/products/css',
76+
// ],
77+
// }),
78+
// TODO let's try this workaround...
79+
scss({
80+
fileName:
81+
'styles/@hashicorp/design-system-components--themed-with-prefers-color-scheme.css',
82+
}),
83+
scss({
84+
fileName:
85+
'styles/@hashicorp/design-system-components--themed-with-css-selectors.css',
86+
}),
87+
6088
scss({
6189
fileName: 'styles/@hashicorp/design-system-power-select-overrides.css',
6290
}),
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{{!
2+
Copyright (c) HashiCorp, Inc.
3+
SPDX-License-Identifier: MPL-2.0
4+
}}
5+
6+
<Hds::Dropdown @enableCollisionDetection={{true}} @matchToggleWidth={{@toggleIsFullWidth}} class="hds-theme-switcher-control" ...attributes as |D|>
7+
<D.ToggleButton @color="secondary" @size={{this.toggleSize}} @isFullWidth={{@toggleIsFullWidth}} @text={{this.toggleContent.label}} @icon={{this.toggleContent.icon}} />
8+
{{#each-in this._options as |key data|}}
9+
<D.Interactive @icon={{data.icon}} {{on "click" (fn this.setTheme data.theme)}}>{{data.label}}</D.Interactive>
10+
{{/each-in}}
11+
</Hds::Dropdown>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
import Component from '@glimmer/component';
7+
import { inject as service } from '@ember/service';
8+
import { action } from '@ember/object';
9+
10+
import type { HdsDropdownSignature } from '../dropdown/index.ts';
11+
import type { HdsDropdownToggleButtonSignature } from '../dropdown/toggle/button.ts';
12+
import type HdsThemingService from '../../../services/hds-theming.ts';
13+
import { type HdsThemes } from '../../../services/hds-theming.ts';
14+
15+
export const OPTIONS = {
16+
none: { theme: undefined, icon: 'minus', label: 'None' },
17+
system: { theme: 'system', icon: 'monitor', label: 'System' },
18+
light: { theme: 'light', icon: 'sun', label: 'Light' },
19+
dark: { theme: 'dark', icon: 'moon', label: 'Dark' },
20+
} as const;
21+
22+
export interface HdsThemeSwitcherSignature {
23+
Args: {
24+
toggleSize?: HdsDropdownToggleButtonSignature['Args']['size'];
25+
toggleIsFullWidth?: boolean;
26+
};
27+
Element: HdsDropdownSignature['Element'];
28+
}
29+
30+
export default class HdsThemeSwitcher extends Component<HdsThemeSwitcherSignature> {
31+
@service declare readonly hdsTheming: HdsThemingService;
32+
33+
_options = OPTIONS;
34+
35+
get toggleSize() {
36+
return this.args.toggleSize ?? 'small';
37+
}
38+
39+
get toggleContent() {
40+
switch (this.currentTheme) {
41+
case 'system':
42+
case 'light':
43+
case 'dark':
44+
return {
45+
label: OPTIONS[this.currentTheme].label,
46+
icon: OPTIONS[this.currentTheme].icon,
47+
};
48+
case undefined:
49+
default:
50+
return { label: 'Theme', icon: undefined };
51+
}
52+
}
53+
54+
get currentTheme() {
55+
return this.hdsTheming.currentTheme;
56+
}
57+
58+
@action
59+
setTheme(theme: HdsThemes): void {
60+
// we set the theme in the global service
61+
this.hdsTheming.setTheme(theme);
62+
}
63+
}

packages/components/src/services.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
*/
55

66
// This file is used to expose public services
7+
8+
export * from './services/hds-theming.ts';
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import Service from '@ember/service';
2+
import { tracked } from '@glimmer/tracking';
3+
4+
import type Owner from '@ember/owner';
5+
6+
export const LOCALSTORAGE_KEY = 'hds-current-theme';
7+
8+
export enum HdsThemeValues {
9+
System = 'system',
10+
Light = 'light',
11+
Dark = 'dark',
12+
}
13+
14+
export type HdsThemes = `${HdsThemeValues}` | undefined;
15+
16+
export const THEMES: string[] = Object.values(HdsThemeValues);
17+
18+
export default class HdsThemingService extends Service {
19+
@tracked currentTheme: HdsThemes = undefined;
20+
21+
constructor(owner: Owner) {
22+
super(owner);
23+
this.initializeTheme();
24+
}
25+
26+
initializeTheme() {
27+
const _initialTheme = localStorage.getItem(LOCALSTORAGE_KEY);
28+
if (
29+
_initialTheme === 'system' ||
30+
_initialTheme === 'light' ||
31+
_initialTheme === 'dark'
32+
) {
33+
this.setTheme(_initialTheme);
34+
}
35+
}
36+
37+
getTheme(): HdsThemes {
38+
return this.currentTheme;
39+
}
40+
41+
setTheme(theme: HdsThemes) {
42+
// console.log('setting HDS theme', theme);
43+
44+
if (theme === undefined) {
45+
localStorage.removeItem(LOCALSTORAGE_KEY);
46+
} else {
47+
localStorage.setItem(LOCALSTORAGE_KEY, theme);
48+
}
49+
50+
// IMPORTANT: for this to work, it needs to be the HTML tag (it's the `:root` in CSS)
51+
const rootElement = document.querySelector('html');
52+
53+
if (rootElement) {
54+
if (theme === undefined) {
55+
rootElement.removeAttribute('data-hds-theme');
56+
this.currentTheme = undefined;
57+
} else {
58+
rootElement.setAttribute('data-hds-theme', theme);
59+
this.currentTheme = theme;
60+
}
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)