@everchron/ec-shards 6.2.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/ec-shards.common.js +3154 -2114
  2. package/dist/ec-shards.common.js.map +1 -1
  3. package/dist/ec-shards.css +1 -1
  4. package/dist/ec-shards.umd.js +3154 -2114
  5. package/dist/ec-shards.umd.js.map +1 -1
  6. package/dist/ec-shards.umd.min.js +2 -2
  7. package/dist/ec-shards.umd.min.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/components/action-toolbar/action-toolbar.vue +1 -1
  10. package/src/components/alert/alert.vue +27 -4
  11. package/src/components/avatar/avatar.vue +2 -1
  12. package/src/components/breadcrumb/breadcrumb.vue +2 -2
  13. package/src/components/breadcrumb-button/breadcrumb-button.vue +15 -3
  14. package/src/components/breadcrumb-title/breadcrumb-title.vue +1 -1
  15. package/src/components/button/button.vue +65 -54
  16. package/src/components/button-collapse/button-collapse.vue +49 -6
  17. package/src/components/button-context/button-context.vue +30 -1
  18. package/src/components/button-dialog/button-dialog.vue +22 -8
  19. package/src/components/button-more/button-more.vue +44 -4
  20. package/src/components/button-table/button-table.vue +13 -1
  21. package/src/components/button-toolbar/button-toolbar.vue +50 -19
  22. package/src/components/button-toolbar-icon/button-toolbar-icon.vue +23 -7
  23. package/src/components/checkbox/checkbox.vue +0 -1
  24. package/src/components/collapse/collapse.vue +28 -7
  25. package/src/components/collection-control/collection-control.vue +40 -7
  26. package/src/components/comment/comment.vue +1 -1
  27. package/src/components/context-menu/context-menu.vue +88 -5
  28. package/src/components/data-card/data-card.vue +52 -14
  29. package/src/components/data-card-list/data-card-list.vue +1 -1
  30. package/src/components/data-grid/data-grid-cell.vue +1 -1
  31. package/src/components/data-grid/data-grid-group.vue +6 -1
  32. package/src/components/data-grid/data-grid-head-cell.vue +32 -2
  33. package/src/components/data-grid/data-grid-row.vue +1 -1
  34. package/src/components/data-grid/data-grid.vue +2 -2
  35. package/src/components/data-list/data-list.vue +1 -1
  36. package/src/components/data-list-item/data-list-item.vue +28 -9
  37. package/src/components/directory-entry/directory-entry.vue +7 -4
  38. package/src/components/document-state/document-state.vue +1 -1
  39. package/src/components/dropdown/dropdown.vue +23 -1
  40. package/src/components/dropzone/dropzone.vue +21 -3
  41. package/src/components/empty-state/empty-state.vue +1 -1
  42. package/src/components/entry-link/entry-link.vue +16 -3
  43. package/src/components/favicon/favicon.vue +1 -1
  44. package/src/components/file-icon/file-icon.vue +1 -1
  45. package/src/components/file-list/file-list.vue +1 -1
  46. package/src/components/file-list-item/file-list-item.vue +79 -17
  47. package/src/components/flag/flag.vue +75 -1
  48. package/src/components/folder-selector/folder-selector.vue +1 -1
  49. package/src/components/form-check/form-check.vue +9 -2
  50. package/src/components/form-set/form-set.vue +4 -4
  51. package/src/components/index.js +2 -0
  52. package/src/components/input-clear/input-clear.vue +20 -3
  53. package/src/components/jumper-document/jumper-document.vue +16 -4
  54. package/src/components/jumper-index/jumper-index.vue +19 -4
  55. package/src/components/jumper-page/jumper-page.vue +3 -1
  56. package/src/components/layout-data-table/layout-data-table.vue +5 -5
  57. package/src/components/layout-directory/layout-directory.vue +4 -4
  58. package/src/components/layout-index/layout-index.vue +2 -2
  59. package/src/components/legend-item/legend-item.vue +15 -1
  60. package/src/components/log-message/log-message.vue +11 -1
  61. package/src/components/map/map.vue +20 -3
  62. package/src/components/mixins/focus-ring.vue +47 -0
  63. package/src/components/mixins/unique-id.js +17 -0
  64. package/src/components/modal/modal.vue +5 -2
  65. package/src/components/modal-header/modal-header.vue +43 -19
  66. package/src/components/multiselect-option/multiselect-option.vue +1 -1
  67. package/src/components/multiselect-search-token/multiselect-search-token.vue +33 -6
  68. package/src/components/multiselect-token/multiselect-token.vue +28 -3
  69. package/src/components/overlay/overlay.vue +6 -6
  70. package/src/components/pagination/pagination.vue +5 -5
  71. package/src/components/popover-list/popover-list.vue +5 -1
  72. package/src/components/popover-list-headline/popover-list-headline.vue +4 -1
  73. package/src/components/popover-list-item/popover-list-item.vue +27 -8
  74. package/src/components/progress/progress.vue +7 -1
  75. package/src/components/quicklink/quicklink.vue +29 -18
  76. package/src/components/radiobutton/radiobutton.vue +2 -2
  77. package/src/components/rating-favorability/rating-favorability.vue +5 -1
  78. package/src/components/rating-star-read/rating-star-read.vue +1 -1
  79. package/src/components/select/select.vue +12 -2
  80. package/src/components/select-text/select-text.vue +7 -2
  81. package/src/components/select-tile/select-tile.vue +26 -2
  82. package/src/components/separator/separator.vue +1 -1
  83. package/src/components/sequence-map/sequence-map.vue +1 -1
  84. package/src/components/sequence-map-button/sequence-map-button.vue +14 -2
  85. package/src/components/sidebar-footer/sidebar-footer.vue +2 -2
  86. package/src/components/sidebar-header/sidebar-header.vue +2 -2
  87. package/src/components/sortbutton/sortbutton.vue +22 -7
  88. package/src/components/sticker/sticker.vue +1 -1
  89. package/src/components/swatches-picker/swatches-picker.vue +28 -3
  90. package/src/components/switch/switch.vue +24 -8
  91. package/src/components/tab/tab.vue +16 -2
  92. package/src/components/tab-bar/tab-bar.vue +1 -1
  93. package/src/components/tab-button/tab-button.vue +61 -1
  94. package/src/components/tabs/tabs.vue +2 -1
  95. package/src/components/tag/tag.vue +17 -5
  96. package/src/components/tag-cloud/tag-cloud.vue +3 -1
  97. package/src/components/toast/toast.vue +18 -3
  98. package/src/components/toasts/toasts.vue +1 -1
  99. package/src/components/toolbar/toolbar.vue +1 -1
  100. package/src/components/transcript-state/transcript-state.vue +1 -1
  101. package/src/components/tree-list/tree-list-item.vue +77 -12
  102. package/src/components/tree-list/tree-list.vue +7 -1
  103. package/src/stories/Changelog.stories.mdx +8 -0
  104. package/src/stories/button/button.stories.js +7 -7
  105. package/src/stories/button-more/button-more.stories.js +8 -8
  106. package/src/stories/button-toolbar/button-toolbar.stories.js +5 -5
  107. package/src/stories/button-toolbar-icon/button-toolbar-icon.stories.js +6 -6
  108. package/src/stories/popover-list/popover-list.stories.js +7 -2
  109. package/src/stories/sortbutton/sortbutton.stories.js +4 -4
  110. package/src/stories/tag/tag.stories.js +7 -7
  111. package/src/stories/tree-list/tree-list.stories.js +3 -0
