@hashicorp/design-system-components 0.9.2 → 0.10.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.
- package/CHANGELOG.md +15 -0
- package/addon/components/hds/disclosure/index.js +4 -0
- package/addon/components/hds/dropdown/index.hbs +10 -13
- package/addon/components/hds/dropdown/index.js +45 -0
- package/addon/components/hds/dropdown/list-item/copy-item.hbs +20 -0
- package/addon/components/hds/dropdown/list-item/copy-item.js +48 -0
- package/addon/components/hds/dropdown/list-item/description.hbs +3 -0
- package/addon/components/hds/dropdown/list-item/description.js +38 -0
- package/addon/components/hds/dropdown/list-item/generic.hbs +3 -0
- package/addon/components/hds/dropdown/list-item/interactive.hbs +44 -0
- package/addon/components/hds/dropdown/list-item/interactive.js +59 -0
- package/addon/components/hds/dropdown/list-item/separator.hbs +1 -0
- package/addon/components/hds/dropdown/list-item/title.hbs +3 -0
- package/addon/components/hds/dropdown/list-item/title.js +35 -0
- package/addon/components/hds/dropdown/{toggle-button.hbs → toggle/button.hbs} +3 -3
- package/addon/components/hds/dropdown/{toggle-button.js → toggle/button.js} +21 -3
- package/addon/components/hds/dropdown/toggle/icon.hbs +12 -0
- package/addon/components/hds/dropdown/{toggle-icon.js → toggle/icon.js} +28 -13
- package/app/components/hds/dropdown/list-item/copy-item.js +1 -0
- package/app/components/hds/dropdown/list-item/description.js +1 -0
- package/app/components/hds/dropdown/list-item/generic.js +1 -0
- package/app/components/hds/dropdown/list-item/interactive.js +1 -0
- package/app/components/hds/dropdown/list-item/separator.js +1 -0
- package/app/components/hds/dropdown/{toggle-icon.js → list-item/title.js} +1 -1
- package/app/components/hds/dropdown/{toggle-button.js → toggle/button.js} +1 -1
- package/app/components/hds/dropdown/{list-item.js → toggle/icon.js} +1 -1
- package/app/styles/components/dropdown.scss +121 -113
- package/package.json +2 -1
- package/addon/components/hds/dropdown/list-item.hbs +0 -84
- package/addon/components/hds/dropdown/list-item.js +0 -120
- package/addon/components/hds/dropdown/toggle-icon.hbs +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @hashicorp/design-system-components
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#200](https://github.com/hashicorp/design-system/pull/200) [`a8072537`](https://github.com/hashicorp/design-system/commit/a8072537542791398d375cde4a7a85c2955c66da) Thanks [@didoo](https://github.com/didoo)! - Updated Dropdown component:
|
|
8
|
+
|
|
9
|
+
- added chevron animation for `toggle` elements
|
|
10
|
+
- fixed issue with `list-item/interactive` height
|
|
11
|
+
- added handling of dynamic `width` for the list
|
|
12
|
+
- exposed an `onClose` event
|
|
13
|
+
- removed the default icon for `toggle/icon`
|
|
14
|
+
- removed icon requirement from the `critical` list item
|
|
15
|
+
- updated the documentation and integration tests
|
|
16
|
+
- some code refactorings, reorganizations and cleanups
|
|
17
|
+
|
|
3
18
|
## 0.9.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -38,6 +38,10 @@ export default class HdsDisclosureComponent extends Component {
|
|
|
38
38
|
this.isActive = false;
|
|
39
39
|
// we need to reset this check
|
|
40
40
|
this.isToggleClicked = false;
|
|
41
|
+
// we call the "onClose" callback if it exists (and is a function)
|
|
42
|
+
if (this.args.onClose && typeof this.args.onClose === 'function') {
|
|
43
|
+
this.args.onClose();
|
|
44
|
+
}
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
<Hds::Disclosure class="hds-dropdown">
|
|
1
|
+
<Hds::Disclosure class="hds-dropdown" @onClose={{@onClose}} ...attributes>
|
|
2
2
|
<:toggle as |t|>
|
|
3
3
|
{{yield
|
|
4
4
|
(hash
|
|
5
|
-
ToggleButton=(component "hds/dropdown/toggle
|
|
6
|
-
ToggleIcon=(component "hds/dropdown/toggle
|
|
5
|
+
ToggleButton=(component "hds/dropdown/toggle/button" isOpen=t.isActive onClick=t.onClickToggle)
|
|
6
|
+
ToggleIcon=(component "hds/dropdown/toggle/icon" isOpen=t.isActive onClick=t.onClickToggle)
|
|
7
7
|
)
|
|
8
8
|
}}
|
|
9
9
|
</:toggle>
|
|
10
10
|
<:content>
|
|
11
|
-
<ul
|
|
12
|
-
class="hds-dropdown-list
|
|
13
|
-
{{if (eq @listPosition 'left') 'hds-dropdown-list--position-left' 'hds-dropdown-list--position-right'}}"
|
|
14
|
-
>
|
|
11
|
+
<ul class={{this.listClassNames}} {{style width=@width}}>
|
|
15
12
|
{{yield
|
|
16
13
|
(hash
|
|
17
|
-
CopyItem=(component "hds/dropdown/list-item
|
|
18
|
-
Description=(component "hds/dropdown/list-item
|
|
19
|
-
Generic=(component "hds/dropdown/list-item
|
|
20
|
-
Interactive=(component "hds/dropdown/list-item")
|
|
21
|
-
Separator=(component "hds/dropdown/list-item
|
|
22
|
-
Title=(component "hds/dropdown/list-item
|
|
14
|
+
CopyItem=(component "hds/dropdown/list-item/copy-item")
|
|
15
|
+
Description=(component "hds/dropdown/list-item/description")
|
|
16
|
+
Generic=(component "hds/dropdown/list-item/generic")
|
|
17
|
+
Interactive=(component "hds/dropdown/list-item/interactive")
|
|
18
|
+
Separator=(component "hds/dropdown/list-item/separator")
|
|
19
|
+
Title=(component "hds/dropdown/list-item/title")
|
|
23
20
|
)
|
|
24
21
|
}}
|
|
25
22
|
</ul>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_POSITION = 'right';
|
|
5
|
+
export const POSITIONS = ['right', 'left'];
|
|
6
|
+
|
|
7
|
+
export default class HdsDropdownIndexComponent extends Component {
|
|
8
|
+
/**
|
|
9
|
+
* @param listPosition
|
|
10
|
+
* @type {string}
|
|
11
|
+
* @default primary
|
|
12
|
+
* @description Determines the position of the "list"
|
|
13
|
+
*/
|
|
14
|
+
get listPosition() {
|
|
15
|
+
let { listPosition = DEFAULT_POSITION } = this.args;
|
|
16
|
+
|
|
17
|
+
assert(
|
|
18
|
+
`@listPosition for "Hds::Dropdown::Index" must be one of the following: ${POSITIONS.join(
|
|
19
|
+
', '
|
|
20
|
+
)}; received: ${listPosition}`,
|
|
21
|
+
POSITIONS.includes(listPosition)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return listPosition;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the class names to apply to the "list"
|
|
29
|
+
* @method DropdownIndex#listClassNames
|
|
30
|
+
* @return {string} The "class" attribute to apply to the "list" element
|
|
31
|
+
*/
|
|
32
|
+
get listClassNames() {
|
|
33
|
+
let classes = ['hds-dropdown-list'];
|
|
34
|
+
|
|
35
|
+
// add a class based on the @listPosition argument
|
|
36
|
+
classes.push(`hds-dropdown-list--position-${this.listPosition}`);
|
|
37
|
+
|
|
38
|
+
// add a class based on the @width argument
|
|
39
|
+
if (this.args.width) {
|
|
40
|
+
classes.push('hds-dropdown-list--fixed-width');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return classes.join(' ');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<li class={{this.classNames}} ...attributes>
|
|
2
|
+
{{#if @copyItemTitle}}
|
|
3
|
+
<div
|
|
4
|
+
class="hds-dropdown-list-item__copy-item-title hds-typography-body-100 hds-font-weight-semibold"
|
|
5
|
+
>{{@copyItemTitle}}</div>
|
|
6
|
+
{{/if}}
|
|
7
|
+
<button
|
|
8
|
+
type="button"
|
|
9
|
+
class="{{if @state (concat 'is-' @state)}} {{if this.isSuccess 'is-success'}}"
|
|
10
|
+
{{on "click" this.copyCode}}
|
|
11
|
+
>
|
|
12
|
+
<div class="hds-dropdown-list-item__copy-item-text hds-typography-code-100">
|
|
13
|
+
{{this.text}}
|
|
14
|
+
</div>
|
|
15
|
+
<FlightIcon
|
|
16
|
+
@name="{{if this.isSuccess 'clipboard-checked' 'clipboard-copy'}}"
|
|
17
|
+
class="hds-dropdown-list-item__copy-item-icon"
|
|
18
|
+
/>
|
|
19
|
+
</button>
|
|
20
|
+
</li>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
|
|
6
|
+
export default class HdsDropdownListItemCopyItemComponent extends Component {
|
|
7
|
+
@tracked isSuccess = this.args.isSuccess ?? false;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param text
|
|
11
|
+
* @type {string}
|
|
12
|
+
* @description The text of the item. If no text value is defined an error will be thrown
|
|
13
|
+
*/
|
|
14
|
+
get text() {
|
|
15
|
+
let { text } = this.args;
|
|
16
|
+
|
|
17
|
+
assert(
|
|
18
|
+
'@text for "Hds::Dropdown::ListItem::CopyItem" must have a valid value',
|
|
19
|
+
text !== undefined
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return text;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the class names to apply to the component.
|
|
27
|
+
* @method classNames
|
|
28
|
+
* @return {string} The "class" attribute to apply to the component.
|
|
29
|
+
*/
|
|
30
|
+
get classNames() {
|
|
31
|
+
let classes = [
|
|
32
|
+
'hds-dropdown-list-item',
|
|
33
|
+
'hds-dropdown-list-item--copy-item',
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
return classes.join(' ');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@action
|
|
40
|
+
copyCode() {
|
|
41
|
+
navigator.clipboard.writeText(this.args.text);
|
|
42
|
+
// this if statement resolves to [object Promise] so maybe some improvements
|
|
43
|
+
// could be made here
|
|
44
|
+
if (navigator.clipboard.readText()) {
|
|
45
|
+
this.isSuccess = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
4
|
+
export default class HdsDropdownListItemDescriptionComponent extends Component {
|
|
5
|
+
/**
|
|
6
|
+
* @param text
|
|
7
|
+
* @type {string}
|
|
8
|
+
* @description The text of the item. If no text value is defined an error will be thrown
|
|
9
|
+
*/
|
|
10
|
+
get text() {
|
|
11
|
+
let { text } = this.args;
|
|
12
|
+
|
|
13
|
+
assert(
|
|
14
|
+
'@text for "Hds::Dropdown::ListItem::Description" must have a valid value',
|
|
15
|
+
text !== undefined
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return text;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the class names to apply to the component.
|
|
23
|
+
* @method classNames
|
|
24
|
+
* @return {string} The "class" attribute to apply to the component.
|
|
25
|
+
*/
|
|
26
|
+
get classNames() {
|
|
27
|
+
let classes = [
|
|
28
|
+
'hds-dropdown-list-item',
|
|
29
|
+
'hds-dropdown-list-item--description',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// add classes for the typographic style
|
|
33
|
+
classes.push('hds-typography-body-100');
|
|
34
|
+
classes.push('hds-font-weight-regular');
|
|
35
|
+
|
|
36
|
+
return classes.join(' ');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<li class={{this.classNames}}>
|
|
2
|
+
{{#if @route}}
|
|
3
|
+
<LinkTo
|
|
4
|
+
class="{{if @state (concat 'is-' @state)}}"
|
|
5
|
+
@current-when={{@current-when}}
|
|
6
|
+
@models={{hds-link-to-models @model @models}}
|
|
7
|
+
@query={{hds-link-to-query @query}}
|
|
8
|
+
@replace={{@replace}}
|
|
9
|
+
@route={{@route}}
|
|
10
|
+
...attributes
|
|
11
|
+
>
|
|
12
|
+
{{#if @icon}}
|
|
13
|
+
<div class="hds-dropdown-list-item__interactive-icon">
|
|
14
|
+
<FlightIcon @name={{@icon}} @isInlineBlock={{false}} />
|
|
15
|
+
</div>
|
|
16
|
+
{{/if}}
|
|
17
|
+
<div class="hds-dropdown-list-item__interactive-text hds-typography-body-200 hds-font-weight-medium">
|
|
18
|
+
{{this.text}}
|
|
19
|
+
</div>
|
|
20
|
+
</LinkTo>
|
|
21
|
+
{{else if @href}}
|
|
22
|
+
<a target="_blank" rel="noopener noreferrer" href={{@href}} class="{{if @state (concat 'is-' @state)}}">
|
|
23
|
+
{{#if @icon}}
|
|
24
|
+
<div class="hds-dropdown-list-item__interactive-icon">
|
|
25
|
+
<FlightIcon @name={{@icon}} @isInlineBlock={{false}} />
|
|
26
|
+
</div>
|
|
27
|
+
{{/if}}
|
|
28
|
+
<div class="hds-dropdown-list-item__interactive-text hds-typography-body-200 hds-font-weight-medium">
|
|
29
|
+
{{this.text}}
|
|
30
|
+
</div>
|
|
31
|
+
</a>
|
|
32
|
+
{{else}}
|
|
33
|
+
<button class="{{if @state (concat 'is-' @state)}}" type="button" ...attributes>
|
|
34
|
+
{{#if @icon}}
|
|
35
|
+
<div class="hds-dropdown-list-item__interactive-icon">
|
|
36
|
+
<FlightIcon @name={{@icon}} @isInlineBlock={{false}} />
|
|
37
|
+
</div>
|
|
38
|
+
{{/if}}
|
|
39
|
+
<div class="hds-dropdown-list-item__interactive-text hds-typography-body-200 hds-font-weight-medium">
|
|
40
|
+
{{this.text}}
|
|
41
|
+
</div>
|
|
42
|
+
</button>
|
|
43
|
+
{{/if}}
|
|
44
|
+
</li>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_COLOR = 'action';
|
|
5
|
+
export const COLORS = ['action', 'critical'];
|
|
6
|
+
|
|
7
|
+
export default class HdsDropdownListItemInteractiveComponent extends Component {
|
|
8
|
+
/**
|
|
9
|
+
* @param text
|
|
10
|
+
* @type {string}
|
|
11
|
+
* @description The text of the item. If no text value is defined an error will be thrown
|
|
12
|
+
*/
|
|
13
|
+
get text() {
|
|
14
|
+
let { text } = this.args;
|
|
15
|
+
|
|
16
|
+
assert(
|
|
17
|
+
'@text for "Hds::Dropdown::ListItem::Interactive" must have a valid value',
|
|
18
|
+
text !== undefined
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return text;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param color
|
|
26
|
+
* @type {string}
|
|
27
|
+
* @default primary
|
|
28
|
+
* @description Determines the color of the item (when item is set to interactive)
|
|
29
|
+
*/
|
|
30
|
+
get color() {
|
|
31
|
+
let { color = DEFAULT_COLOR } = this.args;
|
|
32
|
+
|
|
33
|
+
assert(
|
|
34
|
+
`@color for "Hds::Dropdown::ListItem::Interactive" must be one of the following: ${COLORS.join(
|
|
35
|
+
', '
|
|
36
|
+
)}; received: ${color}`,
|
|
37
|
+
COLORS.includes(color)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return color;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the class names to apply to the component.
|
|
45
|
+
* @method classNames
|
|
46
|
+
* @return {string} The "class" attribute to apply to the component.
|
|
47
|
+
*/
|
|
48
|
+
get classNames() {
|
|
49
|
+
let classes = [
|
|
50
|
+
'hds-dropdown-list-item',
|
|
51
|
+
'hds-dropdown-list-item--interactive',
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// add a class based on the @color argument
|
|
55
|
+
classes.push(`hds-dropdown-list-item--color-${this.color}`);
|
|
56
|
+
|
|
57
|
+
return classes.join(' ');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<li class="hds-dropdown-list-item hds-dropdown-list-item--separator" role="separator" ...attributes></li>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
4
|
+
export default class HdsDropdownListItemTitleComponent extends Component {
|
|
5
|
+
/**
|
|
6
|
+
* @param text
|
|
7
|
+
* @type {string}
|
|
8
|
+
* @description The text of the item. If no text value is defined an error will be thrown
|
|
9
|
+
*/
|
|
10
|
+
get text() {
|
|
11
|
+
let { text } = this.args;
|
|
12
|
+
|
|
13
|
+
assert(
|
|
14
|
+
'@text for "Hds::Dropdown::ListItem::Title" must have a valid value',
|
|
15
|
+
text !== undefined
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return text;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the class names to apply to the component.
|
|
23
|
+
* @method classNames
|
|
24
|
+
* @return {string} The "class" attribute to apply to the component.
|
|
25
|
+
*/
|
|
26
|
+
get classNames() {
|
|
27
|
+
let classes = ['hds-dropdown-list-item', 'hds-dropdown-list-item--title'];
|
|
28
|
+
|
|
29
|
+
// add classes for the typographic style
|
|
30
|
+
classes.push('hds-typography-body-100');
|
|
31
|
+
classes.push('hds-font-weight-semibold');
|
|
32
|
+
|
|
33
|
+
return classes.join(' ');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
}}
|
|
14
14
|
|
|
15
15
|
<Hds::Button
|
|
16
|
+
class={{this.classNames}}
|
|
16
17
|
@text={{this.text}}
|
|
17
|
-
@icon="chevron-
|
|
18
|
+
@icon="chevron-down"
|
|
18
19
|
@iconPosition="trailing"
|
|
19
20
|
@color={{this.color}}
|
|
20
|
-
class="hds-dropdown-toggle--with-button-component"
|
|
21
|
-
{{on "click" this.onClick}}
|
|
22
21
|
...attributes
|
|
22
|
+
{{on "click" this.onClick}}
|
|
23
23
|
/>
|
|
@@ -4,6 +4,8 @@ import { assert } from '@ember/debug';
|
|
|
4
4
|
export const DEFAULT_COLOR = 'primary';
|
|
5
5
|
export const COLORS = ['primary', 'secondary'];
|
|
6
6
|
|
|
7
|
+
const NOOP = () => {};
|
|
8
|
+
|
|
7
9
|
export default class HdsDropdownToggleButtonComponent extends Component {
|
|
8
10
|
/**
|
|
9
11
|
* @param text
|
|
@@ -14,7 +16,7 @@ export default class HdsDropdownToggleButtonComponent extends Component {
|
|
|
14
16
|
let { text } = this.args;
|
|
15
17
|
|
|
16
18
|
assert(
|
|
17
|
-
'@text for "Hds::Dropdown::
|
|
19
|
+
'@text for "Hds::Dropdown::Toggle::Button" must have a valid value',
|
|
18
20
|
text !== undefined
|
|
19
21
|
);
|
|
20
22
|
|
|
@@ -31,7 +33,7 @@ export default class HdsDropdownToggleButtonComponent extends Component {
|
|
|
31
33
|
let { color = DEFAULT_COLOR } = this.args;
|
|
32
34
|
|
|
33
35
|
assert(
|
|
34
|
-
`@color for "Hds::Dropdown::
|
|
36
|
+
`@color for "Hds::Dropdown::Toggle::Button" must be one of the following: ${COLORS.join(
|
|
35
37
|
', '
|
|
36
38
|
)}; received: ${color}`,
|
|
37
39
|
COLORS.includes(color)
|
|
@@ -53,7 +55,23 @@ export default class HdsDropdownToggleButtonComponent extends Component {
|
|
|
53
55
|
if (typeof onClick === 'function') {
|
|
54
56
|
return onClick;
|
|
55
57
|
} else {
|
|
56
|
-
return
|
|
58
|
+
return NOOP;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get the class names to apply to the component.
|
|
64
|
+
* @method ToggleButton#classNames
|
|
65
|
+
* @return {string} The "class" attribute to apply to the component.
|
|
66
|
+
*/
|
|
67
|
+
get classNames() {
|
|
68
|
+
let classes = ['hds-dropdown-toggle-button'];
|
|
69
|
+
|
|
70
|
+
// add a class based on the @isOpen argument
|
|
71
|
+
if (this.args.isOpen) {
|
|
72
|
+
classes.push('hds-dropdown-toggle-button--is-open');
|
|
57
73
|
}
|
|
74
|
+
|
|
75
|
+
return classes.join(' ');
|
|
58
76
|
}
|
|
59
77
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<button class={{this.classNames}} aria-label={{this.text}} ...attributes {{on "click" this.onClick}} type="button">
|
|
2
|
+
<div class="hds-dropdown-toggle-icon__wrapper">
|
|
3
|
+
{{#if @imageSrc}}
|
|
4
|
+
<img src={{@imageSrc}} alt="" role="presentation" height="32" width="32" />
|
|
5
|
+
{{else if @icon}}
|
|
6
|
+
<FlightIcon @name={{@icon}} @size="24" />
|
|
7
|
+
{{/if}}
|
|
8
|
+
</div>
|
|
9
|
+
{{#if this.hasChevron}}
|
|
10
|
+
<FlightIcon @name="chevron-down" class="hds-dropdown-toggle-icon__chevron" @isInlineBlock={{false}} />
|
|
11
|
+
{{/if}}
|
|
12
|
+
</button>
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
2
|
import { assert } from '@ember/debug';
|
|
3
3
|
|
|
4
|
+
const NOOP = () => {};
|
|
4
5
|
export default class HdsDropdownToggleIconComponent extends Component {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
if (!(this.args.icon || this.args.imageSrc)) {
|
|
9
|
+
assert(
|
|
10
|
+
'@icon or @imageSrc must be defined for "Hds::Dropdown::Toggle::Icon"'
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
/**
|
|
6
16
|
* @param text
|
|
7
17
|
* @type {string}
|
|
@@ -11,7 +21,7 @@ export default class HdsDropdownToggleIconComponent extends Component {
|
|
|
11
21
|
let { text } = this.args;
|
|
12
22
|
|
|
13
23
|
assert(
|
|
14
|
-
'@text for "Hds::Dropdown::
|
|
24
|
+
'@text for "Hds::Dropdown::Toggle::Icon" must have a valid value',
|
|
15
25
|
text !== undefined
|
|
16
26
|
);
|
|
17
27
|
|
|
@@ -29,17 +39,6 @@ export default class HdsDropdownToggleIconComponent extends Component {
|
|
|
29
39
|
return this.args.hasChevron ?? true;
|
|
30
40
|
}
|
|
31
41
|
|
|
32
|
-
/**
|
|
33
|
-
* Sets the icon name
|
|
34
|
-
*
|
|
35
|
-
* @param icon
|
|
36
|
-
* @type {string}
|
|
37
|
-
* @default user
|
|
38
|
-
*/
|
|
39
|
-
get icon() {
|
|
40
|
-
return this.args.icon ?? 'user';
|
|
41
|
-
}
|
|
42
|
-
|
|
43
42
|
/**
|
|
44
43
|
* @param onClick
|
|
45
44
|
* @type {function}
|
|
@@ -53,7 +52,23 @@ export default class HdsDropdownToggleIconComponent extends Component {
|
|
|
53
52
|
if (typeof onClick === 'function') {
|
|
54
53
|
return onClick;
|
|
55
54
|
} else {
|
|
56
|
-
return
|
|
55
|
+
return NOOP;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get the class names to apply to the component.
|
|
61
|
+
* @method ToggleIcon#classNames
|
|
62
|
+
* @return {string} The "class" attribute to apply to the component.
|
|
63
|
+
*/
|
|
64
|
+
get classNames() {
|
|
65
|
+
let classes = ['hds-dropdown-toggle-icon'];
|
|
66
|
+
|
|
67
|
+
// add a class based on the @isOpen argument
|
|
68
|
+
if (this.args.isOpen) {
|
|
69
|
+
classes.push('hds-dropdown-toggle-icon--is-open');
|
|
57
70
|
}
|
|
71
|
+
|
|
72
|
+
return classes.join(' ');
|
|
58
73
|
}
|
|
59
74
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item/copy-item';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item/description';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item/generic';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item/interactive';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item/separator';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item/title';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/toggle
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/toggle/button';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/toggle/icon';
|
|
@@ -20,29 +20,33 @@
|
|
|
20
20
|
|
|
21
21
|
@use '../mixins/focus-ring' as *;
|
|
22
22
|
|
|
23
|
+
$hds-dropdown-toggle-base-height: 36px;
|
|
24
|
+
$hds-dropdown-toggle-border-radius: 5px;
|
|
25
|
+
|
|
26
|
+
|
|
23
27
|
// TOGGLE/ICON
|
|
28
|
+
|
|
24
29
|
.hds-dropdown-toggle-icon {
|
|
25
30
|
align-items: center;
|
|
26
31
|
background-color: transparent;
|
|
27
32
|
border: 1px solid transparent; // We need this to be transparent for a11y
|
|
28
|
-
border-radius:
|
|
33
|
+
border-radius: $hds-dropdown-toggle-border-radius;
|
|
29
34
|
display: flex;
|
|
30
|
-
height:
|
|
35
|
+
height: $hds-dropdown-toggle-base-height;
|
|
31
36
|
justify-content: center;
|
|
37
|
+
min-width: $hds-dropdown-toggle-base-height;
|
|
32
38
|
outline-style: solid; // used to avoid double outline+focus-ring in Safari (see https://github.com/hashicorp/design-system-components/issues/161#issuecomment-1031548656)
|
|
33
39
|
outline-color: transparent; // We need this to be transparent for a11y
|
|
34
40
|
padding: 1px;
|
|
35
|
-
min-width: 36px;
|
|
36
41
|
|
|
37
|
-
&:hover,
|
|
42
|
+
&:hover,
|
|
38
43
|
&.is-hover {
|
|
39
44
|
background-color: var(--token-color-surface-interactive);
|
|
40
45
|
border-color: var(--token-color-border-strong);
|
|
41
46
|
cursor: pointer;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
@include hds-focus-ring-with-pseudo-element($top: -1px, $right: -1px, $bottom: -1px, $left: -1px, $radius: 5px);
|
|
49
|
+
@include hds-focus-ring-with-pseudo-element($top: -1px, $right: -1px, $bottom: -1px, $left: -1px, $radius: $hds-dropdown-toggle-border-radius);
|
|
46
50
|
|
|
47
51
|
&:active,
|
|
48
52
|
&.is-active {
|
|
@@ -53,7 +57,7 @@
|
|
|
53
57
|
|
|
54
58
|
.hds-dropdown-toggle-icon__wrapper {
|
|
55
59
|
align-items: center;
|
|
56
|
-
border-radius: 3px; //
|
|
60
|
+
border-radius: 3px; // $hds-dropdown-toggle-border-radius - 1px padding - 1px border
|
|
57
61
|
display: flex;
|
|
58
62
|
justify-content: center;
|
|
59
63
|
height: 32px;
|
|
@@ -62,21 +66,43 @@
|
|
|
62
66
|
|
|
63
67
|
img {
|
|
64
68
|
border-radius: inherit;
|
|
69
|
+
height: 100%;
|
|
65
70
|
object-fit: cover; // this will make sure it's correct even if the item isn't square
|
|
71
|
+
width: 100%;
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
.hds-dropdown-toggle-icon__chevron {
|
|
70
|
-
margin-left:
|
|
76
|
+
margin-left: 4px;
|
|
77
|
+
|
|
78
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
79
|
+
transition: transform .3s;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.hds-dropdown-toggle-icon--is-open & {
|
|
83
|
+
transform: rotate(-180deg);
|
|
84
|
+
}
|
|
71
85
|
}
|
|
72
86
|
|
|
73
87
|
// TOGGLE/BUTTON
|
|
74
|
-
|
|
88
|
+
|
|
89
|
+
.hds-dropdown-toggle-button {
|
|
75
90
|
box-shadow: none; // we override this to remove the elevation style
|
|
76
91
|
|
|
77
92
|
.hds-button__icon {
|
|
93
|
+
margin-left: 8px; // this overrides the rule `.hds-button__text + .hds-button__icon`
|
|
78
94
|
margin-right: -6px; // we apply a negative margin to counter the padding-right of the button and reduce the visual space between the icon and the right border
|
|
79
|
-
|
|
95
|
+
|
|
96
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
97
|
+
transition: transform .3s;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
.hds-dropdown-toggle-button--is-open {
|
|
104
|
+
.hds-button__icon {
|
|
105
|
+
transform: rotate(-180deg);
|
|
80
106
|
}
|
|
81
107
|
}
|
|
82
108
|
|
|
@@ -91,71 +117,37 @@
|
|
|
91
117
|
box-shadow: var(--token-surface-high-box-shadow);
|
|
92
118
|
list-style: none;
|
|
93
119
|
margin: 0;
|
|
94
|
-
max-width:
|
|
95
|
-
min-width:
|
|
120
|
+
max-width: 400px;
|
|
121
|
+
min-width: 200px;
|
|
96
122
|
padding: 4px 0;
|
|
97
|
-
|
|
98
|
-
position: absolute;
|
|
99
|
-
right: 0;
|
|
100
|
-
top: calc(100% + 0.25rem);
|
|
101
|
-
z-index: 2; // https://github.com/hashicorp/design-system/issues/114
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
&.hds-dropdown-list--position-left {
|
|
105
|
-
position: absolute;
|
|
106
|
-
left: 0;
|
|
107
|
-
top: calc(100% + 0.25rem);
|
|
108
|
-
z-index: 2; // https://github.com/hashicorp/design-system/issues/114
|
|
109
|
-
}
|
|
123
|
+
width: max-content; // notice: this is important because being in a position absolute means the layout algorithm assigns a width of 0 and this impacts on the flex algorithm of the children (in some cases they don't use the full width)
|
|
110
124
|
}
|
|
111
125
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
.hds-dropdown-list-item--title {
|
|
116
|
-
color: var(--token-color-foreground-strong);
|
|
117
|
-
font-family: var(--token-typography-body-100-font-family);
|
|
118
|
-
font-size: var(--token-typography-body-100-font-size);
|
|
119
|
-
font-weight: var(--token-typography-font-weight-semibold);
|
|
120
|
-
line-height: var(--token-typography-body-100-line-height);
|
|
121
|
-
padding: 10px 16px 4px;
|
|
126
|
+
.hds-dropdown-list--fixed-width {
|
|
127
|
+
max-width: initial;
|
|
128
|
+
min-width: initial;
|
|
122
129
|
}
|
|
123
130
|
|
|
124
|
-
.hds-dropdown-list-
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
.hds-dropdown-list--position-right {
|
|
132
|
+
position: absolute;
|
|
133
|
+
right: 0;
|
|
134
|
+
top: calc(100% + 4px);
|
|
135
|
+
z-index: 2; // https://github.com/hashicorp/design-system/issues/114
|
|
127
136
|
}
|
|
128
137
|
|
|
129
|
-
.hds-dropdown-list-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
line-height: var(--token-typography-body-100-line-height);
|
|
135
|
-
padding: 2px 16px 4px;
|
|
138
|
+
.hds-dropdown-list--position-left {
|
|
139
|
+
left: 0;
|
|
140
|
+
position: absolute;
|
|
141
|
+
top: calc(100% + 4px);
|
|
142
|
+
z-index: 2; // https://github.com/hashicorp/design-system/issues/114
|
|
136
143
|
}
|
|
137
144
|
|
|
138
|
-
.hds-dropdown-list-item--separator {
|
|
139
|
-
position: relative;
|
|
140
|
-
height: 4px;
|
|
141
|
-
width: 100%;
|
|
142
145
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
right: 6px;
|
|
146
|
-
left: 6px;
|
|
147
|
-
bottom: 0;
|
|
148
|
-
border-bottom: 1px solid var(--token-color-border-primary);
|
|
149
|
-
content: '';
|
|
150
|
-
}
|
|
151
|
-
}
|
|
146
|
+
// LIST > LIST-ITEM
|
|
147
|
+
// HDS::DROPDOWN::LIST-ITEM
|
|
152
148
|
|
|
153
149
|
.hds-dropdown-list-item__copy-item-title {
|
|
154
150
|
color: var(--token-color-foreground-faint);
|
|
155
|
-
font-family: var(--token-typography-body-100-font-family);
|
|
156
|
-
font-size: var(--token-typography-body-100-font-size); // 13
|
|
157
|
-
font-weight: var(--token-typography-font-weight-semibold);
|
|
158
|
-
line-height: var(--token-typography-body-100-line-height); // 18
|
|
159
151
|
padding: 2px 0 4px;
|
|
160
152
|
}
|
|
161
153
|
|
|
@@ -163,17 +155,16 @@
|
|
|
163
155
|
padding: 10px 16px 12px;
|
|
164
156
|
width: 100%;
|
|
165
157
|
|
|
166
|
-
button {
|
|
158
|
+
button {
|
|
167
159
|
background-color: transparent;
|
|
168
160
|
border-radius: 5px;
|
|
169
161
|
border: 1px solid var(--token-color-border-primary);
|
|
170
|
-
color: var(--token-color-foreground-primary);
|
|
162
|
+
color: var(--token-color-foreground-primary);
|
|
171
163
|
display: flex;
|
|
172
|
-
font-family: var(--token-typography-font-stack-code);
|
|
173
164
|
justify-content: space-between;
|
|
174
165
|
padding: 12px 8px;
|
|
175
166
|
width: 100%;
|
|
176
|
-
|
|
167
|
+
|
|
177
168
|
&:hover,
|
|
178
169
|
&.is-hover {
|
|
179
170
|
background-color: var(--token-color-surface-interactive-hover);
|
|
@@ -181,55 +172,60 @@
|
|
|
181
172
|
}
|
|
182
173
|
|
|
183
174
|
@include hds-focus-ring-basic();
|
|
184
|
-
|
|
175
|
+
|
|
185
176
|
&:focus,
|
|
186
177
|
&.is-focus {
|
|
187
|
-
//TODO this focus is just way too complex
|
|
178
|
+
//TODO this focus is just way too complex
|
|
188
179
|
background-color: var(--token-color-surface-action);
|
|
189
180
|
border-color: var(--token-color-focus-action-internal);
|
|
190
181
|
}
|
|
191
|
-
|
|
192
|
-
&:active,
|
|
182
|
+
|
|
183
|
+
&:active,
|
|
193
184
|
&.is-active {
|
|
194
185
|
background-color: var(--token-color-surface-interactive-active);
|
|
195
186
|
}
|
|
196
187
|
|
|
197
188
|
&.is-success {
|
|
198
|
-
border-color: var(--token-color-border-success);
|
|
199
189
|
background-color: var(--token-color-surface-success);
|
|
200
|
-
|
|
190
|
+
border-color: var(--token-color-border-success);
|
|
191
|
+
|
|
201
192
|
.hds-dropdown-list-item__copy-item-icon {
|
|
202
193
|
color: var(--token-color-foreground-success);
|
|
203
194
|
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.hds-dropdown-list-item__copy-item-text {
|
|
207
|
-
font-size: var(--token-typography-code-100-font-size);
|
|
208
|
-
font-weight: var(--token-typography-font-weight-regular);
|
|
209
|
-
line-height: var(--token-typography-code-100-line-height);
|
|
210
|
-
// max-width: 250px; // TODO we should be able to figure out the proportions here
|
|
211
|
-
overflow: hidden;
|
|
212
|
-
text-align: left;
|
|
213
|
-
text-overflow: ellipsis;
|
|
214
|
-
white-space: nowrap;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.hds-dropdown-list-item__copy-item-icon {
|
|
218
|
-
color: var(--token-color-foreground-action);
|
|
219
|
-
margin-left: 0.5rem;
|
|
220
195
|
}
|
|
221
196
|
}
|
|
222
197
|
}
|
|
223
198
|
|
|
199
|
+
.hds-dropdown-list-item__copy-item-text {
|
|
200
|
+
overflow: hidden;
|
|
201
|
+
text-align: left;
|
|
202
|
+
text-overflow: ellipsis;
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.hds-dropdown-list-item__copy-item-icon {
|
|
207
|
+
color: var(--token-color-foreground-action);
|
|
208
|
+
margin-left: 8px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.hds-dropdown-list-item--description {
|
|
212
|
+
color: var(--token-color-foreground-faint);
|
|
213
|
+
padding: 2px 16px 4px;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.hds-dropdown-list-item--generic {
|
|
217
|
+
padding-left: 16px;
|
|
218
|
+
padding-right: 16px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
224
222
|
.hds-dropdown-list-item--interactive {
|
|
225
|
-
position: relative;
|
|
226
223
|
isolation: isolate; // used to create a new stacking context (needed to have the pseudo element below text/icon but not the parent container)
|
|
227
224
|
min-height: 36px;
|
|
225
|
+
position: relative;
|
|
228
226
|
|
|
229
|
-
// need to reset a few extra things to make the button visually appear the same as the
|
|
230
|
-
// TODO this is 0.125rem taller than the link...
|
|
227
|
+
// need to reset a few extra things to make the button visually appear the same as the link
|
|
231
228
|
button {
|
|
232
|
-
border: 1px inset transparent; // cause of the extra height
|
|
233
229
|
background-color: transparent;
|
|
234
230
|
width: 100%;
|
|
235
231
|
|
|
@@ -242,10 +238,11 @@
|
|
|
242
238
|
// shared styles for links and buttons
|
|
243
239
|
a, button {
|
|
244
240
|
align-items: center;
|
|
241
|
+
border: 1px solid transparent; // because a border for the button is needed for a11y, we apply it to both the button and the link so they have the same height
|
|
245
242
|
display: flex;
|
|
246
243
|
outline-style: solid; // used to avoid double outline+focus-ring in Safari (see https://github.com/hashicorp/design-system-components/issues/161#issuecomment-1031548656)
|
|
247
244
|
outline-color: transparent;
|
|
248
|
-
padding:
|
|
245
|
+
padding: 7px 9px 7px 15px; // notice: we're subtracting 1px because of the transparent border
|
|
249
246
|
text-decoration: none;
|
|
250
247
|
|
|
251
248
|
// this is used for the left "hover" indicator
|
|
@@ -253,7 +250,7 @@
|
|
|
253
250
|
border-radius: 1px;
|
|
254
251
|
bottom: 6px;
|
|
255
252
|
content: '';
|
|
256
|
-
left:
|
|
253
|
+
left: 4px;
|
|
257
254
|
position: absolute;
|
|
258
255
|
top: 6px;
|
|
259
256
|
width: 2px;
|
|
@@ -266,11 +263,11 @@
|
|
|
266
263
|
border-radius: 5px;
|
|
267
264
|
bottom: 0px;
|
|
268
265
|
content: '';
|
|
269
|
-
left:
|
|
266
|
+
left: 10px;
|
|
270
267
|
position: absolute;
|
|
271
|
-
right:
|
|
272
|
-
z-index: -1;
|
|
268
|
+
right: 4px;
|
|
273
269
|
top: 0;
|
|
270
|
+
z-index: -1;
|
|
274
271
|
}
|
|
275
272
|
|
|
276
273
|
// Notice: to avoid too much duplication we define two local CSS variables
|
|
@@ -282,7 +279,7 @@
|
|
|
282
279
|
&::after {
|
|
283
280
|
background-color: var(--current-background-color);
|
|
284
281
|
box-shadow: var(--current-focus-ring-box-shadow);
|
|
285
|
-
left:
|
|
282
|
+
left: 4px;
|
|
286
283
|
}
|
|
287
284
|
}
|
|
288
285
|
// undo the previous declaration for browsers that support ":focus-visible" but wouldn't normally show default focus styles
|
|
@@ -296,7 +293,7 @@
|
|
|
296
293
|
&::after {
|
|
297
294
|
background-color: var(--current-background-color);
|
|
298
295
|
box-shadow: var(--current-focus-ring-box-shadow);
|
|
299
|
-
left:
|
|
296
|
+
left: 4px;
|
|
300
297
|
}
|
|
301
298
|
}
|
|
302
299
|
// remove the focus ring on "active + focused" state (by design)
|
|
@@ -310,15 +307,11 @@
|
|
|
310
307
|
}
|
|
311
308
|
|
|
312
309
|
.hds-dropdown-list-item__interactive-text {
|
|
313
|
-
font-family: var(--token-typography-body-200-font-family);
|
|
314
|
-
font-size: var(--token-typography-body-200-font-size);
|
|
315
|
-
font-weight: var(--token-typography-font-weight-medium);
|
|
316
|
-
line-height: var(--token-typography-body-200-line-height);
|
|
317
310
|
text-align: left; // the button element was centering text
|
|
318
311
|
}
|
|
319
312
|
|
|
320
313
|
.hds-dropdown-list-item__interactive-icon {
|
|
321
|
-
margin-right:
|
|
314
|
+
margin-right: 8px;
|
|
322
315
|
}
|
|
323
316
|
|
|
324
317
|
.hds-dropdown-list-item--color-action {
|
|
@@ -361,25 +354,19 @@
|
|
|
361
354
|
// assign the values to the local CSS variables used above
|
|
362
355
|
&::after {
|
|
363
356
|
--current-background-color: var(--token-color-surface-critical);
|
|
364
|
-
--current-focus-ring-box-shadow: var(
|
|
365
|
-
--token-focus-ring-critical-box-shadow
|
|
366
|
-
);
|
|
357
|
+
--current-focus-ring-box-shadow: var(--token-focus-ring-critical-box-shadow);
|
|
367
358
|
}
|
|
368
359
|
|
|
369
360
|
&:hover,
|
|
370
361
|
&.is-hover {
|
|
371
|
-
color: var(
|
|
372
|
-
--token-color-palette-red-300
|
|
373
|
-
); // TODO we need to add this token to the design system
|
|
362
|
+
color: var(--token-color-palette-red-300);
|
|
374
363
|
&::before {
|
|
375
364
|
background-color: currentColor;
|
|
376
365
|
}
|
|
377
366
|
}
|
|
378
367
|
&:active,
|
|
379
368
|
&.is-active {
|
|
380
|
-
color: var(
|
|
381
|
-
--token-color-palette-red-400
|
|
382
|
-
); // TODO we need to add this token to the design system
|
|
369
|
+
color: var(--token-color-palette-red-400);
|
|
383
370
|
&::before {
|
|
384
371
|
background-color: currentColor;
|
|
385
372
|
}
|
|
@@ -389,3 +376,24 @@
|
|
|
389
376
|
}
|
|
390
377
|
}
|
|
391
378
|
}
|
|
379
|
+
|
|
380
|
+
.hds-dropdown-list-item--separator {
|
|
381
|
+
height: 4px;
|
|
382
|
+
position: relative;
|
|
383
|
+
width: 100%;
|
|
384
|
+
|
|
385
|
+
&::before {
|
|
386
|
+
border-bottom: 1px solid var(--token-color-border-primary);
|
|
387
|
+
bottom: 0;
|
|
388
|
+
content: '';
|
|
389
|
+
left: 6px;
|
|
390
|
+
position: absolute;
|
|
391
|
+
right: 6px;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.hds-dropdown-list-item--title {
|
|
396
|
+
color: var(--token-color-foreground-strong);
|
|
397
|
+
padding: 10px 16px 4px;
|
|
398
|
+
}
|
|
399
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hashicorp/design-system-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "HashiCorp Design System Components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hashicorp",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
"ember-resolver": "^8.0.2",
|
|
76
76
|
"ember-source": "~3.28.0",
|
|
77
77
|
"ember-source-channel-url": "^3.0.0",
|
|
78
|
+
"ember-style-modifier": "^0.8.0",
|
|
78
79
|
"ember-template-lint": "^3.6.0",
|
|
79
80
|
"ember-template-lint-plugin-prettier": "^3.0.1",
|
|
80
81
|
"ember-truth-helpers": "^3.0.0",
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
{{#if (eq this.item "title")}}
|
|
2
|
-
<li class={{this.classNames}}>
|
|
3
|
-
{{this.text}}
|
|
4
|
-
</li>
|
|
5
|
-
|
|
6
|
-
{{else if (eq this.item "generic")}}
|
|
7
|
-
<li class={{this.classNames}}>
|
|
8
|
-
{{yield}}
|
|
9
|
-
</li>
|
|
10
|
-
|
|
11
|
-
{{else if (eq this.item "copy-item")}}
|
|
12
|
-
<li class={{this.classNames}}>
|
|
13
|
-
{{#if @copyItemTitle}}
|
|
14
|
-
<div class="hds-dropdown-list-item__copy-item-title">{{@copyItemTitle}}</div>
|
|
15
|
-
{{/if}}
|
|
16
|
-
<button
|
|
17
|
-
type="button"
|
|
18
|
-
class="{{if @state (concat 'is-' @state)}} {{if this.isSuccess 'is-success'}}"
|
|
19
|
-
{{on "click" this.copyCode}}
|
|
20
|
-
>
|
|
21
|
-
<div class="hds-dropdown-list-item__copy-item-text">
|
|
22
|
-
{{this.text}}
|
|
23
|
-
</div>
|
|
24
|
-
<FlightIcon
|
|
25
|
-
@name="{{if this.isSuccess 'clipboard-checked' 'clipboard-copy'}}"
|
|
26
|
-
class="hds-dropdown-list-item__copy-item-icon"
|
|
27
|
-
/>
|
|
28
|
-
</button>
|
|
29
|
-
</li>
|
|
30
|
-
|
|
31
|
-
{{else if (eq this.item "description")}}
|
|
32
|
-
<li class={{this.classNames}}>
|
|
33
|
-
{{this.text}}
|
|
34
|
-
</li>
|
|
35
|
-
|
|
36
|
-
{{else if (eq this.item "separator")}}
|
|
37
|
-
<li class={{this.classNames}} role="separator"></li>
|
|
38
|
-
|
|
39
|
-
{{else if (eq this.item "interactive")}}
|
|
40
|
-
<li class={{this.classNames}}>
|
|
41
|
-
{{#if @route}}
|
|
42
|
-
<LinkTo
|
|
43
|
-
class="{{if @state (concat 'is-' @state)}}"
|
|
44
|
-
@current-when={{@current-when}}
|
|
45
|
-
@models={{hds-link-to-models @model @models}}
|
|
46
|
-
@query={{hds-link-to-query @query}}
|
|
47
|
-
@replace={{@replace}}
|
|
48
|
-
@route={{@route}}
|
|
49
|
-
...attributes
|
|
50
|
-
>
|
|
51
|
-
{{#if @icon}}
|
|
52
|
-
<div class="hds-dropdown-list-item__interactive-icon">
|
|
53
|
-
<FlightIcon @name={{this.icon}} @isInlineBlock={{false}} />
|
|
54
|
-
</div>
|
|
55
|
-
{{/if}}
|
|
56
|
-
<div class="hds-dropdown-list-item__interactive-text">
|
|
57
|
-
{{this.text}}
|
|
58
|
-
</div>
|
|
59
|
-
</LinkTo>
|
|
60
|
-
{{else if @href}}
|
|
61
|
-
<a target="_blank" rel="noopener noreferrer" href={{@href}} class="{{if @state (concat 'is-' @state)}}">
|
|
62
|
-
{{#if this.icon}}
|
|
63
|
-
<div class="hds-dropdown-list-item__interactive-icon">
|
|
64
|
-
<FlightIcon @name={{this.icon}} @isInlineBlock={{false}} />
|
|
65
|
-
</div>
|
|
66
|
-
{{/if}}
|
|
67
|
-
<div class="hds-dropdown-list-item__interactive-text">
|
|
68
|
-
{{this.text}}
|
|
69
|
-
</div>
|
|
70
|
-
</a>
|
|
71
|
-
{{else}}
|
|
72
|
-
<button class="{{if @state (concat 'is-' @state)}}" type="button" ...attributes>
|
|
73
|
-
{{#if this.icon}}
|
|
74
|
-
<div class="hds-dropdown-list-item__interactive-icon">
|
|
75
|
-
<FlightIcon @name={{this.icon}} @isInlineBlock={{false}} />
|
|
76
|
-
</div>
|
|
77
|
-
{{/if}}
|
|
78
|
-
<div class="hds-dropdown-list-item__interactive-text">
|
|
79
|
-
{{this.text}}
|
|
80
|
-
</div>
|
|
81
|
-
</button>
|
|
82
|
-
{{/if}}
|
|
83
|
-
</li>
|
|
84
|
-
{{/if}}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import Component from '@glimmer/component';
|
|
2
|
-
import { assert } from '@ember/debug';
|
|
3
|
-
import { tracked } from '@glimmer/tracking';
|
|
4
|
-
import { action } from '@ember/object';
|
|
5
|
-
|
|
6
|
-
export const DEFAULT_COLOR = 'action';
|
|
7
|
-
export const DEFAULT_ITEM = 'interactive';
|
|
8
|
-
export const COLORS = ['action', 'critical'];
|
|
9
|
-
export const ITEMS = [
|
|
10
|
-
'copy-item',
|
|
11
|
-
'description',
|
|
12
|
-
'generic',
|
|
13
|
-
'interactive',
|
|
14
|
-
'separator',
|
|
15
|
-
'title',
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
export default class HdsDropdownListItemComponent extends Component {
|
|
19
|
-
@tracked isSuccess = this.args.isSuccess ?? false;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param item
|
|
23
|
-
* @type {string}
|
|
24
|
-
* @default interactive
|
|
25
|
-
* @description Determines the type of item to show
|
|
26
|
-
*/
|
|
27
|
-
get item() {
|
|
28
|
-
let { item = DEFAULT_ITEM } = this.args;
|
|
29
|
-
|
|
30
|
-
assert(
|
|
31
|
-
`@item for "Hds::Dropdown::ListItem" must be one of the following: ${ITEMS.join(
|
|
32
|
-
', '
|
|
33
|
-
)}; received: ${item}`,
|
|
34
|
-
ITEMS.includes(item)
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
return item;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param text
|
|
42
|
-
* @type {string}
|
|
43
|
-
* @description The text of the item. If no text value is defined an error will be thrown unless it is the generic or separator item type.
|
|
44
|
-
*/
|
|
45
|
-
get text() {
|
|
46
|
-
let { text } = this.args;
|
|
47
|
-
|
|
48
|
-
assert(
|
|
49
|
-
'@text for "Hds::Dropdown::ListItem" must have a valid value',
|
|
50
|
-
text !== undefined
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
return text;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @param color
|
|
58
|
-
* @type {string}
|
|
59
|
-
* @default primary
|
|
60
|
-
* @description Determines the color of the item (when item is set to interactive)
|
|
61
|
-
*/
|
|
62
|
-
get color() {
|
|
63
|
-
let { color = DEFAULT_COLOR } = this.args;
|
|
64
|
-
|
|
65
|
-
assert(
|
|
66
|
-
`@color for "Hds::Dropdown::ListItem" must be one of the following: ${COLORS.join(
|
|
67
|
-
', '
|
|
68
|
-
)}; received: ${color}`,
|
|
69
|
-
COLORS.includes(color)
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
return color;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @param icon
|
|
77
|
-
* @type {string}
|
|
78
|
-
* @default null
|
|
79
|
-
* @description The name of the icon to be used.
|
|
80
|
-
*/
|
|
81
|
-
get icon() {
|
|
82
|
-
assert(
|
|
83
|
-
`when the "Hds::ListItem" @color is "critical" an @icon is required`,
|
|
84
|
-
!(this.color === 'critical' && !this.args.icon)
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
return this.args.icon ?? null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Get the class names to apply to the component.
|
|
92
|
-
* @method classNames
|
|
93
|
-
* @return {string} The "class" attribute to apply to the component.
|
|
94
|
-
*/
|
|
95
|
-
get classNames() {
|
|
96
|
-
let classes = ['hds-dropdown-list-item'];
|
|
97
|
-
|
|
98
|
-
// add a class based on the @item argument
|
|
99
|
-
if (this.item) {
|
|
100
|
-
classes.push(`hds-dropdown-list-item--${this.item}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// add a class based on the @color argument
|
|
104
|
-
if (this.item === 'interactive') {
|
|
105
|
-
classes.push(`hds-dropdown-list-item--color-${this.color}`);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return classes.join(' ');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
@action
|
|
112
|
-
copyCode() {
|
|
113
|
-
navigator.clipboard.writeText(this.args.text);
|
|
114
|
-
// this if statement resolves to [object Promise] so maybe some improvements
|
|
115
|
-
// could be made here
|
|
116
|
-
if (navigator.clipboard.readText()) {
|
|
117
|
-
this.isSuccess = true;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<button
|
|
2
|
-
class="hds-dropdown-toggle-icon"
|
|
3
|
-
aria-label={{this.text}}
|
|
4
|
-
...attributes
|
|
5
|
-
{{on "click" this.onClick}}
|
|
6
|
-
type="button"
|
|
7
|
-
>
|
|
8
|
-
<div class="hds-dropdown-toggle-icon__wrapper">
|
|
9
|
-
{{#if @imageSrc}}
|
|
10
|
-
<img src={{@imageSrc}} alt="" role="presentation" height="32" width="32" />
|
|
11
|
-
{{else}}
|
|
12
|
-
<FlightIcon @name={{this.icon}} @size="24" />
|
|
13
|
-
{{/if}}
|
|
14
|
-
</div>
|
|
15
|
-
{{#if this.hasChevron}}
|
|
16
|
-
<FlightIcon
|
|
17
|
-
@name="chevron-{{if @isOpen 'up' 'down'}}"
|
|
18
|
-
class="hds-dropdown-toggle-icon__chevron"
|
|
19
|
-
@isInlineBlock={{false}}
|
|
20
|
-
/>
|
|
21
|
-
{{/if}}
|
|
22
|
-
</button>
|