+
+
+
+
+
+
+
+ Lorem
+ Ipsum
+ Dolor
+
+
+
+
+
+
+
+
+
+ Active
+ Establishing
+ Pending
+ Failing
+
+
+
+ {{/if}}
+
+ {{#if @text}}
+ {{@text}}
+ {{else}}
+ {{yield}}
+ {{/if}}
+
+ ;
+
+export default CodeFragmentWithThemingBasicContainer;
diff --git a/showcase/app/components/page-foundations/theming/index.gts b/showcase/app/components/page-foundations/theming/index.gts
new file mode 100644
index 00000000000..d0fc53f4c87
--- /dev/null
+++ b/showcase/app/components/page-foundations/theming/index.gts
@@ -0,0 +1,32 @@
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+import { pageTitle } from 'ember-page-title';
+
+import ShwTextH1 from 'showcase/components/shw/text/h1';
+import ShwDivider from 'showcase/components/shw/divider';
+
+import SubSectionThemeSwitcher from 'showcase/components/page-foundations/theming/sub-sections/theme-switcher';
+import SubSectionContexts from 'showcase/components/page-foundations/theming/sub-sections/contexts';
+import SubSectionComponents from 'showcase/components/page-foundations/theming/sub-sections/components';
+import SubSectionDemo from 'showcase/components/page-foundations/theming/sub-sections/demo';
+
+const ThemingIndex: TemplateOnlyComponent =
+ {{pageTitle "Theming"}}
+
+
+
+
+
+
+ System
+ Dark
+ Light
+
+
+
+ Changelog
+
+
+
+
+
+
+
+
+ System
+ Dark
+ Light
+
+
+
+ Changelog
+
+
+
+ foreground-strong
+ / background
+ surface-strong
.hds-theme-light
class
+
+
+ .hds-theme-dark
class
+
+
+ .hds-theme-light
+ >
+ .hds-theme-dark
+
+
+
+
+
+
+ .hds-theme-dark
+ >
+ .hds-theme-light
+
+
+
+
+
+
+ .hds-theme-dark
+ >
+ .hds-theme-light
+ >
+ .hds-theme-dark
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/showcase/app/components/shw/theme-switcher/index.gts b/showcase/app/components/shw/theme-switcher/index.gts
new file mode 100644
index 00000000000..72964641168
--- /dev/null
+++ b/showcase/app/components/shw/theme-switcher/index.gts
@@ -0,0 +1,161 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { service } from '@ember/service';
+import { guidFor } from '@ember/object/internals';
+
+import ShwThemeSwitcherPopover from './popover';
+import ShwThemeSwitcherSelector from './selector';
+import type { OnApplyArgs } from './popover';
+import type { OnSelectThemeArgs } from './selector';
+
+import config from 'showcase/config/environment';
+import { HdsIcon } from '@hashicorp/design-system-components/components';
+import {
+ HdsThemeValues,
+ HdsModesLightValues,
+ HdsModesDarkValues,
+ HdsCssSelectorsValues,
+ // DEFAULT_THEMING_OPTIONS,
+} from '@hashicorp/design-system-components/services/hds-theming';
+import type HdsThemingService from '@hashicorp/design-system-components/services/hds-theming';
+import type {
+ HdsThemes,
+ HdsModesLight,
+ HdsModesDark,
+ HdsCssSelectors,
+ // HdsThemingServiceOptions,
+} from '@hashicorp/design-system-components/services/hds-theming';
+
+const updatePageStylesheet = (currentStylesheet: string) => {
+ let newStylesheet;
+ switch (currentStylesheet) {
+ case 'prefers-color-scheme':
+ // themed CSS where theming is applied via `@media(prefers-color-scheme)`
+ newStylesheet =
+ 'assets/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css';
+ break;
+ case 'css-selectors':
+ // themed CSS where theming is applied via CSS selectors
+ newStylesheet =
+ 'assets/styles/@hashicorp/design-system-components-theming-with-css-selectors.css';
+ break;
+ case 'combined-strategies':
+ // this is used for local testing purposes
+ newStylesheet =
+ 'assets/styles/@hashicorp/design-system-components-theming-with-combined-strategies.css';
+ break;
+ default:
+ // this is the standard CSS for HDS components, without any theming
+ newStylesheet = 'assets/styles/@hashicorp/design-system-components.css';
+ break;
+ }
+
+ // re-assign the stylesheet `href` attribute
+ const hdsComponentsStylesheet = document.getElementById(
+ 'hds-components-stylesheet',
+ );
+ if (hdsComponentsStylesheet) {
+ hdsComponentsStylesheet.setAttribute(
+ 'href',
+ `${config.rootURL}${newStylesheet}`,
+ );
+ }
+};
+
+export default class ShwThemeSwitcher extends Component {
+ @service declare readonly hdsTheming: HdsThemingService;
+
+ @tracked currentStylesheet = 'standard';
+ @tracked currentTheme: HdsThemes = undefined;
+ @tracked currentLightTheme: HdsModesLight = HdsModesLightValues.CdsG0;
+ @tracked currentDarkTheme: HdsModesDark = HdsModesDarkValues.CdsG100;
+ @tracked currentCssSelector: HdsCssSelectors = HdsCssSelectorsValues.Data;
+
+ popoverId = `shw-theming-options-popover-${guidFor(this)}`;
+
+ onSelectPageTheme = (args: OnSelectThemeArgs) => {
+ const { currentStylesheet, currentTheme } = args;
+
+ console.log(
+ 'onSelectPageTheme invoked',
+ `currentStylesheet=${currentStylesheet}`,
+ `currentTheme=${currentTheme}`,
+ );
+
+ // update the theming preferences
+ this.currentStylesheet = currentStylesheet;
+ this.currentTheme = currentTheme;
+
+ // update the page's stylesheet
+ updatePageStylesheet(this.currentStylesheet);
+
+ // we set the theme in the global service
+ this.hdsTheming.setTheme(this.currentTheme);
+
+ // we set the theme for the showcase itself
+ const rootElement = document.querySelector('html');
+ if (rootElement) {
+ if (this.currentTheme) {
+ rootElement.setAttribute('data-shw-theme', this.currentTheme);
+ } else {
+ rootElement.removeAttribute('data-shw-theme');
+ }
+ }
+ };
+
+ onApplyAdvancedThemingPreferences = (args: OnApplyArgs) => {
+ const { currentLightTheme, currentDarkTheme, currentCssSelector } = args;
+
+ console.log(
+ 'onApplyAdvancedThemingPreferences invoked',
+ `currentLightTheme=${currentLightTheme}`,
+ `currentDarkTheme=${currentDarkTheme}`,
+ `currentCssSelector=${currentCssSelector}`,
+ );
+
+ // update the theming preferences
+ this.currentLightTheme = currentLightTheme;
+ this.currentDarkTheme = currentDarkTheme;
+ this.currentCssSelector = currentCssSelector;
+
+ // update the theming options in the global service
+ this.hdsTheming.setThemingServiceOptions({
+ themeMap: {
+ [HdsThemeValues.Light]: this.currentLightTheme,
+ [HdsThemeValues.Dark]: this.currentDarkTheme,
+ },
+ cssSelector: this.currentCssSelector,
+ });
+ };
+
+
+
+
+
+
+
+
+}
diff --git a/showcase/app/components/shw/theme-switcher/popover.gts b/showcase/app/components/shw/theme-switcher/popover.gts
new file mode 100644
index 00000000000..5e2ca63551b
--- /dev/null
+++ b/showcase/app/components/shw/theme-switcher/popover.gts
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { on } from '@ember/modifier';
+import { hash, fn } from '@ember/helper';
+import type Owner from '@ember/owner';
+
+import ShwThemeSwitcherControlSelect from './control/select';
+
+import {
+ MODES_LIGHT,
+ MODES_DARK,
+} from '@hashicorp/design-system-components/services/hds-theming';
+import type {
+ HdsModesLight,
+ HdsModesDark,
+ HdsCssSelectors,
+} from '@hashicorp/design-system-components/services/hds-theming';
+
+export interface OnApplyArgs {
+ currentLightTheme: HdsModesLight;
+ currentDarkTheme: HdsModesDark;
+ currentCssSelector: HdsCssSelectors;
+}
+
+export interface ShwThemeSwitcherPopoverSignature {
+ Args: {
+ popoverId: string;
+ currentLightTheme: HdsModesLight;
+ currentDarkTheme: HdsModesDark;
+ currentCssSelector: HdsCssSelectors;
+ onApply: (args: OnApplyArgs) => void;
+ };
+ Element: HTMLDivElement;
+}
+
+export default class ShwThemeSwitcherPopover extends Component
+
+
+}
diff --git a/showcase/app/components/shw/theme-switcher/selector.gts b/showcase/app/components/shw/theme-switcher/selector.gts
new file mode 100644
index 00000000000..3b40e0c0faa
--- /dev/null
+++ b/showcase/app/components/shw/theme-switcher/selector.gts
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { eq } from 'ember-truth-helpers';
+import type Owner from '@ember/owner';
+
+import ShwThemeSwitcherControlSelect from './control/select';
+
+import type {
+ HdsModesLight,
+ HdsModesDark,
+ HdsThemes,
+} from '@hashicorp/design-system-components/services/hds-theming';
+
+export interface ShwThemeSwitcherSelectorSignature {
+ Args: {
+ currentStylesheet: string;
+ currentTheme: HdsThemes;
+ currentLightTheme: HdsModesLight;
+ currentDarkTheme: HdsModesDark;
+ onSelectTheme?: (args: OnSelectThemeArgs) => void;
+ };
+ Element: HTMLDivElement;
+}
+
+export interface OnSelectThemeArgs {
+ currentStylesheet: string;
+ currentTheme: HdsThemes;
+}
+
+export default class ShwThemeSwitcherSelector extends ComponentAdvanced options
+You can change what + modes are used for the light/dark themes, and what CSS selector is used + to apply the mode to the page:
+
+
+
+
+
+
+
+
+
+
+ Components showcase
+
+
+