@@ -1,16 +1,22 @@
1
1
  <template>
2
- <button class="ecs-dialog-footer-button" :class="[typeClass, loading ? `loading` : '']" @click="$emit('click', $event)">
2
+ <button @click="$emit('click', $event)"
3
+ :class="[typeClass, loading ? `loading` : '']"
4
+ :arial-busy="loading"
5
+ class="ecs-dialog-footer-button">
3
6
  <ecs-icon v-if="icon || loading" :type="iconType" />
4
7
  <slot></slot>
8
+ <ecs-focus-ring :radius="12" :danger="type == 'danger'" />
5
9
  </button>
6
10
  </template>
7
11
 
8
12
  <script>
9
13
  import EcsIcon from '../icon/icon'
14
+ import EcsFocusRing from '../mixins/focus-ring'
10
15
 
11
16
  export default {
12
17
  components: {
13
- EcsIcon
18
+ EcsIcon,
19
+ EcsFocusRing
14
20
  },
15
21
 
16
22
  props: {
@@ -65,10 +71,11 @@
65
71
  justify-content: center;
66
72
  cursor: pointer;
67
73
  flex-shrink: 0;
74
+ position: relative;
68
75
 
69
76
  .icon{
70
77
  margin-right: $spacing-10;
71
- opacity: .8;
78
+ opacity: .9;
72
79
  }
73
80
 
74
81
  &:hover{
@@ -79,24 +86,31 @@
79
86
  }
80
87
  }
81
88
 
82
- &:focus,
89
+ &:focus-visible{
90
+ z-index: 1;
91
+
92
+ .ecs-focus-ring{
93
+ display: block;
94
+ }
95
+ }
96
+
83
97
  &:active{
84
98
  background: rgba($color-gray-13, .04);
85
99
  }
86
100
 
87
101
  &-confirm{
88
- color: $color-blue-8;
102
+ color: $color-blue-10;
89
103
 
90
104
  &:hover{
91
- color: $color-blue-10;
105
+ color: $color-blue-11;
92
106
  }
93
107
  }
94
108
 
95
109
  &-danger{
96
- color: $color-red-9;
110
+ color: $color-red-11;
97
111
 
98
112
  &:hover{
99
- color: $color-red-10;
113
+ color: $color-red-12;
100
114
  }
101
115
  }
102
116
 
@@ -1,21 +1,29 @@
1
1
  <template>
2
2
  <button
3
+ @click="$emit('click', $event)"
4
+ :aria-label="ariaLabel"
5
+ :aria-disabled="disabled"
6
+ :aria-expanded="active"
7
+ :aria-haspopup="type == 'dropdown'"
8
+ :disabled="disabled"
3
9
  :class="[ active ? `active` : '',
4
10
  typeClass
5
- ]"
6
- @click="$emit('click', $event)">
11
+ ]">
7
12
 
