Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
ab6700c
added `Hds::ThemeSwitcher` component
didoo Sep 30, 2025
6d6d7ca
added `Hds::Theming` service
didoo Sep 30, 2025
57ecc17
added theming to the Showcase itself (and replaced hardcoded values w…
didoo Sep 30, 2025
4b2549e
added `Shw::ThemeSwitcher` component for showcase
didoo Sep 30, 2025
6746107
updated `Mock::App` and added new yielded sub-components
didoo Sep 30, 2025
55a9491
added `Shw:: ThemeSwitcher` to the Showcase page header
didoo Sep 30, 2025
4b48670
added `foundations/theming` showcase page (and a frameless demo)
didoo Sep 30, 2025
af67d84
refactored `hds-theming` service to align with the new themes/modes a…
didoo Oct 1, 2025
0e46e57
added `hdsTheming` initialization to main showcase app
didoo Oct 1, 2025
cbca213
removed compilation of components Scss and replaced it with static in…
didoo Oct 3, 2025
aac4323
added theming options via popover - part 1
didoo Oct 3, 2025
d77b8ac
added theming options via popover - part 2
didoo Oct 3, 2025
dcc0b6b
added theming options via popover - part 3
didoo Oct 3, 2025
aced362
added theming options via popover - part 4
didoo Oct 4, 2025
ae0d11c
added theming options via popover - part 5
didoo Oct 6, 2025
a817eb6
big code refactoring for the theme selector, to streamline user selec…
didoo Oct 6, 2025
cf7ed9f
updated logic that sets the theming for the showcase itself (without …
didoo Oct 7, 2025
ee7d8bc
small fixes here and there for cleanup and linting
didoo Oct 10, 2025
e207156
fixed issue with `pnpm lint:format` (missing newline at the end of `p…
didoo Oct 10, 2025
66eeaa4
fixed accessibility issue in `advanced-table` page, due to changes to…
didoo Oct 10, 2025
763fdcf
fixed typescript error due to new mock page being added
didoo Oct 10, 2025
84ffcba
added fix for tests failing
didoo Oct 13, 2025
7fc5b11
started large refactoring/rewrite of the theming switcher and page in…
didoo Oct 14, 2025
deafaf5
updated logic by creating a `shwTheming` service that extends `hdsThe…
didoo Oct 15, 2025
35bc27b
moved theming logic from `ShwThemeSwitcher` component/subcomponents t…
didoo Oct 15, 2025
d8a629c
updated reference CSS files to follow new theming approach/logic
didoo Oct 16, 2025
352764b
further refactoring/rewriting of theming logic
didoo Oct 16, 2025
ac06c81
updated approach to `light/dark` styles in showcase by using the HDS …
didoo Oct 17, 2025
1ba1a2d
migrated back the `Contextual` demo content to the index page
didoo Oct 17, 2025
0e0d261
added a `DebuggingPanel` to the `ShwThemeSwitcher` controls
didoo Oct 17, 2025
3c26aea
refactored/improved `DebuggingPanel` and added new preferences to adv…
didoo Oct 17, 2025
2974fba
small cleanups and refactorings
didoo Oct 17, 2025
811cfd0
fixed small issue with `ShwThemeSwitcher` selector
didoo Oct 20, 2025
8bb238d
removed some outdated comments
didoo Oct 20, 2025
63af275
small refactorings
didoo Oct 20, 2025
df426e2
added local storage support for theming options
didoo Oct 20, 2025
4ffc477
big refactoring of the `hdsTheming` service to simplify logic and red…
didoo Oct 20, 2025
59d5a82
cleanup of debugging comments and other stuff
didoo Oct 20, 2025
a6d7ebd
refactor and cleanup in preparation for PR review
didoo Oct 21, 2025
e5573d2
refactored code to fix logic flow for theming initialization
didoo Oct 21, 2025
1162e09
fixed how the theming options were saved in local storage
didoo Oct 21, 2025
08409e0
Apply suggestions from Copilot's code review
didoo Oct 21, 2025
3f3138a
fixed issue with `setTheme` not being passed `options` by the `ShwThe…
didoo Oct 22, 2025
658922b
fix issue with the popover of the ShwThemeSwitcher component, where t…
didoo Oct 22, 2025
f849855
Update showcase/app/services/shw-theming.ts
didoo Oct 23, 2025
4a14421
small tweak to the typing of `HdsModes` per code review suggestion
didoo Oct 23, 2025
b3a1c0e
updated how the CSS files (tokens and components, with/without themin…
didoo Oct 24, 2025
8ff9558
updated logic for styleshet switching using the `disabled` attribute
didoo Oct 24, 2025
413510a
removed unused import
didoo Oct 24, 2025
ff19bb7
removed `isInitialized` logic from the `hdeTheming` service to avoid bug
didoo Oct 24, 2025
91ddbd7
TEMP - added temporary `hds-theme-light/dark` selectors
didoo Oct 24, 2025
2fab643
TEMP - Added back custom token values for testing purpose
didoo Oct 24, 2025
deab041
fixed small issue with the `HdsThemeSwitcher` components used in the …
didoo Oct 29, 2025
79aa445
added small comment
didoo Oct 29, 2025
d9fd100
updated `hdsTheming` service to support `default` theme / mode
didoo Nov 7, 2025
fcb145b
added support for `default` option to HDS ThemeSwitcher component
didoo Nov 7, 2025
1086033
Updated β€œfoundations/theming” showcase page to include variants of HD…
didoo Nov 7, 2025
8cdeb0b
updated Showcase ThemeSwitcher to use ``default` as theme option
didoo Nov 7, 2025
6bc8726
updated logic for how CSS selectors are applied to the `html:root` el…
didoo Nov 7, 2025
6beef64
updated CSS selectors for local `public/assets` themed tokens CSS fil…
didoo Nov 7, 2025
549f2bb
added fake theming for display/text typography to `public/assets` the…
didoo Nov 7, 2025
f710b0b
updated β€œfoundations/theming” showcase page to include `default` and …
didoo Nov 7, 2025
45fef94
implemented `ThemeContex` component
didoo Nov 13, 2025
77ec00b
added demos of `ThemeContext` component to showcase β€œfoundations/them…
didoo Nov 13, 2025
531ea7b
improved type definitions for ThemeContext and showcase β€œfoundations/…
didoo Nov 13, 2025
f9087dd
refactored how CSS selectors are applied to enable mode-specific over…
didoo Nov 14, 2025
d51a4d7
updated CSS selectors for local `public/assets` themed tokens CSS fil…
didoo Nov 14, 2025
dd4255d
updated `ThemeContext` to use a more generic `context` argument
didoo Nov 14, 2025
7b166b0
updated showcase β€œtheming” page to use the new `@context` argument fo…
didoo Nov 14, 2025
a0ed075
finally defined proper typing for `ThemeContext` component
didoo Nov 14, 2025
71588fb
refactored showcase code to remove handling of `[data-hds-theme]` CSS…
didoo Nov 17, 2025
74cf9b5
updated CSS selectors for local `public/assets` themed tokens CSS fil…
didoo Nov 18, 2025
7cfccbf
refactored theme switching in showcase to use new CSS files
didoo Nov 18, 2025
c2d12f7
updated theme switcher in showcase to allow toggling of the β€œadvanced…
didoo Nov 18, 2025
1946dfd
introduced a β€œcarbonization” mixin for applying styles only for certa…
didoo Nov 19, 2025
65c08ef
added subtle shadow to `ThemingBasicContainer`
didoo Nov 19, 2025
ee26327
fixed small bug that would cause the showcase pages to crash if the v…
didoo Nov 19, 2025
9bed043
small fix to the control logic for the `HdsThemeSwitcher` demo in sho…
didoo Nov 18, 2025
ed980d8
fixed TypeScript issue
didoo Nov 20, 2025
9bc31cd
fix small bug in the logic when the β€œapply” with β€œshow advanced optio…
didoo Nov 20, 2025
a9239d2
added `ShwBodyLinkToRoute` component
didoo Nov 20, 2025
318c915
replaced custom link in AdvancedTable showcase page with newly create…
didoo Nov 20, 2025
aad753f
reworked the demo frameless for application with theme switcher to av…
didoo Nov 20, 2025
d80eaac
replaced custom theme switcher with proper `HdsThemeSwitcher` in `App…
didoo Nov 21, 2025
34c5e91
some cleanup before code review
didoo Nov 21, 2025
a89edd6
changed how theming is applied to the showcase itself, to limit `pref…
didoo Nov 25, 2025
016918f
fixed wrong CSS selector, per code review suggestion
didoo Nov 25, 2025
f2193d9
prefixed `OnSetThemeCallback` with `Hds` per review suggestion
didoo Nov 25, 2025
e10494b
Update packages/components/src/template-registry.ts
didoo Nov 25, 2025
4c76fe9
converted `updatePageStylesheets` function to a private method
didoo Nov 26, 2025
2688039
small cleanup per code reviews suggestions
didoo Nov 26, 2025
ae0c48a
small fixes per code review
didoo Nov 28, 2025
0219437
updated logic that reads the stored theming data for the `HdsThemingS…
didoo Nov 28, 2025
a736ccf
removed comment
didoo Dec 2, 2025
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: 3 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@
"./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.js": "./dist/_app_/components/hds/text.js",
"./components/hds/theme-context.js": "./dist/_app_/components/hds/theme-context.js",
"./components/hds/theme-switcher.js": "./dist/_app_/components/hds/theme-switcher.js",
"./components/hds/time.js": "./dist/_app_/components/hds/time.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 Down Expand Up @@ -397,6 +399,7 @@
"./modifiers/hds-register-event.js": "./dist/_app_/modifiers/hds-register-event.js",
"./modifiers/hds-tooltip.js": "./dist/_app_/modifiers/hds-tooltip.js",
"./services/hds-intl.js": "./dist/_app_/services/hds-intl.js",
"./services/hds-theming.js": "./dist/_app_/services/hds-theming.js",
"./services/hds-time.js": "./dist/_app_/services/hds-time.js"
}
},
Expand Down
6 changes: 6 additions & 0 deletions packages/components/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ export { default as HdsTextCode } from './components/hds/text/code.ts';
export { default as HdsTextDisplay } from './components/hds/text/display.ts';
export * from './components/hds/text/types.ts';

// Theme Context
export { default as HdsThemeContext } from './components/hds/theme-context/index.ts';

// Theme Switcher
export { default as HdsThemeSwitcher } from './components/hds/theme-switcher/index.ts';

// Time
export { default as HdsTime } from './components/hds/time/index.ts';
export { default as HdsTimeSingle } from './components/hds/time/single.ts';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
<div class={{this.classNames}} ...attributes>{{yield}}</div>
69 changes: 69 additions & 0 deletions packages/components/src/components/hds/theme-context/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { assert } from '@ember/debug';
import type Owner from '@ember/owner';

import {
HdsThemeContextThemesValues,
HdsThemeContextModesValues,
} from './types.ts';
import type { HdsThemeContexts } from './types.ts';

import type { HdsThemes, HdsModes } from '../../../services/hds-theming.ts';

export interface HdsThemeContextSignature {
Args: {
// can be either an `HdsTheme` or an `HdsMode`
context: HdsThemeContexts;
};
Blocks: {
default: [];
};
Element: HTMLElement;
}

export const CONTEXTUAL_THEMES: HdsThemes[] = Object.values(
HdsThemeContextThemesValues
);
export const CONTEXTUAL_MODES: HdsModes[] = Object.values(
HdsThemeContextModesValues
);
export const CONTEXTUAL_VALUES: HdsThemeContexts[] = [
...CONTEXTUAL_THEMES,
...CONTEXTUAL_MODES,
];

export default class HdsThemeContext extends Component<HdsThemeContextSignature> {
constructor(owner: Owner, args: HdsThemeContextSignature['Args']) {
super(owner, args);

const { context } = args;

assert(
`@context for "Hds::ThemeContext" must be one of the following: ${CONTEXTUAL_VALUES.join(
', '
)}; received: ${context}`,
CONTEXTUAL_VALUES.includes(context)
);
}

// Get the class names to apply to the component.
get classNames(): string {
const classes = ['hds-theme-context'];

const { context } = this.args;

// add "theme" or "mode" classes based on the @context arguments
if (CONTEXTUAL_THEMES.includes(context as HdsThemes)) {
classes.push(`hds-theme-${context}`);
} else if (CONTEXTUAL_MODES.includes(context as HdsModes)) {
classes.push(`hds-mode-${context}`);
}

return classes.join(' ');
}
}
32 changes: 32 additions & 0 deletions packages/components/src/components/hds/theme-context/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import {
HdsThemeValues,
HdsModesLightValues,
HdsModesDarkValues,
} from '../../../services/hds-theming.ts';

import type { HdsThemes, HdsModes } from '../../../services/hds-theming.ts';

// re-export the enum values for the `HdsThemes` to use in the component
// note: using `as const` ensures Object.values() returns only the values (not keys _and_ values)
export const HdsThemeContextThemesValues = {
Default: HdsThemeValues.Default,
System: HdsThemeValues.System,
Light: HdsThemeValues.Light,
Dark: HdsThemeValues.Dark,
} as const;

// re-export the enum values for the `HdsModes` to use in the component
// note: using `as const` ensures Object.values() returns only the values (not keys _and_ values)
export const HdsThemeContextModesValues = {
CdsG0: HdsModesLightValues.CdsG0,
CdsG10: HdsModesLightValues.CdsG10,
CdsG90: HdsModesDarkValues.CdsG90,
CdsG100: HdsModesDarkValues.CdsG100,
} as const;

export type HdsThemeContexts = HdsThemes | Exclude<HdsModes, 'default'>;
29 changes: 29 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,29 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}

{{!
------------------------------------------------------------------------------------------
IMPORTANT: this is a temporary implementation, while we wait for the design specifications
------------------------------------------------------------------------------------------
}}

<Hds::Dropdown
@enableCollisionDetection={{true}}
@matchToggleWidth={{@toggleIsFullWidth}}
class="hds-theme-switcher-control"
...attributes
as |D|
>
<D.ToggleButton
@color="secondary"
@size={{this.toggleSize}}
@isFullWidth={{this.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.onSelectTheme data.theme)}}>{{data.label}}</D.Interactive>
{{/each-in}}
</Hds::Dropdown>
108 changes: 108 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,108 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

// ------------------------------------------------------------------------------------------
// IMPORTANT: this is a temporary implementation, while we wait for the design specifications
// ------------------------------------------------------------------------------------------

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 { HdsIconSignature } from '../icon/index.ts';
import type HdsThemingService from '../../../services/hds-theming.ts';
import type {
HdsThemes,
HdsOnSetThemeCallback,
} from '../../../services/hds-theming.ts';

interface ThemeOption {
theme: HdsThemes | undefined;
icon: HdsIconSignature['Args']['name'];
label: string;
}

const OPTIONS: Record<HdsThemes, ThemeOption> = {
default: { theme: 'default', icon: 'hashicorp', label: 'Default' },
system: { theme: 'system', icon: 'monitor', label: 'System' },
light: { theme: 'light', icon: 'sun', label: 'Light' },
dark: { theme: 'dark', icon: 'moon', label: 'Dark' },
};

export interface HdsThemeSwitcherSignature {
Args: {
toggleSize?: HdsDropdownToggleButtonSignature['Args']['size'];
toggleIsFullWidth?: HdsDropdownToggleButtonSignature['Args']['isFullWidth'];
hasDefaultOption?: boolean;
hasSystemOption?: boolean;
onSetTheme?: HdsOnSetThemeCallback;
};
Element: HdsDropdownSignature['Element'];
}

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

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

get toggleIsFullWidth() {
return this.args.toggleIsFullWidth ?? false;
}

get toggleContent() {
if (
(this.currentTheme === 'default' && this.hasDefaultOption) ||
(this.currentTheme === 'system' && this.hasSystemOption) ||
this.currentTheme === 'light' ||
this.currentTheme === 'dark'
) {
return {
label: OPTIONS[this.currentTheme].label,
icon: OPTIONS[this.currentTheme].icon,
};
} else {
return { label: 'Theme', icon: undefined };
}
}

// note: we will use the `default` option in development, while migrating to the `cds` theming
// during this process, consumers will enable/disable this option via code logic or feature flag
get hasDefaultOption() {
return this.args.hasDefaultOption ?? false;
}

get hasSystemOption() {
return this.args.hasSystemOption ?? true;
}

get _options() {
const options: Partial<typeof OPTIONS> = { ...OPTIONS };

if (!this.hasDefaultOption) {
delete options.default;
}

if (!this.hasSystemOption) {
delete options.system;
}

return options;
}

get currentTheme() {
// we get the theme from the global service
return this.hdsTheming.currentTheme;
}

@action
onSelectTheme(theme: HdsThemes | undefined): void {
// we set the theme in the global service (and provide an optional user-defined callback)
this.hdsTheming.setTheme({ theme, onSetTheme: this.args.onSetTheme });
}
}
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';
Loading