@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.
- package/dist/ec-shards.common.js +3154 -2114
- package/dist/ec-shards.common.js.map +1 -1
- package/dist/ec-shards.css +1 -1
- package/dist/ec-shards.umd.js +3154 -2114
- package/dist/ec-shards.umd.js.map +1 -1
- package/dist/ec-shards.umd.min.js +2 -2
- package/dist/ec-shards.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/action-toolbar/action-toolbar.vue +1 -1
- package/src/components/alert/alert.vue +27 -4
- package/src/components/avatar/avatar.vue +2 -1
- package/src/components/breadcrumb/breadcrumb.vue +2 -2
- package/src/components/breadcrumb-button/breadcrumb-button.vue +15 -3
- package/src/components/breadcrumb-title/breadcrumb-title.vue +1 -1
- package/src/components/button/button.vue +65 -54
- package/src/components/button-collapse/button-collapse.vue +49 -6
- package/src/components/button-context/button-context.vue +30 -1
- package/src/components/button-dialog/button-dialog.vue +22 -8
- package/src/components/button-more/button-more.vue +44 -4
- package/src/components/button-table/button-table.vue +13 -1
- package/src/components/button-toolbar/button-toolbar.vue +50 -19
- package/src/components/button-toolbar-icon/button-toolbar-icon.vue +23 -7
- package/src/components/checkbox/checkbox.vue +0 -1
- package/src/components/collapse/collapse.vue +28 -7
- package/src/components/collection-control/collection-control.vue +40 -7
- package/src/components/comment/comment.vue +1 -1
- package/src/components/context-menu/context-menu.vue +88 -5
- package/src/components/data-card/data-card.vue +52 -14
- package/src/components/data-card-list/data-card-list.vue +1 -1
- package/src/components/data-grid/data-grid-cell.vue +1 -1
- package/src/components/data-grid/data-grid-group.vue +6 -1
- package/src/components/data-grid/data-grid-head-cell.vue +32 -2
- package/src/components/data-grid/data-grid-row.vue +1 -1
- package/src/components/data-grid/data-grid.vue +2 -2
- package/src/components/data-list/data-list.vue +1 -1
- package/src/components/data-list-item/data-list-item.vue +28 -9
- package/src/components/directory-entry/directory-entry.vue +7 -4
- package/src/components/document-state/document-state.vue +1 -1
- package/src/components/dropdown/dropdown.vue +23 -1
- package/src/components/dropzone/dropzone.vue +21 -3
- package/src/components/empty-state/empty-state.vue +1 -1
- package/src/components/entry-link/entry-link.vue +16 -3
- package/src/components/favicon/favicon.vue +1 -1
- package/src/components/file-icon/file-icon.vue +1 -1
- package/src/components/file-list/file-list.vue +1 -1
- package/src/components/file-list-item/file-list-item.vue +79 -17
- package/src/components/flag/flag.vue +75 -1
- package/src/components/folder-selector/folder-selector.vue +1 -1
- package/src/components/form-check/form-check.vue +9 -2
- package/src/components/form-set/form-set.vue +4 -4
- package/src/components/index.js +2 -0
- package/src/components/input-clear/input-clear.vue +20 -3
- package/src/components/jumper-document/jumper-document.vue +16 -4
- package/src/components/jumper-index/jumper-index.vue +19 -4
- package/src/components/jumper-page/jumper-page.vue +3 -1
- package/src/components/layout-data-table/layout-data-table.vue +5 -5
- package/src/components/layout-directory/layout-directory.vue +4 -4
- package/src/components/layout-index/layout-index.vue +2 -2
- package/src/components/legend-item/legend-item.vue +15 -1
- package/src/components/log-message/log-message.vue +11 -1
- package/src/components/map/map.vue +20 -3
- package/src/components/mixins/focus-ring.vue +47 -0
- package/src/components/mixins/unique-id.js +17 -0
- package/src/components/modal/modal.vue +5 -2
- package/src/components/modal-header/modal-header.vue +43 -19
- package/src/components/multiselect-option/multiselect-option.vue +1 -1
- package/src/components/multiselect-search-token/multiselect-search-token.vue +33 -6
- package/src/components/multiselect-token/multiselect-token.vue +28 -3
- package/src/components/overlay/overlay.vue +6 -6
- package/src/components/pagination/pagination.vue +5 -5
- package/src/components/popover-list/popover-list.vue +5 -1
- package/src/components/popover-list-headline/popover-list-headline.vue +4 -1
- package/src/components/popover-list-item/popover-list-item.vue +27 -8
- package/src/components/progress/progress.vue +7 -1
- package/src/components/quicklink/quicklink.vue +29 -18
- package/src/components/radiobutton/radiobutton.vue +2 -2
- package/src/components/rating-favorability/rating-favorability.vue +5 -1
- package/src/components/rating-star-read/rating-star-read.vue +1 -1
- package/src/components/select/select.vue +12 -2
- package/src/components/select-text/select-text.vue +7 -2
- package/src/components/select-tile/select-tile.vue +26 -2
- package/src/components/separator/separator.vue +1 -1
- package/src/components/sequence-map/sequence-map.vue +1 -1
- package/src/components/sequence-map-button/sequence-map-button.vue +14 -2
- package/src/components/sidebar-footer/sidebar-footer.vue +2 -2
- package/src/components/sidebar-header/sidebar-header.vue +2 -2
- package/src/components/sortbutton/sortbutton.vue +22 -7
- package/src/components/sticker/sticker.vue +1 -1
- package/src/components/swatches-picker/swatches-picker.vue +28 -3
- package/src/components/switch/switch.vue +24 -8
- package/src/components/tab/tab.vue +16 -2
- package/src/components/tab-bar/tab-bar.vue +1 -1
- package/src/components/tab-button/tab-button.vue +61 -1
- package/src/components/tabs/tabs.vue +2 -1
- package/src/components/tag/tag.vue +17 -5
- package/src/components/tag-cloud/tag-cloud.vue +3 -1
- package/src/components/toast/toast.vue +18 -3
- package/src/components/toasts/toasts.vue +1 -1
- package/src/components/toolbar/toolbar.vue +1 -1
- package/src/components/transcript-state/transcript-state.vue +1 -1
- package/src/components/tree-list/tree-list-item.vue +77 -12
- package/src/components/tree-list/tree-list.vue +7 -1
- package/src/stories/Changelog.stories.mdx +8 -0
- package/src/stories/button/button.stories.js +7 -7
- package/src/stories/button-more/button-more.stories.js +8 -8
- package/src/stories/button-toolbar/button-toolbar.stories.js +5 -5
- package/src/stories/button-toolbar-icon/button-toolbar-icon.stories.js +6 -6
- package/src/stories/popover-list/popover-list.stories.js +7 -2
- package/src/stories/sortbutton/sortbutton.stories.js +4 -4
- package/src/stories/tag/tag.stories.js +7 -7
- package/src/stories/tree-list/tree-list.stories.js +3 -0
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
class="ecs-context-menu"
|
|
4
|
+
:class="opened ? ' opened': ''"
|
|
5
|
+
:id="elementId"
|
|
6
|
+
:style="[postionStyles]"
|
|
7
|
+
v-click-outside="onClickOutside"
|
|
8
|
+
>
|
|
9
|
+
<ul
|
|
10
|
+
role="menu"
|
|
11
|
+
aria-orientation="vertical"
|
|
12
|
+
tabindex="0"
|
|
13
|
+
@keydown.up.prevent="focusPrevious"
|
|
14
|
+
@keydown.down.prevent="focusNext"
|
|
15
|
+
ref="menu" id="my-menu">
|
|
4
16
|
<li
|
|
5
17
|
v-for="(option, index) in options"
|
|
6
18
|
:key="index"
|
|
7
19
|
@click.stop="optionClicked(option)"
|
|
20
|
+
:role="option.type === 'divider' ? 'separator' : 'menuitem'"
|
|
21
|
+
:tabindex="option.type === 'divider' || option.disabled ? '-1' : '0'"
|
|
22
|
+
:aria-disabled="option.disabled"
|
|
8
23
|
:class="[
|
|
9
24
|
option.type === 'divider' ? 'ecs-context-menu-divider' : 'ecs-context-menu-item',
|
|
10
25
|
option.type === 'danger' ? 'danger' : '',
|
|
@@ -13,6 +28,7 @@
|
|
|
13
28
|
>
|
|
14
29
|
<ecs-icon v-if="option.icon" :type="option.icon" size="20" />
|
|
15
30
|
<span v-if="option.type != 'divider'">{{ option.name}}</span>
|
|
31
|
+
<ecs-focus-ring :danger="option.type == 'danger'" />
|
|
16
32
|
</li>
|
|
17
33
|
</ul>
|
|
18
34
|
</div>
|
|
@@ -23,9 +39,10 @@ import Vue from "vue";
|
|
|
23
39
|
import vClickOutside from "v-click-outside"
|
|
24
40
|
Vue.use(vClickOutside)
|
|
25
41
|
import EcsIcon from '../icon/icon'
|
|
42
|
+
import EcsFocusRing from '../mixins/focus-ring'
|
|
26
43
|
|
|
27
44
|
export default {
|
|
28
|
-
components: { EcsIcon },
|
|
45
|
+
components: { EcsIcon, EcsFocusRing },
|
|
29
46
|
|
|
30
47
|
props: {
|
|
31
48
|
/** Unique String that acts as the id for the menu. */
|
|
@@ -97,6 +114,10 @@ export default {
|
|
|
97
114
|
this.top = event.pageY - 2
|
|
98
115
|
}
|
|
99
116
|
this.opened = true
|
|
117
|
+
|
|
118
|
+
this.$nextTick(() => {
|
|
119
|
+
this.$refs.menu.focus();
|
|
120
|
+
});
|
|
100
121
|
},
|
|
101
122
|
|
|
102
123
|
hideContextMenu() {
|
|
@@ -126,11 +147,62 @@ export default {
|
|
|
126
147
|
if (event.keyCode === 27) {
|
|
127
148
|
this.hideContextMenu()
|
|
128
149
|
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
// Focus the first menu item when the context menu opens
|
|
153
|
+
focusFirst() {
|
|
154
|
+
this.$refs.menu.children[0].focus();
|
|
155
|
+
},
|
|
156
|
+
// Focus the last menu item when the user presses the up arrow key on the first menu item
|
|
157
|
+
focusLast() {
|
|
158
|
+
const items = this.$refs.menu.children;
|
|
159
|
+
items[items.length - 1].focus();
|
|
160
|
+
},
|
|
161
|
+
// Focus the previous menu item when the user presses the up arrow key
|
|
162
|
+
focusPrevious(event) {
|
|
163
|
+
const items = this.$refs.menu.children;
|
|
164
|
+
const index = Array.prototype.indexOf.call(items, event.target);
|
|
165
|
+
if (index > 0) {
|
|
166
|
+
let prevIndex = index - 1;
|
|
167
|
+
while (prevIndex >= 0 && items[prevIndex].getAttribute('tabindex') === '-1') {
|
|
168
|
+
prevIndex--;
|
|
169
|
+
}
|
|
170
|
+
if (prevIndex >= 0) {
|
|
171
|
+
items[prevIndex].focus();
|
|
172
|
+
} else {
|
|
173
|
+
this.focusLast();
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
this.focusLast();
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
focusNext(event) {
|
|
181
|
+
const items = this.$refs.menu.children;
|
|
182
|
+
let index = Array.prototype.indexOf.call(items, event.target);
|
|
183
|
+
|
|
184
|
+
while (index < items.length - 1) {
|
|
185
|
+
index++;
|
|
186
|
+
|
|
187
|
+
if (items[index].getAttribute('tabindex') !== '-1') {
|
|
188
|
+
items[index].focus();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
this.focusFirst();
|
|
129
193
|
}
|
|
130
194
|
},
|
|
131
195
|
|
|
132
196
|
mounted() {
|
|
133
197
|
document.body.addEventListener("keyup", this.onEscKeyRelease)
|
|
198
|
+
|
|
199
|
+
this.$refs.menu.addEventListener("keydown", event => {
|
|
200
|
+
// Check if the Tab key was pressed
|
|
201
|
+
if (event.keyCode === 9) {
|
|
202
|
+
event.preventDefault();
|
|
203
|
+
this.focusFirst();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
134
206
|
},
|
|
135
207
|
|
|
136
208
|
beforeDestroy() {
|
|
@@ -172,13 +244,23 @@ export default {
|
|
|
172
244
|
line-height: $type-scale-3-line-height;
|
|
173
245
|
color: $color-gray-15;
|
|
174
246
|
cursor: pointer;
|
|
247
|
+
position: relative;
|
|
248
|
+
|
|
249
|
+
&:focus-visible{
|
|
250
|
+
z-index: 1;
|
|
251
|
+
|
|
252
|
+
.ecs-focus-ring{
|
|
253
|
+
display: block;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
175
256
|
|
|
176
257
|
.icon{
|
|
177
258
|
color: $color-gray-8;
|
|
178
259
|
}
|
|
179
260
|
|
|
180
261
|
&:not(.disabled){
|
|
181
|
-
&.danger:hover
|
|
262
|
+
&.danger:hover,
|
|
263
|
+
&.danger:focus{
|
|
182
264
|
background: $color-red-1;
|
|
183
265
|
|
|
184
266
|
.icon{
|
|
@@ -186,7 +268,8 @@ export default {
|
|
|
186
268
|
}
|
|
187
269
|
}
|
|
188
270
|
|
|
189
|
-
&:hover
|
|
271
|
+
&:hover,
|
|
272
|
+
&:focus{
|
|
190
273
|
background: $color-blue-1;
|
|
191
274
|
|
|
192
275
|
.icon{
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
<div @click="$emit('click')"
|
|
3
|
+
class="ecs-data-card"
|
|
4
|
+
role="listitem"
|
|
5
|
+
:aria-busy="loading"
|
|
6
|
+
:tabindex="hover ? '0' : '-1'"
|
|
7
|
+
:class="[
|
|
8
|
+
$slots.meta ? 'ecs-data-card-sml' : '',
|
|
9
|
+
$slots.actions ? 'ecs-data-card-hover' : '',
|
|
10
|
+
hover ? 'ecs-data-card-hover' : '',
|
|
11
|
+
active ? 'active' : '',
|
|
12
|
+
shadow ? 'shadow' : '',
|
|
13
|
+
isExpanded ? 'expanded' : '',
|
|
14
|
+
loading ? 'loading' : ''
|
|
15
|
+
]">
|
|
12
16
|
|
|
13
17
|
<div v-if="control && $slots.control" class="control">
|
|
14
18
|
<!-- @slot Slot for adding a control, such as a checkbox or radiobutton. -->
|
|
@@ -29,7 +33,18 @@
|
|
|
29
33
|
<!-- @slot Slot for adding action buttons. -->
|
|
30
34
|
<slot name="actions"></slot>
|
|
31
35
|
</div>
|
|
32
|
-
<ecs-button-table
|
|
36
|
+
<ecs-button-table
|
|
37
|
+
@click="isExpanded = !isExpanded"
|
|
38
|
+
v-if="expandable"
|
|
39
|
+
:aria-controls="expandId"
|
|
40
|
+
:aria-expanded="isExpanded ? 'true' : 'false'"
|
|
41
|
+
pale
|
|
42
|
+
chevron
|
|
43
|
+
size="sml"
|
|
44
|
+
:active="isExpanded"
|
|
45
|
+
:icon="expandIcon"
|
|
46
|
+
:label="expandLabel"
|
|
47
|
+
class="expand-button" />
|
|
33
48
|
</div>
|
|
34
49
|
</div>
|
|
35
50
|
<div v-if="$slots.meta" class="ecs-data-card-row">
|
|
@@ -39,13 +54,19 @@
|
|
|
39
54
|
<ecs-skeleton-loader v-if="loading" type="single" :width="skeletonWidth(15, 30)" />
|
|
40
55
|
</div>
|
|
41
56
|
</div>
|
|
42
|
-
<div
|
|
57
|
+
<div
|
|
58
|
+
v-if="$slots.expand"
|
|
59
|
+
v-show="isExpanded"
|
|
60
|
+
:id="expandId"
|
|
61
|
+
:aria-hidden="isExpanded ? 'false' : 'true'"
|
|
62
|
+
class="ecs-data-card-expand">
|
|
43
63
|
<div class="ecs-data-card-expand-inner">
|
|
44
64
|
<!-- @slot Slot for expandable content. -->
|
|
45
65
|
<slot name="expand"></slot>
|
|
46
66
|
</div>
|
|
47
67
|
</div>
|
|
48
68
|
</div>
|
|
69
|
+
<ecs-focus-ring v-if="hover" :inset="0" :radius="0" />
|
|
49
70
|
</div>
|
|
50
71
|
</template>
|
|
51
72
|
|
|
@@ -53,9 +74,12 @@
|
|
|
53
74
|
import EcsIcon from '../icon/icon'
|
|
54
75
|
import EcsSkeletonLoader from '../skeleton-loader/skeleton-loader'
|
|
55
76
|
import EcsButtonTable from '../button-table/button-table'
|
|
77
|
+
import EcsFocusRing from '../mixins/focus-ring'
|
|
78
|
+
import { uniqueIdMixin } from '../mixins/unique-id'
|
|
56
79
|
|
|
57
80
|
export default {
|
|
58
|
-
components: { EcsIcon, EcsSkeletonLoader, EcsButtonTable },
|
|
81
|
+
components: { EcsIcon, EcsSkeletonLoader, EcsButtonTable, EcsFocusRing },
|
|
82
|
+
mixins: [uniqueIdMixin],
|
|
59
83
|
|
|
60
84
|
props: {
|
|
61
85
|
/** If passed, an icon will be displayed in the data card. The icon prop must match a specific icons name. The list of available icon names can be found [here](https://github.com/everchron/ec-shards/tree/main/src/assets/icons). */
|
|
@@ -118,7 +142,8 @@
|
|
|
118
142
|
|
|
119
143
|
data () {
|
|
120
144
|
return {
|
|
121
|
-
isExpanded: this.expanded
|
|
145
|
+
isExpanded: this.expanded,
|
|
146
|
+
expandId: ''
|
|
122
147
|
}
|
|
123
148
|
},
|
|
124
149
|
|
|
@@ -126,6 +151,10 @@
|
|
|
126
151
|
skeletonWidth : function(min, max){
|
|
127
152
|
return Math.floor(Math.random() * (max - min + 1) + min)
|
|
128
153
|
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
created(){
|
|
157
|
+
this.expandId = this.generateUniqueId()
|
|
129
158
|
}
|
|
130
159
|
}
|
|
131
160
|
</script>
|
|
@@ -144,6 +173,15 @@
|
|
|
144
173
|
min-height: 46px;
|
|
145
174
|
user-select: none;
|
|
146
175
|
|
|
176
|
+
&:focus-visible{
|
|
177
|
+
z-index: 1;
|
|
178
|
+
outline: none;
|
|
179
|
+
|
|
180
|
+
.ecs-focus-ring{
|
|
181
|
+
display: block;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
147
185
|
&:before,
|
|
148
186
|
&:after{
|
|
149
187
|
content: "";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="ecs-data-grid-cell" :style="[fixedStyles]" :class="[fixedLeft ? 'fixed-left' : '', fixedLeftLast ? 'fixed-left-last' : '', fixedRight ? 'fixed-right' : '']">
|
|
2
|
+
<div class="ecs-data-grid-cell" :style="[fixedStyles]" :class="[fixedLeft ? 'fixed-left' : '', fixedLeftLast ? 'fixed-left-last' : '', fixedRight ? 'fixed-right' : '']" role="cell">
|
|
3
3
|
<div v-if="fixedRight" class="shadow" :class="fixedRight ? 'left' : ''" />
|
|
4
4
|
<div class="ecs-data-grid-cell-inner" :style="[widthStyles, paddingStyles]" :data-column="computedId" :data-test="computedId">
|
|
5
5
|
<div v-if="firstNonStaticCell" class="first-cell-spacer" />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-show="show" class="ecs-data-grid-group">
|
|
2
|
+
<div v-show="show" class="ecs-data-grid-group" role="tabpanel" :aria-labeled-by="ariaLabeledBy">
|
|
3
3
|
<template v-if="show">
|
|
4
4
|
<slot></slot>
|
|
5
5
|
</template>
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
show: {
|
|
14
14
|
type: Boolean,
|
|
15
15
|
default: false
|
|
16
|
+
},
|
|
17
|
+
/** Sets the aria-labeled-by attribute. Should match the ID of the tab button which controls this tab panel. */
|
|
18
|
+
ariaLabeledBy: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: true
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="ecs-data-grid-head-cell"
|
|
4
|
+
:style="[fixedStyles]"
|
|
5
|
+
:class="[fixedLeft ? 'fixed-left' : '', fixedLeftLast ? 'fixed-left-last' : '', fixedRight ? 'fixed-right' : '']"
|
|
6
|
+
role="columnheader"
|
|
7
|
+
:aria-sort="ariaSort"
|
|
8
|
+
:aria-label="icon ? name : false">
|
|
9
|
+
|
|
3
10
|
<div v-if="fixedRight" class="shadow" :class="fixedRight ? 'left' : ''" />
|
|
4
11
|
<div ref="resizer" class="ecs-data-grid-head-cell-inner" :style="[widthStyles, paddingStyles, resizeStyles]" :class="resizable ? 'resizable' : ''" :data-column="computedId" :data-headname="beingResizedName" :data-test="computedId">
|
|
5
12
|
<div v-if="firstNonStaticCell" class="first-cell-spacer" />
|
|
@@ -17,6 +24,7 @@
|
|
|
17
24
|
<path d="M3.99023 11.802L6.76923 14.722L9.54823 11.802" :stroke="sorting == 'desc' ? '#157EFB' : '#B9BCC2'" :stroke-width="sorting == 'desc' ? '1.5' : '1'" :opacity="sorting == 'desc' || sorting == 'none' ? '1' : '0.5'" stroke-linecap="round" stroke-linejoin="round"/>
|
|
18
25
|
<path d="M3.99023 8.722L6.76923 5.802L9.54823 8.722" :stroke="sorting == 'asc' ? '#157EFB' : '#B9BCC2'" :stroke-width="sorting == 'asc' ? '1.5' : '1'" :opacity="sorting == 'asc' || sorting == 'none' ? '1' : '0.5'" stroke-linecap="round" stroke-linejoin="round"/>
|
|
19
26
|
</svg>
|
|
27
|
+
<ecs-focus-ring />
|
|
20
28
|
</button>
|
|
21
29
|
</div>
|
|
22
30
|
<div v-if="fixedLeftLast" class="shadow" :class="fixedLeftLast ? 'right' : ''" />
|
|
@@ -26,10 +34,13 @@
|
|
|
26
34
|
<script>
|
|
27
35
|
import EcsIcon from '../icon/icon'
|
|
28
36
|
import EcsSelect from '../select/select'
|
|
37
|
+
import EcsFocusRing from '../mixins/focus-ring'
|
|
29
38
|
|
|
30
39
|
export default {
|
|
31
40
|
components: {
|
|
32
|
-
EcsIcon,
|
|
41
|
+
EcsIcon,
|
|
42
|
+
EcsSelect,
|
|
43
|
+
EcsFocusRing
|
|
33
44
|
},
|
|
34
45
|
|
|
35
46
|
props: {
|
|
@@ -179,6 +190,15 @@
|
|
|
179
190
|
|
|
180
191
|
beingResizedName(){
|
|
181
192
|
return this.beingResized ? this.uniformName + '-noresize' : this.uniformName
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
ariaSort(){
|
|
196
|
+
switch (this.sorting) {
|
|
197
|
+
case 'asc':
|
|
198
|
+
return 'ascending';
|
|
199
|
+
case 'desc':
|
|
200
|
+
return 'descending';
|
|
201
|
+
}
|
|
182
202
|
}
|
|
183
203
|
},
|
|
184
204
|
|
|
@@ -341,7 +361,17 @@
|
|
|
341
361
|
background: none;
|
|
342
362
|
padding: 0 1px;
|
|
343
363
|
height: 24px;
|
|
364
|
+
position: relative;
|
|
344
365
|
cursor: pointer;
|
|
366
|
+
|
|
367
|
+
&:focus-visible{
|
|
368
|
+
z-index: 1;
|
|
369
|
+
outline: none;
|
|
370
|
+
|
|
371
|
+
.ecs-focus-ring{
|
|
372
|
+
display: block;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
345
375
|
}
|
|
346
376
|
|
|
347
377
|
.shadow{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="ecs-data-grid-row" :class="state" ref="grid_row">
|
|
2
|
+
<div class="ecs-data-grid-row" :class="state" ref="grid_row" role="row">
|
|
3
3
|
<div v-if="state == 'droppable'" @click="handleDropzoneClick" class="ecs-data-grid-row-drop-zone" />
|
|
4
4
|
|
|
5
5
|
<!-- @slot All of the row's cells go here. There should **never** be any other child component other than EcsDataGridCell be used. -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-on:scroll="tableScroll" class="ecs-data-grid scrollbar" :class="$slots.empty
|
|
3
|
-
<div class="ecs-data-grid-head" :class="sidebarOverlay ? 'sidebar-space' : ''">
|
|
2
|
+
<div v-on:scroll="tableScroll" class="ecs-data-grid scrollbar" :class="$slots.empty ? 'empty' : ''" ref="dataGridScroller" role="table">
|
|
3
|
+
<div class="ecs-data-grid-head" :class="sidebarOverlay ? 'sidebar-space' : ''" role="row">
|
|
4
4
|
<!-- @slot Slot for the table head row cells. -->
|
|
5
5
|
<slot name="head"></slot>
|
|
6
6
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div class="ecs-data-list-item"
|
|
3
|
+
<div class="ecs-data-list-item" role="listitem"
|
|
4
4
|
:class="[
|
|
5
5
|
small ? 'ecs-data-list-item-sml' : '',
|
|
6
6
|
full ? 'ecs-data-list-item-full' : '',
|
|
@@ -14,21 +14,33 @@
|
|
|
14
14
|
v-if="$slots.collapse"
|
|
15
15
|
class="ecs-data-list-expand-button"
|
|
16
16
|
:active="isVisible"
|
|
17
|
+
:aria-controls="expandId"
|
|
18
|
+
:aria-expanded="isVisible ? 'true' : 'false'"
|
|
17
19
|
@click="toggleCollapse" />
|
|
18
20
|
</div>
|
|
19
21
|
<div class="ecs-data-list-data"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
:aria-busy="loading"
|
|
23
|
+
:class="[
|
|
24
|
+
escape ? 'ecs-data-list-data-escape' : '',
|
|
25
|
+
error ? 'ecs-data-list-data-error' : '',
|
|
26
|
+
typeClass
|
|
27
|
+
]">
|
|
25
28
|
<slot v-if="!loading"></slot>
|
|
26
29
|
<ecs-skeleton-loader v-else type="single" :width="skeletonWidth(25, 70)" />
|
|
27
|
-
<div v-if="progress"
|
|
30
|
+
<div v-if="progress"
|
|
31
|
+
class="progress"
|
|
32
|
+
role="progressbar"
|
|
33
|
+
:style="{ width: progress + '%' }"
|
|
34
|
+
:aria-valuenow="progress">
|
|
35
|
+
</div>
|
|
28
36
|
</div>
|
|
29
37
|
</div>
|
|
30
38
|
|
|
31
|
-
<div v-if="$slots.collapse"
|
|
39
|
+
<div v-if="$slots.collapse"
|
|
40
|
+
:class="isVisible ? 'collapse-show' : 'collapse-hide'"
|
|
41
|
+
role="list"
|
|
42
|
+
:id="expandId"
|
|
43
|
+
:aria-hidden="isVisible ? 'false' : 'true'">
|
|
32
44
|
<!-- @slot Slot for expandable content. -->
|
|
33
45
|
<slot name="collapse"></slot>
|
|
34
46
|
</div>
|
|
@@ -38,9 +50,11 @@
|
|
|
38
50
|
<script>
|
|
39
51
|
import EcsButtonMore from '../button-more/button-more'
|
|
40
52
|
import EcsSkeletonLoader from '../skeleton-loader/skeleton-loader'
|
|
53
|
+
import { uniqueIdMixin } from '../mixins/unique-id'
|
|
41
54
|
|
|
42
55
|
export default {
|
|
43
56
|
components: { EcsButtonMore, EcsSkeletonLoader },
|
|
57
|
+
mixins: [uniqueIdMixin],
|
|
44
58
|
|
|
45
59
|
props: {
|
|
46
60
|
/** The label that shows up to the left of the list item. Usually describes the content to the left, e.g.: "Type", "Profiles", etc. */
|
|
@@ -106,7 +120,8 @@
|
|
|
106
120
|
|
|
107
121
|
data () {
|
|
108
122
|
return {
|
|
109
|
-
isVisible: this.visible
|
|
123
|
+
isVisible: this.visible,
|
|
124
|
+
expandId: ''
|
|
110
125
|
}
|
|
111
126
|
},
|
|
112
127
|
|
|
@@ -138,6 +153,10 @@
|
|
|
138
153
|
visible(){
|
|
139
154
|
this.isVisible = this.visible
|
|
140
155
|
}
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
created() {
|
|
159
|
+
this.expandId = this.generateUniqueId()
|
|
141
160
|
}
|
|
142
161
|
}
|
|
143
162
|
</script>
|
|
@@ -83,14 +83,17 @@
|
|
|
83
83
|
display: inline-block;
|
|
84
84
|
position: relative;
|
|
85
85
|
z-index: 1;
|
|
86
|
+
padding: 2px 4px;
|
|
87
|
+
border-radius: $border-radius-small;
|
|
88
|
+
|
|
89
|
+
&:focus-visible{
|
|
90
|
+
box-shadow: 0 0 0 2px $color-blue-9;
|
|
91
|
+
}
|
|
86
92
|
|
|
87
93
|
&:after{
|
|
88
94
|
content: "";
|
|
89
95
|
position: absolute;
|
|
90
|
-
|
|
91
|
-
left: -4px;
|
|
92
|
-
bottom: -2px;
|
|
93
|
-
right: -4px;
|
|
96
|
+
inset: 0;
|
|
94
97
|
opacity: 0;
|
|
95
98
|
transform: scale(.6);
|
|
96
99
|
transition: opacity .15s ease-in-out, transform .3s cubic-bezier(0.3, 0.76, 0.27, 1.5);
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div @click="handleClick"
|
|
2
|
+
<div @click="handleClick"
|
|
3
|
+
class="ecs-dropdown"
|
|
4
|
+
:class="[sizeClass, disabled ? 'disabled' : '', inline ? 'inline' : '']"
|
|
5
|
+
role="button"
|
|
6
|
+
:aria-disabled="disabled"
|
|
7
|
+
:tabindex="disabled ? '-1' : '0'">
|
|
3
8
|
<div class="ecs-dropdown-inner">
|
|
4
9
|
<slot></slot>
|
|
5
10
|
</div>
|
|
11
|
+
<ecs-focus-ring :inset="-5" />
|
|
6
12
|
</div>
|
|
7
13
|
</template>
|
|
8
14
|
|
|
9
15
|
<script>
|
|
16
|
+
import EcsFocusRing from '../mixins/focus-ring'
|
|
17
|
+
|
|
10
18
|
export default {
|
|
19
|
+
components: {
|
|
20
|
+
EcsFocusRing
|
|
21
|
+
},
|
|
22
|
+
|
|
11
23
|
props: {
|
|
12
24
|
/** Sets the size of the dropdown component. */
|
|
13
25
|
size: {
|
|
@@ -60,10 +72,20 @@ export default {
|
|
|
60
72
|
cursor: pointer;
|
|
61
73
|
user-select: none;
|
|
62
74
|
|
|
75
|
+
&:focus-visible{
|
|
76
|
+
z-index: 1;
|
|
77
|
+
outline: none;
|
|
78
|
+
|
|
79
|
+
.ecs-focus-ring{
|
|
80
|
+
display: block;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
&:hover,
|
|
64
85
|
&:focus{
|
|
65
86
|
border-color: darken(rgba($color-gray-8, .4), 4%);
|
|
66
87
|
box-shadow: 0 1px 1px rgba($color-gray-8, .1);
|
|
88
|
+
outline: none;
|
|
67
89
|
|
|
68
90
|
&:after{
|
|
69
91
|
opacity: .5;
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
@dragenter="dragging=true"
|
|
9
9
|
@dragleave="dragging=false"
|
|
10
10
|
@drop.prevent="drop"
|
|
11
|
-
@dragover.prevent
|
|
11
|
+
@dragover.prevent
|
|
12
|
+
:aria-busy="loading || progress"
|
|
13
|
+
:aria-invalid="error">
|
|
12
14
|
|
|
13
15
|
<input @change="change" type="file" :multiple="multiple" ref="file" />
|
|
14
16
|
|
|
@@ -16,7 +18,7 @@
|
|
|
16
18
|
<ecs-skeleton-loader v-if="initializing" type="single" :width="100" class="ecs-dropzone-skeleton" />
|
|
17
19
|
<div v-else>
|
|
18
20
|
<template v-if="!$slots.customlabel">
|
|
19
|
-
Drag and drop your {{ fileTypeLabel }} or <i @click="
|
|
21
|
+
Drag and drop your {{ fileTypeLabel }} or <i @click="browseFile" @keydown.enter="browseFile" tabindex="0">browse<ecs-focus-ring /></i> to upload.
|
|
20
22
|
</template>
|
|
21
23
|
<div v-if="$slots.customlabel">
|
|
22
24
|
<!-- @slot Slot for a custom main label. Note: this will replace the file selector button as well as drag & drop label. Should only be used for states that do not require a drop action, such as active virus scanning. -->
|
|
@@ -40,13 +42,15 @@
|
|
|
40
42
|
import EcsSkeletonLoader from '../skeleton-loader/skeleton-loader'
|
|
41
43
|
import EcsProgress from '../progress/progress'
|
|
42
44
|
import EcsButton from '../button/button'
|
|
45
|
+
import EcsFocusRing from '../mixins/focus-ring'
|
|
43
46
|
|
|
44
47
|
export default {
|
|
45
48
|
components: {
|
|
46
49
|
EcsEmptyState,
|
|
47
50
|
EcsSkeletonLoader,
|
|
48
51
|
EcsProgress,
|
|
49
|
-
EcsButton
|
|
52
|
+
EcsButton,
|
|
53
|
+
EcsFocusRing
|
|
50
54
|
},
|
|
51
55
|
|
|
52
56
|
props: {
|
|
@@ -149,6 +153,10 @@
|
|
|
149
153
|
},
|
|
150
154
|
|
|
151
155
|
methods: {
|
|
156
|
+
browseFile() {
|
|
157
|
+
this.$refs.file.click()
|
|
158
|
+
},
|
|
159
|
+
|
|
152
160
|
drop({ dataTransfer }) {
|
|
153
161
|
this.dragging = false
|
|
154
162
|
const files = dataTransfer.files
|
|
@@ -220,6 +228,16 @@
|
|
|
220
228
|
font-weight: $font-weight-medium;
|
|
221
229
|
font-style: normal;
|
|
222
230
|
cursor: pointer;
|
|
231
|
+
position: relative;
|
|
232
|
+
|
|
233
|
+
&:focus-visible{
|
|
234
|
+
z-index: 1;
|
|
235
|
+
outline: none;
|
|
236
|
+
|
|
237
|
+
.ecs-focus-ring{
|
|
238
|
+
display: block;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
223
241
|
}
|
|
224
242
|
|
|
225
243
|
&-skeleton{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="ecs-empty-state">
|
|
2
|
+
<div class="ecs-empty-state" :aria-busy="type == 'loading'">
|
|
3
3
|
<ecs-icon v-if="type!='loading'" :type="type" :color="iconColor" :size="iconSize" />
|
|
4
4
|
<div v-else class="ecs-empty-state-loading" />
|
|
5
5
|
<div v-if="type!='loading'" class="ecs-empty-state-message" :class="size">
|