8
13
  <ecs-icon v-if="type == 'ellipsis'" type="more" size="20" color="#FFF" />
9
14
  <slot></slot>
15
+ <ecs-focus-ring />
10
16
  </button>
11
17
  </template>
12
18
 
13
19
  <script>
14
20
  import EcsIcon from '../icon/icon'
21
+ import EcsFocusRing from '../mixins/focus-ring'
15
22
 
16
23
  export default {
17
24
  components: {
18
- EcsIcon
25
+ EcsIcon,
26
+ EcsFocusRing
19
27
  },
20
28
 
21
29
  props: {
@@ -27,6 +35,14 @@
27
35
  validator: v => ['dropdown', 'ellipsis', 'expand'].includes(v),
28
36
  default: 'dropdown'
29
37
  },
38
+ /** Provide a meaningful label for the button to improve accessibility for screenreaders. */
39
+ ariaLabel: {
40
+ type: String
41
+ },
42
+ /** Disables the button and prevent pointer events. */
43
+ disabled: {
44
+ type: Boolean
45
+ }
30
46
  },
31
47
 
32
48
  computed: {
@@ -35,6 +51,12 @@
35
51
  return `ecs-button-more-${this.type}`
36
52
  return this.type
37
53
  }
54
+ },
55
+
56
+ mounted() {
57
+ if (this.$slots.default === undefined && (!this.ariaLabel || this.ariaLabel.trim() === '')) {
58
+ console.warn('Warning: ariaLabel must be provided on buttons with only an icon and no label.');
59
+ }
38
60
  }
39
61
  }
40
62
  </script>
@@ -54,6 +76,12 @@
54
76
  cursor: pointer;
55
77
  flex-shrink: 0;
56
78
 
79
+ &:focus-visible{
80
+ .ecs-focus-ring{
81
+ display: block;
82
+ }
83
+ }
84
+
57
85
  &:hover,
