ketekny-ui-kit 1.0.105 → 1.0.107
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/package.json +1 -1
- package/src/style/style.css +9 -0
- package/src/ui/componentDescription.vue +13 -3
- package/src/ui/componentShowcase.vue +9 -5
- package/src/ui/kArrayList.vue +1 -1
- package/src/ui/kCheckbox.vue +3 -1
- package/src/ui/kDialog.vue +35 -4
- package/src/ui/kEditor.vue +2 -2
- package/src/ui/kInputDialog.vue +1 -1
- package/src/ui/kList.vue +1 -1
- package/src/ui/kOptionGroup.vue +3 -6
- package/src/ui/kSearch.vue +1 -1
- package/src/ui/kSelect.vue +3 -3
- package/src/ui/kSelectButton.vue +1 -1
- package/src/ui/kTable.vue +10 -3
- package/src/ui/kTags.vue +1 -1
- package/src/ui/kTextArea.vue +2 -2
- package/src/ui/kToggle.vue +8 -7
- package/src/ui/kUploader.vue +2 -2
- package/src/ui/themes/kButton.theme.js +1 -1
- package/src/ui/themes/kInput.theme.js +2 -2
package/package.json
CHANGED
package/src/style/style.css
CHANGED
|
@@ -20,4 +20,13 @@ body {
|
|
|
20
20
|
html {
|
|
21
21
|
font-size: 14px;
|
|
22
22
|
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@media (prefers-reduced-motion: reduce) {
|
|
26
|
+
*, *::before, *::after {
|
|
27
|
+
animation-duration: 0.01ms !important;
|
|
28
|
+
animation-iteration-count: 1 !important;
|
|
29
|
+
transition-duration: 0.01ms !important;
|
|
30
|
+
scroll-behavior: auto !important;
|
|
31
|
+
}
|
|
23
32
|
}
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
<div class="flex items-center justify-between px-4 py-3 border-b cp-border cp-muted-50">
|
|
4
4
|
<h2 class="text-[15px] font-semibold cp-text">{{ componentName }} Description</h2>
|
|
5
5
|
|
|
6
|
-
<div class="flex items-center gap-1">
|
|
6
|
+
<div class="flex items-center gap-1" role="tablist">
|
|
7
7
|
<button
|
|
8
8
|
v-for="tab in tabs"
|
|
9
9
|
:key="tab.id"
|
|
10
|
+
type="button"
|
|
11
|
+
role="tab"
|
|
12
|
+
:aria-selected="activeTab === tab.id"
|
|
10
13
|
@click="activeTab = tab.id"
|
|
11
14
|
:class="['px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors', activeTab === tab.id ? 'cp-tab-active' : 'cp-tab']">
|
|
12
15
|
{{ tab.label }}
|
|
@@ -15,13 +18,14 @@
|
|
|
15
18
|
</div>
|
|
16
19
|
|
|
17
20
|
<div class="p-4">
|
|
18
|
-
<div v-show="activeTab === 'props'">
|
|
21
|
+
<div v-show="activeTab === 'props'" role="tabpanel">
|
|
19
22
|
<div v-if="props.length > 0" class="overflow-x-auto">
|
|
20
23
|
<table class="w-full text-[13px]">
|
|
21
24
|
<thead>
|
|
22
25
|
<tr class="border-b cp-border">
|
|
23
26
|
<th class="px-4 py-3 font-semibold text-left cp-text">Name</th>
|
|
24
27
|
<th class="px-4 py-3 font-semibold text-left cp-text">Type</th>
|
|
28
|
+
<th class="px-4 py-3 font-semibold text-left cp-text">Values</th>
|
|
25
29
|
<th class="px-4 py-3 font-semibold text-left cp-text">Default</th>
|
|
26
30
|
<th class="px-4 py-3 font-semibold text-left cp-text">Description</th>
|
|
27
31
|
</tr>
|
|
@@ -33,6 +37,12 @@
|
|
|
33
37
|
<code class="text-[13px] font-mono px-1.5 py-0.5 rounded cp-chip cp-chip-text">{{ prop.name }}</code>
|
|
34
38
|
</td>
|
|
35
39
|
<td class="px-4 py-3"><span class="font-mono text-[13px] text-blue-600">{{ prop.type }}</span></td>
|
|
40
|
+
<td class="px-4 py-3">
|
|
41
|
+
<div v-if="prop.values && prop.values.length" class="flex flex-wrap gap-1">
|
|
42
|
+
<code v-for="v in prop.values" :key="v" class="text-[12px] font-mono px-1.5 py-0.5 rounded cp-chip cp-chip-text">{{ v }}</code>
|
|
43
|
+
</div>
|
|
44
|
+
<span v-else class="cp-text-muted">-</span>
|
|
45
|
+
</td>
|
|
36
46
|
<td class="px-4 py-3">
|
|
37
47
|
<code v-if="prop.default !== undefined" class="font-mono text-[13px] text-slate-700">{{ prop.default }}</code>
|
|
38
48
|
<span v-else class="cp-text-muted">-</span>
|
|
@@ -48,7 +58,7 @@
|
|
|
48
58
|
</div>
|
|
49
59
|
</div>
|
|
50
60
|
|
|
51
|
-
<div v-show="activeTab === 'slots'">
|
|
61
|
+
<div v-show="activeTab === 'slots'" role="tabpanel">
|
|
52
62
|
<div v-if="slots.length > 0" class="overflow-x-auto">
|
|
53
63
|
<table class="w-full text-[13px]">
|
|
54
64
|
<thead>
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
<div class="flex items-center justify-between px-4 py-3 border-b cp-border cp-muted-50">
|
|
4
4
|
<h2 class="text-[15px] font-semibold cp-text">{{ componentName }} Preview</h2>
|
|
5
5
|
|
|
6
|
-
<div class="flex items-center gap-1">
|
|
6
|
+
<div class="flex items-center gap-1" role="tablist">
|
|
7
7
|
<button
|
|
8
8
|
v-for="tab in tabs"
|
|
9
9
|
:key="tab.id"
|
|
10
|
+
type="button"
|
|
11
|
+
role="tab"
|
|
12
|
+
:aria-selected="activeTab === tab.id"
|
|
10
13
|
@click="activeTab = tab.id"
|
|
11
14
|
:class="['px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors', activeTab === tab.id ? 'cp-tab-active' : 'cp-tab']">
|
|
12
15
|
{{ tab.label }}
|
|
@@ -15,13 +18,14 @@
|
|
|
15
18
|
</div>
|
|
16
19
|
|
|
17
20
|
<div class="p-4">
|
|
18
|
-
<div v-show="activeTab === 'preview'" class="min-h-[120px] rounded-lg p-6 border cp-muted-30 cp-border-50">
|
|
21
|
+
<div v-show="activeTab === 'preview'" role="tabpanel" class="min-h-[120px] rounded-lg p-6 border cp-muted-30 cp-border-50">
|
|
19
22
|
<div class="flex justify-end mb-4">
|
|
20
23
|
<div class="inline-flex p-1 rounded-md cp-muted-50">
|
|
21
24
|
<button
|
|
22
25
|
v-for="vp in previewViewports"
|
|
23
26
|
:key="vp.id"
|
|
24
27
|
@click="activeViewport = vp.id"
|
|
28
|
+
:aria-pressed="activeViewport === vp.id"
|
|
25
29
|
:class="['px-3 py-1.5 text-[13px] font-semibold rounded-md transition-colors', activeViewport === vp.id ? 'cp-tab-active' : 'cp-tab']">
|
|
26
30
|
{{ vp.label }}
|
|
27
31
|
</button>
|
|
@@ -35,9 +39,9 @@
|
|
|
35
39
|
</div>
|
|
36
40
|
</div>
|
|
37
41
|
|
|
38
|
-
<div v-show="activeTab === 'code'" class="relative">
|
|
42
|
+
<div v-show="activeTab === 'code'" role="tabpanel" class="relative">
|
|
39
43
|
<div class="absolute z-10 top-3 right-3">
|
|
40
|
-
<button @click="copyCode" class="flex items-center gap-1.5 px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors cp-chip cp-chip-hover cp-chip-text">
|
|
44
|
+
<button @click="copyCode" type="button" aria-label="Copy code" class="flex items-center gap-1.5 px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors cp-chip cp-chip-hover cp-chip-text">
|
|
41
45
|
<svg
|
|
42
46
|
v-if="!copied"
|
|
43
47
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -68,7 +72,7 @@
|
|
|
68
72
|
<polyline points="20 6 9 17 4 12" />
|
|
69
73
|
</svg>
|
|
70
74
|
|
|
71
|
-
{{ copied ? "Copied!" : "Copy" }}
|
|
75
|
+
<span aria-live="polite">{{ copied ? "Copied!" : "Copy" }}</span>
|
|
72
76
|
</button>
|
|
73
77
|
</div>
|
|
74
78
|
|
package/src/ui/kArrayList.vue
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
:disabled="disabled"
|
|
14
14
|
:class="[
|
|
15
15
|
'block w-full p-3 transition border border-gray-300 shadow-sm outline-none rounded-xl dark:border-slate-600 dark:text-slate-100 dark:placeholder-slate-500',
|
|
16
|
-
disabled ? 'bg-gray-100 text-gray-400 cursor-not-allowed dark:bg-slate-900 dark:text-slate-500' : 'bg-white focus:border-primary focus:ring-2 focus:ring-primary/20 dark:bg-slate-800',
|
|
16
|
+
disabled ? 'bg-gray-100 text-gray-400 cursor-not-allowed dark:bg-slate-900 dark:text-slate-500' : 'bg-white focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-primary/20 dark:bg-slate-800',
|
|
17
17
|
]"
|
|
18
18
|
@focus="isFocused = true"
|
|
19
19
|
@blur="isFocused = false"
|
package/src/ui/kCheckbox.vue
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
3
|
type="button"
|
|
4
|
+
role="checkbox"
|
|
5
|
+
:aria-checked="isActive"
|
|
4
6
|
class="admin-checkbox flex w-full items-center gap-2.5 rounded-2xl px-3 py-2 transition"
|
|
5
7
|
:class="[themeTextClass, isActive ? activeTextClass : inactiveTextClass, combinedContainerClass]"
|
|
6
8
|
:title="hoverCaption"
|
|
@@ -114,7 +116,7 @@ export default {
|
|
|
114
116
|
return this.theme === 'dark' ? 'text-slate-300' : 'text-slate-500'
|
|
115
117
|
},
|
|
116
118
|
themeActiveClass() {
|
|
117
|
-
return this.theme === 'dark' ? 'bg-
|
|
119
|
+
return this.theme === 'dark' ? 'bg-primary/90 text-white' : 'bg-primary text-white'
|
|
118
120
|
},
|
|
119
121
|
themeInactiveClass() {
|
|
120
122
|
return this.theme === 'dark' ? 'bg-white/10 text-transparent' : 'bg-slate-200 text-transparent'
|
package/src/ui/kDialog.vue
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<transition name="dialog">
|
|
9
9
|
<div
|
|
10
10
|
ref="dialogPanel"
|
|
11
|
-
class="relative bg-white dark:bg-
|
|
11
|
+
class="relative bg-white dark:bg-slate-900 shadow-lg overflow-hidden rounded-2xl flex flex-col max-h-[calc(100dvh-1rem)] sm:max-h-[90vh] m-2 sm:m-4"
|
|
12
12
|
:class="dialogClasses"
|
|
13
13
|
:role="'dialog'"
|
|
14
14
|
:aria-modal="'true'"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
<div class="flex-1" />
|
|
23
23
|
<button
|
|
24
24
|
type="button"
|
|
25
|
-
class="p-1.5 rounded-md text-
|
|
25
|
+
class="p-1.5 rounded-md text-slate-400 hover:text-primary dark:text-slate-500 dark:hover:text-primary hover:bg-primary/10 transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
26
26
|
aria-label="Close dialog"
|
|
27
27
|
@click="close"
|
|
28
28
|
>
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
<!-- Footer -->
|
|
44
44
|
<div
|
|
45
45
|
v-if="$slots.footer"
|
|
46
|
-
class="flex flex-col-reverse gap-2 p-3 border-t shrink-0 border-
|
|
46
|
+
class="flex flex-col-reverse gap-2 p-3 border-t shrink-0 border-slate-200 dark:border-slate-800 sm:flex-row sm:justify-end sm:p-4"
|
|
47
47
|
>
|
|
48
48
|
<slot name="footer"></slot>
|
|
49
49
|
</div>
|
|
@@ -130,10 +130,41 @@ export default {
|
|
|
130
130
|
this.close()
|
|
131
131
|
},
|
|
132
132
|
handleKeydown(event) {
|
|
133
|
-
if (!this.visible
|
|
133
|
+
if (!this.visible) return
|
|
134
134
|
if (event.key === 'Escape') {
|
|
135
|
+
if (!this.closeOnEsc) return
|
|
135
136
|
event.preventDefault()
|
|
136
137
|
this.close()
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
if (event.key === 'Tab') {
|
|
141
|
+
this.trapFocus(event)
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
trapFocus(event) {
|
|
145
|
+
const panel = this.$refs.dialogPanel
|
|
146
|
+
if (!panel) return
|
|
147
|
+
const focusable = panel.querySelectorAll(
|
|
148
|
+
'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
|
|
149
|
+
)
|
|
150
|
+
if (focusable.length === 0) {
|
|
151
|
+
event.preventDefault()
|
|
152
|
+
panel.focus()
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
const first = focusable[0]
|
|
156
|
+
const last = focusable[focusable.length - 1]
|
|
157
|
+
const active = document.activeElement
|
|
158
|
+
if (event.shiftKey) {
|
|
159
|
+
if (active === first || active === panel || !panel.contains(active)) {
|
|
160
|
+
event.preventDefault()
|
|
161
|
+
last.focus()
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
if (active === last) {
|
|
165
|
+
event.preventDefault()
|
|
166
|
+
first.focus()
|
|
167
|
+
}
|
|
137
168
|
}
|
|
138
169
|
},
|
|
139
170
|
lockBodyScroll() {
|
package/src/ui/kEditor.vue
CHANGED
|
@@ -66,8 +66,8 @@ export default {
|
|
|
66
66
|
data() {
|
|
67
67
|
return {
|
|
68
68
|
defaultStyle:
|
|
69
|
-
"w-full px-3 py-2 border rounded-b-lg transition shadow-sm focus:outline-none focus:ring-2 focus:ring-primary/20 min-h-[150px] focus:border-primary bg-white placeholder-gray-400 !list-disc !list-inside prose dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500",
|
|
70
|
-
errorStyle: "border-red-500 focus:ring focus:ring-red-300 dark:border-rose-500 dark:focus:ring-rose-500/20",
|
|
69
|
+
"w-full px-3 py-2 border rounded-b-lg transition shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/20 min-h-[150px] focus-visible:border-primary bg-white placeholder-gray-400 !list-disc !list-inside prose dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500",
|
|
70
|
+
errorStyle: "border-red-500 focus-visible:ring focus-visible:ring-red-300 dark:border-rose-500 dark:focus-visible:ring-rose-500/20",
|
|
71
71
|
disabledStyle: "!bg-gray-100 !text-gray-400 !cursor-not-allowed editor pointer-events-none select-none dark:!bg-slate-900 dark:!text-slate-500",
|
|
72
72
|
isFocused: false,
|
|
73
73
|
pendingModelValue: null,
|
package/src/ui/kInputDialog.vue
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
:type="inputType"
|
|
15
15
|
v-model="value"
|
|
16
16
|
:placeholder="placeholder"
|
|
17
|
-
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500 dark:focus:ring-indigo-400"
|
|
17
|
+
class="w-full px-3 py-2 border border-gray-300 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500 dark:focus-visible:ring-indigo-400"
|
|
18
18
|
:disabled="loading"
|
|
19
19
|
ref="inputEl"
|
|
20
20
|
@keyup.enter="confirm"
|
package/src/ui/kList.vue
CHANGED
|
@@ -122,7 +122,7 @@ export default {
|
|
|
122
122
|
},
|
|
123
123
|
entryClass(stat) {
|
|
124
124
|
return stat.action
|
|
125
|
-
? 'cursor-pointer transition hover:border-primary/40 hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-primary/20 dark:hover:bg-slate-700/70'
|
|
125
|
+
? 'cursor-pointer transition hover:border-primary/40 hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/20 dark:hover:bg-slate-700/70'
|
|
126
126
|
: ''
|
|
127
127
|
},
|
|
128
128
|
handleAction(stat, index) {
|
package/src/ui/kOptionGroup.vue
CHANGED
|
@@ -240,7 +240,7 @@ export default {
|
|
|
240
240
|
const pieces = ["items-center gap-3 rounded-lg border px-3 py-2.5 transition"];
|
|
241
241
|
|
|
242
242
|
if (selected) {
|
|
243
|
-
pieces.push(styles.selBg);
|
|
243
|
+
pieces.push(styles.selBg, styles.text);
|
|
244
244
|
if (colored) pieces.push(`border-l-2 ${styles.accent}`);
|
|
245
245
|
} else if (colored) {
|
|
246
246
|
pieces.push(styles.text);
|
|
@@ -255,11 +255,8 @@ export default {
|
|
|
255
255
|
|
|
256
256
|
if (this.isTableVariant) {
|
|
257
257
|
if (this.isSelected(option)) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return `items-center gap-3 border-b border-slate-200 px-3 py-3 last:border-b-0 dark:border-slate-700 ${styles.softBg} ${styles.text}`;
|
|
261
|
-
}
|
|
262
|
-
return "items-center gap-3 border-b border-slate-200 bg-primary/10 px-3 py-3 text-primary last:border-b-0 dark:border-slate-700 dark:bg-primary/15 dark:text-slate-100";
|
|
258
|
+
const styles = this.intentStyles(option);
|
|
259
|
+
return `items-center gap-3 border-b border-slate-200 px-3 py-3 last:border-b-0 dark:border-slate-700 ${styles.softBg} ${styles.text}`;
|
|
263
260
|
}
|
|
264
261
|
return "items-center gap-3 border-b border-slate-200 bg-white px-3 py-3 text-gray-700 hover:bg-slate-50 last:border-b-0 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:bg-slate-800";
|
|
265
262
|
}
|
package/src/ui/kSearch.vue
CHANGED
|
@@ -39,7 +39,7 @@ export default {
|
|
|
39
39
|
data() {
|
|
40
40
|
return {
|
|
41
41
|
inputId: `ksearch-${Math.random().toString(36).slice(2, 10)}`,
|
|
42
|
-
defaultStyle: "w-full px-3 py-2 border rounded-lg transition shadow-sm focus:outline-none text-gray-700 focus:ring-2 focus:ring-primary/20 focus:border-primary bg-white placeholder-gray-400 dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500",
|
|
42
|
+
defaultStyle: "w-full px-3 py-2 border rounded-lg transition shadow-sm focus-visible:outline-none text-gray-700 focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:border-primary bg-white placeholder-gray-400 dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500",
|
|
43
43
|
disabledStyle: "bg-gray-100 text-gray-400 cursor-not-allowed dark:bg-slate-900 dark:text-slate-500",
|
|
44
44
|
|
|
45
45
|
localValue: this.modelValue,
|
package/src/ui/kSelect.vue
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
type="text"
|
|
49
49
|
v-model="searchQuery"
|
|
50
50
|
placeholder="Αναζήτηση..."
|
|
51
|
-
class="w-full pl-9 pr-3 py-2 text-base border border-gray-200 rounded-lg focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20 transition-colors placeholder-gray-400 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500"
|
|
51
|
+
class="w-full pl-9 pr-3 py-2 text-base border border-gray-200 rounded-lg focus-visible:outline-none focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-primary/20 transition-colors placeholder-gray-400 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500"
|
|
52
52
|
role="searchbox"
|
|
53
53
|
aria-label="Search options"
|
|
54
54
|
@keydown="handleSearchKeydown"
|
|
@@ -137,8 +137,8 @@ const searchQuery = ref("");
|
|
|
137
137
|
const searchInput = ref(null);
|
|
138
138
|
const viewportRef = ref(null);
|
|
139
139
|
const generatedId = `select-${Math.random().toString(36).substr(2, 9)}`;
|
|
140
|
-
const defaultStyle = "w-full px-3 py-2 border rounded-lg transition shadow-sm focus:outline-none text-gray-700 focus:ring-2 focus:ring-primary/20 focus:border-primary bg-white placeholder-gray-400 dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500";
|
|
141
|
-
const errorStyle = "border-red-500 focus:ring focus:ring-red-300 dark:border-rose-500 dark:focus:ring-rose-500/20";
|
|
140
|
+
const defaultStyle = "w-full px-3 py-2 border rounded-lg transition shadow-sm focus-visible:outline-none text-gray-700 focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:border-primary bg-white placeholder-gray-400 dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500";
|
|
141
|
+
const errorStyle = "border-red-500 focus-visible:ring focus-visible:ring-red-300 dark:border-rose-500 dark:focus-visible:ring-rose-500/20";
|
|
142
142
|
const disabledStyle = "!bg-gray-100 !text-gray-400 !cursor-not-allowed dark:!bg-slate-900 dark:!text-slate-500";
|
|
143
143
|
|
|
144
144
|
function normalizeDropdownHeight(value) {
|
package/src/ui/kSelectButton.vue
CHANGED
|
@@ -34,7 +34,7 @@ export default {
|
|
|
34
34
|
emits: ["update:modelValue"],
|
|
35
35
|
computed: {
|
|
36
36
|
baseClasses() {
|
|
37
|
-
return "shrink-0 whitespace-nowrap px-3 py-2.5 text-sm font-medium border-none focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-inset sm:px-4 sm:py-2";
|
|
37
|
+
return "shrink-0 whitespace-nowrap px-3 py-2.5 text-sm font-medium border-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:ring-inset sm:px-4 sm:py-2";
|
|
38
38
|
},
|
|
39
39
|
activeClasses() {
|
|
40
40
|
return "bg-primary text-white";
|
package/src/ui/kTable.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="tableWrapper" :class="['w-full', { 'k-table-mobile': isMobileLayout }]">
|
|
3
|
-
<table ref="tableRef" :class="['table-custom', `table-custom--${variant}`]">
|
|
3
|
+
<table ref="tableRef" role="table" :class="['table-custom', `table-custom--${variant}`]">
|
|
4
4
|
<template v-if="hasNamedSlots">
|
|
5
5
|
<thead ref="theadRef">
|
|
6
6
|
<slot name="head"></slot>
|
|
@@ -74,15 +74,22 @@ export default {
|
|
|
74
74
|
const thead = this.getTheadRef();
|
|
75
75
|
if (!thead) return;
|
|
76
76
|
|
|
77
|
-
const
|
|
77
|
+
const headerCells = Array.from(thead.querySelectorAll("th"));
|
|
78
|
+
headerCells.forEach((th) => {
|
|
79
|
+
th.setAttribute("role", "columnheader");
|
|
80
|
+
th.setAttribute("scope", "col");
|
|
81
|
+
});
|
|
82
|
+
const headers = headerCells.map((th) => th.textContent.trim());
|
|
78
83
|
|
|
79
84
|
const tbody = this.getTbodyRef();
|
|
80
85
|
if (!tbody) return;
|
|
81
86
|
const rows = tbody.querySelectorAll("tr");
|
|
82
87
|
|
|
83
88
|
rows.forEach((row) => {
|
|
89
|
+
row.setAttribute("role", "row");
|
|
84
90
|
const cells = row.querySelectorAll("td");
|
|
85
91
|
cells.forEach((cell, index) => {
|
|
92
|
+
cell.setAttribute("role", "cell");
|
|
86
93
|
cell.setAttribute("data-label", headers[index] || "");
|
|
87
94
|
});
|
|
88
95
|
});
|
|
@@ -97,7 +104,7 @@ export default {
|
|
|
97
104
|
};
|
|
98
105
|
</script>
|
|
99
106
|
|
|
100
|
-
<style
|
|
107
|
+
<style>
|
|
101
108
|
.table-custom {
|
|
102
109
|
@apply table-auto w-full border-collapse;
|
|
103
110
|
}
|
package/src/ui/kTags.vue
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
:placeholder="placeholder"
|
|
28
28
|
:aria-label="!label ? placeholder || 'Add tag' : null"
|
|
29
29
|
:disabled="disabled"
|
|
30
|
-
:class="['flex-1 p-1 bg-transparent border-none focus:outline-none dark:text-slate-100 dark:placeholder-slate-500', disabled ? 'text-gray-400 cursor-not-allowed dark:text-slate-500' : '']"
|
|
30
|
+
:class="['flex-1 p-1 bg-transparent border-none focus-visible:outline-none dark:text-slate-100 dark:placeholder-slate-500', disabled ? 'text-gray-400 cursor-not-allowed dark:text-slate-500' : '']"
|
|
31
31
|
/>
|
|
32
32
|
</div>
|
|
33
33
|
<!-- Error message -->
|
package/src/ui/kTextArea.vue
CHANGED
|
@@ -74,8 +74,8 @@ export default {
|
|
|
74
74
|
},
|
|
75
75
|
textareaClass() {
|
|
76
76
|
return [
|
|
77
|
-
'w-full px-3 py-2 border rounded-lg transition shadow-sm focus:outline-none text-gray-700 focus:ring-2 focus:ring-primary/20 focus:border-primary bg-white placeholder-gray-400 dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500',
|
|
78
|
-
this.hasError ? 'border-red-500 focus:ring focus:ring-red-300 dark:border-rose-500 dark:focus:ring-rose-500/20' : '',
|
|
77
|
+
'w-full px-3 py-2 border rounded-lg transition shadow-sm focus-visible:outline-none text-gray-700 focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:border-primary bg-white placeholder-gray-400 dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500',
|
|
78
|
+
this.hasError ? 'border-red-500 focus-visible:ring focus-visible:ring-red-300 dark:border-rose-500 dark:focus-visible:ring-rose-500/20' : '',
|
|
79
79
|
this.disabled ? '!bg-gray-100 !text-gray-400 !cursor-not-allowed dark:!bg-slate-900 dark:!text-slate-500 dark:!border-slate-700' : '',
|
|
80
80
|
]
|
|
81
81
|
},
|
package/src/ui/kToggle.vue
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
'block mb-1 text-sm font-bold',
|
|
8
8
|
disabled ? 'text-slate-500' : 'text-primary/90',
|
|
9
9
|
]"
|
|
10
|
-
for="toggle"
|
|
11
10
|
>
|
|
12
11
|
{{ label }}
|
|
13
12
|
</div>
|
|
@@ -15,7 +14,9 @@
|
|
|
15
14
|
<!-- Toggle button -->
|
|
16
15
|
<button
|
|
17
16
|
@click="toggle"
|
|
18
|
-
|
|
17
|
+
role="switch"
|
|
18
|
+
:aria-checked="modelValue"
|
|
19
|
+
:id="computedId"
|
|
19
20
|
:aria-label="label || 'Toggle'"
|
|
20
21
|
:aria-disabled="disabled.toString()"
|
|
21
22
|
:disabled="disabled"
|
|
@@ -100,12 +101,12 @@ export default {
|
|
|
100
101
|
|
|
101
102
|
.k-toggle-track:focus-visible {
|
|
102
103
|
outline: none;
|
|
103
|
-
box-shadow: 0 0 0 2px rgb(
|
|
104
|
+
box-shadow: 0 0 0 2px rgb(3 105 161 / 0.35);
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
.k-toggle-track--on {
|
|
107
|
-
background: #
|
|
108
|
-
border-color: #
|
|
108
|
+
background: #0369A1;
|
|
109
|
+
border-color: #0369A1;
|
|
109
110
|
box-shadow: 0 2px 8px rgb(2 6 23 / 0.25);
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -148,8 +149,8 @@ export default {
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
:global(html.dark) .k-toggle-track--on {
|
|
151
|
-
background: #
|
|
152
|
-
border-color: #
|
|
152
|
+
background: #0369A1;
|
|
153
|
+
border-color: #0369A1;
|
|
153
154
|
box-shadow: 0 2px 8px rgb(2 6 23 / 0.45);
|
|
154
155
|
}
|
|
155
156
|
|
package/src/ui/kUploader.vue
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
Σύρετε το αρχείο εδώ, ή
|
|
17
17
|
<label
|
|
18
18
|
for="file-input"
|
|
19
|
-
class="underline cursor-pointer text-primary hover:text-primary/80 focus:outline-none"
|
|
19
|
+
class="underline cursor-pointer text-primary hover:text-primary/80 focus-visible:outline-none"
|
|
20
20
|
>
|
|
21
21
|
αναζητήστε
|
|
22
22
|
</label>
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
<CheckCircleIcon class="w-5 h-5 text-green-500" />
|
|
64
64
|
<button
|
|
65
65
|
@click="removeFile(file)"
|
|
66
|
-
class="text-gray-400 hover:text-red-500 focus:outline-none dark:text-slate-500 dark:hover:text-red-400"
|
|
66
|
+
class="text-gray-400 hover:text-red-500 focus-visible:outline-none dark:text-slate-500 dark:hover:text-red-400"
|
|
67
67
|
:disabled="disabled"
|
|
68
68
|
aria-label="Remove file"
|
|
69
69
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { INTENT_VARIANT_STYLES } from "./intentColors";
|
|
2
2
|
|
|
3
|
-
export const K_BUTTON_FOCUS_RING = "focus-visible:ring-slate-900";
|
|
3
|
+
export const K_BUTTON_FOCUS_RING = "focus-visible:ring-slate-900 dark:focus-visible:ring-primary";
|
|
4
4
|
export const K_BUTTON_BASE = "inline-flex flex-row items-center justify-center font-medium transition-all rounded-lg border border-transparent";
|
|
5
5
|
|
|
6
6
|
export const K_BUTTON_SIZE_STYLES = {
|
|
@@ -3,11 +3,11 @@ export const K_INPUT_THEME = {
|
|
|
3
3
|
labelDisabled: "text-slate-500 dark:text-slate-400",
|
|
4
4
|
labelError: "text-rose-800 dark:text-rose-400",
|
|
5
5
|
baseInput:
|
|
6
|
-
"w-full px-3 py-2 border rounded-lg transition shadow-sm focus:outline-none text-slate-900 bg-white placeholder-gray-400 focus:ring-2 focus:ring-primary/25 focus:border-primary dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500",
|
|
6
|
+
"w-full px-3 py-2 border rounded-lg transition shadow-sm focus-visible:outline-none text-slate-900 bg-white placeholder-gray-400 focus-visible:ring-2 focus-visible:ring-primary/25 focus-visible:border-primary dark:bg-slate-800 dark:text-slate-100 dark:border-slate-600 dark:placeholder-slate-500",
|
|
7
7
|
withRightAdornment: "pr-10",
|
|
8
8
|
withPasswordToggle: "pr-14",
|
|
9
9
|
disabled: "!bg-slate-50 !text-slate-400 !border-slate-200 !shadow-none cursor-not-allowed placeholder-slate-400 dark:!bg-slate-900 dark:!text-slate-500 dark:!border-slate-700",
|
|
10
|
-
errorInput: "border-rose-500 bg-rose-50/40 focus:border-rose-600 focus:ring-rose-500/20 dark:bg-rose-950/40 dark:border-rose-500 dark:focus:ring-rose-500/20",
|
|
10
|
+
errorInput: "border-rose-500 bg-rose-50/40 focus-visible:border-rose-600 focus-visible:ring-rose-500/20 dark:bg-rose-950/40 dark:border-rose-500 dark:focus-visible:ring-rose-500/20",
|
|
11
11
|
infoText: "text-sm text-slate-600 dark:text-slate-400",
|
|
12
12
|
errorText: "text-sm text-rose-700 dark:text-rose-400",
|
|
13
13
|
trailingIcon: "absolute w-4 h-4 text-primary/70 -translate-y-1/2 pointer-events-none right-3 top-1/2",
|