@hashicorp/design-system-components 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/HOW-TO-TEST-A-COMPONENT-IN-CLOUD-UI.md +54 -0
  3. package/LICENSE.md +2 -0
  4. package/addon/components/hds/form/radio-card/description.hbs +1 -0
  5. package/addon/components/hds/form/radio-card/group.hbs +26 -0
  6. package/addon/components/hds/form/radio-card/index.hbs +20 -0
  7. package/addon/components/hds/form/radio-card/index.js +90 -0
  8. package/addon/components/hds/form/radio-card/label.hbs +1 -0
  9. package/addon/components/hds/tabs/index.hbs +33 -0
  10. package/addon/components/hds/tabs/index.js +107 -0
  11. package/addon/components/hds/tabs/panel.hbs +11 -0
  12. package/addon/components/hds/tabs/panel.js +40 -0
  13. package/addon/components/hds/tabs/tab.hbs +25 -0
  14. package/addon/components/hds/tabs/tab.js +88 -0
  15. package/app/components/hds/form/radio-card/description.js +1 -0
  16. package/app/components/hds/form/radio-card/group.js +1 -0
  17. package/app/components/hds/form/radio-card/index.js +1 -0
  18. package/app/components/hds/form/radio-card/label.js +1 -0
  19. package/app/components/hds/tabs/index.js +1 -0
  20. package/app/components/hds/tabs/panel.js +1 -0
  21. package/app/components/hds/tabs/tab.js +1 -0
  22. package/app/styles/@hashicorp/design-system-components.scss +2 -2
  23. package/app/styles/components/alert.scss +1 -4
  24. package/app/styles/components/avatar.scss +1 -3
  25. package/app/styles/components/badge-count.scss +1 -3
  26. package/app/styles/components/badge.scss +1 -4
  27. package/app/styles/components/breadcrumb.scss +1 -3
  28. package/app/styles/components/button-set.scss +1 -3
  29. package/app/styles/components/button.scss +11 -2
  30. package/app/styles/components/card/container.scss +0 -4
  31. package/app/styles/components/disclosure.scss +0 -2
  32. package/app/styles/components/dropdown.scss +0 -2
  33. package/app/styles/components/empty-state.scss +4 -0
  34. package/app/styles/components/form/checkbox.scss +0 -2
  35. package/app/styles/components/form/error.scss +0 -2
  36. package/app/styles/components/form/field.scss +0 -2
  37. package/app/styles/components/form/group.scss +0 -2
  38. package/app/styles/components/form/helper-text.scss +0 -2
  39. package/app/styles/components/form/index.scss +1 -0
  40. package/app/styles/components/form/indicator.scss +0 -2
  41. package/app/styles/components/form/label.scss +0 -2
  42. package/app/styles/components/form/legend.scss +0 -2
  43. package/app/styles/components/form/radio-card.scss +149 -0
  44. package/app/styles/components/form/radio.scss +0 -2
  45. package/app/styles/components/form/select.scss +1 -2
  46. package/app/styles/components/form/text-input.scss +1 -2
  47. package/app/styles/components/form/textarea.scss +1 -2
  48. package/app/styles/components/form/toggle.scss +0 -2
  49. package/app/styles/components/icon-tile.scss +1 -4
  50. package/app/styles/components/link/index.scss +2 -0
  51. package/app/styles/components/link/inline.scss +0 -2
  52. package/app/styles/components/link/standalone.scss +0 -2
  53. package/app/styles/components/stepper/step-indicator.scss +0 -2
  54. package/app/styles/components/stepper/task-indicator.scss +0 -2
  55. package/app/styles/components/tabs.scss +113 -0
  56. package/app/styles/components/tag.scss +0 -3
  57. package/app/styles/components/toast.scss +1 -4
  58. package/blueprints/hds-component/files/app/styles/components/__name__.scss +0 -2
  59. package/package.json +23 -27
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @hashicorp/design-system-components
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#548](https://github.com/hashicorp/design-system/pull/548) [`5d1e2cb4`](https://github.com/hashicorp/design-system/commit/5d1e2cb4f953bfbe55ae1fa8a675903712a66a1c) Thanks [@KristinLBradley](https://github.com/KristinLBradley)! - Add new Tabs component
8
+
9
+ ### Patch Changes
10
+
11
+ - [#618](https://github.com/hashicorp/design-system/pull/618) [`11d39410`](https://github.com/hashicorp/design-system/commit/11d39410c40725ff34a291e17eac3f8f8321c659) Thanks [@alex-ju](https://github.com/alex-ju)! - Update `ember` to `4.7.0`
12
+
13
+ * [#660](https://github.com/hashicorp/design-system/pull/660) [`4d0826a6`](https://github.com/hashicorp/design-system/commit/4d0826a6df220031b36f4918c5c5365012672c27) Thanks [@alex-ju](https://github.com/alex-ju)! - Update the `Hds::Button` style when rendered as a link
14
+
15
+ - [#638](https://github.com/hashicorp/design-system/pull/638) [`90182235`](https://github.com/hashicorp/design-system/commit/901822353453e98c914c8d57e523d64b32a23f75) Thanks [@Dhaulagiri](https://github.com/Dhaulagiri)! - explicitly add ember-style-modifiers as a dependency
16
+
17
+ * [#636](https://github.com/hashicorp/design-system/pull/636) [`27a283a5`](https://github.com/hashicorp/design-system/commit/27a283a52c2828b32c282401f91df9bd929f9dda) Thanks [@Dhaulagiri](https://github.com/Dhaulagiri)! - Add copyright notice to license file
18
+
19
+ * Updated dependencies [[`a079992f`](https://github.com/hashicorp/design-system/commit/a079992fbbed11812fcf4cdd4409a00fa2d246f1), [`11d39410`](https://github.com/hashicorp/design-system/commit/11d39410c40725ff34a291e17eac3f8f8321c659), [`27a283a5`](https://github.com/hashicorp/design-system/commit/27a283a52c2828b32c282401f91df9bd929f9dda), [`ecbe26df`](https://github.com/hashicorp/design-system/commit/ecbe26df6bdbaf7b4f00c70d016eead0da9168f0)]:
20
+ - @hashicorp/design-system-tokens@1.2.0
21
+ - @hashicorp/ember-flight-icons@3.0.1
22
+
23
+ ## 1.2.0
24
+
25
+ ### Minor Changes
26
+
27
+ - [#576](https://github.com/hashicorp/design-system/pull/576) [`ab821911`](https://github.com/hashicorp/design-system/commit/ab821911e8d7f99b2b70e41e06f3fe8f681f9c8f) Thanks [@alex-ju](https://github.com/alex-ju)! - Add `RadioCard` component
28
+
29
+ ### Patch Changes
30
+
31
+ - [#586](https://github.com/hashicorp/design-system/pull/586) [`55ec4246`](https://github.com/hashicorp/design-system/commit/55ec424615505733159ac420284c47758f0667a3) Thanks [@Dhaulagiri](https://github.com/Dhaulagiri)! - make ember-truth-helpers a dependency
32
+
33
+ - Updated dependencies [[`55f38cb3`](https://github.com/hashicorp/design-system/commit/55f38cb3a30a6edf8854e53ce3642270fe00efdc), [`258c06d9`](https://github.com/hashicorp/design-system/commit/258c06d952d41696bb8c5b4bab19eb46e4612cdc)]:
34
+ - @hashicorp/ember-flight-icons@3.0.0
35
+ - @hashicorp/design-system-tokens@1.1.0
36
+
3
37
  ## 1.1.0
4
38
 
5
39
  ### Minor Changes
@@ -0,0 +1,54 @@
1
+ # How to test a component in Cloud UI
2
+
3
+ To test a new component (or a component that has been modified) using your local environment as source for the `@hashicorp/design-system-components` package, you have to follow a few steps.
4
+
5
+ ## Prepare the Cloud UI project
6
+
7
+ For simplicity, you will need three CLI/terminal windows/tabs opened.
8
+
9
+ In in the first terminal window go the folder containing your local version of the https://github.com/hashicorp/cloud-ui/ codebase:
10
+
11
+ - go to the root of the project
12
+ - eg. `cd ~/path-to/your-local/hashicorp/cloud-ui`
13
+ - run `rm -fr node_modules/` to start from a blank slate
14
+ - run `yarn` to make sure all the packages are installed
15
+
16
+ ## Replace the installed `@hashicorp/design-system-components` package in Cloud UI with the local one
17
+
18
+ In the second terminal window:
19
+
20
+ - run `cd ~/path-to/your-local/hashicorp/cloud-ui/node_modules/@hashicorp` to go in the folder containing the `@hashicorp` packages
21
+ - run `ls -la` to check that the folder `design-system-components` is present
22
+ - run `rm -fr design-system-components` to remove (recursively) the folder with the published version of the `@hashicorp/design-system-components` package
23
+
24
+ Now you have to create a symlink between the folder containing your local code for the `design-system-components` and the folder you have just removed:
25
+
26
+ In the third terminal window:
27
+
28
+ - go in the folder containing the https://github.com/hashicorp/design-system codebase
29
+ - eg. `cd ~/path-to/your-local/hashicorp/design-system/packages/components/`
30
+ - run `pwd` and copy the full path to this folder
31
+ - eg. `/Users/mynamesurname/src/hashicorp/design-system/packages/components`
32
+
33
+ Go back to the second terminal window:
34
+
35
+ - run `pwd` and make sure you're still in the `node_modules/@hashicorp` folder of the Cloud UI repo
36
+ - run `ln -s [full-path-to-your-local-components-folder] design-system-components` to create a symbolic link [**IMPORTANT**: you need to set `design-system-components` and not just `components` as target folder name, because that's the name expected by `yarn` (same as the folder you deleted one moment ago)]
37
+ - eg. `ln -s /Users/mynamesurname/src/hashicorp/design-system/packages/components design-system-components`
38
+
39
+ **IMPORTANT**: if you have a new version of the design tokens package that needs to be included as well for your component to work, you will need to do the same process to symlink the local folder of the **compiled** design tokens with the one expected in the Cloud UI `node_modules` folder
40
+
41
+ - eg. `rm -fr design-system-tokens` + `ln -s /Users/mynamesurname/src/hashicorp/design-system/packages/tokens design-system-tokens`
42
+
43
+ In the first terminal window (you should be be in the Cloud UI root):
44
+ - run `yarn start` to launch the compilation of the Cloud UI project and start the local webserver
45
+ - visit the URL that appears in the command line at the end of the build (typically http://localhost:4200/ but you can specify a different port using the command `yarn start --port NNNN`)
46
+
47
+ Everything should work and you should be able to do whatever you need to do in the Cloud UI codebase using your local HDS components (eg testing a new component, or checking the impact of a change in an existing one).
48
+
49
+ **Don't forget**: once you've finished, it is better to reset the state of the Cloud UI project, to make sure that if you're doing some other tests not involving HDS components, you're using the actual code that a user will see in production:
50
+
51
+ - go to the `node_modules/@hashicorp` folder of the Cloud UI repo
52
+ - run `rm design-system-components` (no need for the `-fr` option, it's a symlink file not a folder)
53
+ - go to the root of the Cloud UI project
54
+ - run `yarn` to reinstall all the missing packages (including `@hashicorp/design-system-components` from NPM)
package/LICENSE.md CHANGED
@@ -1,3 +1,5 @@
1
+ Copyright (c) 2021 HashiCorp, Inc
2
+
1
3
  Mozilla Public License Version 2.0
2
4
  ==================================
3
5
 
@@ -0,0 +1 @@
1
+ <span class="hds-form-radio-card__description hds-typography-body-100" ...attributes>{{yield}}</span>
@@ -0,0 +1,26 @@
1
+ <Hds::Form::Fieldset
2
+ class="hds-form-group--radio-cards"
3
+ @layout="horizontal"
4
+ @name={{@name}}
5
+ @isRequired={{@isRequired}}
6
+ @isOptional={{@isOptional}}
7
+ ...attributes
8
+ as |F|
9
+ >
10
+ {{! Notice: the order of the elements is not relevant here, because it's controlled at "Hds::Form::Fieldset" component level }}
11
+ {{yield (hash Legend=F.Legend isRequired=F.isRequired isOptional=F.isOptional)}}
12
+ {{yield (hash HelperText=F.HelperText Error=F.Error)}}
13
+ <F.Control>
14
+ {{yield
15
+ (hash
16
+ RadioCard=(component
17
+ "hds/form/radio-card"
18
+ name=@name
19
+ alignment=@alignment
20
+ controlPosition=@controlPosition
21
+ extraAriaDescribedBy=F.ariaDescribedBy
22
+ )
23
+ )
24
+ }}
25
+ </F.Control>
26
+ </Hds::Form::Fieldset>
@@ -0,0 +1,20 @@
1
+ <label class={{this.classNames}} {{did-insert this.setAriaDescribedBy}} {{style maxWidth=@maxWidth}}>
2
+ <span class="hds-form-radio-card__content">
3
+ {{yield (hash Icon=(component "flight-icon" size="24" isInlineBlock=false))}}
4
+ {{yield (hash Label=(component "hds/form/radio-card/label"))}}
5
+ {{yield (hash Badge=(component "hds/badge"))}}
6
+ {{yield (hash Description=(component "hds/form/radio-card/description"))}}
7
+ {{yield (hash Generic=(component "hds/yield"))}}
8
+ </span>
9
+ <span class="hds-form-radio-card__control-wrapper">
10
+ <Hds::Form::Radio::Base
11
+ class="hds-form-radio-card__control"
12
+ @value={{@value}}
13
+ name={{@name}}
14
+ checked={{@checked}}
15
+ disabled={{@disabled}}
16
+ aria-describedby={{this.ariaDescribedBy}}
17
+ ...attributes
18
+ />
19
+ </span>
20
+ </label>
@@ -0,0 +1,90 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+ import { assert } from '@ember/debug';
5
+ import { setAriaDescribedBy } from '../utils/setAriaDescribedBy';
6
+ import { schedule } from '@ember/runloop';
7
+
8
+ export const DEFAULT_CONTROL_POSITION = 'bottom';
9
+ export const DEFAULT_ALIGNMENT = 'left';
10
+ export const CONTROL_POSITIONS = ['bottom', 'left'];
11
+ export const ALIGNMENTS = ['left', 'center'];
12
+
13
+ export default class HdsFormRadioCardIndexComponent extends Component {
14
+ @tracked ariaDescribedBy = this.args.extraAriaDescribedBy;
15
+ @tracked descriptors = [];
16
+
17
+ @action
18
+ setAriaDescribedBy() {
19
+ // we schedule this afterRender to capture all descriptors registered onInsert
20
+ schedule('afterRender', () => {
21
+ setAriaDescribedBy(this);
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Sets the position of the control
27
+ * Accepted values: buttom, left
28
+ *
29
+ * @param type
30
+ * @type {string}
31
+ * @default 'bottom'
32
+ */
33
+ get controlPosition() {
34
+ let { controlPosition = DEFAULT_CONTROL_POSITION } = this.args;
35
+
36
+ assert(
37
+ `@controlPosition for "Hds::Form::RadioCard" must be one of the following: ${CONTROL_POSITIONS.join(
38
+ ', '
39
+ )}; received: ${controlPosition}`,
40
+ CONTROL_POSITIONS.includes(controlPosition)
41
+ );
42
+
43
+ return controlPosition;
44
+ }
45
+
46
+ /**
47
+ * Sets the alignment of the content
48
+ * Accepted values: left, center
49
+ *
50
+ * @param alignnment
51
+ * @type {string}
52
+ * @default 'left'
53
+ */
54
+ get alignment() {
55
+ let { alignment = DEFAULT_ALIGNMENT } = this.args;
56
+
57
+ assert(
58
+ `@alignment for "Hds::Form::RadioCard" must be one of the following: ${ALIGNMENTS.join(
59
+ ', '
60
+ )}; received: ${alignment}`,
61
+ ALIGNMENTS.includes(alignment)
62
+ );
63
+
64
+ return alignment;
65
+ }
66
+
67
+ /**
68
+ * Get the class names to apply to the component.
69
+ * @method classNames
70
+ * @return {string} The "class" attribute to apply to the component.
71
+ */
72
+ get classNames() {
73
+ let classes = ['hds-form-radio-card'];
74
+
75
+ if (this.args.checked) {
76
+ classes.push('hds-form-radio-card--checked');
77
+ }
78
+ if (this.args.disabled) {
79
+ classes.push('hds-form-radio-card--disabled');
80
+ }
81
+
82
+ // add a class based on the @controlPosition argument
83
+ classes.push(`hds-form-radio-card--control-${this.controlPosition}`);
84
+
85
+ // add a class based on the @alignment argument
86
+ classes.push(`hds-form-radio-card--align-${this.alignment}`);
87
+
88
+ return classes.join(' ');
89
+ }
90
+ }
@@ -0,0 +1 @@
1
+ <span class="hds-form-radio-card__label hds-typography-display-300 hds-font-weight-bold" ...attributes>{{yield}}</span>
@@ -0,0 +1,33 @@
1
+ {{! template-lint-disable no-invalid-role }}
2
+ <div class="hds-tabs" {{did-insert this.didInsert}} ...attributes>
3
+ <div class="hds-tabs__tablist-wrapper">
4
+ <ul class="hds-tabs__tablist" role="tablist">
5
+ {{yield
6
+ (hash
7
+ Tab=(component
8
+ "hds/tabs/tab"
9
+ didInsertNode=this.didInsertTab
10
+ tabIds=this.tabIds
11
+ panelIds=this.panelIds
12
+ selectedTabIndex=this.selectedTabIndex
13
+ onClick=this.onClick
14
+ onKeyUp=this.onKeyUp
15
+ )
16
+ )
17
+ }}
18
+ <li class="hds-tabs__tab-indicator" role="presentation"></li>
19
+ </ul>
20
+ </div>
21
+
22
+ {{yield
23
+ (hash
24
+ Panel=(component
25
+ "hds/tabs/panel"
26
+ didInsertNode=this.didInsertPanel
27
+ tabIds=this.tabIds
28
+ panelIds=this.panelIds
29
+ selectedTabIndex=this.selectedTabIndex
30
+ )
31
+ )
32
+ }}
33
+ </div>
@@ -0,0 +1,107 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+ import { assert } from '@ember/debug';
5
+
6
+ export default class HdsTabsIndexComponent extends Component {
7
+ @tracked tabNodes = [];
8
+ @tracked tabIds = [];
9
+ @tracked panelNodes = [];
10
+ @tracked panelIds = [];
11
+ @tracked selectedTabIndex;
12
+
13
+ @action
14
+ didInsert() {
15
+ // default starting tab index
16
+ let initialTabIndex = 0;
17
+ let selectedCount = 0;
18
+
19
+ this.tabNodes.forEach((tabElement, index) => {
20
+ if (tabElement.hasAttribute('data-is-selected')) {
21
+ initialTabIndex = index;
22
+ selectedCount++;
23
+ }
24
+ });
25
+ this.selectedTabIndex = initialTabIndex;
26
+ this.setTabIndicator(initialTabIndex);
27
+
28
+ assert('Only one tab may use isSelected argument', selectedCount <= 1);
29
+
30
+ assert(
31
+ 'The number of Tabs must be equal to the number of Panels',
32
+ this.tabNodes.length === this.panelNodes.length
33
+ );
34
+ }
35
+
36
+ @action
37
+ didInsertTab(element) {
38
+ this.tabNodes = [...this.tabNodes, element];
39
+ this.tabIds = [...this.tabIds, element.id];
40
+ }
41
+
42
+ @action
43
+ didInsertPanel(panelId, element) {
44
+ this.panelNodes = [...this.panelNodes, element];
45
+ this.panelIds = [...this.panelIds, panelId];
46
+ }
47
+
48
+ @action
49
+ onClick(tabIndex, event) {
50
+ this.selectedTabIndex = tabIndex;
51
+ this.setTabIndicator(tabIndex);
52
+
53
+ // Scroll Tab into view if it's out of view
54
+ this.tabNodes[tabIndex].parentNode.scrollIntoView({
55
+ behavior: 'smooth',
56
+ block: 'nearest',
57
+ inline: 'nearest',
58
+ });
59
+
60
+ // invoke the callback function if it's provided as argument
61
+ if (typeof this.args.onClickTab === 'function') {
62
+ this.args.onClickTab(event);
63
+ }
64
+ }
65
+
66
+ @action
67
+ onKeyUp(tabIndex, e) {
68
+ const leftArrow = 37;
69
+ const rightArrow = 39;
70
+ const enterKey = 13;
71
+ const spaceKey = 32;
72
+
73
+ if (e.keyCode === rightArrow) {
74
+ const nextTabIndex = (tabIndex + 1) % this.tabIds.length;
75
+ this.focusTab(nextTabIndex, e);
76
+ } else if (e.keyCode === leftArrow) {
77
+ const prevTabIndex =
78
+ (tabIndex + this.tabIds.length - 1) % this.tabIds.length;
79
+ this.focusTab(prevTabIndex, e);
80
+ } else if (e.keyCode === enterKey || e.keyCode === spaceKey) {
81
+ this.selectedTabIndex = tabIndex;
82
+ }
83
+ }
84
+
85
+ // Focus tab for keyboard & mouse navigation:
86
+ focusTab(tabIndex, e) {
87
+ e.preventDefault();
88
+ this.tabNodes[tabIndex].focus();
89
+ }
90
+
91
+ setSelectedPanelFocus(tabIndex, e) {
92
+ e.preventDefault();
93
+ this.panelNodes[tabIndex].focus();
94
+ }
95
+
96
+ setTabIndicator(tabIndex) {
97
+ const tabElem = this.tabNodes[tabIndex];
98
+ const tabsParentElem = tabElem.closest('.hds-tabs');
99
+
100
+ const tabLeftPos = tabElem.parentNode.offsetLeft;
101
+ const tabWidth = tabElem.parentNode.offsetWidth;
102
+
103
+ // Set CSS custom properties for indicator
104
+ tabsParentElem.style.setProperty('--indicator-left-pos', tabLeftPos + 'px');
105
+ tabsParentElem.style.setProperty('--indicator-width', tabWidth + 'px');
106
+ }
107
+ }
@@ -0,0 +1,11 @@
1
+ <section
2
+ class="hds-tabs__panel"
3
+ ...attributes
4
+ role="tabpanel"
5
+ aria-labelledby={{this.tabId}}
6
+ id={{this.panelId}}
7
+ hidden={{(not this.isSelected)}}
8
+ {{did-insert this.didInsertNode}}
9
+ >
10
+ {{yield}}
11
+ </section>
@@ -0,0 +1,40 @@
1
+ import Component from '@glimmer/component';
2
+ import { cached } from '@glimmer/tracking';
3
+ import { guidFor } from '@ember/object/internals';
4
+ import { action } from '@ember/object';
5
+
6
+ export default class HdsTabsIndexComponent extends Component {
7
+ /**
8
+ * Generates a unique ID for the Panel
9
+ *
10
+ * @param panelId
11
+ */
12
+ panelId = 'panel-' + guidFor(this);
13
+
14
+ @cached
15
+ get nodeIndex() {
16
+ return this.args.panelIds
17
+ ? this.args.panelIds.indexOf(this.panelId)
18
+ : undefined;
19
+ }
20
+
21
+ get tabId() {
22
+ return this.nodeIndex !== undefined
23
+ ? this.args.tabIds[this.nodeIndex]
24
+ : undefined;
25
+ }
26
+
27
+ get isSelected() {
28
+ return this.nodeIndex === this.args.selectedTabIndex;
29
+ }
30
+
31
+ @action
32
+ didInsertNode(element) {
33
+ let { didInsertNode } = this.args;
34
+
35
+ if (typeof didInsertNode === 'function') {
36
+ this.elementId = element.id;
37
+ didInsertNode(this.elementId, ...arguments);
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,25 @@
1
+ {{! template-lint-disable require-context-role no-invalid-role }}
2
+ <li class={{this.classNames}} ...attributes role="presentation">
3
+ {{#if @icon}}
4
+ <FlightIcon @name={{@icon}} class="hds-tabs__tab-icon" />
5
+ {{/if}}
6
+
7
+ <button
8
+ class="hds-tabs__tab-button hds-typography-body-200 hds-font-weight-medium"
9
+ role="tab"
10
+ type="button"
11
+ id={{this.tabId}}
12
+ aria-selected={{this.isSelected}}
13
+ tabindex={{unless this.isSelected "-1"}}
14
+ data-is-selected={{this.isInitialTab}}
15
+ {{did-insert this.didInsertNode}}
16
+ {{on "click" this.onClick}}
17
+ {{on "keyup" this.onKeyUp}}
18
+ >
19
+ {{yield}}
20
+ </button>
21
+
22
+ {{#if @count}}
23
+ <Hds::BadgeCount @text={{@count}} @size="small" class="hds-tabs__tab-count" />
24
+ {{/if}}
25
+ </li>
@@ -0,0 +1,88 @@
1
+ import Component from '@glimmer/component';
2
+ import { cached } from '@glimmer/tracking';
3
+ import { guidFor } from '@ember/object/internals';
4
+ import { action } from '@ember/object';
5
+
6
+ export default class HdsTabsIndexComponent extends Component {
7
+ /**
8
+ * Generates a unique ID for the Tab
9
+ *
10
+ * @param tabId
11
+ */
12
+ tabId = 'tab-' + guidFor(this);
13
+
14
+ @cached
15
+ get nodeIndex() {
16
+ return this.args.tabIds ? this.args.tabIds.indexOf(this.tabId) : undefined;
17
+ }
18
+
19
+ get panelId() {
20
+ return this.nodeIndex !== undefined
21
+ ? this.args.panelIds[this.nodeIndex]
22
+ : undefined;
23
+ }
24
+
25
+ /**
26
+ * @param isSelected
27
+ * @type {boolean}
28
+ * @default false (1st tab is selected by default)
29
+ * @description Determines if the tab is the selected tab
30
+ */
31
+ get isSelected() {
32
+ return (
33
+ this.nodeIndex !== undefined &&
34
+ this.nodeIndex === this.args.selectedTabIndex
35
+ );
36
+ }
37
+
38
+ get isInitialTab() {
39
+ let { isSelected } = this.args;
40
+ return isSelected;
41
+ }
42
+
43
+ @action
44
+ didInsertNode() {
45
+ let { didInsertNode } = this.args;
46
+
47
+ if (typeof didInsertNode === 'function') {
48
+ didInsertNode(...arguments);
49
+ }
50
+ }
51
+
52
+ @action
53
+ onClick() {
54
+ let { onClick } = this.args;
55
+
56
+ if (typeof onClick === 'function') {
57
+ onClick(this.nodeIndex, ...arguments);
58
+ } else {
59
+ return false;
60
+ }
61
+ }
62
+
63
+ @action
64
+ onKeyUp() {
65
+ let { onKeyUp } = this.args;
66
+
67
+ if (typeof onKeyUp === 'function') {
68
+ onKeyUp(this.nodeIndex, ...arguments);
69
+ } else {
70
+ return false;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Get the class names to apply to the component.
76
+ * @method classNames
77
+ * @return {string} The "class" attribute to apply to the component.
78
+ */
79
+ get classNames() {
80
+ let classes = ['hds-tabs__tab'];
81
+
82
+ if (this.isSelected) {
83
+ classes.push(`hds-tabs__tab--is-selected`);
84
+ }
85
+
86
+ return classes.join(' ');
87
+ }
88
+ }
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/form/radio-card/description';
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/form/radio-card/group';
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/form/radio-card/index';
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/form/radio-card/label';
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/tabs/index';
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/tabs/panel';
@@ -0,0 +1 @@
1
+ export { default } from '@hashicorp/design-system-components/components/hds/tabs/tab';
@@ -20,9 +20,9 @@
20
20
  @use "../components/empty-state";
21
21
  @use "../components/form"; // multiple components
22
22
  @use "../components/icon-tile";
23
- @use "../components/link/inline";
24
- @use "../components/link/standalone";
23
+ @use "../components/link"; // multiple components
25
24
  @use "../components/stepper";
25
+ @use "../components/tabs";
26
26
  @use "../components/tag";
27
27
  @use "../components/toast";
28
28
  // END COMPONENT CSS FILES IMPORTS
@@ -1,8 +1,5 @@
1
1
  //
2
- // ALERT
3
- //
4
- // properties within each class are sorted alphabetically
5
- //
2
+ // ALERT COMPONENT
6
3
  //
7
4
 
8
5
  @use "../mixins/focus-ring" as *;
@@ -1,7 +1,5 @@
1
1
  //
2
- // AVATAR
3
- //
4
- // properties within each class are sorted alphabetically
2
+ // AVATAR COMPONENT
5
3
  //
6
4
 
7
5
  .hds-avatar {
@@ -1,7 +1,5 @@
1
1
  //
2
- // BADGE-COUNT
3
- //
4
- // properties within each class are sorted alphabetically
2
+ // BADGE-COUNT COMPONENT
5
3
  //
6
4
 
7
5
  @use "sass:math";
@@ -1,8 +1,5 @@
1
1
  //
2
- // BADGE
3
- //
4
- // properties within each class are sorted alphabetically
5
- //
2
+ // BADGE COMPONENT
6
3
  //
7
4
 
8
5
  $hds-badge-types: ( "flat","inverted","outlined" );
@@ -1,10 +1,8 @@
1
1
  //
2
- // BREADCRUMB
2
+ // BREADCRUMB COMPONENT
3
3
  //
4
- // properties within each class are sorted alphabetically
5
4
  // notice: pseudo-classes for the states *must* follow the order link > visited > hover > focus > active
6
5
  //
7
- //
8
6
 
9
7
  @use "../mixins/focus-ring" as *;
10
8
 
@@ -1,7 +1,5 @@
1
1
  //
2
- // BUTTON-SET
3
- //
4
- // properties within each class are sorted alphabetically
2
+ // BUTTON-SET COMPONENT
5
3
  //
6
4
 
7
5
  .hds-button-set {