58
86
  &.active{
59
87
  background: rgba($color-gray-8, .3);
@@ -89,6 +117,12 @@
89
117
  min-width: 16px;
90
118
  cursor: pointer;
91
119
 
120
+ &:focus-visible{
121
+ .ecs-focus-ring{
122
+ display: block;
123
+ }
124
+ }
125
+
92
126
  .icon{
93
127
  position: absolute;
94
128
  left: -2px;
@@ -121,6 +155,12 @@
121
155
  cursor: pointer;
122
156
  position: relative;
123
157
 
158
+ &:focus-visible{
159
+ .ecs-focus-ring{
160
+ display: block;
161
+ }
162
+ }
163
+
124
164
  &:before{
125
165
  content: "";
126
166
  width: 20px;
@@ -133,7 +173,7 @@
133
173
  background: rgba($color-gray-6, .05);
134
174
  }
135
175
 
136
- &.active{
176
+ &.active{
137
177
  &:before{
138
178
  transform: rotate(180deg);
139
179
  }
@@ -11,6 +11,9 @@
11
11
  sizeClass
12
12
  ]"
13
13
  :disabled="disabled"
14
+ :aria-disabled="disabled || unreactive"
15
+ :aria-expanded="active"
16
+ :aria-busy="loading"
14
17
  @click="$emit('click', $event)"
15
18
  @mouseover="$emit('mouseover', $event)"
16
19
  @mouseleave="$emit('mouseleave', $event)">
@@ -18,15 +21,18 @@
18
21
  <ecs-icon v-if="icon || loading" :type="iconType" :size="iconSize" />
19
22
  <div v-if="label != null" class="button-label">{{ label }}</div>
20
23
  <div v-if="chevron" class="chevron" :class="active ? 'expand' : ''" />
24
+ <ecs-focus-ring />
21
25
  </button>
22
26
  </template>
23
27
 
24
28
  <script>
25
29
  import EcsIcon from '../icon/icon'
30
+ import EcsFocusRing from '../mixins/focus-ring'
26
31
 
27
32
  export default {
28
33
  components: {
29
- EcsIcon
34
+ EcsIcon,
35
+ EcsFocusRing
30
36
  },
31
37
 
32
38
  props: {
@@ -124,6 +130,12 @@
124
130
  z-index: 1;
125
131
  flex-shrink: 0;
126
132
 
133
+ &:focus-visible{
134
+ .ecs-focus-ring{
135
+ display: block;
136
+ }
137
+ }
138
+
127
139
  &-md{
128
140
  font-size: $type-scale-3-font-size;
129
141
  padding: 1px;
@@ -1,43 +1,56 @@
1
1
  <template>
2
- <a v-if="href" :href="href" :target="target" class="ecs-toolbar-button"
3
- :class="[
4
- iconClass,
5
- active ? 'active' : '',
6
- loading ? 'loading' : '',
7
- activeHighlight ? 'active-highlight' : '',
8
- dropdown ? 'ecs-toolbar-button-dropdown' : '',
9
- dropdownClass]"
10
- @click="$emit('click', $event)">
2
+ <a v-if="href" @click="$emit('click', $event)"
3
+ :href="href"
4
+ :target="target"
5
+ role="button"
6
+ :aria-expanded="active && dropdown"
7
+ :aria-busy="loading"
8
+ :aria-label="ariaLabel"
9
+ class="ecs-toolbar-button"
10
+ :class="[
11
+ iconClass,
12
+ active ? 'active' : '',
13
+ loading ? 'loading' : '',
14
+ activeHighlight ? 'active-highlight' : '',
15
+ dropdown ? 'ecs-toolbar-button-dropdown' : '',
16
+ dropdownClass]">
11
17
 
12
18
  <ecs-icon v-if="(icon && iconPosition == 'left') || (loading && iconPosition == 'left')" :size="iconSize" :color="iconTint" :type="iconType" :spinning="loading" />
13
19
  <slot></slot>
14
20
  <span class="badge" v-if="badge" :style="{ background: badgeColor }"></span>
15
21
  <ecs-icon v-if="(icon && iconPosition == 'right') || (loading && iconPosition == 'right')" :size="iconSize" :color="iconTint" :type="iconType" :spinning="loading" />
22
+ <ecs-focus-ring />
16
23
  </a>
17
24
 
18
- <button v-else class="ecs-toolbar-button"
19
- :class="[
20
- iconClass,
21
- active ? 'active' : '',
22
- loading ? 'loading' : '',
23
- activeHighlight ? 'active-highlight' : '',
24
- dropdown ? 'ecs-toolbar-button-dropdown' : '',
25
- dropdownClass]"
26
- @click="$emit('click', $event)">
25
+ <button v-else @click="$emit('click', $event)"
26
+ :aria-expanded="active && dropdown"
27
+ :aria-busy="loading"
28
+ :aria-label="ariaLabel"
29
+ class="ecs-toolbar-button"
30
+ :class="[
31
+ iconClass,
32
+ active ? 'active' : '',
33
+ loading ? 'loading' : '',
34
+ activeHighlight ? 'active-highlight' : '',
35
+ dropdown ? 'ecs-toolbar-button-dropdown' : '',
36
+ dropdownClass]">
27
37
 
28
38
  <ecs-icon v-if="(icon && iconPosition == 'left') || (loading && iconPosition == 'left')" :size="iconSize" :color="iconTint" :type="iconType" :spinning="loading" />
29
39
  <slot></slot>
30
40
  <span class="badge" v-if="badge" :style="{ background: badgeColor }"></span>
31
41
  <ecs-icon v-if="(icon && iconPosition == 'right') || (loading && iconPosition == 'right')" :size="iconSize" :color="iconTint" :type="iconType" :spinning="loading" />
42
+ <ecs-focus-ring />
32
43
  </button>
33
44
  </template>
34
45
 
35
46
  <script>
36
47
  import EcsIcon from '../icon/icon'
48
+ import EcsFocusRing from '../mixins/focus-ring'
37
49
 
38
50
  export default {
39
51
  components: {
40
- EcsIcon
52
+ EcsIcon,
53
+ EcsFocusRing
41
54
  },
42
55
 
43
56
  props: {
@@ -101,6 +114,10 @@
101
114
  badgeColor: {
102
115
  type: String,
103
116
  default: '#FF4B62'
117
+ },
118
+ /** Sets the aria-label attribute. Required for buttons that only contain an icon. */
119
+ ariaLabel: {
120
+ type: String
104
121
  }
105
122
  },
106
123
 
@@ -136,6 +153,12 @@
136
153
  if (this.dropdown && !!this.$slots.default)
137
154
  return `ecs-toolbar-button-dropdown-text`
138
155
  }
156
+ },
157
+
158
+ mounted() {
159
+ if (this.$slots.default === undefined && (!this.ariaLabel || this.ariaLabel.trim() === '')) {
160
+ console.warn('Warning: ariaLabel must be provided on buttons with only an icon and no label.');
161
+ }
139
162
  }
140
163
  }
