diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 45646612aad..83730fe9f4e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -797,6 +797,18 @@ importers:
'@glimmer/tracking':
specifier: ^1.1.2
version: 1.1.2
+ '@glint/core':
+ specifier: ^1.5.2
+ version: 1.5.2(typescript@5.9.2)
+ '@glint/environment-ember-loose':
+ specifier: ^1.5.2
+ version: 1.5.2(@glimmer/component@2.0.0)(@glint/template@1.5.2)(ember-cli-htmlbars@6.3.0)(ember-modifier@4.2.2(@babel/core@7.28.0))
+ '@glint/environment-ember-template-imports':
+ specifier: ^1.5.2
+ version: 1.5.2(@glint/environment-ember-loose@1.5.2(@glimmer/component@2.0.0)(@glint/template@1.5.2)(ember-cli-htmlbars@6.3.0)(ember-modifier@4.2.2(@babel/core@7.28.0)))(@glint/template@1.5.2)
+ '@glint/template':
+ specifier: ^1.5.2
+ version: 1.5.2
'@hashicorp/design-system-components':
specifier: workspace:*
version: file:packages/components(@babel/core@7.28.0)(@ember/string@4.0.1)(@ember/test-helpers@5.4.0(@babel/core@7.28.0)(@glint/template@1.5.2))(@glimmer/component@2.0.0)(@glint/environment-ember-loose@1.5.2(@glimmer/component@2.0.0)(@glint/template@1.5.2)(ember-cli-htmlbars@6.3.0)(ember-modifier@4.2.2(@babel/core@7.28.0)))(@glint/template@1.5.2)(ember-basic-dropdown@8.6.2(@babel/core@7.28.0)(@ember/string@4.0.1)(@ember/test-helpers@5.4.0(@babel/core@7.28.0)(@glint/template@1.5.2))(@glimmer/component@2.0.0)(@glint/environment-ember-loose@1.5.2(@glimmer/component@2.0.0)(@glint/template@1.5.2)(ember-cli-htmlbars@6.3.0)(ember-modifier@4.2.2(@babel/core@7.28.0)))(@glint/template@1.5.2)(ember-source@6.4.0(@glimmer/component@2.0.0)(rsvp@4.8.5)))(ember-intl@7.3.1(@ember/test-helpers@5.4.0(@babel/core@7.28.0)(@glint/template@1.5.2))(@glint/template@1.5.2)(typescript@5.9.2)(webpack@5.101.0))(ember-source@6.4.0(@glimmer/component@2.0.0)(rsvp@4.8.5))
@@ -806,6 +818,15 @@ importers:
'@hashicorp/flight-icons':
specifier: workspace:*
version: link:../packages/flight-icons
+ '@tsconfig/ember':
+ specifier: ^3.0.10
+ version: 3.0.11
+ '@types/qunit':
+ specifier: ^2.19.12
+ version: 2.19.12
+ '@types/rsvp':
+ specifier: ^4.0.9
+ version: 4.0.9
algoliasearch:
specifier: ^4.24.0
version: 4.25.2
@@ -1061,6 +1082,12 @@ importers:
stylelint-config-standard-scss:
specifier: ^14.0.0
version: 14.0.0(postcss@8.5.6)(stylelint@16.23.0(typescript@5.9.2))
+ typescript:
+ specifier: ^5.8.3
+ version: 5.9.2
+ typescript-eslint:
+ specifier: ^8.32.1
+ version: 8.38.0(eslint@9.32.0)(typescript@5.9.2)
unified:
specifier: ^11.0.5
version: 11.0.5
diff --git a/website/.ember-cli b/website/.ember-cli
index 465c4050deb..a37e45fab5b 100644
--- a/website/.ember-cli
+++ b/website/.ember-cli
@@ -3,5 +3,17 @@
Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript
rather than JavaScript by default, when a TypeScript version of a given blueprint is available.
*/
- "isTypeScriptProject": false
+ "isTypeScriptProject": true,
+
+ /**
+ Setting `componentAuthoringFormat` to "strict" will force the blueprint generators to generate GJS
+ or GTS files for the component and the component rendering test. "loose" is the default.
+ */
+ "componentAuthoringFormat": "strict",
+
+ /**
+ Setting `routeAuthoringFormat` to "strict" will force the blueprint generators to generate GJS
+ or GTS templates for routes. "loose" is the default
+ */
+ "routeAuthoringFormat": "strict"
}
diff --git a/website/.prettierrc.js b/website/.prettierrc.js
index 68d5b279677..0c6172d13dd 100644
--- a/website/.prettierrc.js
+++ b/website/.prettierrc.js
@@ -2,6 +2,7 @@
module.exports = {
plugins: ['prettier-plugin-ember-template-tag'],
+ templateSingleQuote: false,
overrides: [
{
files: '*.{js,gjs,ts,gts,mjs,mts,cjs,cts}',
diff --git a/website/app/components/doc/a11y-support.gts b/website/app/components/doc/a11y-support.gts
new file mode 100644
index 00000000000..12a92e1eb9b
--- /dev/null
+++ b/website/app/components/doc/a11y-support.gts
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { LinkTo } from '@ember/routing';
+
+const DocA11ySupport: TemplateOnlyComponent =
+ Support
+ If any accessibility issues have been found within
+ this component, let us know by
+ submitting an issue .
+ ;
+
+export default DocA11ySupport;
diff --git a/website/app/components/doc/a11y-support.hbs b/website/app/components/doc/a11y-support.hbs
deleted file mode 100644
index d7c77cd1d52..00000000000
--- a/website/app/components/doc/a11y-support.hbs
+++ /dev/null
@@ -1,8 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
Support
-If any accessibility issues have been found within this component, let us know by
- submitting an issue .
\ No newline at end of file
diff --git a/website/app/components/doc/badge-group/index.gts b/website/app/components/doc/badge-group/index.gts
new file mode 100644
index 00000000000..28153deed04
--- /dev/null
+++ b/website/app/components/doc/badge-group/index.gts
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+interface DocBadgeGroupSignature {
+ Blocks: {
+ default: [];
+ };
+ Element: HTMLDivElement;
+}
+
+const DocBadgeGroup: TemplateOnlyComponent =
+
+ {{yield}}
+
+ ;
+
+export default DocBadgeGroup;
diff --git a/website/app/components/doc/badge-group/index.hbs b/website/app/components/doc/badge-group/index.hbs
deleted file mode 100644
index 3f6bbcd0727..00000000000
--- a/website/app/components/doc/badge-group/index.hbs
+++ /dev/null
@@ -1,8 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{yield}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/component-api/index.gts b/website/app/components/doc/component-api/index.gts
new file mode 100644
index 00000000000..48e110ee9d8
--- /dev/null
+++ b/website/app/components/doc/component-api/index.gts
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { hash } from '@ember/helper';
+
+import DocComponentApiProperty from 'website/components/doc/component-api/property';
+
+interface DocComponentApiSignature {
+ Blocks: {
+ default: [
+ {
+ Property: typeof DocComponentApiProperty;
+ },
+ ];
+ };
+ Element: HTMLDivElement;
+}
+
+const DocComponentApi: TemplateOnlyComponent =
+
+
+ {{yield (hash Property=DocComponentApiProperty)}}
+
+ ;
+
+export default DocComponentApi;
diff --git a/website/app/components/doc/component-api/index.hbs b/website/app/components/doc/component-api/index.hbs
deleted file mode 100644
index 5899bc92d69..00000000000
--- a/website/app/components/doc/component-api/index.hbs
+++ /dev/null
@@ -1,8 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{yield (hash Property=(component "doc/component-api/property"))}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/component-api/property.gts b/website/app/components/doc/component-api/property.gts
new file mode 100644
index 00000000000..a7700b34cef
--- /dev/null
+++ b/website/app/components/doc/component-api/property.gts
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { or, eq } from 'ember-truth-helpers';
+import type { WithBoundArgs } from '@glint/template';
+import { hash } from '@ember/helper';
+
+import DocBadge from 'website/components/doc/badge';
+import DocBanner from 'website/components/doc/banner';
+
+export interface DocComponentApiPropertySignature {
+ Args: {
+ name?: string;
+ type?: string;
+ required?: boolean;
+ deprecated?: boolean;
+ values?: string[];
+ default?: string;
+ valueNote?: string;
+ };
+ Blocks: {
+ default: [
+ {
+ Banner: WithBoundArgs;
+ },
+ ];
+ };
+ Element: HTMLDivElement;
+}
+
+const DocComponentApiProperty: TemplateOnlyComponent =
+
+
+ {{#if @name}}
+
+ {{@name}}
+ {{#if @type}}
+ {{@type}}
+ {{/if}}
+ {{#if @required}}
+ {{! @glint-expect-error - component not typed yet }}
+ Required
+ {{/if}}
+ {{#if @deprecated}}
+ {{! @glint-expect-error - component not typed yet }}
+ Deprecated
+ {{/if}}
+
+ {{/if}}
+ {{#if (or @values @valueNote)}}
+ {{#if @values}}
+
+ {{#each @values as |value|}}
+
+ {{value}}{{#if (eq @default value)}}
+ (default) {{/if}}
+
+ {{/each}}
+
+ {{else if @valueNote}}
+
+ {{@valueNote}}
+
+ {{/if}}
+ {{else if @default}}
+
+
+ {{@default}}
+ (default)
+
+
+ {{/if}}
+ {{#if (has-block)}}
+
+ {{yield (hash Banner=(component DocBanner type="warning"))}}
+
+ {{/if}}
+
+ ;
+
+export default DocComponentApiProperty;
diff --git a/website/app/components/doc/component-api/property.hbs b/website/app/components/doc/component-api/property.hbs
deleted file mode 100644
index fc244baf79b..00000000000
--- a/website/app/components/doc/component-api/property.hbs
+++ /dev/null
@@ -1,51 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{#if @name}}
-
- {{@name}}
- {{#if @type}}
- {{@type}}
- {{/if}}
- {{#if @required}}
- Required
- {{/if}}
- {{#if @deprecated}}
- Deprecated
- {{/if}}
-
- {{/if}}
- {{#if (or @values @valueNote)}}
- {{#if @values}}
-
- {{#each @values as |value|}}
-
- {{value}}{{#if (eq @default value)}} (default) {{/if}}
-
- {{/each}}
-
- {{else if @valueNote}}
-
- {{@valueNote}}
-
- {{/if}}
- {{else if @default}}
-
-
- {{@default}}
- (default)
-
-
- {{/if}}
- {{#if (has-block)}}
-
- {{yield (hash Banner=(component "doc/banner" type="warning"))}}
-
- {{/if}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/font-helpers-list/index.gts b/website/app/components/doc/font-helpers-list/index.gts
new file mode 100644
index 00000000000..4100b879e8e
--- /dev/null
+++ b/website/app/components/doc/font-helpers-list/index.gts
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+import DocCopyButton from 'website/components/doc/copy-button';
+
+interface DocFontHelpersListSignature {
+ Args: {
+ items: Array<{
+ previewClass: string;
+ previewText: string;
+ copyText?: string;
+ otherText?: string;
+ }>;
+ };
+}
+
+const DocFontHelpersList: TemplateOnlyComponent =
+
+
+ ;
+
+export default DocFontHelpersList;
diff --git a/website/app/components/doc/font-helpers-list/index.hbs b/website/app/components/doc/font-helpers-list/index.hbs
deleted file mode 100644
index 7f506b31cad..00000000000
--- a/website/app/components/doc/font-helpers-list/index.hbs
+++ /dev/null
@@ -1,21 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/form/filter.gts b/website/app/components/doc/form/filter.gts
new file mode 100644
index 00000000000..263d889c64a
--- /dev/null
+++ b/website/app/components/doc/form/filter.gts
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import Component from '@glimmer/component';
+import { guidFor } from '@ember/object/internals';
+import { on } from '@ember/modifier';
+import perform from 'ember-concurrency/helpers/perform';
+
+import DocFormLabel from 'website/components/doc/form/label';
+
+interface DocFormFilterSignature {
+ Args: {
+ label?: string;
+ placeholder?: string;
+ filterQuery?: string;
+ onInput: (query: string) => void;
+ isCompact?: boolean;
+ };
+ Element: HTMLInputElement;
+}
+
+export default class DocFormFilter extends Component {
+ filterId = guidFor(this);
+
+
+
+ {{#if @label}}
+
+ {{/if}}
+
+
+
+}
diff --git a/website/app/components/doc/form/filter.hbs b/website/app/components/doc/form/filter.hbs
deleted file mode 100644
index c5f10c818bc..00000000000
--- a/website/app/components/doc/form/filter.hbs
+++ /dev/null
@@ -1,23 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{#let (unique-id) as |filterId|}}
- {{#if @label}}
-
- {{/if}}
-
- {{/let}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/form/label.gts b/website/app/components/doc/form/label.gts
new file mode 100644
index 00000000000..3d234704cd6
--- /dev/null
+++ b/website/app/components/doc/form/label.gts
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+interface DocFormLabelSignature {
+ Args: {
+ label: string;
+ for: string;
+ };
+}
+
+const DocFormLabel: TemplateOnlyComponent =
+ {{@label}}
+ ;
+
+export default DocFormLabel;
diff --git a/website/app/components/doc/form/label.hbs b/website/app/components/doc/form/label.hbs
deleted file mode 100644
index 551c3d1fd63..00000000000
--- a/website/app/components/doc/form/label.hbs
+++ /dev/null
@@ -1,6 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-{{@label}}
\ No newline at end of file
diff --git a/website/app/components/doc/form/select-group-type.js b/website/app/components/doc/form/select-group-type.js
new file mode 100644
index 00000000000..4784b01cb60
--- /dev/null
+++ b/website/app/components/doc/form/select-group-type.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocFormSelectGroupType = TemplateOnlyComponent();
+
+export default DocFormSelectGroupType;
diff --git a/website/app/components/doc/form/select.gts b/website/app/components/doc/form/select.gts
new file mode 100644
index 00000000000..27f5181b83e
--- /dev/null
+++ b/website/app/components/doc/form/select.gts
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import Component from '@glimmer/component';
+import { guidFor } from '@ember/object/internals';
+import { on } from '@ember/modifier';
+import { eq } from 'ember-truth-helpers';
+
+import DocFormLabel from 'website/components/doc/form/label';
+
+interface DocFormSelectSignature {
+ Args: {
+ label: string;
+ selectedValue: string;
+ onSelect: (event: Event) => void;
+ };
+}
+
+export default class DocFormSelect extends Component {
+ selectId = guidFor(this);
+
+
+
+
+
+ 16px
+ 24px
+
+
+
+}
diff --git a/website/app/components/doc/form/select.hbs b/website/app/components/doc/form/select.hbs
deleted file mode 100644
index def867519d0..00000000000
--- a/website/app/components/doc/form/select.hbs
+++ /dev/null
@@ -1,14 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{#let (unique-id) as |selectId|}}
-
-
- 16px
- 24px
-
- {{/let}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/icons-list/grid.gts b/website/app/components/doc/icons-list/grid.gts
new file mode 100644
index 00000000000..dcabc076f7f
--- /dev/null
+++ b/website/app/components/doc/icons-list/grid.gts
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { capitalize } from '@ember/string';
+
+import type { HdsIconSignature } from '@hashicorp/design-system-components/components/hds/icon/index';
+
+import DocIconsListItem from 'website/components/doc/icons-list/item';
+
+export interface CategoryIcon {
+ iconName: HdsIconSignature['Args']['name'];
+ name: string;
+ description: string;
+ size: HdsIconSignature['Args']['size'];
+ isHidden?: boolean;
+}
+
+interface DocIconsListGridSignature {
+ Args: {
+ categoryName?: string;
+ categoryIcons: CategoryIcon[];
+ };
+}
+
+const DocIconsListGrid: TemplateOnlyComponent =
+
+ {{#if @categoryName}}
+ {{capitalize @categoryName}}
+ {{/if}}
+
+ {{#each @categoryIcons as |meta|}}
+
+ {{/each}}
+
+ ;
+
+export default DocIconsListGrid;
diff --git a/website/app/components/doc/icons-list/grid.hbs b/website/app/components/doc/icons-list/grid.hbs
deleted file mode 100644
index 32f0794d22a..00000000000
--- a/website/app/components/doc/icons-list/grid.hbs
+++ /dev/null
@@ -1,12 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-{{#if @categoryName}}
- {{capitalize @categoryName}}
-{{/if}}
-
- {{#each @categoryIcons as |meta|}}
-
- {{/each}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/icons-list/index.gts b/website/app/components/doc/icons-list/index.gts
new file mode 100644
index 00000000000..7f6bcd56dbe
--- /dev/null
+++ b/website/app/components/doc/icons-list/index.gts
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+import DocIconsListGrid from 'website/components/doc/icons-list/grid';
+import DocFormFilter from 'website/components/doc/form/filter';
+import DocFormSelect from 'website/components/doc/form/select';
+import DocFormSelectGroupType from 'website/components/doc/form/select-group-type';
+import type { CategoryIcon } from 'website/components/doc/icons-list/grid';
+
+interface DocIconsListSignature {
+ Args: {
+ searchQuery: string;
+ onSelectGroupType: (event: Event) => void;
+ selectedGroupType: string;
+ onSelectIconSize: (event: Event) => void;
+ selectedIconSize: string;
+ searchIcons: (query: string) => void;
+ groupedIcons: Record;
+ };
+}
+
+const DocIconsList: TemplateOnlyComponent =
+
+
+ Note: Icon list will
+ automatically update as you type.
+
+
+
+
+ {{#each-in @groupedIcons as |categoryName categoryIcons|}}
+
+ {{else}}
+ No icons found. 🤷♀️
+ {{/each-in}}
+ ;
+
+export default DocIconsList;
diff --git a/website/app/components/doc/icons-list/index.hbs b/website/app/components/doc/icons-list/index.hbs
deleted file mode 100644
index ba9cd0c5067..00000000000
--- a/website/app/components/doc/icons-list/index.hbs
+++ /dev/null
@@ -1,28 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
-
- Note: Icon list will automatically update as you type.
-
-
-
-
-{{#each-in @groupedIcons as |categoryName categoryIcons|}}
-
-{{else}}
- No icons found. 🤷♀️
-{{/each-in}}
\ No newline at end of file
diff --git a/website/app/components/doc/icons-list/item.gts b/website/app/components/doc/icons-list/item.gts
new file mode 100644
index 00000000000..453f7e2cc89
--- /dev/null
+++ b/website/app/components/doc/icons-list/item.gts
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { hash, concat } from '@ember/helper';
+import { LinkTo } from '@ember/routing';
+
+import { HdsIcon } from '@hashicorp/design-system-components/components';
+import type { HdsIconSignature } from '@hashicorp/design-system-components/components/hds/icon/index';
+
+import DocMetaRow from 'website/components/doc/meta-row';
+
+interface DocIconsListItemSignature {
+ Args: {
+ meta: {
+ iconName: HdsIconSignature['Args']['name'];
+ name: string;
+ description: string;
+ size: HdsIconSignature['Args']['size'];
+ isHidden?: boolean;
+ };
+ };
+}
+
+const DocIconsListItem: TemplateOnlyComponent =
+
+
+
+
+
+
+
+ {{#let (concat "icon:" @meta.iconName) as |searchQueryValue|}}
+
+
+
+ {{/let}}
+
+
+ ;
+
+export default DocIconsListItem;
diff --git a/website/app/components/doc/icons-list/item.hbs b/website/app/components/doc/icons-list/item.hbs
deleted file mode 100644
index 5f1838b4c20..00000000000
--- a/website/app/components/doc/icons-list/item.hbs
+++ /dev/null
@@ -1,29 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
-
-
-
-
-
- {{#let (concat "icon:" @meta.iconName) as |searchQueryValue|}}
-
-
-
- {{/let}}
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/image-caption/index.gts b/website/app/components/doc/image-caption/index.gts
new file mode 100644
index 00000000000..7d0f0070603
--- /dev/null
+++ b/website/app/components/doc/image-caption/index.gts
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+interface DocImageCaptionSignature {
+ Args: {
+ text: string;
+ };
+ Element: HTMLDivElement;
+}
+
+const DocImageCaption: TemplateOnlyComponent =
+
+
+ {{@text}}
+
+ ;
+
+export default DocImageCaption;
diff --git a/website/app/components/doc/image-caption/index.hbs b/website/app/components/doc/image-caption/index.hbs
deleted file mode 100644
index 302ad27095d..00000000000
--- a/website/app/components/doc/image-caption/index.hbs
+++ /dev/null
@@ -1,8 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{@text}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/logo/design-system.gts b/website/app/components/doc/logo/design-system.gts
new file mode 100644
index 00000000000..62fe9a98a30
--- /dev/null
+++ b/website/app/components/doc/logo/design-system.gts
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+const DocLogoDesignSystem: TemplateOnlyComponent =
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+
+export default DocLogoDesignSystem;
diff --git a/website/app/components/doc/logo/design-system.hbs b/website/app/components/doc/logo/design-system.hbs
deleted file mode 100644
index 37fbf188933..00000000000
--- a/website/app/components/doc/logo/design-system.hbs
+++ /dev/null
@@ -1,126 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/logo/hashi-corp.gts b/website/app/components/doc/logo/hashi-corp.gts
new file mode 100644
index 00000000000..35b9941e358
--- /dev/null
+++ b/website/app/components/doc/logo/hashi-corp.gts
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+const DocLogoHashiCorp: TemplateOnlyComponent =
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+
+export default DocLogoHashiCorp;
diff --git a/website/app/components/doc/logo/hashi-corp.hbs b/website/app/components/doc/logo/hashi-corp.hbs
deleted file mode 100644
index 169f9a1d2aa..00000000000
--- a/website/app/components/doc/logo/hashi-corp.hbs
+++ /dev/null
@@ -1,108 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/meta-row.gts b/website/app/components/doc/meta-row.gts
new file mode 100644
index 00000000000..daebbd89886
--- /dev/null
+++ b/website/app/components/doc/meta-row.gts
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { or } from 'ember-truth-helpers';
+
+import DocCopyButton from 'website/components/doc/copy-button';
+
+interface DocMetaRowSignature {
+ Args: {
+ label: string;
+ valueToShow?: string;
+ valueToCopy?: string;
+ multipleValuesToShow?: string[];
+ copyable?: boolean;
+ isClipped?: boolean;
+ };
+ Element: HTMLDivElement;
+}
+
+const DocMetaRow: TemplateOnlyComponent =
+
+ ;
+
+export default DocMetaRow;
diff --git a/website/app/components/doc/meta-row.hbs b/website/app/components/doc/meta-row.hbs
deleted file mode 100644
index 596196480e8..00000000000
--- a/website/app/components/doc/meta-row.hbs
+++ /dev/null
@@ -1,29 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/npm-version.gts b/website/app/components/doc/npm-version.gts
new file mode 100644
index 00000000000..28838025f7c
--- /dev/null
+++ b/website/app/components/doc/npm-version.gts
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+const DocNpmVersion: TemplateOnlyComponent =
+
+
+
+ ;
+
+export default DocNpmVersion;
diff --git a/website/app/components/doc/npm-version.hbs b/website/app/components/doc/npm-version.hbs
deleted file mode 100644
index fdf6a82f585..00000000000
--- a/website/app/components/doc/npm-version.hbs
+++ /dev/null
@@ -1,12 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/page/content.gts b/website/app/components/doc/page/content.gts
new file mode 100644
index 00000000000..22683ef13f0
--- /dev/null
+++ b/website/app/components/doc/page/content.gts
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import Component from '@glimmer/component';
+
+import DocScrollToTop from 'website/components/doc/scroll-to-top';
+
+interface DocPageContentSignature {
+ Args: {
+ breakthrough?: boolean;
+ };
+ Blocks: {
+ default: [];
+ };
+ Element: HTMLDivElement;
+}
+
+export default class DocPageContentComponent extends Component {
+ get classNames() {
+ const classes = ['doc-page-content'];
+
+ // add a class based on the @breakthrough argument
+ if (this.args.breakthrough) {
+ classes.push(`doc-page-content--breakthrough`);
+ }
+
+ return classes.join(' ');
+ }
+
+
+
+ {{yield}}
+
+
+
+}
diff --git a/website/app/components/doc/page/content.hbs b/website/app/components/doc/page/content.hbs
deleted file mode 100644
index cbf358a700e..00000000000
--- a/website/app/components/doc/page/content.hbs
+++ /dev/null
@@ -1,9 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{yield}}
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/page/content.js b/website/app/components/doc/page/content.js
deleted file mode 100644
index 65fdc2ac2b9..00000000000
--- a/website/app/components/doc/page/content.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) HashiCorp, Inc.
- * SPDX-License-Identifier: MPL-2.0
- */
-
-import Component from '@glimmer/component';
-
-export default class DocPageContentComponent extends Component {
- get classNames() {
- let classes = ['doc-page-content'];
-
- // add a class based on the @breakthrough argument
- if (this.args.breakthrough) {
- classes.push(`doc-page-content--breakthrough`);
- }
-
- return classes.join(' ');
- }
-}
diff --git a/website/app/components/doc/page/footer.gts b/website/app/components/doc/page/footer.gts
new file mode 100644
index 00000000000..faef25910bd
--- /dev/null
+++ b/website/app/components/doc/page/footer.gts
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { LinkTo } from '@ember/routing';
+
+import DocLogoHashiCorp from 'website/components/doc/logo/hashi-corp';
+import docTrackEvent from 'website/modifiers/doc-track-event';
+
+interface DocFooterSignature {
+ Element: HTMLElement;
+}
+
+const DocFooter: TemplateOnlyComponent =
+
+ ;
+
+export default DocFooter;
diff --git a/website/app/components/doc/page/footer.hbs b/website/app/components/doc/page/footer.hbs
deleted file mode 100644
index 24c4d5eb025..00000000000
--- a/website/app/components/doc/page/footer.hbs
+++ /dev/null
@@ -1,58 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
\ No newline at end of file
diff --git a/website/app/components/doc/page/header/index.js b/website/app/components/doc/page/header/index.js
new file mode 100644
index 00000000000..263c08458cc
--- /dev/null
+++ b/website/app/components/doc/page/header/index.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocPageHeader = TemplateOnlyComponent();
+
+export default DocPageHeader;
diff --git a/website/app/components/doc/page/header/nav-item.js b/website/app/components/doc/page/header/nav-item.js
new file mode 100644
index 00000000000..1ee1e4c8a12
--- /dev/null
+++ b/website/app/components/doc/page/header/nav-item.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocPageHeaderNavItem = TemplateOnlyComponent();
+
+export default DocPageHeaderNavItem;
diff --git a/website/app/components/doc/page/sidecar.js b/website/app/components/doc/page/sidecar.js
new file mode 100644
index 00000000000..3f5113be730
--- /dev/null
+++ b/website/app/components/doc/page/sidecar.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocPageSidecar = TemplateOnlyComponent();
+
+export default DocPageSidecar;
diff --git a/website/app/components/doc/page/stage.gts b/website/app/components/doc/page/stage.gts
new file mode 100644
index 00000000000..46d34126d0b
--- /dev/null
+++ b/website/app/components/doc/page/stage.gts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+interface DocPageStageSignature {
+ Blocks: {
+ default: [];
+ };
+ Element: HTMLElement;
+}
+
+const DocPageStage: TemplateOnlyComponent =
+
+ {{yield}}
+
+ ;
+
+export default DocPageStage;
diff --git a/website/app/components/doc/page/stage.hbs b/website/app/components/doc/page/stage.hbs
deleted file mode 100644
index 5b36f5e97c7..00000000000
--- a/website/app/components/doc/page/stage.hbs
+++ /dev/null
@@ -1,8 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{yield}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/related-components/index.gts b/website/app/components/doc/related-components/index.gts
new file mode 100644
index 00000000000..08f50858418
--- /dev/null
+++ b/website/app/components/doc/related-components/index.gts
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+import { concat } from '@ember/helper';
+
+import DocCardsDeck from 'website/components/doc/cards/deck';
+import DocCardsCard from 'website/components/doc/cards/card';
+import docTrackEvent from 'website/modifiers/doc-track-event';
+
+interface DocRelatedComponentsSignature {
+ Args: {
+ componentTitle: string;
+ cards: Array<{
+ image?: string;
+ title: string;
+ caption?: string;
+ route?: string;
+ model?: unknown;
+ href?: string;
+ }>;
+ };
+}
+
+const DocRelatedComponents: TemplateOnlyComponent =
+
+
+
+ Related
+
+ {{! @glint-expect-error - component not typed yet }}
+
+ {{#each @cards as |card|}}
+
+ {{/each}}
+
+ ;
+
+export default DocRelatedComponents;
diff --git a/website/app/components/doc/related-components/index.hbs b/website/app/components/doc/related-components/index.hbs
deleted file mode 100644
index 7f976f9c854..00000000000
--- a/website/app/components/doc/related-components/index.hbs
+++ /dev/null
@@ -1,23 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
-
-Related
-
-
- {{#each @cards as |card|}}
-
- {{/each}}
-
\ No newline at end of file
diff --git a/website/app/components/doc/table-of-contents/index.js b/website/app/components/doc/table-of-contents/index.js
new file mode 100644
index 00000000000..f4087dea118
--- /dev/null
+++ b/website/app/components/doc/table-of-contents/index.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocTableOfContents = TemplateOnlyComponent();
+
+export default DocTableOfContents;
diff --git a/website/app/components/doc/tokens-list/grid.js b/website/app/components/doc/tokens-list/grid.js
new file mode 100644
index 00000000000..86623643527
--- /dev/null
+++ b/website/app/components/doc/tokens-list/grid.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocTokensListGrid = TemplateOnlyComponent();
+
+export default DocTokensListGrid;
diff --git a/website/app/components/doc/tokens-list/index.js b/website/app/components/doc/tokens-list/index.js
new file mode 100644
index 00000000000..46236d70307
--- /dev/null
+++ b/website/app/components/doc/tokens-list/index.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const DocTokensList = TemplateOnlyComponent();
+
+export default DocTokensList;
diff --git a/website/app/components/doc/vars-list/index.gts b/website/app/components/doc/vars-list/index.gts
new file mode 100644
index 00000000000..75f643fa310
--- /dev/null
+++ b/website/app/components/doc/vars-list/index.gts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+import type { TemplateOnlyComponent } from '@ember/component/template-only';
+
+import DocCopyButton from 'website/components/doc/copy-button';
+
+interface DocVarsListSignature {
+ Args: {
+ items: string[];
+ };
+}
+
+const DocVarsList: TemplateOnlyComponent =
+
+ {{#each @items as |item|}}
+
+
+
+ {{/each}}
+
+ ;
+
+export default DocVarsList;
diff --git a/website/app/components/doc/vars-list/index.hbs b/website/app/components/doc/vars-list/index.hbs
deleted file mode 100644
index 3764a3a5841..00000000000
--- a/website/app/components/doc/vars-list/index.hbs
+++ /dev/null
@@ -1,12 +0,0 @@
-{{!
- Copyright (c) HashiCorp, Inc.
- SPDX-License-Identifier: MPL-2.0
-}}
-
-
- {{#each @items as |item|}}
-
-
-
- {{/each}}
-
\ No newline at end of file
diff --git a/website/app/components/power-select/selected-option-multiple.js b/website/app/components/power-select/selected-option-multiple.js
new file mode 100644
index 00000000000..c1753ae85e1
--- /dev/null
+++ b/website/app/components/power-select/selected-option-multiple.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const PowerSelectSelectedOptionMultiple = TemplateOnlyComponent();
+
+export default PowerSelectSelectedOptionMultiple;
diff --git a/website/app/components/power-select/selected-option-single.js b/website/app/components/power-select/selected-option-single.js
new file mode 100644
index 00000000000..d26debac481
--- /dev/null
+++ b/website/app/components/power-select/selected-option-single.js
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import TemplateOnlyComponent from '@ember/component/template-only';
+
+const PowerSelectSelectedOptionSingle = TemplateOnlyComponent();
+
+export default PowerSelectSelectedOptionSingle;
diff --git a/website/app/routes/index.js b/website/app/routes/index.ts
similarity index 100%
rename from website/app/routes/index.js
rename to website/app/routes/index.ts
diff --git a/website/app/templates/head.hbs b/website/app/templates/head.hbs
index fa23b64f2fb..050df1a4233 100644
--- a/website/app/templates/head.hbs
+++ b/website/app/templates/head.hbs
@@ -3,6 +3,8 @@
SPDX-License-Identifier: MPL-2.0
}}
+{{! @glint-nocheck - not typesafe yet (need the model from the show.js file to apply here) }}
+
{{!
Per https://github.com/shipshapecode/ember-meta#defining-your-own-headhbs this is a place where we can customize what information is injected by the ember-meta addon
@@ -11,12 +13,14 @@ We've made some small customizations to simplify this compared to the default te
}}
+{{! We need to disable no-forbidden-elements here because generally meta tags aren't allowed in template files }}
+{{! template-lint-disable no-forbidden-elements }}
+
{{! BEGIN GENERAL }}
{{#if this.model.description}}
{{/if}}
-
{{#if this.model.url}}
diff --git a/website/ember-cli-build.js b/website/ember-cli-build.js
index c425fdec469..eda08831b92 100644
--- a/website/ember-cli-build.js
+++ b/website/ember-cli-build.js
@@ -11,6 +11,7 @@ const isVercelProduction = process.env.VERCEL_ENV === 'production';
module.exports = function (defaults) {
const app = new EmberApp(defaults, {
+ 'ember-cli-babel': { enableTypeScriptTransform: true },
// Add options here
sassOptions: {
precision: 4,
diff --git a/website/eslint.config.mjs b/website/eslint.config.mjs
index 0e18d8cc3b5..9b686c470d8 100644
--- a/website/eslint.config.mjs
+++ b/website/eslint.config.mjs
@@ -20,29 +20,44 @@
import globals from 'globals';
import js from '@eslint/js';
+import ts from 'typescript-eslint';
+
import ember from 'eslint-plugin-ember/recommended';
+
import eslintConfigPrettier from 'eslint-config-prettier';
import qunit from 'eslint-plugin-qunit';
import n from 'eslint-plugin-n';
import babelParser from '@babel/eslint-parser';
-const esmParserOptions = {
- ecmaFeatures: { modules: true },
- ecmaVersion: 'latest',
- requireConfigFile: false,
- babelOptions: {
- plugins: [
- ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
- ],
+const parserOptions = {
+ esm: {
+ js: {
+ ecmaFeatures: { modules: true },
+ ecmaVersion: 'latest',
+ requireConfigFile: false,
+ babelOptions: {
+ plugins: [
+ [
+ '@babel/plugin-proposal-decorators',
+ { decoratorsBeforeExport: true },
+ ],
+ ],
+ },
+ },
+ ts: {
+ projectService: true,
+ tsconfigRootDir: import.meta.dirname,
+ },
},
};
-export default [
+export default ts.config(
js.configs.recommended,
- eslintConfigPrettier,
ember.configs.base,
ember.configs.gjs,
+ ember.configs.gts,
+ eslintConfigPrettier,
/**
* Ignores must be in their own object
* https://eslint.org/docs/latest/use/configure/ignore
@@ -74,14 +89,22 @@ export default [
{
files: ['**/*.{js,gjs}'],
languageOptions: {
- parserOptions: esmParserOptions,
+ parserOptions: parserOptions.esm.js,
globals: {
...globals.browser,
},
},
},
{
- files: ['tests/**/*-test.{js,gjs}'],
+ files: ['**/*.{ts,gts}'],
+ languageOptions: {
+ parser: ember.parser,
+ parserOptions: parserOptions.esm.ts,
+ },
+ extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts],
+ },
+ {
+ files: ['tests/**/*-test.{js,gjs,ts,gts}'],
plugins: {
qunit,
},
@@ -93,10 +116,8 @@ export default [
files: [
'**/*.cjs',
'config/**/*.js',
- 'tests/dummy/config/**/*.js',
'testem.js',
'testem*.js',
- 'index.js',
'.prettierrc.js',
'.stylelintrc.js',
'.template-lintrc.js',
@@ -126,10 +147,10 @@ export default [
languageOptions: {
sourceType: 'module',
ecmaVersion: 'latest',
- parserOptions: esmParserOptions,
+ parserOptions: parserOptions.esm.js,
globals: {
...globals.node,
},
},
},
-];
+);
diff --git a/website/package.json b/website/package.json
index 07e40e8b806..3adfbcfdb04 100644
--- a/website/package.json
+++ b/website/package.json
@@ -30,6 +30,7 @@
"lint:js": "eslint . --cache",
"lint:js:fix": "eslint . --fix",
"lint:spell:docs": "cspell --no-progress --show-suggestions --show-context \"docs/**/*.md\"",
+ "lint:types": "glint",
"start": "pnpm build:packages && ember serve",
"start:prember": "pnpm build:packages && PREMBER=true ember serve",
"algolia:index": "node docs-scraper/index-website-content.mjs",
@@ -53,9 +54,16 @@
"@eslint/js": "^9.27.0",
"@glimmer/component": "^2.0.0",
"@glimmer/tracking": "^1.1.2",
+ "@glint/core": "^1.5.2",
+ "@glint/environment-ember-loose": "^1.5.2",
+ "@glint/environment-ember-template-imports": "^1.5.2",
+ "@glint/template": "^1.5.2",
"@hashicorp/design-system-components": "workspace:*",
"@hashicorp/design-system-tokens": "workspace:*",
"@hashicorp/flight-icons": "workspace:*",
+ "@tsconfig/ember": "^3.0.10",
+ "@types/qunit": "^2.19.12",
+ "@types/rsvp": "^4.0.9",
"algoliasearch": "^4.24.0",
"broccoli-asset-rev": "^3.0.0",
"broccoli-funnel": "^3.0.8",
@@ -141,6 +149,8 @@
"stylelint": "^16.12.0",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-standard-scss": "^14.0.0",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.32.1",
"unified": "^11.0.5",
"unist-util-remove": "^4.0.0",
"unist-util-select": "^5.1.0",
diff --git a/website/tsconfig.json b/website/tsconfig.json
new file mode 100644
index 00000000000..26f80a3b2da
--- /dev/null
+++ b/website/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "@tsconfig/ember",
+ "glint": {
+ "environment": ["ember-loose", "ember-template-imports"]
+ },
+ "compilerOptions": {
+ "allowJs": true,
+ "paths": {
+ "website/tests/*": ["./tests/*"],
+ "website/*": ["./app/*"],
+ "*": ["./types/*"]
+ },
+ "types": ["ember-source/types"]
+ },
+ "include": ["app/**/*", "tests/**/*", "types/**/*"]
+}
diff --git a/website/types/global.d.ts b/website/types/global.d.ts
new file mode 100644
index 00000000000..4a8946524a9
--- /dev/null
+++ b/website/types/global.d.ts
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: MPL-2.0
+ */
+
+import '@glint/environment-ember-loose';
+import '@glint/environment-ember-template-imports';
+
+import type PageTitleRegistry from 'ember-page-title/template-registry';
+import type EmberTruthRegistry from 'ember-truth-helpers/template-registry';
+
+import type HdsComponentsRegistry from '@hashicorp/design-system-components/template-registry';
+
+import type WebsiteRegistry from './template-registry';
+
+declare module '@glint/environment-ember-loose/registry' {
+ export default interface Registry
+ extends HdsComponentsRegistry,
+ PageTitleRegistry,
+ EmberTruthRegistry,
+ WebsiteRegistry {}
+}
diff --git a/website/types/template-registry.ts b/website/types/template-registry.ts
new file mode 100644
index 00000000000..478ec737eb0
--- /dev/null
+++ b/website/types/template-registry.ts
@@ -0,0 +1,213 @@
+import DocA11ySupport from '../app/components/doc/a11y-support';
+import DocBadge from '../app/components/doc/badge';
+import DocBadgeGroup from '../app/components/doc/badge-group';
+import DocBanner from '../app/components/doc/banner';
+import DocCardsCard from '../app/components/doc/cards/card';
+import DocCardsDeck from '../app/components/doc/cards/deck';
+import DocColorCard from '../app/components/doc/color-card';
+import DocColorSwatch from '../app/components/doc/color-swatch';
+import DocComponentApi from '../app/components/doc/component-api';
+import DocComponentApiProperty from '../app/components/doc/component-api/property';
+import DocContentHdsPrinciples from '../app/components/doc/content/hds-principles';
+import DocCopyButton from '../app/components/doc/copy-button';
+import DocDoDont from '../app/components/doc/do-dont';
+import DocFontHelpersList from '../app/components/doc/font-helpers-list';
+import DocFormFilter from '../app/components/doc/form/filter';
+import DocFormLabel from '../app/components/doc/form/label';
+import DocFormSelectGroupType from '../app/components/doc/form/select-group-type';
+import DocFormSelect from '../app/components/doc/form/select';
+import DocIconsListGrid from '../app/components/doc/icons-list/grid';
+import DocIconsListItem from '../app/components/doc/icons-list/item';
+import DocIconsList from '../app/components/doc/icons-list';
+import DocImageCaption from '../app/components/doc/image-caption';
+import DocLayout from '../app/components/doc/layout';
+import DocLinkWithIcon from '../app/components/doc/link-with-icon';
+import DocLogoDesignSystem from '../app/components/doc/logo/design-system';
+import DocLogoHashiCorp from '../app/components/doc/logo/hashi-corp';
+import DocMetaRow from '../app/components/doc/meta-row';
+import DocNpmVersion from '../app/components/doc/npm-version';
+import DocPageHeaderAlgoliaSearch from '../app/components/doc/page/header/algolia-search';
+import DocPageHeader from '../app/components/doc/page/header';
+import DocPageHeaderNavItem from '../app/components/doc/page/header/nav-item';
+import DocPageBanner from '../app/components/doc/page/banner';
+import DocPageContent from '../app/components/doc/page/content';
+import DocPageCover from '../app/components/doc/page/cover';
+import DocPageFooter from '../app/components/doc/page/footer';
+import DocPageSidebar from '../app/components/doc/page/sidebar';
+import DocPageSidecar from '../app/components/doc/page/sidecar';
+import DocPageStage from '../app/components/doc/page/stage';
+import DocPageTabs from '../app/components/doc/page/tabs';
+import DocPlaceholder from '../app/components/doc/placeholder';
+import DocRelatedComponents from '../app/components/doc/related-components';
+import DocScrollToTop from '../app/components/doc/scroll-to-top';
+import DocTableOfContents from '../app/components/doc/table-of-contents';
+import DocTableOfContentsCollapsibleItem from '../app/components/doc/table-of-contents/collapsible-item';
+import DocTokenPreview from '../app/components/doc/token-preview';
+import DocTokensList from '../app/components/doc/tokens-list';
+import DocTokensListGrid from '../app/components/doc/tokens-list/grid';
+import DocTokensListItem from '../app/components/doc/tokens-list/item';
+import DocVarsList from '../app/components/doc/vars-list';
+import DocWcagList from '../app/components/doc/wcag-list';
+
+import DynamicTemplateError from '../app/components/dynamic-template-error';
+import DynamicTemplate from '../app/components/dynamic-template';
+
+export default interface WebsiteTemplateRegistry {
+ // DOC COMPONENTS
+ 'Doc::A11ySupport': typeof DocA11ySupport;
+ 'doc/a11y-support': typeof DocA11ySupport;
+
+ 'Doc::Badge': typeof DocBadge;
+ 'doc/badge': typeof DocBadge;
+
+ 'Doc::BadgeGroup': typeof DocBadgeGroup;
+ 'doc/badge-group': typeof DocBadgeGroup;
+
+ 'Doc::Banner': typeof DocBanner;
+ 'doc/banner': typeof DocBanner;
+
+ 'Doc::Cards::Card': typeof DocCardsCard;
+ 'doc/cards/card': typeof DocCardsCard;
+
+ 'Doc::Cards::Deck': typeof DocCardsDeck;
+ 'doc/cards/deck': typeof DocCardsDeck;
+
+ 'Doc::ColorCard': typeof DocColorCard;
+ 'doc/color-card': typeof DocColorCard;
+
+ 'Doc::ColorSwatch': typeof DocColorSwatch;
+ 'doc/color-swatch': typeof DocColorSwatch;
+
+ 'Doc::ComponentApi': typeof DocComponentApi;
+ 'doc/component-api': typeof DocComponentApi;
+
+ 'Doc::ComponentApi::Property': typeof DocComponentApiProperty;
+ 'doc/component-api/property': typeof DocComponentApiProperty;
+
+ 'Doc::Content::HdsPrinciples': typeof DocContentHdsPrinciples;
+ 'doc/content/hds-principles': typeof DocContentHdsPrinciples;
+
+ 'Doc::CopyButton': typeof DocCopyButton;
+ 'doc/copy-button': typeof DocCopyButton;
+
+ 'Doc::DoDont': typeof DocDoDont;
+ 'doc/do-dont': typeof DocDoDont;
+
+ 'Doc::FontHelpersList': typeof DocFontHelpersList;
+ 'doc/font-helpers-list': typeof DocFontHelpersList;
+
+ 'Doc::Form::Filter': typeof DocFormFilter;
+ 'doc/form/filter': typeof DocFormFilter;
+
+ 'Doc::Form::Label': typeof DocFormLabel;
+ 'doc/form/label': typeof DocFormLabel;
+
+ 'Doc::Form::SelectGroupType': typeof DocFormSelectGroupType;
+ 'doc/form/select-group-type': typeof DocFormSelectGroupType;
+
+ 'Doc::Form::Select': typeof DocFormSelect;
+ 'doc/form/select': typeof DocFormSelect;
+
+ 'Doc::IconsList::Grid': typeof DocIconsListGrid;
+ 'doc/icons-list/grid': typeof DocIconsListGrid;
+
+ 'Doc::IconsList::Item': typeof DocIconsListItem;
+ 'doc/icons-list/item': typeof DocIconsListItem;
+
+ 'Doc::IconsList': typeof DocIconsList;
+ 'doc/icons-list': typeof DocIconsList;
+
+ 'Doc::ImageCaption': typeof DocImageCaption;
+ 'doc/image-caption': typeof DocImageCaption;
+
+ 'Doc::Layout': typeof DocLayout;
+ 'doc/layout': typeof DocLayout;
+
+ 'Doc::LinkWithIcon': typeof DocLinkWithIcon;
+ 'doc/link-with-icon': typeof DocLinkWithIcon;
+
+ 'Doc::Logo::DesignSystem': typeof DocLogoDesignSystem;
+ 'doc/logo/design-system': typeof DocLogoDesignSystem;
+
+ 'Doc::Logo::HashiCorp': typeof DocLogoHashiCorp;
+ 'doc/logo/hashi-corp': typeof DocLogoHashiCorp;
+
+ 'Doc::MetaRow': typeof DocMetaRow;
+ 'doc/meta-row': typeof DocMetaRow;
+
+ 'Doc::NpmVersion': typeof DocNpmVersion;
+ 'doc/npm-version': typeof DocNpmVersion;
+
+ 'Doc::Page::Header::AlgoliaSearch': typeof DocPageHeaderAlgoliaSearch;
+ 'doc/page/header/algolia-search': typeof DocPageHeaderAlgoliaSearch;
+
+ 'Doc::Page::Header::NavItem': typeof DocPageHeaderNavItem;
+ 'doc/page/header/nav-item': typeof DocPageHeaderNavItem;
+
+ 'Doc::Page::Header': typeof DocPageHeader;
+ 'doc/page/header': typeof DocPageHeader;
+
+ 'Doc::Page::Banner': typeof DocPageBanner;
+ 'doc/page/banner': typeof DocPageBanner;
+
+ 'Doc::Page::Content': typeof DocPageContent;
+ 'doc/page/content': typeof DocPageContent;
+
+ 'Doc::Page::Cover': typeof DocPageCover;
+ 'doc/page/cover': typeof DocPageCover;
+
+ 'Doc::Page::Footer': typeof DocPageFooter;
+ 'doc/page/footer': typeof DocPageFooter;
+
+ 'Doc::Page::Sidebar': typeof DocPageSidebar;
+ 'doc/page/sidebar': typeof DocPageSidebar;
+
+ 'Doc::Page::Sidecar': typeof DocPageSidecar;
+ 'doc/page/sidecar': typeof DocPageSidecar;
+
+ 'Doc::Page::Stage': typeof DocPageStage;
+ 'doc/page/stage': typeof DocPageStage;
+
+ 'Doc::Page::Tabs': typeof DocPageTabs;
+ 'doc/page/tabs': typeof DocPageTabs;
+
+ 'Doc::Placeholder': typeof DocPlaceholder;
+ 'doc/placeholder': typeof DocPlaceholder;
+
+ 'Doc::RelatedComponents': typeof DocRelatedComponents;
+ 'doc/related-components': typeof DocRelatedComponents;
+
+ 'Doc::ScrollToTop': typeof DocScrollToTop;
+ 'doc/scroll-to-top': typeof DocScrollToTop;
+
+ 'Doc::TableOfContents': typeof DocTableOfContents;
+ 'doc/table-of-contents': typeof DocTableOfContents;
+
+ 'Doc::TableOfContentsCollapsibleItem': typeof DocTableOfContentsCollapsibleItem;
+ 'doc/table-of-contents-collapsible-item': typeof DocTableOfContentsCollapsibleItem;
+
+ 'Doc::TokenPreview': typeof DocTokenPreview;
+ 'doc/token-preview': typeof DocTokenPreview;
+
+ 'Doc::TokensList': typeof DocTokensList;
+ 'doc/tokens-list': typeof DocTokensList;
+
+ 'Doc::TokensList::Grid': typeof DocTokensListGrid;
+ 'doc/tokens-list/grid': typeof DocTokensListGrid;
+
+ 'Doc::TokensList::Item': typeof DocTokensListItem;
+ 'doc/tokens-list/item': typeof DocTokensListItem;
+
+ 'Doc::VarsList': typeof DocVarsList;
+ 'doc/vars-list': typeof DocVarsList;
+
+ 'Doc::WcagList': typeof DocWcagList;
+ 'doc/wcag-list': typeof DocWcagList;
+
+ // DYNAMIC TEMPLATE COMPONENTS
+ DynamicTemplateError: typeof DynamicTemplateError;
+ 'dynamic-template-error': typeof DynamicTemplateError;
+
+ DynamicTemplate: typeof DynamicTemplate;
+ 'dynamic-template': typeof DynamicTemplate;
+}