From 5879400efdfc216de62f5bd2480e79d222ff1dbd Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 24 Sep 2025 16:21:59 +0100 Subject: [PATCH 001/139] Draft a custom plugin to compile the themed SCSS --- packages/components/rollup.config.mjs | 26 +++++++++++++++++++ ...-system-components-with-css-selectors.scss | 12 +++++++++ 2 files changed, 38 insertions(+) create mode 100644 packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index 9b83a1c23c6..5fbef1b94af 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -9,6 +9,7 @@ import copy from 'rollup-plugin-copy'; import scss from 'rollup-plugin-scss'; import process from 'process'; import path from 'node:path'; +import * as sass from 'sass'; const addon = new Addon({ srcDir: 'src', @@ -61,6 +62,31 @@ const plugins = [ fileName: 'styles/@hashicorp/design-system-power-select-overrides.css', }), + // Custom plugin to compile the themed SCSS with different include paths + { + name: 'compile-themed-scss', + generateBundle() { + // Compile the themed SCSS file + try { + const result = sass.compile('src/styles/@hashicorp/design-system-components-with-css-selectors.scss', { + // equivalent to includePaths in rollup-plugin-scss + loadPaths: [ + 'node_modules/@hashicorp/design-system-tokens/dist/products/css/themed-tokens/with-css-selectors', + ], + }); + + // Emit the compiled CSS + this.emitFile({ + type: 'asset', + fileName: 'styles/@hashicorp/design-system-components-with-css-selectors.css', + source: result.css, + }); + } catch (error) { + this.error(`Failed to compile themed SCSS: ${error.message}`); + } + }, + }, + // Ensure that standalone .hbs files are properly integrated as Javascript. addon.hbs(), diff --git a/packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss b/packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss new file mode 100644 index 00000000000..4c30f8588da --- /dev/null +++ b/packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss @@ -0,0 +1,12 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// this file comes from packages/tokens/dist/products/css/tokens.css +@use "tokens"; +@use "../mixins/screen-reader-only" as *; + +.sr-only { + @include screen-reader-only(); +} From 134affb197d08af861cf45b140f04c995a1cc7c8 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Fri, 26 Sep 2025 22:00:43 +0100 Subject: [PATCH 002/139] updated SCSS files organization for components (split common part) + added custom source files for theming + updated rollup config to process different files --- packages/components/rollup.config.mjs | 55 ++++++++++++---- ...components-theming-with-css-selectors.scss | 22 +++++++ ...nts-theming-with-prefers-color-scheme.scss | 22 +++++++ ...-system-components-with-css-selectors.scss | 12 ---- .../@hashicorp/design-system-components.scss | 65 ++++--------------- .../src/styles/components/index.scss | 52 +++++++++++++++ 6 files changed, 149 insertions(+), 79 deletions(-) create mode 100644 packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss create mode 100644 packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss delete mode 100644 packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss create mode 100644 packages/components/src/styles/components/index.scss diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index 5fbef1b94af..70b4fa29594 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -53,36 +53,65 @@ const plugins = [ scss({ fileName: 'styles/@hashicorp/design-system-components.css', - includePaths: [ - 'node_modules/@hashicorp/design-system-tokens/dist/products/css', - ], + includePaths: ['node_modules/@hashicorp/design-system-tokens/dist'], }), scss({ fileName: 'styles/@hashicorp/design-system-power-select-overrides.css', }), - // Custom plugin to compile the themed SCSS with different include paths + // Custom plugins to compile the "themed" SCSS files { - name: 'compile-themed-scss', + name: 'compile-scss-themed-with-css-selectors', generateBundle() { // Compile the themed SCSS file try { - const result = sass.compile('src/styles/@hashicorp/design-system-components-with-css-selectors.scss', { - // equivalent to includePaths in rollup-plugin-scss - loadPaths: [ - 'node_modules/@hashicorp/design-system-tokens/dist/products/css/themed-tokens/with-css-selectors', - ], + const result = sass.compile( + 'src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss', + { + // equivalent to includePaths in rollup-plugin-scss + loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], + } + ); + + // Emit the compiled CSS + this.emitFile({ + type: 'asset', + fileName: + 'styles/@hashicorp/design-system-components-theming-with-css-selectors.css', + source: result.css, }); - + } catch (error) { + this.error( + `Failed to compile themed ("with CSS selectors") SCSS: ${error.message}` + ); + } + }, + }, + { + name: 'compile-scss-themed-with-prefers-color-scheme', + generateBundle() { + // Compile the themed SCSS file + try { + const result = sass.compile( + 'src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss', + { + // equivalent to includePaths in rollup-plugin-scss + loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], + } + ); + // Emit the compiled CSS this.emitFile({ type: 'asset', - fileName: 'styles/@hashicorp/design-system-components-with-css-selectors.css', + fileName: + 'styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css', source: result.css, }); } catch (error) { - this.error(`Failed to compile themed SCSS: ${error.message}`); + this.error( + `Failed to compile themed ("with CSS selectors") SCSS: ${error.message}` + ); } }, }, diff --git a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss new file mode 100644 index 00000000000..8fb787a5541 --- /dev/null +++ b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss @@ -0,0 +1,22 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// these files come from `packages/tokens/dist/` +@use "products/css/themed-tokens/with-css-selectors/tokens.css"; +// TODO understand if these are common/shared or we should have different ones for the themed tokens +@use "products/css/helpers/color"; +@use "products/css/helpers/elevation"; +@use "products/css/helpers/focus-ring"; +@use "products/css/helpers/typography"; + +// main components file +@use "../components/index"; + +// screen-reader utility class +@use "../mixins/screen-reader-only" as *; + +.sr-only { + @include screen-reader-only(); +} diff --git a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss new file mode 100644 index 00000000000..c83e68e495b --- /dev/null +++ b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss @@ -0,0 +1,22 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// these files come from `packages/tokens/dist/` +@use "products/css/themed-tokens/with-prefers-color-scheme/tokens.css"; +// TODO understand if these are common/shared or we should have different ones for the themed tokens +@use "products/css/helpers/color"; +@use "products/css/helpers/elevation"; +@use "products/css/helpers/focus-ring"; +@use "products/css/helpers/typography"; + +// main components file +@use "../components/index"; + +// screen-reader utility class +@use "../mixins/screen-reader-only" as *; + +.sr-only { + @include screen-reader-only(); +} diff --git a/packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss b/packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss deleted file mode 100644 index 4c30f8588da..00000000000 --- a/packages/components/src/styles/@hashicorp/design-system-components-with-css-selectors.scss +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -// this file comes from packages/tokens/dist/products/css/tokens.css -@use "tokens"; -@use "../mixins/screen-reader-only" as *; - -.sr-only { - @include screen-reader-only(); -} diff --git a/packages/components/src/styles/@hashicorp/design-system-components.scss b/packages/components/src/styles/@hashicorp/design-system-components.scss index 00c6008b820..a07b10042c8 100644 --- a/packages/components/src/styles/@hashicorp/design-system-components.scss +++ b/packages/components/src/styles/@hashicorp/design-system-components.scss @@ -3,63 +3,20 @@ * SPDX-License-Identifier: MPL-2.0 */ -// these files come from the 'design-system-tokens' package -@use "tokens"; -@use "helpers/color"; -@use "helpers/elevation"; -@use "helpers/focus-ring"; -@use "helpers/typography"; +// these files come from `packages/tokens/dist/` +@use "products/css/tokens"; +// TODO understand if these are common/shared or we should have different ones for the themed tokens +@use "products/css/helpers/color"; +@use "products/css/helpers/elevation"; +@use "products/css/helpers/focus-ring"; +@use "products/css/helpers/typography"; -// Notice: this list can be automatically edited by the Ember blueprint, please don't remove the start/end comments -// START COMPONENTS CSS FILES IMPORTS -@use "../components/accordion"; -@use "../components/advanced-table"; -@use "../components/alert"; -@use "../components/app-footer"; -@use "../components/app-frame"; -@use "../components/app-header"; -@use "../components/app-side-nav"; -@use "../components/application-state"; -@use "../components/badge"; -@use "../components/badge-count"; -@use "../components/breadcrumb"; -@use "../components/button"; -@use "../components/button-set"; -@use "../components/card"; -@use "../components/code-block"; -@use "../components/code-editor"; -@use "../components/copy"; -@use "../components/dialog-primitive"; -@use "../components/disclosure-primitive"; -@use "../components/dismiss-button"; -@use "../components/dropdown"; -@use "../components/flyout"; -@use "../components/form"; // multiple components -@use "../components/icon"; -@use "../components/icon-tile"; -@use "../components/layout"; // multiple components -@use "../components/link"; // multiple components -@use "../components/menu-primitive"; -@use "../components/modal"; -@use "../components/page-header"; -@use "../components/pagination"; -@use "../components/reveal"; -@use "../components/rich-tooltip"; -@use "../components/segmented-group"; -@use "../components/separator"; -@use "../components/side-nav"; -@use "../components/stepper"; -@use "../components/table"; -@use "../components/tabs"; -@use "../components/tag"; -@use "../components/text"; -@use "../components/time"; -@use "../components/toast"; -@use "../components/tooltip"; -// END COMPONENT CSS FILES IMPORTS +// main components file +@use "../components/index"; +// screen-reader utility class @use "../mixins/screen-reader-only" as *; -// stylelint-disable-next-line selector-class-pattern + .sr-only { @include screen-reader-only(); } diff --git a/packages/components/src/styles/components/index.scss b/packages/components/src/styles/components/index.scss new file mode 100644 index 00000000000..aa64026dd67 --- /dev/null +++ b/packages/components/src/styles/components/index.scss @@ -0,0 +1,52 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// Notice: this list can be automatically edited by the Ember blueprint, please don't remove the start/end comments +// START COMPONENTS CSS FILES IMPORTS +@use "./accordion"; +@use "./advanced-table"; +@use "./alert"; +@use "./app-footer"; +@use "./app-frame"; +@use "./app-header"; +@use "./app-side-nav"; +@use "./application-state"; +@use "./badge"; +@use "./badge-count"; +@use "./breadcrumb"; +@use "./button"; +@use "./button-set"; +@use "./card"; +@use "./code-block"; +@use "./code-editor"; +@use "./copy"; +@use "./dialog-primitive"; +@use "./disclosure-primitive"; +@use "./dismiss-button"; +@use "./dropdown"; +@use "./flyout"; +@use "./form"; // multiple components +@use "./icon"; +@use "./icon-tile"; +@use "./layout"; // multiple components +@use "./link"; // multiple components +@use "./menu-primitive"; +@use "./modal"; +@use "./page-header"; +@use "./pagination"; +@use "./reveal"; +@use "./rich-tooltip"; +@use "./segmented-group"; +@use "./separator"; +@use "./side-nav"; +@use "./stepper"; +@use "./table"; +@use "./tabs"; +@use "./tag"; +@use "./text"; +@use "./time"; +@use "./toast"; +@use "./tooltip"; +// END COMPONENT CSS FILES IMPORTS From 6abe91ad805f066d5add469a4daaa05b8541f4e9 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Mon, 29 Sep 2025 16:18:18 +0100 Subject: [PATCH 003/139] added support for source maps for generated themed CSS files --- packages/components/rollup.config.mjs | 32 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index 70b4fa29594..f58a111bea2 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -69,18 +69,30 @@ const plugins = [ const result = sass.compile( 'src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss', { + sourceMap: true, // equivalent to includePaths in rollup-plugin-scss loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], } ); + const cssFileName = + 'styles/@hashicorp/design-system-components-theming-with-css-selectors.css'; + // Emit the compiled CSS this.emitFile({ type: 'asset', - fileName: - 'styles/@hashicorp/design-system-components-theming-with-css-selectors.css', + fileName: cssFileName, source: result.css, }); + + // Emit the source map + if (result.sourceMap) { + this.emitFile({ + type: 'asset', + fileName: `${cssFileName}.map`, + source: JSON.stringify(result.sourceMap), + }); + } } catch (error) { this.error( `Failed to compile themed ("with CSS selectors") SCSS: ${error.message}` @@ -96,18 +108,30 @@ const plugins = [ const result = sass.compile( 'src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss', { + sourceMap: true, // equivalent to includePaths in rollup-plugin-scss loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], } ); + const cssFileName = + 'styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css'; + // Emit the compiled CSS this.emitFile({ type: 'asset', - fileName: - 'styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css', + fileName: cssFileName, source: result.css, }); + + // Emit the source map + if (result.sourceMap) { + this.emitFile({ + type: 'asset', + fileName: `${cssFileName}.map`, + source: JSON.stringify(result.sourceMap), + }); + } } catch (error) { this.error( `Failed to compile themed ("with CSS selectors") SCSS: ${error.message}` From e59a86ddfe7feda876cb0cacd6a57f5e2d276830 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 11:42:40 +0100 Subject: [PATCH 004/139] =?UTF-8?q?TEMP=20-=20Added=20generation=20of=20?= =?UTF-8?q?=E2=80=9Calt=E2=80=9D=20CSS=20for=20HDS=20components=20to=20com?= =?UTF-8?q?pare=20with=20output=20from=20`rollup-plugin-scss`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/components/rollup.config.mjs | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index f58a111bea2..e31d3ac56db 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -100,6 +100,43 @@ const plugins = [ } }, }, + { + name: 'compile-scss-alt', + generateBundle() { + // Compile the themed SCSS file + try { + const result = sass.compile( + 'src/styles/@hashicorp/design-system-components.scss', + { + sourceMap: true, + // equivalent to includePaths in rollup-plugin-scss + loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], + } + ); + + const cssFileName = + 'styles/@hashicorp/design-system-components-ALT.css'; + + // Emit the compiled CSS + this.emitFile({ + type: 'asset', + fileName: cssFileName, + source: result.css, + }); + + // Emit the source map + if (result.sourceMap) { + this.emitFile({ + type: 'asset', + fileName: `${cssFileName}.map`, + source: JSON.stringify(result.sourceMap), + }); + } + } catch (error) { + this.error(`Failed to compile ALT SCSS: ${error.message}`); + } + }, + }, { name: 'compile-scss-themed-with-prefers-color-scheme', generateBundle() { From 2d5eeb57070aa249ea48e36c4b20ca70d5c7317a Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 14:39:47 +0100 Subject: [PATCH 005/139] abstracted logic for custom Rollup plugin to compile multiple Sass files to CSS files --- packages/components/rollup.config.mjs | 166 ++++++++------------------ 1 file changed, 53 insertions(+), 113 deletions(-) diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index e31d3ac56db..cfde8baedd4 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -16,6 +16,45 @@ const addon = new Addon({ destDir: 'dist', }); +// Custom SCSS compilation plugins for Rollup +function addScssCompilationPlugins(options) { + return options.map(({ inputFile, outputFile }) => ({ + name: `rollup custom plugin to generate ${outputFile}`, + generateBundle() { + try { + const inputFileFullPath = `src/styles/@hashicorp/${inputFile}`; + const outputFileFullPath = `styles/@hashicorp/${outputFile}`; + + const result = sass.compile(inputFileFullPath, { + sourceMap: true, + // equivalent to includePaths in rollup-plugin-scss + loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], + }); + + // Emit the compiled CSS + this.emitFile({ + type: 'asset', + fileName: outputFileFullPath, + source: result.css, + }); + + // Emit the source map + if (result.sourceMap) { + this.emitFile({ + type: 'asset', + fileName: `${outputFileFullPath}.map`, + source: JSON.stringify(result.sourceMap), + }); + } + } catch (error) { + this.error( + `Failed to compile SCSS file "${inputFile}": ${error.message}` + ); + } + }, + })); +} + const plugins = [ // These are the modules that users should be able to import from your // addon. Anything not listed here may get optimized away. @@ -60,122 +99,23 @@ const plugins = [ fileName: 'styles/@hashicorp/design-system-power-select-overrides.css', }), - // Custom plugins to compile the "themed" SCSS files - { - name: 'compile-scss-themed-with-css-selectors', - generateBundle() { - // Compile the themed SCSS file - try { - const result = sass.compile( - 'src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss', - { - sourceMap: true, - // equivalent to includePaths in rollup-plugin-scss - loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], - } - ); - - const cssFileName = - 'styles/@hashicorp/design-system-components-theming-with-css-selectors.css'; - - // Emit the compiled CSS - this.emitFile({ - type: 'asset', - fileName: cssFileName, - source: result.css, - }); - - // Emit the source map - if (result.sourceMap) { - this.emitFile({ - type: 'asset', - fileName: `${cssFileName}.map`, - source: JSON.stringify(result.sourceMap), - }); - } - } catch (error) { - this.error( - `Failed to compile themed ("with CSS selectors") SCSS: ${error.message}` - ); - } + // Custom SCSS compilation plugin function + ...addScssCompilationPlugins([ + { + inputFile: 'design-system-components.scss', + outputFile: 'design-system-components-ALT.css', }, - }, - { - name: 'compile-scss-alt', - generateBundle() { - // Compile the themed SCSS file - try { - const result = sass.compile( - 'src/styles/@hashicorp/design-system-components.scss', - { - sourceMap: true, - // equivalent to includePaths in rollup-plugin-scss - loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], - } - ); - - const cssFileName = - 'styles/@hashicorp/design-system-components-ALT.css'; - - // Emit the compiled CSS - this.emitFile({ - type: 'asset', - fileName: cssFileName, - source: result.css, - }); - - // Emit the source map - if (result.sourceMap) { - this.emitFile({ - type: 'asset', - fileName: `${cssFileName}.map`, - source: JSON.stringify(result.sourceMap), - }); - } - } catch (error) { - this.error(`Failed to compile ALT SCSS: ${error.message}`); - } + { + inputFile: 'design-system-components-theming-with-css-selectors.scss', + outputFile: 'design-system-components-theming-with-css-selectors.css', }, - }, - { - name: 'compile-scss-themed-with-prefers-color-scheme', - generateBundle() { - // Compile the themed SCSS file - try { - const result = sass.compile( - 'src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss', - { - sourceMap: true, - // equivalent to includePaths in rollup-plugin-scss - loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], - } - ); - - const cssFileName = - 'styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css'; - - // Emit the compiled CSS - this.emitFile({ - type: 'asset', - fileName: cssFileName, - source: result.css, - }); - - // Emit the source map - if (result.sourceMap) { - this.emitFile({ - type: 'asset', - fileName: `${cssFileName}.map`, - source: JSON.stringify(result.sourceMap), - }); - } - } catch (error) { - this.error( - `Failed to compile themed ("with CSS selectors") SCSS: ${error.message}` - ); - } + { + inputFile: + 'design-system-components-theming-with-prefers-color-scheme.scss', + outputFile: + 'design-system-components-theming-with-prefers-color-scheme.css', }, - }, + ]), // Ensure that standalone .hbs files are properly integrated as Javascript. addon.hbs(), From 746e48711b8eac866cb78ac0793a9a1f53821489 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 15:46:09 +0100 Subject: [PATCH 006/139] updated `includePaths` for design tokens in Showcase and Website `ember-cli-build.js` --- showcase/ember-cli-build.js | 2 +- website/ember-cli-build.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/showcase/ember-cli-build.js b/showcase/ember-cli-build.js index 72fd5925260..7fb71fdd38e 100644 --- a/showcase/ember-cli-build.js +++ b/showcase/ember-cli-build.js @@ -17,7 +17,7 @@ module.exports = function (defaults) { sassOptions: { precision: 4, includePaths: [ - 'node_modules/@hashicorp/design-system-tokens/dist/products/css', + 'node_modules/@hashicorp/design-system-tokens/dist', 'node_modules/@hashicorp/design-system-components/dist/styles', 'node_modules/ember-power-select/vendor', ], diff --git a/website/ember-cli-build.js b/website/ember-cli-build.js index ad5b7ca6183..fd0f2390547 100644 --- a/website/ember-cli-build.js +++ b/website/ember-cli-build.js @@ -15,7 +15,7 @@ module.exports = function (defaults) { sassOptions: { precision: 4, includePaths: [ - 'node_modules/@hashicorp/design-system-tokens/dist/products/css', + 'node_modules/@hashicorp/design-system-tokens/dist', 'node_modules/@hashicorp/design-system-components/dist/styles', 'node_modules/ember-power-select/vendor', ], From 9a5bc174232243a489daf26397f4f7300f3fb687 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 16:40:53 +0100 Subject: [PATCH 007/139] moved compilation of existing Scss files for components and overrides to new custom plugin --- packages/components/rollup.config.mjs | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index cfde8baedd4..6d6253330a4 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -6,7 +6,6 @@ import { Addon } from '@embroider/addon-dev/rollup'; import { babel } from '@rollup/plugin-babel'; import copy from 'rollup-plugin-copy'; -import scss from 'rollup-plugin-scss'; import process from 'process'; import path from 'node:path'; import * as sass from 'sass'; @@ -27,7 +26,6 @@ function addScssCompilationPlugins(options) { const result = sass.compile(inputFileFullPath, { sourceMap: true, - // equivalent to includePaths in rollup-plugin-scss loadPaths: ['node_modules/@hashicorp/design-system-tokens/dist'], }); @@ -58,12 +56,7 @@ function addScssCompilationPlugins(options) { const plugins = [ // These are the modules that users should be able to import from your // addon. Anything not listed here may get optimized away. - addon.publicEntrypoints([ - '**/*.{js,ts}', - 'index.js', - 'template-registry.js', - 'styles/@hashicorp/design-system-components.scss', - ]), + addon.publicEntrypoints(['**/*.{js,ts}', 'index.js', 'template-registry.js']), // These are the modules that should get reexported into the traditional // "app" tree. Things in here should also be in publicEntrypoints above, but @@ -90,20 +83,12 @@ const plugins = [ // package names. addon.dependencies(), - scss({ - fileName: 'styles/@hashicorp/design-system-components.css', - includePaths: ['node_modules/@hashicorp/design-system-tokens/dist'], - }), - - scss({ - fileName: 'styles/@hashicorp/design-system-power-select-overrides.css', - }), - - // Custom SCSS compilation plugin function + // We use a custom plugin for the Sass/SCSS compilation + // so we can have multiple input and multiple outputs ...addScssCompilationPlugins([ { inputFile: 'design-system-components.scss', - outputFile: 'design-system-components-ALT.css', + outputFile: 'design-system-components.css', }, { inputFile: 'design-system-components-theming-with-css-selectors.scss', @@ -115,6 +100,10 @@ const plugins = [ outputFile: 'design-system-components-theming-with-prefers-color-scheme.css', }, + { + inputFile: 'design-system-power-select-overrides.scss', + outputFile: 'design-system-power-select-overrides.css', + }, ]), // Ensure that standalone .hbs files are properly integrated as Javascript. From 59d230ccbd858394d0ddeab02a1b09c54c1b2f37 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 17:10:39 +0100 Subject: [PATCH 008/139] removed `rollup-plugin-scss` dev dependency (we use our own custom plugin for every Scss compilation) --- packages/components/package.json | 1 - pnpm-lock.yaml | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index caa55b250ec..ba03c3ec5eb 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -112,7 +112,6 @@ "prettier-plugin-ember-template-tag": "^2.0.5", "rollup": "^4.39.0", "rollup-plugin-copy": "^3.5.0", - "rollup-plugin-scss": "^4.0.1", "stylelint": "^16.17.0", "stylelint-config-rational-order": "^0.1.2", "stylelint-config-standard-scss": "^14.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5fdc76dbdb8..8559de4c48a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -295,9 +295,6 @@ importers: rollup-plugin-copy: specifier: ^3.5.0 version: 3.5.0 - rollup-plugin-scss: - specifier: ^4.0.1 - version: 4.0.1 stylelint: specifier: ^16.17.0 version: 16.23.0(typescript@5.9.2) @@ -10247,9 +10244,6 @@ packages: resolution: {integrity: sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==} engines: {node: '>=8.3'} - rollup-plugin-scss@4.0.1: - resolution: {integrity: sha512-3W3+3OzR+shkDl3hJ1XTAuGkP4AfiLgIjie2GtcoZ9pHfRiNqeDbtCu1EUnkjZ98EPIM6nnMIXkKlc7Sx5bRvA==} - rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} @@ -24712,10 +24706,6 @@ snapshots: globby: 10.0.1 is-plain-object: 3.0.1 - rollup-plugin-scss@4.0.1: - dependencies: - rollup-pluginutils: 2.8.2 - rollup-pluginutils@2.8.2: dependencies: estree-walker: 0.6.1 From 9ab20a66b0d44193ad8c5bd01bb0725a44216c00 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Thu, 2 Oct 2025 12:43:37 +0100 Subject: [PATCH 009/139] added CSS compilation for `combined-strategies` tokens --- packages/components/rollup.config.mjs | 6 +++++ ...ents-theming-with-combined-strategies.scss | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index 6d6253330a4..8b52c2fe51f 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -100,6 +100,12 @@ const plugins = [ outputFile: 'design-system-components-theming-with-prefers-color-scheme.css', }, + { + inputFile: + 'design-system-components-theming-with-combined-strategies.scss', + outputFile: + 'design-system-components-theming-with-combined-strategies.css', + }, { inputFile: 'design-system-power-select-overrides.scss', outputFile: 'design-system-power-select-overrides.css', diff --git a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss new file mode 100644 index 00000000000..28ac7a9f0b4 --- /dev/null +++ b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss @@ -0,0 +1,22 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// these files come from `packages/tokens/dist/` +@use "products/css/themed-tokens/with-combined-strategies/tokens.css"; +// TODO understand if these are common/shared or we should have different ones for the themed tokens +@use "products/css/helpers/color"; +@use "products/css/helpers/elevation"; +@use "products/css/helpers/focus-ring"; +@use "products/css/helpers/typography"; + +// main components file +@use "../components/index"; + +// screen-reader utility class +@use "../mixins/screen-reader-only" as *; + +.sr-only { + @include screen-reader-only(); +} From 5f2f7fb87c5f2cba8b448f648ab471ebf8af5b82 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Wed, 15 Oct 2025 15:43:36 +0100 Subject: [PATCH 010/139] updated the `prePublish` script in `package.json` of `components` to validate that all the new CSS files are generated too --- packages/components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/package.json b/packages/components/package.json index ba03c3ec5eb..155b6a5cfa8 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -30,7 +30,7 @@ "lint:js:fix": "eslint . --fix", "lint:types": "glint", "start": "rollup --config --watch --environment development", - "prepublishOnly": "pnpm build && test -f 'dist/styles/@hashicorp/design-system-components.css' || (echo \"\n\\033[31m⚠️ Error: the pre-compiled CSS file \\`dist/styles/@hashicorp/design-system-components.css\\` was not found\\033[0m\\n\" && exit 1)" + "prepublishOnly": "pnpm build && test -f 'dist/styles/@hashicorp/design-system-components.css' && test -f 'dist/styles/@hashicorp/design-system-components-theming-with-css-selectors.css' && test -f 'dist/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css' && test -f 'dist/styles/@hashicorp/design-system-components.css' && test -f 'dist/styles/@hashicorp/design-system-power-select-overrides.css' || (echo \"\n\\033[31m⚠️ Error: the pre-compiled CSS file was not found\\033[0m\\n\" && exit 1)" }, "dependencies": { "@codemirror/commands": "^6.8.0", From e747c6b73d4b6b02c5a10f8c5d5b0357e5aacd3d Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Fri, 24 Oct 2025 11:52:28 +0100 Subject: [PATCH 011/139] simplified architecture of CSS compilation for HDS components (as agreed) --- packages/components/rollup.config.mjs | 16 ++------------ ...s => design-system-components-common.scss} | 2 -- ...ents-theming-with-combined-strategies.scss | 22 ------------------- ...nts-theming-with-prefers-color-scheme.scss | 22 ------------------- .../@hashicorp/design-system-components.scss | 18 +++------------ 5 files changed, 5 insertions(+), 75 deletions(-) rename packages/components/src/styles/@hashicorp/{design-system-components-theming-with-css-selectors.scss => design-system-components-common.scss} (73%) delete mode 100644 packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss delete mode 100644 packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss diff --git a/packages/components/rollup.config.mjs b/packages/components/rollup.config.mjs index 8b52c2fe51f..4b50ba4595d 100644 --- a/packages/components/rollup.config.mjs +++ b/packages/components/rollup.config.mjs @@ -91,20 +91,8 @@ const plugins = [ outputFile: 'design-system-components.css', }, { - inputFile: 'design-system-components-theming-with-css-selectors.scss', - outputFile: 'design-system-components-theming-with-css-selectors.css', - }, - { - inputFile: - 'design-system-components-theming-with-prefers-color-scheme.scss', - outputFile: - 'design-system-components-theming-with-prefers-color-scheme.css', - }, - { - inputFile: - 'design-system-components-theming-with-combined-strategies.scss', - outputFile: - 'design-system-components-theming-with-combined-strategies.css', + inputFile: 'design-system-components-common.scss', + outputFile: 'design-system-components-common.css', }, { inputFile: 'design-system-power-select-overrides.scss', diff --git a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss b/packages/components/src/styles/@hashicorp/design-system-components-common.scss similarity index 73% rename from packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss rename to packages/components/src/styles/@hashicorp/design-system-components-common.scss index 8fb787a5541..25a3f81a9f5 100644 --- a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-css-selectors.scss +++ b/packages/components/src/styles/@hashicorp/design-system-components-common.scss @@ -4,8 +4,6 @@ */ // these files come from `packages/tokens/dist/` -@use "products/css/themed-tokens/with-css-selectors/tokens.css"; -// TODO understand if these are common/shared or we should have different ones for the themed tokens @use "products/css/helpers/color"; @use "products/css/helpers/elevation"; @use "products/css/helpers/focus-ring"; diff --git a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss deleted file mode 100644 index 28ac7a9f0b4..00000000000 --- a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-combined-strategies.scss +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -// these files come from `packages/tokens/dist/` -@use "products/css/themed-tokens/with-combined-strategies/tokens.css"; -// TODO understand if these are common/shared or we should have different ones for the themed tokens -@use "products/css/helpers/color"; -@use "products/css/helpers/elevation"; -@use "products/css/helpers/focus-ring"; -@use "products/css/helpers/typography"; - -// main components file -@use "../components/index"; - -// screen-reader utility class -@use "../mixins/screen-reader-only" as *; - -.sr-only { - @include screen-reader-only(); -} diff --git a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss b/packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss deleted file mode 100644 index c83e68e495b..00000000000 --- a/packages/components/src/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.scss +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -// these files come from `packages/tokens/dist/` -@use "products/css/themed-tokens/with-prefers-color-scheme/tokens.css"; -// TODO understand if these are common/shared or we should have different ones for the themed tokens -@use "products/css/helpers/color"; -@use "products/css/helpers/elevation"; -@use "products/css/helpers/focus-ring"; -@use "products/css/helpers/typography"; - -// main components file -@use "../components/index"; - -// screen-reader utility class -@use "../mixins/screen-reader-only" as *; - -.sr-only { - @include screen-reader-only(); -} diff --git a/packages/components/src/styles/@hashicorp/design-system-components.scss b/packages/components/src/styles/@hashicorp/design-system-components.scss index a07b10042c8..cbc8470f7d0 100644 --- a/packages/components/src/styles/@hashicorp/design-system-components.scss +++ b/packages/components/src/styles/@hashicorp/design-system-components.scss @@ -3,20 +3,8 @@ * SPDX-License-Identifier: MPL-2.0 */ -// these files come from `packages/tokens/dist/` +// these are the "standard" HDS tokens (the file comes from `packages/tokens/dist/`) @use "products/css/tokens"; -// TODO understand if these are common/shared or we should have different ones for the themed tokens -@use "products/css/helpers/color"; -@use "products/css/helpers/elevation"; -@use "products/css/helpers/focus-ring"; -@use "products/css/helpers/typography"; -// main components file -@use "../components/index"; - -// screen-reader utility class -@use "../mixins/screen-reader-only" as *; - -.sr-only { - @include screen-reader-only(); -} +// these are the styles specific (and only) for the the HDS components +@use "./design-system-components-common"; From f56ce4b822280948db604e77dbba3ab0c444dd45 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Fri, 24 Oct 2025 16:22:18 +0100 Subject: [PATCH 012/139] =?UTF-8?q?fixed=20`prepublisOnly`=20script=20that?= =?UTF-8?q?=20was=20causing=20error=20in=20build=20(looking=20for=20old=20?= =?UTF-8?q?CSS=20files=20that=20don=E2=80=99t=20exist=20anymore)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/components/package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/components/package.json b/packages/components/package.json index 155b6a5cfa8..a2dfcfe6ba7 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -30,7 +30,10 @@ "lint:js:fix": "eslint . --fix", "lint:types": "glint", "start": "rollup --config --watch --environment development", - "prepublishOnly": "pnpm build && test -f 'dist/styles/@hashicorp/design-system-components.css' && test -f 'dist/styles/@hashicorp/design-system-components-theming-with-css-selectors.css' && test -f 'dist/styles/@hashicorp/design-system-components-theming-with-prefers-color-scheme.css' && test -f 'dist/styles/@hashicorp/design-system-components.css' && test -f 'dist/styles/@hashicorp/design-system-power-select-overrides.css' || (echo \"\n\\033[31m⚠️ Error: the pre-compiled CSS file was not found\\033[0m\\n\" && exit 1)" + "test-f:design-system-components": "test -f 'dist/styles/@hashicorp/design-system-components.css' || (echo \"\n\\033[31m⚠️ Error: the pre-compiled CSS file \\`dist/styles/@hashicorp/design-system-components.css\\` was not found\\033[0m\\n\" && exit 1)", + "test-f:design-system-components-common": "test -f 'dist/styles/@hashicorp/design-system-components-common.css' || (echo \"\n\\033[31m⚠️ Error: the pre-compiled CSS file \\`dist/styles/@hashicorp/design-system-components-common.css\\` was not found\\033[0m\\n\" && exit 1)", + "test-f:design-system-power-select-overrides": "test -f 'dist/styles/@hashicorp/design-system-power-select-overrides.css' || (echo \"\n\\033[31m⚠️ Error: the pre-compiled CSS file \\`dist/styles/@hashicorp/design-system-power-select-overrides.css\\` was not found\\033[0m\\n\" && exit 1)", + "prepublishOnly": "pnpm build && pnpm test-f:design-system-components && pnpm test-f:design-system-components-common && pnpm test-f:design-system-power-select-overrides" }, "dependencies": { "@codemirror/commands": "^6.8.0", From e1384c57c73260130a654a3e6b104cdb22d96730 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Wed, 29 Oct 2025 09:59:43 +0000 Subject: [PATCH 013/139] updated `cssFilePath` in blueprints to reflect new Scss file organization, per code review suggestion https://github.com/hashicorp/design-system/pull/3259#discussion_r2469643577 --- showcase/blueprints/hds-component/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/showcase/blueprints/hds-component/index.js b/showcase/blueprints/hds-component/index.js index 37f0c063d8e..48b79420c85 100644 --- a/showcase/blueprints/hds-component/index.js +++ b/showcase/blueprints/hds-component/index.js @@ -38,7 +38,7 @@ module.exports = { const updateHDSComponentsCSS = (options) => { const name = options.entity.name; - const cssFilePath = `${options.project.root}/../packages/components/src/styles/@hashicorp/design-system-components.scss`; + const cssFilePath = `${options.project.root}/../packages/components/src/styles/components/index.scss`; const source = fs.readFileSync(cssFilePath, 'utf-8'); const oldLinesArray = source.split(/\r?\n/); const firstComponentImportIndex = From 88b29409e59d930a490010e3f89c415f39397013 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 20:52:07 +0100 Subject: [PATCH 014/139] added `Hds::ThemeSwitcher` component --- packages/components/package.json | 3 +- packages/components/src/components.ts | 3 + .../components/hds/theme-switcher/index.hbs | 11 ++++ .../components/hds/theme-switcher/index.ts | 63 +++++++++++++++++++ packages/components/src/template-registry.ts | 5 ++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 packages/components/src/components/hds/theme-switcher/index.hbs create mode 100644 packages/components/src/components/hds/theme-switcher/index.ts diff --git a/packages/components/package.json b/packages/components/package.json index a2dfcfe6ba7..136ab3b6824 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -369,6 +369,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.js": "./dist/_app_/components/hds/text.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", @@ -427,4 +428,4 @@ "engines": { "node": ">= 18" } -} +} \ No newline at end of file diff --git a/packages/components/src/components.ts b/packages/components/src/components.ts index 400dc061324..adb7400d800 100644 --- a/packages/components/src/components.ts +++ b/packages/components/src/components.ts @@ -327,6 +327,9 @@ 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 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'; diff --git a/packages/components/src/components/hds/theme-switcher/index.hbs b/packages/components/src/components/hds/theme-switcher/index.hbs new file mode 100644 index 00000000000..4486348faff --- /dev/null +++ b/packages/components/src/components/hds/theme-switcher/index.hbs @@ -0,0 +1,11 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: MPL-2.0 +}} + + + + {{#each-in this._options as |key data|}} + {{data.label}} + {{/each-in}} + diff --git a/packages/components/src/components/hds/theme-switcher/index.ts b/packages/components/src/components/hds/theme-switcher/index.ts new file mode 100644 index 00000000000..4f6ec8fb882 --- /dev/null +++ b/packages/components/src/components/hds/theme-switcher/index.ts @@ -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 { + @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); + } +} diff --git a/packages/components/src/template-registry.ts b/packages/components/src/template-registry.ts index 66183aa31c6..25f4575d028 100644 --- a/packages/components/src/template-registry.ts +++ b/packages/components/src/template-registry.ts @@ -232,6 +232,7 @@ import type HdsTagComponent from './components/hds/tag'; import type HdsTooltipButtonComponent from './components/hds/tooltip-button'; import type HdsToastComponent from './components/hds/toast'; import type HdsTextCodeComponent from './components/hds/text/code'; +import type HdsThemeSwitcherComponent from './components/hds/theme-switcher'; import type HdsTimeComponent from './components/hds/time'; import type HdsTimeSingleComponent from './components/hds/time/single'; import type HdsTimeRangeComponent from './components/hds/time/range'; @@ -1021,6 +1022,10 @@ export default interface HdsComponentsRegistry { 'Hds::Toast': typeof HdsToastComponent; 'hds/toast': typeof HdsToastComponent; + // ThemeSwitcher + 'Hds::ThemeSwitcher': typeof HdsThemeSwitcherComponent; + 'hds/theme-switcher': typeof HdsThemeSwitcherComponent; + // Time 'Hds::Time': typeof HdsTimeComponent; 'hds/time': typeof HdsTimeComponent; From 3d408da9d91e269024a8a8131b4ed7132459708a Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 20:53:01 +0100 Subject: [PATCH 015/139] added `Hds::Theming` service --- packages/components/package.json | 1 + packages/components/src/services.ts | 2 + .../components/src/services/hds-theming.ts | 63 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 packages/components/src/services/hds-theming.ts diff --git a/packages/components/package.json b/packages/components/package.json index 136ab3b6824..d96dde0bf1a 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -398,6 +398,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" } }, diff --git a/packages/components/src/services.ts b/packages/components/src/services.ts index 2650e722d57..9f61ec10978 100644 --- a/packages/components/src/services.ts +++ b/packages/components/src/services.ts @@ -4,3 +4,5 @@ */ // This file is used to expose public services + +export * from './services/hds-theming.ts'; diff --git a/packages/components/src/services/hds-theming.ts b/packages/components/src/services/hds-theming.ts new file mode 100644 index 00000000000..cb508ddc167 --- /dev/null +++ b/packages/components/src/services/hds-theming.ts @@ -0,0 +1,63 @@ +import Service from '@ember/service'; +import { tracked } from '@glimmer/tracking'; + +import type Owner from '@ember/owner'; + +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: Owner) { + 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; + } + } + } +} From fbb16f8c147c5bba48bb32a6d8ed78b31aa12832 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 21:10:42 +0100 Subject: [PATCH 016/139] =?UTF-8?q?added=20theming=20to=20the=20Showcase?= =?UTF-8?q?=20itself=20(and=20replaced=20hardcoded=20values=20with=20`?= =?UTF-8?q?=E2=80=94shw`=20CSS=20variables)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- showcase/app/styles/_globals.scss | 7 +++- showcase/app/styles/_tokens.scss | 41 ------------------- showcase/app/styles/_typography.scss | 6 ++- showcase/app/styles/app.scss | 3 +- .../styles/showcase-components/divider.scss | 4 +- .../app/styles/showcase-components/flex.scss | 4 +- .../app/styles/showcase-components/frame.scss | 6 +-- .../app/styles/showcase-components/grid.scss | 4 +- .../app/styles/showcase-components/label.scss | 2 +- .../showcase-components/placeholder.scss | 8 ++-- .../app/styles/showcase-pages/typography.scss | 3 +- .../app/styles/showcase-theming/dark.scss | 33 +++++++++++++++ .../app/styles/showcase-theming/light.scss | 37 +++++++++++++++++ 13 files changed, 99 insertions(+), 59 deletions(-) delete mode 100644 showcase/app/styles/_tokens.scss create mode 100644 showcase/app/styles/showcase-theming/dark.scss create mode 100644 showcase/app/styles/showcase-theming/light.scss diff --git a/showcase/app/styles/_globals.scss b/showcase/app/styles/_globals.scss index 1447a120e7e..76695a082fc 100644 --- a/showcase/app/styles/_globals.scss +++ b/showcase/app/styles/_globals.scss @@ -19,6 +19,7 @@ body { min-height: 100vh; margin: 0; padding: 0; + color: var(--shw-color-black); background: var(--shw-color-white); } @@ -32,7 +33,7 @@ body { height: 68px; padding: 0 24px; color: var(--shw-color-black); - border-bottom: 1px solid #eaeaea; + border-bottom: 1px solid var(--shw-color-gray-500); } .shw-page-header__logo { @@ -68,6 +69,10 @@ body { line-height: 1; } +.shw-page-header__theme-toggle { + margin-left: auto; +} + .shw-page-aside { padding: 1rem; diff --git a/showcase/app/styles/_tokens.scss b/showcase/app/styles/_tokens.scss deleted file mode 100644 index fa11ede62f2..00000000000 --- a/showcase/app/styles/_tokens.scss +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -// TOKENS (CSS PROPS) - -:root { - // COLORS - --shw-color-white: #fff; - --shw-color-gray-600: #f2f2f3; - --shw-color-gray-500: #dbdbdc; - --shw-color-gray-400: #bfbfc0; - --shw-color-gray-300: #727374; - --shw-color-gray-200: #343536; - --shw-color-gray-100: #1d1e1f; - --shw-color-black: #000; - --shw-color-link-on-black: #4294ff; - --shw-color-link-on-white: #2264d6; - --shw-color-feedback-information-100: #0d44cc; - --shw-color-feedback-information-200: #1563ff; - --shw-color-feedback-information-300: #d0e0ff; - --shw-color-feedback-information-400: #eff5ff; - --shw-color-feedback-success-100: #007854; - --shw-color-feedback-success-200: #00bc7f; - --shw-color-feedback-success-300: #c1f1e0; - --shw-color-feedback-success-400: #ebfdf7; - --shw-color-feedback-warning-100: #975b06; - --shw-color-feedback-warning-200: #eaaa32; - --shw-color-feedback-warning-300: #f9eacd; - --shw-color-feedback-warning-400: #fcf6ea; - --shw-color-feedback-critical-100: #ba2226; - --shw-color-feedback-critical-200: #f25054; - --shw-color-feedback-critical-300: #ffd4d6; - --shw-color-feedback-critical-400: #fcf0f2; - --shw-color-action-active-foreground: #00f; // HTML "blue" - --shw-color-action-active-border: #00f; // HTML "blue" - --shw-color-action-active-background: #f0f8ff; // HTML "aliceblue" - // "FLEX/GRID" COMPONENTS - --shw-layout-gap-base: 1rem; -} diff --git a/showcase/app/styles/_typography.scss b/showcase/app/styles/_typography.scss index d94b4c80230..cad0d0452bf 100644 --- a/showcase/app/styles/_typography.scss +++ b/showcase/app/styles/_typography.scss @@ -86,6 +86,7 @@ $show-font-family-mono: ui-monospace, menlo, consolas, monospace; @mixin shw-font-style-h1() { @include shw-font-family("gilmer"); + color: var(--shw-color-black); font-weight: 700; font-size: 3rem; line-height: 1.3; @@ -95,6 +96,7 @@ $show-font-family-mono: ui-monospace, menlo, consolas, monospace; @mixin shw-font-style-h2() { @include shw-font-family("gilmer"); + color: var(--shw-color-black); font-weight: 400; font-size: 1.8rem; line-height: 1.3; @@ -104,6 +106,7 @@ $show-font-family-mono: ui-monospace, menlo, consolas, monospace; @mixin shw-font-style-h3() { @include shw-font-family("gilmer"); + color: var(--shw-color-black); font-weight: 400; font-size: 1.4rem; line-height: 1.3; @@ -113,7 +116,7 @@ $show-font-family-mono: ui-monospace, menlo, consolas, monospace; @mixin shw-font-style-h4() { @include shw-font-family("gilmer"); - color: #666; // equivalent to `opacity: 0.5` + color: var(--shw-color-gray-300); font-weight: 500; font-size: 1.2rem; line-height: 1.3; @@ -123,6 +126,7 @@ $show-font-family-mono: ui-monospace, menlo, consolas, monospace; @mixin shw-font-style-body { @include shw-font-family("gilmer"); + color: var(--shw-color-black); font-size: 1rem; line-height: 1.4; } diff --git a/showcase/app/styles/app.scss b/showcase/app/styles/app.scss index 3f80ec0b870..a8808eedabd 100644 --- a/showcase/app/styles/app.scss +++ b/showcase/app/styles/app.scss @@ -8,7 +8,8 @@ // global declarations -@use "./tokens"; +@use "./showcase-theming/light"; +@use "./showcase-theming/dark"; @use "./layout"; @use "./typography"; @use "./globals"; diff --git a/showcase/app/styles/showcase-components/divider.scss b/showcase/app/styles/showcase-components/divider.scss index 51f63676a67..19718e76ab3 100644 --- a/showcase/app/styles/showcase-components/divider.scss +++ b/showcase/app/styles/showcase-components/divider.scss @@ -6,9 +6,9 @@ .shw-divider { margin: 3rem 0; border: none; - border-top: 2px solid #ccc; + border-top: 2px solid var(--shw-color-gray-500); } .shw-divider--level-2 { - border-top: 2px dotted #ddd; + border-top-style: dotted; } diff --git a/showcase/app/styles/showcase-components/flex.scss b/showcase/app/styles/showcase-components/flex.scss index d5779511a0a..32808edb42f 100644 --- a/showcase/app/styles/showcase-components/flex.scss +++ b/showcase/app/styles/showcase-components/flex.scss @@ -8,13 +8,13 @@ .shw-flex { & + &, & + .shw-grid { - margin-top: var(--shw-layout-gap-base); + margin-top: 1rem; } } .shw-flex__items { display: flex; - gap: var(--shw-layout-gap-base); + gap: 1rem; .shw-flex--direction-row > & { flex-direction: row; diff --git a/showcase/app/styles/showcase-components/frame.scss b/showcase/app/styles/showcase-components/frame.scss index 3f06392e9a3..08c40f5d49a 100644 --- a/showcase/app/styles/showcase-components/frame.scss +++ b/showcase/app/styles/showcase-components/frame.scss @@ -15,7 +15,7 @@ $shw-frame-navigation-bar-height: 48px; max-width: 100%; height: calc(var(--iframe-height) + #{$shw-frame-navigation-bar-height}); max-height: 100%; - outline: 1px solid #e4e4d4; + outline: 1px solid var(--shw-color-gray-500); } .shw-frame__browser-navigation { @@ -25,12 +25,12 @@ $shw-frame-navigation-bar-height: 48px; height: $shw-frame-navigation-bar-height; // safe area for the dots padding: 8px 24px 8px 120px; - background-color: #fafafa; + background-color: var(--shw-frame-browser-navigation-background); background-image: url('data:image/svg+xml,'); background-repeat: no-repeat; background-position: 24px 50%; background-size: 56px 14px; - border-bottom: 1px solid #e4e4d4; + border-bottom: 1px solid var(--shw-color-gray-500); } .shw-frame__open-link { diff --git a/showcase/app/styles/showcase-components/grid.scss b/showcase/app/styles/showcase-components/grid.scss index 313db6e024b..9d2b9d92d23 100644 --- a/showcase/app/styles/showcase-components/grid.scss +++ b/showcase/app/styles/showcase-components/grid.scss @@ -8,7 +8,7 @@ .shw-grid { & + &, & + .shw-flex { - margin-top: var(--shw-layout-gap-base); + margin-top: 1rem; } } @@ -17,7 +17,7 @@ flex-wrap: wrap; // this will be set via JS grid-template-columns: repeat(var(--shw-grid-columns), 1fr); - gap: var(--shw-layout-gap-base); + gap: 1rem; } .shw-grid__item--grow { diff --git a/showcase/app/styles/showcase-components/label.scss b/showcase/app/styles/showcase-components/label.scss index 2340e936091..bdee3f9b876 100644 --- a/showcase/app/styles/showcase-components/label.scss +++ b/showcase/app/styles/showcase-components/label.scss @@ -10,7 +10,7 @@ .shw-label { @include shw-font-family("rubik"); margin: 0 0 10px 0; - color: #545454; + color: var(--shw-label-text-color); font-size: 0.8rem; line-height: 1.2; } diff --git a/showcase/app/styles/showcase-components/placeholder.scss b/showcase/app/styles/showcase-components/placeholder.scss index df37357fc9b..664ff2e37d4 100644 --- a/showcase/app/styles/showcase-components/placeholder.scss +++ b/showcase/app/styles/showcase-components/placeholder.scss @@ -11,18 +11,18 @@ display: flex; align-items: center; justify-content: center; - color: #6b6b6b; // if background is #EEE then this has the appropriate color contrast (4.59:1) + color: var(--shw-placeholder-text-color); font-weight: bold; font-size: 10px; font-family: monaco, Consolas, "Lucida Console", monospace; line-height: 1.2; text-align: center; - text-shadow: 0 0 5px #fff; - background-color: #eee; + text-shadow: 0 0 5px var(--shw-color-white); + background-color: var(--shw-placeholder-background-color); a, a > & { - color: #333; + color: var(--shw-placeholder-link-color); text-decoration: underline; } } diff --git a/showcase/app/styles/showcase-pages/typography.scss b/showcase/app/styles/showcase-pages/typography.scss index aa44b080a01..6ec00b2e738 100644 --- a/showcase/app/styles/showcase-pages/typography.scss +++ b/showcase/app/styles/showcase-pages/typography.scss @@ -7,11 +7,12 @@ body.page-foundations-typography { .shw-label { - color: #999; + color: var(--shw-color-gray-300); } p[class^="hds-"] { margin: 0; padding: 0; + color: var(--shw-color-black); } } diff --git a/showcase/app/styles/showcase-theming/dark.scss b/showcase/app/styles/showcase-theming/dark.scss new file mode 100644 index 00000000000..a00d5ccb79d --- /dev/null +++ b/showcase/app/styles/showcase-theming/dark.scss @@ -0,0 +1,33 @@ +// SHOWCASE COLORS > DARK THEME + +@mixin shw-theme-color-variables-dark() { + // SEMANTIC PALETTE + --shw-color-white: #1a1a1a; + --shw-color-gray-600: #222225; + --shw-color-gray-500: #353537; + --shw-color-gray-400: #4c4c4d; + --shw-color-gray-300: #89898a; + --shw-color-gray-200: #babbbc; + --shw-color-gray-100: #cccdcf; + --shw-color-black: #e5e5e5; + --shw-color-action-active-foreground: #1a1ae5; + --shw-color-action-active-border: #1a1ae5; + --shw-color-action-active-background: #062139; + // COMPONENTS + --shw-frame-browser-navigation-background: #050505; + --shw-label-text-color: #c4c4c4; + --shw-placeholder-text-color: #949494; + --shw-placeholder-background-color: #121212; + --shw-placeholder-link-color: #ccc; +} + +@media (prefers-color-scheme: dark) { + :root[data-hds-theme="auto"] { + @include shw-theme-color-variables-dark(); + } +} + +.hds-theme-dark, +[data-hds-theme="dark"] { + @include shw-theme-color-variables-dark(); +} diff --git a/showcase/app/styles/showcase-theming/light.scss b/showcase/app/styles/showcase-theming/light.scss new file mode 100644 index 00000000000..5ad549848fa --- /dev/null +++ b/showcase/app/styles/showcase-theming/light.scss @@ -0,0 +1,37 @@ +// SHOWCASE COLORS > LIGHT THEME + +@mixin shw-theme-color-variables-light() { + // SEMANTIC PALETTE + --shw-color-white: #fff; + --shw-color-gray-600: #f2f2f3; + --shw-color-gray-500: #dbdbdc; + --shw-color-gray-400: #bfbfc0; + --shw-color-gray-300: #727374; + --shw-color-gray-200: #343536; + --shw-color-gray-100: #1d1e1f; + --shw-color-black: #000; + --shw-color-action-active-foreground: #00f; // HTML "blue" + --shw-color-action-active-border: #00f; // HTML "blue" + --shw-color-action-active-background: #f0f8ff; // HTML "aliceblue" + // COMPONENTS + --shw-frame-browser-navigation-background: #fafafa; + --shw-label-text-color: #545454; + --shw-placeholder-text-color: #6b6b6b; // if background is #EEE then this has the appropriate color contrast (4.59:1) + --shw-placeholder-background-color: #eee; + --shw-placeholder-link-color: #333; +} + +:root { + @include shw-theme-color-variables-light(); +} + +@media (prefers-color-scheme: light) { + :root[data-shw-theme="auto"] { + @include shw-theme-color-variables-light(); + } +} + +.hds-theme-light, +[data-hds-theme="light"] { + @include shw-theme-color-variables-light(); +} From d7e3e92ee8956a00e0ae895e114103a4198fe77e Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 20:17:51 +0100 Subject: [PATCH 017/139] added `Shw::ThemeSwitcher` component for showcase --- .../components/shw/theme-switcher/index.gts | 57 +++++++++++++++++++ showcase/app/styles/app.scss | 1 + .../showcase-components/theme-switcher.scss | 32 +++++++++++ 3 files changed, 90 insertions(+) create mode 100644 showcase/app/components/shw/theme-switcher/index.gts create mode 100644 showcase/app/styles/showcase-components/theme-switcher.scss 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..d2c3c37504b --- /dev/null +++ b/showcase/app/components/shw/theme-switcher/index.gts @@ -0,0 +1,57 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import { on } from '@ember/modifier'; +import { action } from '@ember/object'; +import { service } from '@ember/service'; +import { eq } from 'ember-truth-helpers'; +// import { tracked } from '@glimmer/tracking'; + +import type HdsThemingService from '@hashicorp/design-system-components/services/hds-theming.ts'; + +interface ShwThemeSwitcherSignature { + Element: HTMLDivElement; +} + +const options = { + none: 'None (No theming)', + system: 'System (prefers-color-scheme)', + light: 'Light (data-attribute)', + dark: 'Dark (data-attribute)', +}; + +export default class ShwThemeSwitcher extends Component { + @service declare readonly hdsTheming: HdsThemingService; + + @action + onChangePageTheme(event: Event) { + const select = event.target as HTMLSelectElement; + + // we set the theme in the global service + this.hdsTheming.setTheme(select.value); + } + + +} diff --git a/showcase/app/styles/app.scss b/showcase/app/styles/app.scss index a8808eedabd..ece7e869bb8 100644 --- a/showcase/app/styles/app.scss +++ b/showcase/app/styles/app.scss @@ -24,6 +24,7 @@ @use "./showcase-components/label"; @use "./showcase-components/outliner"; @use "./showcase-components/placeholder"; +@use "./showcase-components/theme-switcher"; @use "./mock-components/app"; @use "./mock-components/demo/breakpoints"; diff --git a/showcase/app/styles/showcase-components/theme-switcher.scss b/showcase/app/styles/showcase-components/theme-switcher.scss new file mode 100644 index 00000000000..f61937282bc --- /dev/null +++ b/showcase/app/styles/showcase-components/theme-switcher.scss @@ -0,0 +1,32 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +.shw-theme-switcher { + display: flex; + gap: 8px; + align-items: center; +} + +.shw-theme-switcher__label { + color: var(--shw-color-black); + font-size: 0.75rem; + font-family: monaco, Consolas, "Lucida Console", monospace; +} + +.shw-theme-switcher__control { + height: 24px; + padding: 2px 24px 2px 8px; + color: var(--shw-color-gray-100); + font-size: 0.75rem; + font-family: monaco, Consolas, "Lucida Console", monospace; + background-color: var(--shw-color-gray-600); + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.34572 7H20.6543C21.8517 7 22.4504 8.4463 21.6028 9.29391L12.9519 17.9515C12.4272 18.4763 11.5728 18.4763 11.0481 17.9515L2.39722 9.29391C1.54961 8.4463 2.14832 7 3.34572 7Z' fill='%23808080'/%3E%3C/svg%3E"); // notice: the 'caret' color is hardcoded here! + background-repeat: no-repeat; + background-position: right 6px top 4px; + background-size: 12px 12px; + border: 1px solid var(--shw-color-gray-400); + border-radius: 3px; + appearance: none; +} From de0984ed00b70b057d6b06dd269b73c6ffef8521 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Tue, 30 Sep 2025 20:24:05 +0100 Subject: [PATCH 018/139] updated `Mock::App` and added new yielded sub-components --- showcase/app/components/mock/app/index.gts | 22 +- .../components/mock/app/main/form-complex.gts | 357 ++++++++++++++++++ .../mock/app/main/generic-text-content.gts | 13 + .../components/mock/app/main/pagination.gts | 31 ++ .../mock/app/main/table-complex.gts | 164 ++++++++ .../mock/app/sidebar/app-side-nav.gts | 9 + .../components/mock/app/sidebar/side-nav.gts | 2 + 7 files changed, 597 insertions(+), 1 deletion(-) create mode 100644 showcase/app/components/mock/app/main/form-complex.gts create mode 100644 showcase/app/components/mock/app/main/pagination.gts create mode 100644 showcase/app/components/mock/app/main/table-complex.gts diff --git a/showcase/app/components/mock/app/index.gts b/showcase/app/components/mock/app/index.gts index e8ffe853e0b..22d4933ec5e 100644 --- a/showcase/app/components/mock/app/index.gts +++ b/showcase/app/components/mock/app/index.gts @@ -11,10 +11,15 @@ import MockAppSidebarOldSideNav from './sidebar/side-nav'; import MockAppMainPageHeader from './main/page-header'; import MockAppMainGenericTextContent from './main/generic-text-content'; import MockAppMainGenericAdvancedTable from './main/generic-advanced-table'; +import MockAppMainFormComplex from './main/form-complex'; +import MockAppMainTableComplex from './main/table-complex'; import MockAppFooterAppFooter from './footer/app-footer'; // HDS components -import { HdsAppFrame } from '@hashicorp/design-system-components/components'; +import { + HdsAlert, + HdsAppFrame, +} from '@hashicorp/design-system-components/components'; // types import type { ComponentLike } from '@glint/template'; @@ -25,10 +30,14 @@ import type { MockAppSidebarOldSideNavSignature } from './sidebar/side-nav'; import type { MockAppMainPageHeaderSignature } from './main/page-header'; import type { MockAppMainGenericTextContentSignature } from './main/generic-text-content'; import type { MockAppMainGenericAdvancedTableSignature } from './main/generic-advanced-table'; +import type { MockAppMainFormComplexSignature } from './main/form-complex'; +import type { MockAppMainTableComplexSignature } from './main/table-complex'; +import type { MockAppMainPaginationSignature } from './main/pagination'; import type { MockAppFooterAppFooterSignature } from './footer/app-footer'; export interface MockAppSignature { Args: { + hasPageAlert?: boolean; hasHeader?: HdsAppFrameSignature['Args']['hasHeader']; hasSidebar?: HdsAppFrameSignature['Args']['hasSidebar']; hasOldSidebar?: boolean; @@ -52,6 +61,9 @@ export interface MockAppSignature { PageHeader?: ComponentLike; GenericTextContent?: ComponentLike; GenericAdvancedTable?: ComponentLike; + FormComplex?: ComponentLike; + TableComplex?: ComponentLike; + Pagination?: ComponentLike; }, ]; footer?: [ @@ -92,12 +104,20 @@ export default class MockApp extends Component { {{/if}} + {{#if @hasPageAlert}} + + Lorem ipsum + Lorem ipsum dolor sit amet. + + {{/if}}
{{yield (hash PageHeader=MockAppMainPageHeader GenericTextContent=MockAppMainGenericTextContent GenericAdvancedTable=MockAppMainGenericAdvancedTable + FormComplex=MockAppMainFormComplex + TableComplex=MockAppMainTableComplex ) to="main" }} diff --git a/showcase/app/components/mock/app/main/form-complex.gts b/showcase/app/components/mock/app/main/form-complex.gts new file mode 100644 index 00000000000..0b32daaedc3 --- /dev/null +++ b/showcase/app/components/mock/app/main/form-complex.gts @@ -0,0 +1,357 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Component from '@glimmer/component'; +import style from 'ember-style-modifier/modifiers/style'; + +// HDS components +import { + HdsButton, + HdsButtonSet, + HdsFormCheckboxGroup, + HdsFormFileInputField, + HdsFormMaskedInputField, + HdsFormRadioGroup, + HdsFormRadioCardGroup, + HdsFormSelectField, + HdsFormSuperSelectSingleField, + HdsFormSuperSelectMultipleField, + HdsFormTextInputField, + HdsFormTextareaField, + HdsFormToggleField, + HdsLinkInline, + HdsSeparator, + HdsTextBody, + HdsTextDisplay, +} from '@hashicorp/design-system-components/components'; + +const RADIOCARDS = [ + { + value: '1', + label: 'Radio card label 1', + badge: 'Badge', + checked: true, + description: 'Radio card description 1', + generic: 'Radio card custom content 1', + }, + { + value: '2', + label: 'Radio card label 2', + badge: 'Badge', + description: 'Radio card description 2', + generic: 'Radio card custom content 2', + }, + { + value: '3', + label: 'Radio card label 3', + badge: 'Badge', + description: 'Radio card description 3', + generic: 'Radio card custom content 3', + }, +]; + +const SUPERSELECT1_OPTIONS = [ + { + size: 'Extra Small', + description: '2 vCPU | 1 GiB RAM', + price: '$0.02', + }, + { + size: 'Small', + description: '2 vCPU | 2 GiB RAM', + price: '$0.04', + disabled: true, + }, + { + size: 'Medium', + description: '4 vCPU | 4 GiB RAM', + price: '$0.08', + disabled: true, + }, + { size: 'Large', description: '8 vCPU | 8 GiB RAM', price: '$0.16' }, + { + size: 'Extra Large', + description: '16 vCPU | 16 GiB RAM', + price: '$0.32', + }, +]; +const SELECTED_SUPERSELECT1_OPTION = SUPERSELECT1_OPTIONS[1]; + +const SUPERSELECT2_OPTIONS = ['Option 1', 'Option 2', 'Option 3']; +const SELECTED_SUPERSELECT2_OPTIONS = [ + SUPERSELECT2_OPTIONS[0], + SUPERSELECT2_OPTIONS[1], +]; + +const noop = () => {}; + +export interface MockAppMainFormComplexSignature { + Args: { + showAll?: boolean; + showErrors?: boolean; + showIntro?: boolean; + showCheckbox?: boolean; + showFileInput?: boolean; + showMaskedInput?: boolean; + showRadio?: boolean; + showRadioCard?: boolean; + showSelect?: boolean; + showSuperSelect?: boolean; + showTextarea?: boolean; + showTextInput?: boolean; + showToggle?: boolean; + showButtons?: boolean; + }; + Element: HTMLDivElement; +} + +export default class MockAppMainFormComplex extends Component { + _showIntro; + _showCheckbox; + _showFileInput; + _showMaskedInput; + _showRadio; + _showRadioCard; + _showSelect; + _showSuperSelect; + _showTextarea; + _showTextInput; + _showToggle; + _showButtons; + _showErrors; + + constructor(owner: unknown, args: MockAppMainFormComplexSignature['Args']) { + super(owner, args); + this._showIntro = this.args.showIntro ?? this.args.showAll ?? false; + this._showCheckbox = this.args.showCheckbox ?? this.args.showAll ?? false; + this._showFileInput = this.args.showFileInput ?? this.args.showAll ?? false; + this._showMaskedInput = + this.args.showMaskedInput ?? this.args.showAll ?? false; + this._showRadio = this.args.showRadio ?? this.args.showAll ?? false; + this._showRadioCard = this.args.showRadioCard ?? this.args.showAll ?? false; + this._showSelect = this.args.showSelect ?? this.args.showAll ?? false; + this._showSuperSelect = + this.args.showSuperSelect ?? this.args.showAll ?? false; + this._showTextarea = this.args.showTextarea ?? this.args.showAll ?? false; + this._showToggle = this.args.showToggle ?? this.args.showAll ?? false; + this._showErrors = this.args.showErrors ?? this.args.showAll ?? false; + // we want at least something to be visible by default + this._showTextInput = this.args.showTextInput ?? this.args.showAll ?? true; + this._showButtons = this.args.showButtons ?? this.args.showAll ?? true; + } + + +} diff --git a/showcase/app/components/mock/app/main/generic-text-content.gts b/showcase/app/components/mock/app/main/generic-text-content.gts index 94c54345959..0fd674d4f35 100644 --- a/showcase/app/components/mock/app/main/generic-text-content.gts +++ b/showcase/app/components/mock/app/main/generic-text-content.gts @@ -8,16 +8,23 @@ import type { TemplateOnlyComponent } from '@ember/component/template-only'; // HDS components import { HdsLinkInline, + HdsTextDisplay, HdsTextBody, } from '@hashicorp/design-system-components/components'; export interface MockAppMainGenericTextContentSignature { + Args: { + showHeadings?: boolean; + }; Element: HTMLDivElement; } const MockAppMainGenericTextContent: TemplateOnlyComponent = diff --git a/showcase/app/components/mock/app/sidebar/side-nav.gts b/showcase/app/components/mock/app/sidebar/side-nav.gts index c5f61f41237..2bfad93852e 100644 --- a/showcase/app/components/mock/app/sidebar/side-nav.gts +++ b/showcase/app/components/mock/app/sidebar/side-nav.gts @@ -153,9 +153,11 @@ export default class MockAppSidebarOldSideNav extends Component + {{yield to="extraBodyAfter"}} <:footer> {{#if this.showFooter}} + {{yield to="extraFooterBefore"}} Date: Tue, 30 Sep 2025 21:20:41 +0100 Subject: [PATCH 019/139] added `Shw:: ThemeSwitcher` to the Showcase page header --- showcase/app/templates/application.gts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/showcase/app/templates/application.gts b/showcase/app/templates/application.gts index f7617b77a00..44bb388835e 100644 --- a/showcase/app/templates/application.gts +++ b/showcase/app/templates/application.gts @@ -14,6 +14,7 @@ import { modifier } from 'ember-modifier'; import { HdsIcon } from '@hashicorp/design-system-components/components'; import ShwLogoDesignSystem from 'showcase/components/shw/logo/design-system'; +import ShwThemeSwitcher from 'showcase/components/shw/theme-switcher'; export default class Application extends Component { @service declare readonly router: RouterService; @@ -68,6 +69,9 @@ export default class Application extends Component {
Components showcase
+
+ +