141
164
  </script>
@@ -167,6 +190,14 @@
167
190
  z-index: 1;
168
191
  }
169
192
 
193
+ &:focus-visible{
194
+ z-index: 1;
195
+
196
+ .ecs-focus-ring{
197
+ display: block;
198
+ }
199
+ }
200
+
170
201
  &:hover{
171
202
  border: 1px solid rgba($color-gray-8, .25);
172
203
  box-shadow: 0 1px 2px rgba($color-gray-8, .1);
@@ -1,23 +1,28 @@
1
1
  <template>
2
- <button class="ecs-toolbar-icon-button"
3
- :class="[
4
- refresh ? 'refreshing' : '',
5
- active ? 'active' : '',
6
- loading ? 'loading' : ''
7
- ]" @click="$emit('click', $event)">
2
+ <button @click="$emit('click', $event)"
3
+ :aria-busy="refresh || loading"
4
+ :aria-label="ariaLabel"
5
+ class="ecs-toolbar-icon-button"
6
+ :class="[
7
+ refresh ? 'refreshing' : '',
8
+ active ? 'active' : '',
9
+ loading ? 'loading' : ''
10
+ ]">
8
11
  <ecs-icon :type="icon" />
9
12
  <span v-if="hasBadge" class="badge" />
10
13
  <div class="sub-icon">
11
14
  <ecs-icon v-if="subIcon" :type="subIcon" size="14" />
12
15
  </div>
16
+ <ecs-focus-ring />
13
17
  </button>
14
18
  </template>
15
19
 
16
20
  <script>
17
21
  import EcsIcon from '../icon/icon'
22
+ import EcsFocusRing from '../mixins/focus-ring'
18
23
 
