@hashicorp/design-system-components 0.0.6 → 0.0.10

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.
@@ -90,7 +90,9 @@ jobs:
90
90
  steps.cache-dependencies.outputs.cache-hit != 'true'
91
91
 
92
92
  - name: Test
93
- run: yarn test:ember --launch ${{ matrix.browser }}
93
+ run: yarn test:ember:percy --launch ${{ matrix.browser }}
94
+ env:
95
+ PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
94
96
 
95
97
  floating-dependencies:
96
98
  name: Floating Dependencies
@@ -132,7 +134,9 @@ jobs:
132
134
  run: yarn install --no-lockfile --non-interactive
133
135
 
134
136
  - name: Test
135
- run: yarn test:ember --launch ${{ matrix.browser }}
137
+ run: yarn test:ember:percy --launch ${{ matrix.browser }}
138
+ env:
139
+ PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
136
140
 
137
141
  try-scenarios:
138
142
  name: Tests - ${{ matrix.ember-try-scenario }}
@@ -151,8 +155,8 @@ jobs:
151
155
  # ember-canary,
152
156
  ember-default-with-jquery,
153
157
  ember-classic,
154
- embroider-safe,
155
- embroider-optimized
158
+ # embroider-safe,
159
+ # embroider-optimized
156
160
  ]
157
161
 
158
162
  steps:
