@hashicorp/design-system-components 0.8.0 → 0.9.2
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 +24 -0
- package/NEW-COMPONENT-CHECKLIST.md +20 -11
- package/addon/components/hds/dropdown/index.hbs +27 -0
- package/addon/components/hds/dropdown/list-item.hbs +84 -0
- package/addon/components/hds/dropdown/list-item.js +120 -0
- package/addon/components/hds/dropdown/toggle-button.hbs +23 -0
- package/addon/components/hds/dropdown/toggle-button.js +59 -0
- package/addon/components/hds/dropdown/toggle-icon.hbs +22 -0
- package/addon/components/hds/dropdown/toggle-icon.js +59 -0
- package/addon/components/hds/link/cta.js +13 -13
- package/addon/components/hds/link-to/cta.js +13 -13
- package/app/components/hds/dropdown/index.js +1 -0
- package/app/components/hds/dropdown/list-item.js +1 -0
- package/app/components/hds/dropdown/toggle-button.js +1 -0
- package/app/components/hds/dropdown/toggle-icon.js +1 -0
- package/app/styles/@hashicorp/design-system-components.scss +1 -0
- package/app/styles/components/breadcrumb.scss +14 -11
- package/app/styles/components/button.scss +36 -30
- package/app/styles/components/dropdown.scss +391 -0
- package/app/styles/components/link/standalone.scss +1 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @hashicorp/design-system-components
|
|
2
2
|
|
|
3
|
+
## 0.9.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#209](https://github.com/hashicorp/design-system/pull/209) [`6021d433`](https://github.com/hashicorp/design-system/commit/6021d43352b8e38b268b06cd98ca0c62adb14999) Thanks [@didoo](https://github.com/didoo)! - Re-ordered declarations of CSS states
|
|
8
|
+
|
|
9
|
+
## 0.9.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies []:
|
|
14
|
+
- @hashicorp/ember-flight-icons@2.0.5
|
|
15
|
+
|
|
16
|
+
## 0.9.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- [#66](https://github.com/hashicorp/design-system/pull/66) [`29e2ce55`](https://github.com/hashicorp/design-system/commit/29e2ce55bab74cc02dd511794dfadd2b3ac40a14) Thanks [@MelSumner](https://github.com/MelSumner)! - Adds dropdown component to the design system
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies []:
|
|
25
|
+
- @hashicorp/ember-flight-icons@2.0.4
|
|
26
|
+
|
|
3
27
|
## 0.8.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -14,25 +14,27 @@ The engineering checklist has six parts: creating the feature branch, component
|
|
|
14
14
|
|
|
15
15
|
### Component Creation
|
|
16
16
|
|
|
17
|
-
- [ ] create new branch from main for the component
|
|
17
|
+
- [ ] create new branch from main for the component (`git checkout -b USER/COMPONENT-NAME`)
|
|
18
18
|
- [ ] create new component
|
|
19
|
-
- `ember generate component hds/
|
|
20
|
-
- if
|
|
19
|
+
- `ember generate component hds/COMPONENT-NAME/index --gc` (the component won't need to be invoked with index, it's just to put all the files in the correct place)
|
|
20
|
+
- tip: if you forget to generate the backing class (via `--gc`), you can add it with `ember generate component-class hds/COMPONENT-NAME/index`.
|
|
21
|
+
- if it's a child component, then `hds/COMPONENT_NAME/CHILD_NAME` instead of `index`
|
|
22
|
+
- tip: if you need to destroy a component and start over again, `ember destroy component hds/COMPONENT-NAME/index` will remove the component and the related files as appropriate.
|
|
21
23
|
- [ ] **component template**
|
|
22
24
|
- use semantic HTML
|
|
23
25
|
- the component should have a css class that is the same as the component (e.g. `hds/button` should have a class name of `hds-button` on the component, and additional CSS classes should start with this same class name.
|
|
24
26
|
- add `...attributes` unless doing so would be detrimental (e.g., a parent element and child element in the same component that both have ...attributes)
|
|
25
27
|
- [ ] **component class**
|
|
26
28
|
- use getters (vs template conditionals or constructors, if possible)
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
29
|
+
- we have chosen to define the value of the `class` attribute (containing the different CSS class names) for the "root" of the element's code in the backing class, UNLESS that component only has one CSS class name.
|
|
30
|
+
- write API comments in the [JS doc](https://jsdoc.app/) format (look at existing components for examples)
|
|
31
|
+
- use the same naming as the Figma file for the components API, unless it conflicts with a pre-existing HTML attribute. If that is the case, document the difference in a comment.
|
|
32
|
+
- if there is an existing Structure component that is similar to the HDS component being created, ensure that all existing functionality is accounted for in some way. If we are not providing existing functionality at all, it should be documented (along with the reason why). If we are providing temporary functionality, explain that it's temporary and why.
|
|
31
33
|
- booleans should start with a verb (is/has/etc)
|
|
32
|
-
-
|
|
33
|
-
- goal is a terse invocation
|
|
34
|
+
- assertions should match the content style of the other components, e.g., `'@text for "Hds::Button" must have a valid value'`,
|
|
35
|
+
- program with intent; think about the invocation for the developer who will use the component. The goal is a terse invocation, but we also want to consider the big picture. Try to get feedback when you can.
|
|
34
36
|
- [ ] **component style**
|
|
35
|
-
- create `component/
|
|
37
|
+
- create `component/COMPONENT-NAME.scss` in `app/styles`
|
|
36
38
|
- add `@use` to `app/styles/@hashicorp/design-system-components.scss` (see existing code for precise syntax)
|
|
37
39
|
- use design tokens wherever possible, comment where they are not
|
|
38
40
|
- sizes should be in relative units
|
|
@@ -42,12 +44,18 @@ The engineering checklist has six parts: creating the feature branch, component
|
|
|
42
44
|
- [ ] test defaults
|
|
43
45
|
- [ ] try not to repeat tests (i.e., don't have to test all sizes, all colors, etc.)
|
|
44
46
|
- [ ] test all accessibility attributes
|
|
47
|
+
- [ ] test assertions
|
|
45
48
|
- [ ] **documentation**
|
|
46
49
|
- create component page `ember generate route components/COMPONENT_NAME --dummy`
|
|
47
50
|
- add link to `templates/index.hbs` page
|
|
48
|
-
- [ ]
|
|
51
|
+
- [ ] Definition of component (from CRD) (this should be a paragraph under the component name, and before the first section)
|
|
52
|
+
- [ ] Component API
|
|
49
53
|
- [ ] Usage
|
|
54
|
+
- [ ] Design Guidelines
|
|
50
55
|
- [ ] Accessibility
|
|
56
|
+
- Conformance Rating [(internal document)](https://docs.google.com/document/d/1OjTKpQLB_wuZSVJNLbbguTzMDMYCHKhNdKQz7-Kfqic/edit#bookmark=id.v7r42vfu4pdd)
|
|
57
|
+
- Known Issues (if any)
|
|
58
|
+
- Related WCAG (pull from CRD or ask Melanie)
|
|
51
59
|
- [ ] Showcase
|
|
52
60
|
|
|
53
61
|
### Component Review
|
|
@@ -69,5 +77,6 @@ Pre-review request checks:
|
|
|
69
77
|
- Edge (once available)
|
|
70
78
|
|
|
71
79
|
When ready for review:
|
|
80
|
+
|
|
72
81
|
- [ ] add situationally appropriate reviewers
|
|
73
82
|
- [ ] added instructions for reviewers in your PR, letting them know what kind of review you need
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<Hds::Disclosure class="hds-dropdown">
|
|
2
|
+
<:toggle as |t|>
|
|
3
|
+
{{yield
|
|
4
|
+
(hash
|
|
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
|
+
)
|
|
8
|
+
}}
|
|
9
|
+
</:toggle>
|
|
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
|
+
>
|
|
15
|
+
{{yield
|
|
16
|
+
(hash
|
|
17
|
+
CopyItem=(component "hds/dropdown/list-item" item="copy-item")
|
|
18
|
+
Description=(component "hds/dropdown/list-item" item="description")
|
|
19
|
+
Generic=(component "hds/dropdown/list-item" item="generic")
|
|
20
|
+
Interactive=(component "hds/dropdown/list-item")
|
|
21
|
+
Separator=(component "hds/dropdown/list-item" item="separator")
|
|
22
|
+
Title=(component "hds/dropdown/list-item" item="title")
|
|
23
|
+
)
|
|
24
|
+
}}
|
|
25
|
+
</ul>
|
|
26
|
+
</:content>
|
|
27
|
+
</Hds::Disclosure>
|
|
@@ -0,0 +1,84 @@
|
|
|
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}}
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{{!
|
|
2
|
+
// >>>>>>>>>>> WARNING <<<<<<<<<<
|
|
3
|
+
//
|
|
4
|
+
// Notice: in this component we're directly using the `Hds::Button` component
|
|
5
|
+
// (and adding a specialized class for the "toggle-button" variant, see below)
|
|
6
|
+
// If you need to change the styling of the `Button` component, remember that this will impact also
|
|
7
|
+
// this component too.
|
|
8
|
+
// If instead you need to change only the styling of the `toggle-button` component, you can do it
|
|
9
|
+
// in the CSS file using the specialized class declared there.
|
|
10
|
+
// This is NOT a standard approach that we use in the HDS design system implementation, but it's been
|
|
11
|
+
// the least worst option we could find to solve the problem of sharing the exact same style of the
|
|
12
|
+
// `Button (primary)` with other components.
|
|
13
|
+
}}
|
|
14
|
+
|
|
15
|
+
<Hds::Button
|
|
16
|
+
@text={{this.text}}
|
|
17
|
+
@icon="chevron-{{if @isOpen 'up' 'down'}}"
|
|
18
|
+
@iconPosition="trailing"
|
|
19
|
+
@color={{this.color}}
|
|
20
|
+
class="hds-dropdown-toggle--with-button-component"
|
|
21
|
+
{{on "click" this.onClick}}
|
|
22
|
+
...attributes
|
|
23
|
+
/>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_COLOR = 'primary';
|
|
5
|
+
export const COLORS = ['primary', 'secondary'];
|
|
6
|
+
|
|
7
|
+
export default class HdsDropdownToggleButtonComponent extends Component {
|
|
8
|
+
/**
|
|
9
|
+
* @param text
|
|
10
|
+
* @type {string}
|
|
11
|
+
* @description The text of the button. 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::ToggleButton" 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 button to be used; acceptable values are `primary` and `secondary`
|
|
29
|
+
*/
|
|
30
|
+
get color() {
|
|
31
|
+
let { color = DEFAULT_COLOR } = this.args;
|
|
32
|
+
|
|
33
|
+
assert(
|
|
34
|
+
`@color for "Hds::Dropdown::ToggleButton" 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
|
+
* @param onClick
|
|
45
|
+
* @type {function}
|
|
46
|
+
* @default () => {}
|
|
47
|
+
*/
|
|
48
|
+
get onClick() {
|
|
49
|
+
let { onClick } = this.args;
|
|
50
|
+
|
|
51
|
+
// notice: this is a guard used in case the toggle is used as standalone element (eg. in the showcase)
|
|
52
|
+
// in reality it's always used inside the Dropdown main component as yielded component, so the onClick handler is always defined
|
|
53
|
+
if (typeof onClick === 'function') {
|
|
54
|
+
return onClick;
|
|
55
|
+
} else {
|
|
56
|
+
return () => {};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
4
|
+
export default class HdsDropdownToggleIconComponent extends Component {
|
|
5
|
+
/**
|
|
6
|
+
* @param text
|
|
7
|
+
* @type {string}
|
|
8
|
+
* @description The text of the `aria-label` applied to the toggle
|
|
9
|
+
*/
|
|
10
|
+
get text() {
|
|
11
|
+
let { text } = this.args;
|
|
12
|
+
|
|
13
|
+
assert(
|
|
14
|
+
'@text for "Hds::Dropdown::ToggleIcon" must have a valid value',
|
|
15
|
+
text !== undefined
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
return text;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Indicates if a dropdown chevron icon should be displayed; should be displayed unless the "more-horizontal" icon is used.
|
|
23
|
+
*
|
|
24
|
+
* @param hasChevron
|
|
25
|
+
* @type {boolean}
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
get hasChevron() {
|
|
29
|
+
return this.args.hasChevron ?? true;
|
|
30
|
+
}
|
|
31
|
+
|
|
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
|
+
/**
|
|
44
|
+
* @param onClick
|
|
45
|
+
* @type {function}
|
|
46
|
+
* @default () => {}
|
|
47
|
+
*/
|
|
48
|
+
get onClick() {
|
|
49
|
+
let { onClick } = this.args;
|
|
50
|
+
|
|
51
|
+
// notice: this is a guard used in case the toggle is used as standalone element (eg. in the showcase)
|
|
52
|
+
// in reality it's always used inside the Dropdown main component as yielded component, so the onClick handler is always defined
|
|
53
|
+
if (typeof onClick === 'function') {
|
|
54
|
+
return onClick;
|
|
55
|
+
} else {
|
|
56
|
+
return () => {};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -112,19 +112,6 @@ export default class HdsLinkCtaComponent extends Component {
|
|
|
112
112
|
return this.args.isFullWidth ?? false;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
@action
|
|
116
|
-
didInsert(el) {
|
|
117
|
-
// we need to register the element to compare it with the one that triggered the "key/space" event
|
|
118
|
-
this.el = el;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
@action
|
|
122
|
-
onKeySpace(event) {
|
|
123
|
-
if (event.target === this.el) {
|
|
124
|
-
event.target.click();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
115
|
/**
|
|
129
116
|
* Get the class names to apply to the component.
|
|
130
117
|
* @method classNames
|
|
@@ -147,4 +134,17 @@ export default class HdsLinkCtaComponent extends Component {
|
|
|
147
134
|
|
|
148
135
|
return classes.join(' ');
|
|
149
136
|
}
|
|
137
|
+
|
|
138
|
+
@action
|
|
139
|
+
didInsert(el) {
|
|
140
|
+
// we need to register the element to compare it with the one that triggered the "key/space" event
|
|
141
|
+
this.el = el;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@action
|
|
145
|
+
onKeySpace(event) {
|
|
146
|
+
if (event.target === this.el) {
|
|
147
|
+
event.target.click();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
150
|
}
|
|
@@ -127,19 +127,6 @@ export default class HdsLinkToCtaComponent extends Component {
|
|
|
127
127
|
return route;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
@action
|
|
131
|
-
didInsert(el) {
|
|
132
|
-
// we need to register the element to compare it with the one that triggered the "key/space" event
|
|
133
|
-
this.el = el;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
@action
|
|
137
|
-
onKeySpace(event) {
|
|
138
|
-
if (event.target === this.el) {
|
|
139
|
-
event.target.click();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
130
|
/**
|
|
144
131
|
* Get the class names to apply to the component.
|
|
145
132
|
* @method classNames
|
|
@@ -162,4 +149,17 @@ export default class HdsLinkToCtaComponent extends Component {
|
|
|
162
149
|
|
|
163
150
|
return classes.join(' ');
|
|
164
151
|
}
|
|
152
|
+
|
|
153
|
+
@action
|
|
154
|
+
didInsert(el) {
|
|
155
|
+
// we need to register the element to compare it with the one that triggered the "key/space" event
|
|
156
|
+
this.el = el;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@action
|
|
160
|
+
onKeySpace(event) {
|
|
161
|
+
if (event.target === this.el) {
|
|
162
|
+
event.target.click();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
165
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/list-item';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/toggle-button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@hashicorp/design-system-components/components/hds/dropdown/toggle-icon';
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// BREADCRUMB
|
|
3
3
|
//
|
|
4
4
|
// properties within each class are sorted alphabetically
|
|
5
|
+
// notice: pseudo-classes for the states *must* follow the order link > visited > hover > focus > active
|
|
5
6
|
//
|
|
6
7
|
//
|
|
7
8
|
|
|
@@ -75,9 +76,6 @@ $hds-breadcrumb-item-visual-horizontal-padding: 4px;
|
|
|
75
76
|
// notice: the text decoration is applied directly to the "text" container because of a bug in Safari (see https://github.com/hashicorp/design-system-components/issues/159)
|
|
76
77
|
text-decoration-color: transparent;
|
|
77
78
|
|
|
78
|
-
// we apply the focus directly to the element, without using a pseudo-element
|
|
79
|
-
@include hds-focus-ring-basic();
|
|
80
|
-
|
|
81
79
|
&:hover,
|
|
82
80
|
&.is-hover {
|
|
83
81
|
color: var(--token-color-palette-neutral-600);
|
|
@@ -87,6 +85,9 @@ $hds-breadcrumb-item-visual-horizontal-padding: 4px;
|
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
|
|
88
|
+
// we apply the focus directly to the element, without using a pseudo-element
|
|
89
|
+
@include hds-focus-ring-basic();
|
|
90
|
+
|
|
90
91
|
&:active,
|
|
91
92
|
&.is-active {
|
|
92
93
|
color: var(--token-color-foreground-secondary);
|
|
@@ -153,25 +154,27 @@ $hds-breadcrumb-item-visual-horizontal-padding: 4px;
|
|
|
153
154
|
padding: 0;
|
|
154
155
|
width: $hds-breadcrumb-item-height;
|
|
155
156
|
|
|
156
|
-
// we apply the focus directly to the element, without using a pseudo-element
|
|
157
|
-
@include hds-focus-ring-basic();
|
|
158
|
-
|
|
159
157
|
&:hover,
|
|
160
158
|
&.is-hover {
|
|
161
159
|
border-color: var(--token-color-border-strong);
|
|
162
160
|
color: var(--token-color-foreground-faint);
|
|
163
161
|
}
|
|
162
|
+
|
|
163
|
+
// we apply the focus directly to the element, without using a pseudo-element
|
|
164
|
+
@include hds-focus-ring-basic();
|
|
165
|
+
|
|
166
|
+
&:focus,
|
|
167
|
+
&.is-focus {
|
|
168
|
+
background-color: transparent;
|
|
169
|
+
border: none; // important: we need to completely remove the border, of the inner box-shadow of the focus ring will be drawn inside the border
|
|
170
|
+
}
|
|
171
|
+
|
|
164
172
|
&:active,
|
|
165
173
|
&.is-active {
|
|
166
174
|
background-color: var(--token-color-surface-interactive-active);
|
|
167
175
|
border-color: var(--token-color-border-strong);
|
|
168
176
|
color: var(--token-color-foreground-primary);
|
|
169
177
|
}
|
|
170
|
-
&:focus,
|
|
171
|
-
&.is-focus {
|
|
172
|
-
background-color: transparent;
|
|
173
|
-
border: none; // important: we need to completely remove the border, of the inner box-shadow of the focus ring will be drawn inside the border
|
|
174
|
-
}
|
|
175
178
|
}
|
|
176
179
|
|
|
177
180
|
.hds-breadcrumb__truncation-content {
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// BUTTON COMPONENT
|
|
3
3
|
//
|
|
4
4
|
// properties within each class are sorted alphabetically
|
|
5
|
-
// notice: pseudo-classes for the states *must* follow the order link > visited >
|
|
6
|
-
// see https://github.com/hashicorp/design-system-components/issues/132
|
|
5
|
+
// notice: pseudo-classes for the states *must* follow the order link > visited > hover > focus > active
|
|
7
6
|
//
|
|
8
7
|
//
|
|
9
8
|
|
|
@@ -145,6 +144,14 @@ $size-props: (
|
|
|
145
144
|
box-shadow: var(--token-elevation-low-box-shadow);
|
|
146
145
|
color: var(--token-color-foreground-high-contrast);
|
|
147
146
|
|
|
147
|
+
&:hover,
|
|
148
|
+
&.is-hover {
|
|
149
|
+
background-color: var(--token-color-palette-blue-300);
|
|
150
|
+
border-color: var(--token-color-palette-blue-400);
|
|
151
|
+
color: var(--token-color-foreground-high-contrast);
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
}
|
|
154
|
+
|
|
148
155
|
&:focus,
|
|
149
156
|
&.is-focus {
|
|
150
157
|
background-color: var(--token-color-palette-blue-200);
|
|
@@ -163,13 +170,7 @@ $size-props: (
|
|
|
163
170
|
top: -$shift;
|
|
164
171
|
}
|
|
165
172
|
}
|
|
166
|
-
|
|
167
|
-
&.is-hover {
|
|
168
|
-
background-color: var(--token-color-palette-blue-300);
|
|
169
|
-
border-color: var(--token-color-palette-blue-400);
|
|
170
|
-
color: var(--token-color-foreground-high-contrast);
|
|
171
|
-
cursor: pointer;
|
|
172
|
-
}
|
|
173
|
+
|
|
173
174
|
&:active,
|
|
174
175
|
&.is-active {
|
|
175
176
|
background-color: var(--token-color-palette-blue-400);
|
|
@@ -188,6 +189,14 @@ $size-props: (
|
|
|
188
189
|
box-shadow: var(--token-elevation-low-box-shadow);
|
|
189
190
|
color: var(--token-color-foreground-primary);
|
|
190
191
|
|
|
192
|
+
&:hover,
|
|
193
|
+
&.is-hover {
|
|
194
|
+
background-color: var(--token-color-surface-primary);
|
|
195
|
+
border-color: var(--token-color-border-strong);
|
|
196
|
+
color: var(--token-color-foreground-primary);
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
}
|
|
199
|
+
|
|
191
200
|
&:focus,
|
|
192
201
|
&.is-focus {
|
|
193
202
|
background-color: var(--token-color-surface-faint);
|
|
@@ -197,13 +206,7 @@ $size-props: (
|
|
|
197
206
|
border-color: var(--token-color-focus-action-external);
|
|
198
207
|
}
|
|
199
208
|
}
|
|
200
|
-
|
|
201
|
-
&.is-hover {
|
|
202
|
-
background-color: var(--token-color-surface-primary);
|
|
203
|
-
border-color: var(--token-color-border-strong);
|
|
204
|
-
color: var(--token-color-foreground-primary);
|
|
205
|
-
cursor: pointer;
|
|
206
|
-
}
|
|
209
|
+
|
|
207
210
|
&:active,
|
|
208
211
|
&.is-active {
|
|
209
212
|
background-color: var(--token-color-surface-interactive-active);
|
|
@@ -221,6 +224,14 @@ $size-props: (
|
|
|
221
224
|
border-color: transparent;
|
|
222
225
|
color: var(--token-color-foreground-action);
|
|
223
226
|
|
|
227
|
+
&:hover,
|
|
228
|
+
&.is-hover {
|
|
229
|
+
background-color: var(--token-color-surface-primary);
|
|
230
|
+
border-color: var(--token-color-border-strong);
|
|
231
|
+
color: var(--token-color-foreground-action-hover);
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
}
|
|
234
|
+
|
|
224
235
|
&:focus,
|
|
225
236
|
&.is-focus {
|
|
226
237
|
border-color: var(--token-color-focus-action-internal);
|
|
@@ -229,13 +240,7 @@ $size-props: (
|
|
|
229
240
|
border-color: var(--token-color-focus-action-external);
|
|
230
241
|
}
|
|
231
242
|
}
|
|
232
|
-
|
|
233
|
-
&.is-hover {
|
|
234
|
-
background-color: var(--token-color-surface-primary);
|
|
235
|
-
border-color: var(--token-color-border-strong);
|
|
236
|
-
color: var(--token-color-foreground-action-hover);
|
|
237
|
-
cursor: pointer;
|
|
238
|
-
}
|
|
243
|
+
|
|
239
244
|
&:active,
|
|
240
245
|
&.is-active {
|
|
241
246
|
background-color: var(--token-color-surface-interactive-active);
|
|
@@ -271,6 +276,14 @@ $size-props: (
|
|
|
271
276
|
box-shadow: var(--token-elevation-low-box-shadow);
|
|
272
277
|
color: var(--token-color-foreground-critical-on-surface);
|
|
273
278
|
|
|
279
|
+
&:hover,
|
|
280
|
+
&.is-hover {
|
|
281
|
+
background-color: var(--token-color-palette-red-300);
|
|
282
|
+
border-color: var(--token-color-palette-red-400);
|
|
283
|
+
color: var(--token-color-foreground-high-contrast);
|
|
284
|
+
cursor: pointer;
|
|
285
|
+
}
|
|
286
|
+
|
|
274
287
|
&:focus,
|
|
275
288
|
&.is-focus {
|
|
276
289
|
background-color: var(--token-color-surface-critical);
|
|
@@ -280,13 +293,6 @@ $size-props: (
|
|
|
280
293
|
border-color: var(--token-color-focus-critical-external);
|
|
281
294
|
}
|
|
282
295
|
}
|
|
283
|
-
&:hover,
|
|
284
|
-
&.is-hover {
|
|
285
|
-
background-color: var(--token-color-palette-red-300);
|
|
286
|
-
border-color: var(--token-color-palette-red-400);
|
|
287
|
-
color: var(--token-color-foreground-high-contrast);
|
|
288
|
-
cursor: pointer;
|
|
289
|
-
}
|
|
290
296
|
|
|
291
297
|
&:active,
|
|
292
298
|
&.is-active {
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// >>>>>>>>>> WARNING <<<<<<<<<<<
|
|
2
|
+
//
|
|
3
|
+
// Notice: in this component we're using directly the `Hds::Button` component
|
|
4
|
+
// (and adding a specialized class for the "toggle-button" variant, see below)
|
|
5
|
+
// If you need to change the styling of the `Button` component, remember that this will impact also
|
|
6
|
+
// this component too.
|
|
7
|
+
// If instead you need to change only the styling of the `toggle-button` component, you can do it here using
|
|
8
|
+
// the specialized class declared below.
|
|
9
|
+
// This is NOT a standard approach that we use in the HDS design system implementation, but it's been
|
|
10
|
+
// the least worst option we could find to solve the problem of sharing the exact same style of the
|
|
11
|
+
// `Button (primary)` with other components.
|
|
12
|
+
|
|
13
|
+
//
|
|
14
|
+
// DROPDOWN COMPONENT
|
|
15
|
+
//
|
|
16
|
+
// properties within each class are sorted alphabetically
|
|
17
|
+
// notice: pseudo-classes for the states *must* follow the order link > visited > hover > focus > active
|
|
18
|
+
//
|
|
19
|
+
//
|
|
20
|
+
|
|
21
|
+
@use '../mixins/focus-ring' as *;
|
|
22
|
+
|
|
23
|
+
// TOGGLE/ICON
|
|
24
|
+
.hds-dropdown-toggle-icon {
|
|
25
|
+
align-items: center;
|
|
26
|
+
background-color: transparent;
|
|
27
|
+
border: 1px solid transparent; // We need this to be transparent for a11y
|
|
28
|
+
border-radius: 5px;
|
|
29
|
+
display: flex;
|
|
30
|
+
height: 36px;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
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
|
+
outline-color: transparent; // We need this to be transparent for a11y
|
|
34
|
+
padding: 1px;
|
|
35
|
+
min-width: 36px;
|
|
36
|
+
|
|
37
|
+
&:hover,
|
|
38
|
+
&.is-hover {
|
|
39
|
+
background-color: var(--token-color-surface-interactive);
|
|
40
|
+
border-color: var(--token-color-border-strong);
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// this is the :focus
|
|
45
|
+
@include hds-focus-ring-with-pseudo-element($top: -1px, $right: -1px, $bottom: -1px, $left: -1px, $radius: 5px);
|
|
46
|
+
|
|
47
|
+
&:active,
|
|
48
|
+
&.is-active {
|
|
49
|
+
background-color: var(--token-color-surface-interactive-active);
|
|
50
|
+
border-color: var(--token-color-border-strong);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.hds-dropdown-toggle-icon__wrapper {
|
|
55
|
+
align-items: center;
|
|
56
|
+
border-radius: 3px; // 5px- 1px padding - 1px border
|
|
57
|
+
display: flex;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
height: 32px;
|
|
60
|
+
padding: 1px;
|
|
61
|
+
width: 32px;
|
|
62
|
+
|
|
63
|
+
img {
|
|
64
|
+
border-radius: inherit;
|
|
65
|
+
object-fit: cover; // this will make sure it's correct even if the item isn't square
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.hds-dropdown-toggle-icon__chevron {
|
|
70
|
+
margin-left: 0.25rem;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// TOGGLE/BUTTON
|
|
74
|
+
.hds-dropdown-toggle--with-button-component {
|
|
75
|
+
box-shadow: none; // we override this to remove the elevation style
|
|
76
|
+
|
|
77
|
+
.hds-button__icon {
|
|
78
|
+
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
|
+
margin-left: 0.5rem; // this overrides the rule `.hds-button__text + .hds-button__icon`
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// LIST
|
|
85
|
+
// UL ELEMENT
|
|
86
|
+
// GOES INSIDE HDS::DISCLOSURE's :content block
|
|
87
|
+
|
|
88
|
+
.hds-dropdown-list {
|
|
89
|
+
background-color: var(--token-color-surface-primary);
|
|
90
|
+
border-radius: 6px;
|
|
91
|
+
box-shadow: var(--token-surface-high-box-shadow);
|
|
92
|
+
list-style: none;
|
|
93
|
+
margin: 0;
|
|
94
|
+
max-width: 25rem;
|
|
95
|
+
min-width: 12.5rem;
|
|
96
|
+
padding: 4px 0;
|
|
97
|
+
&.hds-dropdown-list--position-right {
|
|
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
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// LIST > LIST-ITEM
|
|
113
|
+
// HDS::DROPDOWN::LIST-ITEM
|
|
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;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.hds-dropdown-list-item--generic {
|
|
125
|
+
padding-left: 16px;
|
|
126
|
+
padding-right: 16px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.hds-dropdown-list-item--description {
|
|
130
|
+
color: var(--token-color-foreground-faint);
|
|
131
|
+
font-family: var(--token-typography-body-100-font-family);
|
|
132
|
+
font-size: var(--token-typography-body-100-font-size);
|
|
133
|
+
font-weight: var(--token-typography-font-weight-regular);
|
|
134
|
+
line-height: var(--token-typography-body-100-line-height);
|
|
135
|
+
padding: 2px 16px 4px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.hds-dropdown-list-item--separator {
|
|
139
|
+
position: relative;
|
|
140
|
+
height: 4px;
|
|
141
|
+
width: 100%;
|
|
142
|
+
|
|
143
|
+
&::before {
|
|
144
|
+
position: absolute;
|
|
145
|
+
right: 6px;
|
|
146
|
+
left: 6px;
|
|
147
|
+
bottom: 0;
|
|
148
|
+
border-bottom: 1px solid var(--token-color-border-primary);
|
|
149
|
+
content: '';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.hds-dropdown-list-item__copy-item-title {
|
|
154
|
+
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
|
+
padding: 2px 0 4px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.hds-dropdown-list-item--copy-item {
|
|
163
|
+
padding: 10px 16px 12px;
|
|
164
|
+
width: 100%;
|
|
165
|
+
|
|
166
|
+
button {
|
|
167
|
+
background-color: transparent;
|
|
168
|
+
border-radius: 5px;
|
|
169
|
+
border: 1px solid var(--token-color-border-primary);
|
|
170
|
+
color: var(--token-color-foreground-primary);
|
|
171
|
+
display: flex;
|
|
172
|
+
font-family: var(--token-typography-font-stack-code);
|
|
173
|
+
justify-content: space-between;
|
|
174
|
+
padding: 12px 8px;
|
|
175
|
+
width: 100%;
|
|
176
|
+
|
|
177
|
+
&:hover,
|
|
178
|
+
&.is-hover {
|
|
179
|
+
background-color: var(--token-color-surface-interactive-hover);
|
|
180
|
+
cursor: pointer;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@include hds-focus-ring-basic();
|
|
184
|
+
|
|
185
|
+
&:focus,
|
|
186
|
+
&.is-focus {
|
|
187
|
+
//TODO this focus is just way too complex
|
|
188
|
+
background-color: var(--token-color-surface-action);
|
|
189
|
+
border-color: var(--token-color-focus-action-internal);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
&:active,
|
|
193
|
+
&.is-active {
|
|
194
|
+
background-color: var(--token-color-surface-interactive-active);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&.is-success {
|
|
198
|
+
border-color: var(--token-color-border-success);
|
|
199
|
+
background-color: var(--token-color-surface-success);
|
|
200
|
+
|
|
201
|
+
.hds-dropdown-list-item__copy-item-icon {
|
|
202
|
+
color: var(--token-color-foreground-success);
|
|
203
|
+
}
|
|
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
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.hds-dropdown-list-item--interactive {
|
|
225
|
+
position: relative;
|
|
226
|
+
isolation: isolate; // used to create a new stacking context (needed to have the pseudo element below text/icon but not the parent container)
|
|
227
|
+
min-height: 36px;
|
|
228
|
+
|
|
229
|
+
// need to reset a few extra things to make the button visually appear the same as the links
|
|
230
|
+
// TODO this is 0.125rem taller than the link...
|
|
231
|
+
button {
|
|
232
|
+
border: 1px inset transparent; // cause of the extra height
|
|
233
|
+
background-color: transparent;
|
|
234
|
+
width: 100%;
|
|
235
|
+
|
|
236
|
+
&:hover {
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// shared styles for links and buttons
|
|
243
|
+
a, button {
|
|
244
|
+
align-items: center;
|
|
245
|
+
display: flex;
|
|
246
|
+
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
|
+
outline-color: transparent;
|
|
248
|
+
padding: 8px 10px 8px 16px;
|
|
249
|
+
text-decoration: none;
|
|
250
|
+
|
|
251
|
+
// this is used for the left "hover" indicator
|
|
252
|
+
&::before {
|
|
253
|
+
border-radius: 1px;
|
|
254
|
+
bottom: 6px;
|
|
255
|
+
content: '';
|
|
256
|
+
left: 0.25rem;
|
|
257
|
+
position: absolute;
|
|
258
|
+
top: 6px;
|
|
259
|
+
width: 2px;
|
|
260
|
+
z-index: -1;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Notice: this is used for the active/focus states which have very specific positions
|
|
264
|
+
// and also has a background color, so we can't use the existing focus-ring mixins
|
|
265
|
+
&::after {
|
|
266
|
+
border-radius: 5px;
|
|
267
|
+
bottom: 0px;
|
|
268
|
+
content: '';
|
|
269
|
+
left: 0.625rem;
|
|
270
|
+
position: absolute;
|
|
271
|
+
right: 0.25rem;
|
|
272
|
+
z-index: -1;
|
|
273
|
+
top: 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Notice: to avoid too much duplication we define two local CSS variables
|
|
277
|
+
// and define their values in the color variants below
|
|
278
|
+
|
|
279
|
+
// default focus for browsers that still rely on ":focus"
|
|
280
|
+
&:focus,
|
|
281
|
+
&.is-focus {
|
|
282
|
+
&::after {
|
|
283
|
+
background-color: var(--current-background-color);
|
|
284
|
+
box-shadow: var(--current-focus-ring-box-shadow);
|
|
285
|
+
left: 0.25rem;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// undo the previous declaration for browsers that support ":focus-visible" but wouldn't normally show default focus styles
|
|
289
|
+
&:focus:not(:focus-visible) {
|
|
290
|
+
&::after {
|
|
291
|
+
box-shadow: none;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// set focus for browsers that support ":focus-visible"
|
|
295
|
+
&:focus-visible {
|
|
296
|
+
&::after {
|
|
297
|
+
background-color: var(--current-background-color);
|
|
298
|
+
box-shadow: var(--current-focus-ring-box-shadow);
|
|
299
|
+
left: 0.25rem;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// remove the focus ring on "active + focused" state (by design)
|
|
303
|
+
&:focus:active,
|
|
304
|
+
&.is-focus.is-active {
|
|
305
|
+
&::after {
|
|
306
|
+
box-shadow: none;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.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
|
+
text-align: left; // the button element was centering text
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.hds-dropdown-list-item__interactive-icon {
|
|
321
|
+
margin-right: 0.5rem;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.hds-dropdown-list-item--color-action {
|
|
325
|
+
a, button {
|
|
326
|
+
color: var(--token-color-foreground-primary);
|
|
327
|
+
|
|
328
|
+
// assign the values to the local CSS variables used above
|
|
329
|
+
&::after {
|
|
330
|
+
--current-background-color: var(--token-color-surface-action);
|
|
331
|
+
--current-focus-ring-box-shadow: var(
|
|
332
|
+
--token-focus-ring-action-box-shadow
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
&:hover,
|
|
337
|
+
&.is-hover {
|
|
338
|
+
color: var(--token-color-foreground-action-hover);
|
|
339
|
+
&::before {
|
|
340
|
+
background-color: currentColor;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
&:active,
|
|
345
|
+
&.is-active {
|
|
346
|
+
color: var(--token-color-foreground-action-active);
|
|
347
|
+
&::before {
|
|
348
|
+
background-color: currentColor;
|
|
349
|
+
}
|
|
350
|
+
&::after {
|
|
351
|
+
background-color: var(--token-color-surface-action);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.hds-dropdown-list-item--color-critical {
|
|
358
|
+
a, button {
|
|
359
|
+
color: var(--token-color-foreground-critical);
|
|
360
|
+
|
|
361
|
+
// assign the values to the local CSS variables used above
|
|
362
|
+
&::after {
|
|
363
|
+
--current-background-color: var(--token-color-surface-critical);
|
|
364
|
+
--current-focus-ring-box-shadow: var(
|
|
365
|
+
--token-focus-ring-critical-box-shadow
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
&:hover,
|
|
370
|
+
&.is-hover {
|
|
371
|
+
color: var(
|
|
372
|
+
--token-color-palette-red-300
|
|
373
|
+
); // TODO we need to add this token to the design system
|
|
374
|
+
&::before {
|
|
375
|
+
background-color: currentColor;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
&:active,
|
|
379
|
+
&.is-active {
|
|
380
|
+
color: var(
|
|
381
|
+
--token-color-palette-red-400
|
|
382
|
+
); // TODO we need to add this token to the design system
|
|
383
|
+
&::before {
|
|
384
|
+
background-color: currentColor;
|
|
385
|
+
}
|
|
386
|
+
&::after {
|
|
387
|
+
background-color: var(--token-color-surface-critical);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// LINK > STANDALONE COMPONENT
|
|
3
3
|
//
|
|
4
4
|
// properties within each class are sorted alphabetically
|
|
5
|
-
// notice: pseudo-classes for the states *must* follow the order link > visited >
|
|
6
|
-
// see https://github.com/hashicorp/design-system-components/issues/132
|
|
5
|
+
// notice: pseudo-classes for the states *must* follow the order link > visited > hover > focus > active
|
|
7
6
|
//
|
|
8
7
|
//
|
|
9
8
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hashicorp/design-system-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "HashiCorp Design System Components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hashicorp",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@hashicorp/design-system-tokens": "^0.8.0",
|
|
38
|
-
"@hashicorp/ember-flight-icons": "^2.0.
|
|
38
|
+
"@hashicorp/ember-flight-icons": "^2.0.5",
|
|
39
39
|
"ember-auto-import": "^2.2.3",
|
|
40
40
|
"ember-cli-babel": "^7.26.6",
|
|
41
41
|
"ember-cli-htmlbars": "^5.7.1",
|