19
24
  export default {
20
- components: { EcsIcon },
25
+ components: { EcsIcon, EcsFocusRing },
21
26
 
22
27
  props: {
23
28
  /** The icon type of the button. The list of available icon names can be found [here](https://github.com/everchron/ec-shards/tree/main/src/assets/icons). Note that only icons prefixed with `toolbar-` should be used here. */
@@ -48,6 +53,11 @@
48
53
  hasBadge: {
49
54
  type: Boolean,
50
55
  default: false
56
+ },
57
+ /** Sets the aria-label attribute to improve accessibility. */
58
+ ariaLabel: {
59
+ type: String,
60
+ required: true
51
61
  }
52
62
  }
53
63
  }
@@ -71,6 +81,12 @@
71
81
  justify-content: center;
72
82
  flex-shrink: 0;
73
83
 
84
+ &:focus-visible{
85
+ .ecs-focus-ring{
86
+ display: block;
87
+ }
88
+ }
89
+
74
90
  &:after{
75
91
  content: "";
76
92
  position: absolute;
@@ -1,7 +1,6 @@
1
1
  <template>
2
2
  <ecs-form-check :class="[
3
3
  inline ? `ecs-form-check-inline` : '',
4
- disabled ? `disabled` : '',
5
4
  $slots.default ? '' : 'stand-alone']">
6
5
 
7
6
  <input
@@ -6,19 +6,30 @@
6
6
  headlineIndentation]">
7
7
 
8
8
  <div class="wrap">
9
- <ecs-button v-if="removable" @click="$emit('remove', id)" type="secondary" icon-only icon="minus" size="sml" class="remove-button" :class="removeButtonIndentation" :title="removableTooltip" />
10
-
11
- <h3 class="ecs-collapsable-headline"
12
- :class="[headlineBold ? 'ecs-headline-section-bold' : 'ecs-headline-section', isVisible ? '' : 'collapsed']"
13
- @click="toggleCollapse">
9
+ <ecs-button v-if="removable" @click="$emit('remove', id)" type="secondary" icon-only icon="minus" size="sml" class="remove-button" :class="removeButtonIndentation" :title="removableTooltip" :aria-label="removableTooltip" />
10
+
11
+ <h3
12
+ @click="toggleCollapse"
13
+ @keydown.space.prevent="toggleCollapse"
14
+ role="button"
15
+ class="ecs-collapsable-headline"
16
+ tabindex="0"
17
+ :aria-expanded="isVisible ? 'true' : 'false'"
18
+ :aria-controls="`collapse-${this.id}`"
19
+ :class="[headlineBold ? 'ecs-headline-section-bold' : 'ecs-headline-section', isVisible ? '' : 'collapsed']">
14
20
  {{title}}
21
+ <ecs-focus-ring :inset="0" :radius="0" />
15
22
  <div v-if="$slots.controls" class="ecs-collapsable-headline-controls">
16
23
  <slot name="controls"></slot>
17
24
  </div>
18
25
  </h3>
19
26
  </div>
20
27
 
21
- <div :class="isVisible ? 'collapse-show' : 'collapse-hide'" :id="`collapse-${ this.id }`" class="collapse">
28
+ <div
29
+ :class="isVisible ? 'collapse-show' : 'collapse-hide'"
30
+ :id="`collapse-${ this.id }`"
31
+ class="collapse"
32
+ :aria-hidden="isVisible ? 'false' : 'true'">
22
33
  <div class="ecs-collapsable-content" :class="contentPaddingClass">
23
34
  <slot></slot>
24
35
  </div>
@@ -28,9 +39,10 @@
28
39
 
29
40
  <script>
30
41
  import EcsButton from '../button/button'
42
+ import EcsFocusRing from '../mixins/focus-ring'
31
43
 