@@ -0,0 +1,43 @@
1
+ {
2
+ "bitwise": true,
3
+ "camelcase": true,
4
+ "curly": false,
5
+ "eqeqeq": true,
6
+ "es3": true,
7
+ "forin": true,
8
+ "immed": false,
9
+ "indent": false,
10
+ "latedef": "nofunc",
11
+ "newcap": false,
12
+ "noarg": true,
13
+ "noempty": true,
14
+ "nonew": false,
15
+ "plusplus": false,
16
+ "quotmark": false,
17
+ "undef": true,
18
+ "unused": "vars",
19
+ "strict": false,
20
+ "trailing": true,
21
+ "maxparams": 5,
22
+ "maxdepth": false,
23
+ "maxstatements": false,
24
+ "maxcomplexity": false,
25
+ "maxlen": 100,
26
+
27
+ "asi": true,
28
+ "expr": true,
29
+ "globalstrict": true,
30
+ "smarttabs": true,
31
+ "sub": true,
32
+
33
+ "node": true,
34
+ "globals": {
35
+ "describe": false,
36
+ "it": false,
37
+ "before": false,
38
+ "beforeEach": false,
39
+ "after": false,
40
+ "afterEach": false,
41
+ "define": false
42
+ }
43
+ }
package/RELEASE.md ADDED
@@ -0,0 +1,69 @@
1
+ # How To Release
2
+
3
+ Whenever there is an update to the components, and these changes have been approved, we need to release them as package to the npm registry.
4
+
5
+ Please see the instructions in the [CONTRIBUTING](CONTRIBUTING.md) file for more details about how to setup the project and make changes to the code for these packages.
6
+
7
+ ## Bump
8
+
9
+ The "bump" step increases the _SemVer_ version number in the `package.json` file.
10
+
11
+ * Make sure your local `main` branch is up to date.
12
+ * Create new custom branch from `main`.
13
+ * `cd /design-system-components`
14
+ * Run `yarn bump` and choose the _SemVer_ version as agreed upon on the previous PR.
15
+ * _The `bump` command is interactive, you can move up and down with the keyboard, choose one option, and then hit "enter": the tool will automatically update the version in the `package.json` file for you._
16
+ * Check the `git diff` for the project, you should see only the `package.json` file changed (with the new version).
17
+ * Commit, push, open a pull request, and wait for approval.
18
+
19
+ Once the PR has been approved and merged, you can finally move to the next step, the actual release.
20
+
21
+ ## Release
22
+
23
+ The "release" step publishes the package on the npm registry, using the version declared in the `package.json` file, and [tags](https://www.atlassian.com/git/tutorials/inspecting-a-repository/git-tag) that specific release on git.
24
+
25
+ _**IMPORTANT**: Once released a package on the public registry, you can't revert the changes: the only solution is to deprecate the package (this will hide it from the public, but remains there). If you need to do some tests, use a **local** package registry (see below), don't test directly in production!_
26
+
27
+ * Make sure your local `main` branch is up to date.
28
+ * You will need a company-approved 2FA-enabled account on npm to publish (see [npm 2FA docs](https://docs.npmjs.com/configuring-two-factor-authentication) for more info).
29
+ * `cd /design-system-components`
30
+ * `yarn release`
31
+ * Check the git diff, you should not see any change.
32
+
33
+ **Notice**: this action will automatically:
34
+
35
+ * publish the new version of the package on the [NPM registry](https://www.npmjs.com/) using the current _SemVer_ version declared in the `package.json` file (the one previously chosen in the `bump` step).
36
+ * tag the current last commit in the `main` branch and push the tag to the git origin
37
+
38
+ At this point check on npm that the package ([@hashicorp/design-system-components](https://www.npmjs.com/package/@hashicorp/design-system-components) has been successfully published, and if it's so... well done! You just published your new package 🎉.
39
+
40
+ 🚨 **DON'T FORGET**:
41
+
42
+ You need to communicate to the product teams that are consuming the components!
43
+
44
+ ## Using a local NPM registry for testing
45
+
46
+ To test the release of packages without actually polluting the real/production npm registry, you can setup a local private registry using [Verdaccio](https://verdaccio.org/docs/what-is-verdaccio), an open source solution, very easy to setup and use.
47
+
48
+ You can follow [the instructions here](https://verdaccio.org/docs/installation), but essentially here is what you have to:
49
+
50
+ * install the package: `npm install -g verdaccio` - this will install it globally
51
+ * launch the service: `verdaccio` - this will serve a web frontend to the registry at the URL [http://localhost:4873/](http://localhost:4873/)
52
+ * add a user to the registry: `npm adduser --registry http://localhost:4873` - this will ask you for a username/password/email, I suggest you use test/test/test@test.com because is only a local instance. This will also authenticate you with the registry so you don't need to login when you publish.
53
+
54
+ Now you need to add this entry in the `package.json` file of the bundle you want to publish on your local registry:
55
+
56
+ ```json
57
+ "publishConfig": {
58
+ "registry": "http://localhost:4873"
59
+ },
60
+ ```
61
+
62
+ This will make sure the package is published on Verdaccio. Once the package is published, the web page will be available at at [http://localhost:4873/](http://localhost:4873/). It will show you all the packages' details, and if needed you can download the tarballs to check their content.
63
+
64
+ Once you've completed testing the package locally:
65
+
66
+ 1. remove verdaccio via `npm uninstall -g verdaccio`
67
+ 2. remove the files it created with `rm -fr ~/.local/share/verdaccio && rm -fr .config/verdaccio`
68
+
69
+ This same command can be used to cleanup the entire data storage of Verdaccio and start from scratch (no need to reinstall, only cleanup the data).
@@ -1,14 +1,16 @@
1
- <div class="hds-badge {{this.sizeClass}} {{this.typeClass}} {{this.colorClass}}" ...attributes>
1
+ <div
2
+ class="hds-badge {{this.sizeClass}} {{this.typeClass}} {{this.colorClass}}"
3
+ ...attributes>
2
4
  {{#if @icon}}
3
5
  <div class="hds-badge__icon">
4
6
  <FlightIcon @name={{this.icon}} @size="16" @stretched="true" />
5
7
  </div>
6
8
  {{/if}}
7
- {{#if @text}}
8
- <div class="hds-badge__text">
9
- {{@text}}
10
- </div>
9
+ {{#if this.isIconOnly}}
10
+ <span class="sr-only">{{this.text}}</span>
11
11
  {{else}}
12
- <span class="sr-only">{{@srOnlyText}}</span>
12
+ <div class="hds-badge__text">
13
+ {{this.text}}
14
+ </div>
13
15
  {{/if}}
14
16
  </div>
@@ -27,14 +27,12 @@ export default class HdsBadgeIndexComponent extends Component {
27
27
  get size() {
28
28
  let { size = DEFAULT_SIZE } = this.args;
29
29
 
30
- if (size) {
31
- assert(
32
- `@size for "Hds::Badge" must be one of the following: ${SIZES.join(
33
- ', '
34
- )}, received: ${size}`,
35
- SIZES.includes(size)
36
- );
37
- }
30
+ assert(
31
+ `@size for "Hds::Badge" must be one of the following: ${SIZES.join(
32
+ ', '
33
+ )}, received: ${size}`,
34
+ SIZES.includes(size)
35
+ );
38
36
 
39
37
  return size;
40
38
  }
@@ -59,14 +57,12 @@ export default class HdsBadgeIndexComponent extends Component {
59
57
  get type() {
60
58
  let { type = DEFAULT_TYPE } = this.args;
61
59
 
62
- if (type) {
63
- assert(
64
- `@type for "Hds::Badge" must be one of the following: ${TYPES.join(
65
- ', '
66
- )}, received: ${type}`,
67
- TYPES.includes(type)
68
- );
69
- }
60
+ assert(
61
+ `@type for "Hds::Badge" must be one of the following: ${TYPES.join(
62
+ ', '
63
+ )}, received: ${type}`,
64
+ TYPES.includes(type)
65
+ );
70
66
 
71
67
  return type;
72
68
  }
@@ -91,14 +87,12 @@ export default class HdsBadgeIndexComponent extends Component {
91
87
  get color() {
92
88
  let { color = DEFAULT_COLOR } = this.args;
93
89
 
94
- if (color) {
95
- assert(
96
- `@color for "Hds::Badge" must be one of the following: ${COLORS.join(
97
- ', '
98
- )}, received: ${color}`,
99
- COLORS.includes(color)
100
- );
101
- }
90
+ assert(
91
+ `@color for "Hds::Badge" must be one of the following: ${COLORS.join(
92
+ ', '
93
+ )}, received: ${color}`,
94
+ COLORS.includes(color)
95
+ );
102
96
 
103
97
  return color;
104
98
  }
@@ -112,6 +106,22 @@ export default class HdsBadgeIndexComponent extends Component {
112
106
  return `hds-badge--color-${this.color}`;
113
107
  }
114
108
 
109
+ /**
110
+ * @param text
111
+ * @type {string}
112
+ * @description The text of the badge. If `isIconOnly` is set to `true`, the text will be visually hidden but still available to assistive technology. If no text value is defined, an error will be thrown.
113
+ */
114
+ get text() {
115
+ let { text } = this.args;
116
+
117
+ assert(
118
+ '@text for "Hds::Badge" must have a valid value',
119
+ text !== undefined
120
+ );
121
+
122
+ return text;
123
+ }
124
+
115
125
  /**
116
126
  * Sets the icon name if there is one
117
127
  *
@@ -122,4 +132,17 @@ export default class HdsBadgeIndexComponent extends Component {
122
132
  get icon() {
123
133
  return this.args.icon ?? null;
124
134
  }
135
+
136
+ /**
137
+ * @param isIconOnly
138
+ * @type {boolean}
139
+ * @default false
140
+ * @description Indicates if the badge will only contain an icon; component will also ensure that accessible text is still applied to the component.
141
+ */
142
+ get isIconOnly() {
143
+ if (this.icon) {
144
+ return this.args.isIconOnly ?? false;
145
+ }
146
+ return false;
147
+ }
125
148
  }
@@ -20,14 +20,12 @@ export default class HdsBadgeCountIndexComponent extends Component {
20
20
  get size() {
21
21
  let { size = DEFAULT_SIZE } = this.args;
22
22
 
23
- if (size) {
24
- assert(
25
- `@size for "Hds::BadgeCount" must be one of the following: ${SIZES.join(
26
- ', '
27
- )}, received: ${size}`,
28
- SIZES.includes(size)
29
- );
30
- }
23
+ assert(
24
+ `@size for "Hds::BadgeCount" must be one of the following: ${SIZES.join(
25
+ ', '
26
+ )}, received: ${size}`,
27
+ SIZES.includes(size)
28
+ );
31
29
 
32
30
  return size;
33
31
  }
@@ -52,14 +50,12 @@ export default class HdsBadgeCountIndexComponent extends Component {
52
50
  get type() {
53
51
  let { type = DEFAULT_TYPE } = this.args;
54
52
 
55
- if (type) {
56
- assert(
57
- `@type for "Hds::BadgeCount" must be one of the following: ${TYPES.join(
58
- ', '
59
- )}, received: ${type}`,
60
- TYPES.includes(type)
61
- );
62
- }
53
+ assert(
54
+ `@type for "Hds::BadgeCount" must be one of the following: ${TYPES.join(
55
+ ', '
56
+ )}, received: ${type}`,
57
+ TYPES.includes(type)
58
+ );
63
59
 
64
60
  return type;
65
61
  }
@@ -84,14 +80,12 @@ export default class HdsBadgeCountIndexComponent extends Component {
84
80
  get color() {
85
81
  let { color = DEFAULT_COLOR } = this.args;
86
82
 
87
- if (color) {
88
- assert(
89
- `@color for "Hds::BadgeCount" must be one of the following: ${COLORS.join(
90
- ', '
91
- )}, received: ${color}`,
92
- COLORS.includes(color)
93
- );
94
- }
83
+ assert(
84
+ `@color for "Hds::BadgeCount" must be one of the following: ${COLORS.join(
85
+ ', '
86
+ )}, received: ${color}`,
87
+ COLORS.includes(color)
88
+ );
95
89
 
96
90
  return color;
97
91
  }
@@ -0,0 +1,35 @@
1
+ <button
2
+ class="hds-button {{this.sizeClass}} {{this.colorClass}} {{this.widthClass}}"
3
+ ...attributes
4
+ aria-label={{if this.isIconOnly this.text null}}
5
+ type={{this.type}}
6
+ disabled={{if this.isDisabled "disabled" null}}
7
+ >
8
+ {{#if this.isIconOnly}}
9
+ <div class="hds-button__icon">
10
+ <FlightIcon @name={{this.icon}} @size={{this.iconSize}} @stretched={{true}} />
11
+ </div>
12
+ {{else}}
13
+ {{#if this.icon}}
14
+ {{#if (eq this.iconPosition "leading")}}
15
+ <div class="hds-button__icon">
16
+ <FlightIcon @name={{this.icon}} @size={{this.iconSize}} @stretched={{true}} />
17
+ </div>
18
+ <div class="hds-button__text">
19
+ {{this.text}}
20
+ </div>
21
+ {{else}}
22
+ <div class="hds-button__text">
23
+ {{this.text}}
24
+ </div>
25
+ <div class="hds-button__icon">
26
+ <FlightIcon @name={{this.icon}} @size={{this.iconSize}} @stretched={{true}} />
27
+ </div>
28
+ {{/if}}
29
+ {{else}}
30
+ <div class="hds-button__text">
31
+ {{this.text}}
32
+ </div>
33
+ {{/if}}
34
+ {{/if}}
35
+ </button>
@@ -0,0 +1,196 @@
1
+ import Component from '@glimmer/component';
2
+ import { assert } from '@ember/debug';
3
+
4
+ export const DEFAULT_SIZE = 'medium';
5
+ export const DEFAULT_COLOR = 'primary';
6
+ export const DEFAULT_TYPE = 'button';
7
+ export const DEFAULT_ICONPOSITION = 'leading';
8
+ export const SIZES = ['small', 'medium', 'large'];
9
+ export const COLORS = ['primary', 'secondary', 'destructive'];
10
+ export const TYPES = ['button', 'submit', 'reset'];
11
+ export const ICONPOSITIONS = ['leading', 'trailing'];
12
+
13
+ export default class HdsButtonIndexComponent extends Component {
14
+ /**
15
+ * @param text
16
+ * @type {string}
17
+ * @description The text of the button or value of `aria-label` if `isIconOnly` is set to `true`. If no text value is defined an error will be thrown.
18
+ */
19
+ get text() {
20
+ let { text } = this.args;
21
+
22
+ assert(
23
+ '@text for "Hds::Button" must have a valid value',
24
+ text !== undefined
25
+ );
26
+
27
+ return text;
28
+ }
29
+
30
+ /**
31
+ * @param size
32
+ * @type {string}
33
+ * @default medium
34
+ * @description The size of the button; acceptable values are `small`, `medium`, and `large`
35
+ */
36
+ get size() {
37
+ let { size = DEFAULT_SIZE } = this.args;
38
+
39
+ assert(
40
+ `@size for "Hds::Button" must be one of the following: ${SIZES.join(
41
+ ', '
42
+ )}; received: ${size}`,
43
+ SIZES.includes(size)
44
+ );
45
+
46
+ return size;
47
+ }
48
+
49
+ /**
50
+ * @param sizeClass
51
+ * @type {string}
52
+ * @default hds-button--size-medium
53
+ * @description Determines the CSS class that the button should have, based on the size value; automatically set.
54
+ */
55
+ get sizeClass() {
56
+ return `hds-button--size-${this.size}`;
57
+ }
58
+
59
+ /**
60
+ * @param color
61
+ * @type {string}
62
+ * @default primary
63
+ * @description Determines the color of button to be used; acceptable values are `primary`, `secondary`, and `destructive`
64
+ */
65
+ get color() {
66
+ let { color = DEFAULT_COLOR } = this.args;
67
+
68
+ assert(
69
+ `@color for "Hds::Button" must be one of the following: ${COLORS.join(
70
+ ', '
71
+ )}; received: ${color}`,
72
+ COLORS.includes(color)
73
+ );
74
+
75
+ return color;
76
+ }
77
+
78
+ /**
79
+ * @param colorClass
80
+ * @type {string}
81
+ * @default hds-button--color-primary
82
+ * @description Determines the CSS class that the button should have, based on the color value; automatically set
83
+ */
84
+ get colorClass() {
85
+ return `hds-button--color-${this.color}`;
86
+ }
87
+
88
+ /**
89
+ * @param icon
90
+ * @type {string}
91
+ * @default null
92
+ * @description The name of the icon to be used.
93
+ */
94
+ get icon() {
95
+ return this.args.icon ?? null;
96
+ }
97
+
98
+ /**
99
+ * @param isIconOnly
100
+ * @type {boolean}
101
+ * @default false
102
+ * @description Indicates if the button will only contain an icon; component will also ensure that accessible text is still applied to the component.
103
+ */
104
+ get isIconOnly() {
105
+ if (this.icon) {
106
+ return this.args.isIconOnly ?? false;
107
+ }
108
+ return false;
109
+ }
110
+
111
+ /**
112
+ * @param iconPosition
113
+ * @type {string}
114
+ * @default leading
115
+ * @description Positions the icon before or after the text; allowed values are `leading` or `trailing`
116
+ */
117
+ get iconPosition() {
118
+ let { iconPosition = DEFAULT_ICONPOSITION } = this.args;
119
+
120
+ assert(
121
+ `@iconPosition for "Hds::Button" must be one of the following: ${ICONPOSITIONS.join(
122
+ ', '
123
+ )}; received: ${iconPosition}`,
124
+ ICONPOSITIONS.includes(iconPosition)
125
+ );
126
+
127
+ return iconPosition;
128
+ }
129
+
130
+ /**
131
+ * @param iconSize
132
+ * @type {string}
133
+ * @default 16
134
+ * @description ensures that the correct icon size is used. Automatically calculated.
135
+ */
136
+ get iconSize() {
137
+ if (this.args.size === 'large') {
138
+ return '24';
139
+ } else {
140
+ return '16';
141
+ }
142
+ }
143
+
144
+ /**
145
+ * @param type
146
+ * @type {string}
147
+ * @default button
148
+ * @description The value for the button's `type` attribute. Acceptable values are `button`, `submit`, and `reset`
149
+ */
150
+ get type() {
151
+ let { type = DEFAULT_TYPE } = this.args;
152
+
153
+ assert(
154
+ `@type for "Hds::Button" must be one of the following: ${TYPES.join(
155
+ ', '
156
+ )}; received: ${type}`,
157
+ TYPES.includes(type)
158
+ );
159
+
160
+ return type;
161
+ }
162
+
163
+ /**
164
+ * @param isFullWidth
165
+ * @type {boolean}
166
+ * @default false
167
+ * @description Indicates that a button should take up the full width of the parent container. The default is false.
168
+ */
169
+ get isFullWidth() {
170
+ return this.args.isFullWidth ?? false;
171
+ }
172
+
173
+ /**
174
+ * @param widthClass
175
+ * @type {string|null}
176
+ * @default null
177
+ * @description Determines if the full-width class should be applied to the component. This is set automatically based on the value of `isFullWidth`.
178
+ */
179
+ get widthClass() {
180
+ if (this.isFullWidth === true) {
181
+ return 'hds-button--width-full';
182
+ } else {
183
+ return null;
184
+ }
185
+ }
186
+
187
+ /**
188
+ * @param isDisabled
189
+ * @type {boolean}
190
+ * @default null
191
+ * @description Sets the native HTML attribute `disabled` on the button element. Default is null (doesn't render the attribute).
192
+ */
193
+ get isDisabled() {
194
+ return this.args.isDisabled ?? null;
195
+ }
196
+ }
@@ -20,14 +20,12 @@ export default class HdsCardContainerComponent extends Component {
20
20
  get level() {
21
21
  let { level = DEFAULT_LEVEL } = this.args;
22
22
 
23
- if (level) {
24
- assert(
25
- `@level for "Hds::CardContainer" must be one of the following: ${LEVELS.join(
26
- ', '
27
- )}, received: ${level}`,
28
- LEVELS.includes(level)
29
- );
30
- }
23
+ assert(
24
+ `@level for "Hds::CardContainer" must be one of the following: ${LEVELS.join(
25
+ ', '
26
+ )}, received: ${level}`,
27
+ LEVELS.includes(level)
28
+ );
31
29
 
32
30
  return level;
33
31
  }
@@ -52,14 +50,12 @@ export default class HdsCardContainerComponent extends Component {
52
50
  get background() {
53
51
  let { background = DEFAULT_BACKGROUND } = this.args;
54
52
 
55
- if (background) {
56
- assert(
57
- `@background for "Hds::CardContainer" must be one of the following: ${BACKGROUNDS.join(
58
- ', '
59
- )}, received: ${background}`,
60
- BACKGROUNDS.includes(background)
61
- );
62
- }
53
+ assert(
54
+ `@background for "Hds::CardContainer" must be one of the following: ${BACKGROUNDS.join(
55
+ ', '
56
+ )}, received: ${background}`,
57
+ BACKGROUNDS.includes(background)
58
+ );
63
59
 
64
60
  return background;
65
61
  }
@@ -93,14 +89,12 @@ export default class HdsCardContainerComponent extends Component {
93
89
  get overflow() {
94
90
  let { overflow = DEFAULT_OVERFLOW } = this.args;
95
91
 
96
- if (overflow) {
97
- assert(
98
- `@overflow for "Hds::CardContainer" must be one of the following: ${OVERFLOWS.join(
99
- ', '
100
- )}, received: ${overflow}`,
101
- OVERFLOWS.includes(overflow)
102
- );
103
- }
92
+ assert(
93
+ `@overflow for "Hds::CardContainer" must be one of the following: ${OVERFLOWS.join(
94
+ ', '
95
+ )}, received: ${overflow}`,
96
+ OVERFLOWS.includes(overflow)
97
+ );
104
98
 
105
99
  return overflow;
106
100
  }