32
44
  export default {
33
- components: { EcsButton },
45
+ components: { EcsButton, EcsFocusRing },
34
46
 
35
47
  props: {
36
48
  /** Unique ID, is required to handle persist states. */
@@ -202,6 +214,15 @@ export default {
202
214
  user-select: none;
203
215
  flex: 1;
204
216
 
217
+ &:focus-visible{
218
+ z-index: 1;
219
+ outline: none;
220
+
221
+ .ecs-focus-ring{
222
+ display: block;
223
+ }
224
+ }
225
+
205
226
  &:after{
206
227
  content: "";
207
228
  position: absolute;
@@ -4,10 +4,20 @@
4
4
  isVisible || nonInteractive ? '' : 'collapsed',
5
5
  size
6
6
  ]">
7
- <div @click="toggleCollapse" class="ecs-collection-control-header" :class="[
7
+ <div
8
+ @click="toggleCollapse"
9
+ @keydown.enter.prevent="toggleCollapse"
10
+ @keydown.space.prevent="toggleCollapse"
11
+ class="ecs-collection-control-header"
12
+ :class="[
8
13
  isVisible || nonInteractive ? '' : 'collapsed',
9
14
  nonInteractive ? '' : 'interactive',
10
- ]">
15
+ ]"
16
+ :tabindex="nonInteractive ? '-1' : '0'"
17
+ :role="nonInteractive ? false : 'button'"
18
+ :aria-expanded="nonInteractive ? false : isVisible"
19
+ :aria-controls="nonInteractive ? false : expandId">
20
+ <ecs-focus-ring />
11
21
  <ecs-icon v-if="icon" :type="icon" color="#858E9E" :size="iconSize" />
12
22
  <div class="description" v-if="label">{{ label }}</div>
13
23
  <div class="collection"
@@ -17,7 +27,11 @@
17
27
  <span v-for="item in collection" :key="item.name" v-if="item.value">{{ item.name }}</span>
18
28
  </div>
19
29
  </div>
20
- <div :class="isVisible || nonInteractive ? 'collapse-show' : 'collapse-hide'" class="collapse">
30
+ <div
31
+ :class="isVisible || nonInteractive ? 'collapse-show' : 'collapse-hide'"
32
+ class="collapse"
33
+ :id="nonInteractive ? false : expandId"
34
+ :aria-hidden="isVisible ? 'false' : 'true'">
21
35
  <div class="ecs-collection-control-list scrollbar scrollbar-sml" :style="listMaxHeight">
22
36
  <slot></slot>
23
37
  </div>
@@ -27,9 +41,13 @@
27
41
 
28
42
  <script>
29
43
  import EcsIcon from '../icon/icon'
44
+ import EcsFocusRing from '../mixins/focus-ring'
45
+ import { uniqueIdMixin } from '../mixins/unique-id'
30
46
 
31
47
  export default {
32
- components: { EcsIcon },
48
+ components: { EcsIcon, EcsFocusRing },
49
+ mixins: [uniqueIdMixin],
50
+
33
51
  props: {
34
52
  /** Icon representing the type of selection. The list of available icon names can be found [here](https://github.com/everchron/ec-shards/tree/main/src/assets/icons). */
35
53
  icon: {
@@ -74,7 +92,8 @@
74
92
 
75
93
  data() {
76
94
  return {
77
- isVisible: this.visible
95
+ isVisible: this.visible,
96
+ expandId: ''
78
97
  }
79
98
  },
80
99
 
@@ -95,8 +114,9 @@
95
114
 
96
115
  methods: {
97
116
  toggleCollapse(){
98
- this.isVisible = !this.isVisible
99
- this.$emit('toggled', this.id, this.isVisible)
117
+ if(!this.nonInteractive)
118
+ this.isVisible = !this.isVisible
119
+ this.$emit('toggled', this.id, this.isVisible)
100
120
  },
101
121
 
102
122
  toggleTooltip() {
@@ -108,6 +128,10 @@
108
128
  visible(){
109
129
  this.isVisible = this.visible
110
130
  }
131
+ },
132
+
133
+ created() {
134
+ this.expandId = this.generateUniqueId()
111
135
  }
112
136
  }
113
137
  </script>
@@ -159,6 +183,15 @@
159
183
  transition: .2s;
160
184
  user-select: none;
161
185
 
186
+ &:focus-visible{
187
+ z-index: 1;
188
+ outline: none;
189
+
190
+ .ecs-focus-ring{
191
+ display: block;
192
+ }
193
+ }
194
+
162
195
  &.interactive{
163
196
  cursor: pointer;
164
197
  }
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="ecs-comment">
2
+ <div class="ecs-comment" role="comment" :aria-busy="loading">
3
3
  <div class="ecs-comment-header">
4
4
  <div class="ecs-comment-autor">
5
5
  <ecs-skeleton-loader v-if="loading" type="circle" :width="32" :height="32" />