@meistrari/tela-build 1.31.0 → 1.33.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/components/tela/dropdown-menu/DropdownMenu.vue +7 -3
- package/components/tela/header/trailing/pagination/pagination-next-button.vue +1 -1
- package/components/tela/header/trailing/pagination/pagination-prev-button.vue +1 -1
- package/components/tela/header/trailing/trailing-actions.vue +1 -0
- package/components/tela/initials.vue +1 -1
- package/components/tela/input/tela-input.vue +7 -8
- package/components/tela/menubar/menubar-content.vue +1 -1
- package/components/tela/menubar/menubar-item.vue +1 -1
- package/components/tela/menubar/menubar-trigger.vue +1 -1
- package/components/tela/scroll-area/scroll-area.vue +17 -8
- package/components/tela/sidebar/sidebar-item.vue +26 -11
- package/components/tela/sidebar/sidebar-logo.vue +1 -1
- package/components/tela/sidebar/sidebar-user.vue +2 -2
- package/components/tela/sidebar/sidebar.mdx +5 -0
- package/components/tela/sidebar/sidebar.stories.ts +60 -0
- package/components/tela/tags/tags-select.mdx +5 -1
- package/components/tela/tags/tags-select.vue +6 -3
- package/css/reset.css +9 -1
- package/package.json +1 -1
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'vue'
|
|
3
|
+
import type { TooltipProps } from '../tooltip/tooltip.vue'
|
|
4
|
+
|
|
2
5
|
import { VisuallyHidden } from 'radix-vue'
|
|
6
|
+
|
|
3
7
|
import DropdownMenuRoot from './DropdownMenuRoot.vue'
|
|
4
8
|
import DropdownMenuContent from './DropdownMenuContent.vue'
|
|
5
9
|
import DropdownMenuGroup from './DropdownMenuGroup.vue'
|
|
6
10
|
import DropdownMenuItem from './DropdownMenuItem.vue'
|
|
7
11
|
import DropdownMenuLabel from './DropdownMenuLabel.vue'
|
|
8
12
|
import DropdownMenuTrigger from './DropdownMenuTrigger.vue'
|
|
9
|
-
import type { TooltipProps } from '../tooltip/tooltip.vue'
|
|
10
13
|
|
|
11
14
|
const props = withDefaults(defineProps<{
|
|
12
15
|
items: {
|
|
@@ -27,7 +30,8 @@ const props = withDefaults(defineProps<{
|
|
|
27
30
|
allowSearch?: boolean
|
|
28
31
|
searchPlaceholder?: string
|
|
29
32
|
shouldBeModal?: boolean
|
|
30
|
-
|
|
33
|
+
triggerClass?: HTMLAttributes['class']
|
|
34
|
+
contentClass?: HTMLAttributes['class']
|
|
31
35
|
align?: 'start' | 'end' | 'center'
|
|
32
36
|
}>(), {
|
|
33
37
|
align: 'start',
|
|
@@ -66,7 +70,7 @@ function onToggle(open: boolean) {
|
|
|
66
70
|
<template>
|
|
67
71
|
<div data-allow-mismatch @click.stop>
|
|
68
72
|
<DropdownMenuRoot :modal="shouldBeModal" :default-open="isStorybook" @update:open="onToggle">
|
|
69
|
-
<DropdownMenuTrigger as-child class="data-[state=open]:bg-
|
|
73
|
+
<DropdownMenuTrigger as-child :class="cn('data-[state=open]:bg-muted', triggerClass)" @click.prevent.stop>
|
|
70
74
|
<slot />
|
|
71
75
|
<VisuallyHidden v-if="isStorybook" as-child>
|
|
72
76
|
<button />
|
|
@@ -14,7 +14,7 @@ const emit = defineEmits<{
|
|
|
14
14
|
size="md"
|
|
15
15
|
color="secondary"
|
|
16
16
|
:icon-class="disabled ? 'text-icon-subtle' : 'text-icon'"
|
|
17
|
-
button-class="!disabled:bg-transparent"
|
|
17
|
+
button-class="!rounded-12px !disabled:bg-transparent"
|
|
18
18
|
:disabled="disabled"
|
|
19
19
|
@click="emit('click')"
|
|
20
20
|
/>
|
|
@@ -14,7 +14,7 @@ const emit = defineEmits<{
|
|
|
14
14
|
size="md"
|
|
15
15
|
color="secondary"
|
|
16
16
|
:icon-class="disabled ? 'text-icon-subtle' : 'text-icon'"
|
|
17
|
-
button-class="!disabled:bg-transparent"
|
|
17
|
+
button-class="!rounded-12px !disabled:bg-transparent"
|
|
18
18
|
:disabled="disabled"
|
|
19
19
|
@click="emit('click')"
|
|
20
20
|
/>
|
|
@@ -123,10 +123,10 @@ defineExpose({
|
|
|
123
123
|
transition
|
|
124
124
|
cursor-text
|
|
125
125
|
overflow-hidden
|
|
126
|
-
px-
|
|
127
|
-
b="0.5px border
|
|
126
|
+
px-10px py-4px
|
|
127
|
+
b="0.5px border"
|
|
128
128
|
rounded-10px bg-white
|
|
129
|
-
class="focus-within-
|
|
129
|
+
class="focus-within-border-strong focus-within-ring-2 focus-within-ring-gray-100 [box-shadow:0_1px_4px_0_rgba(103,127,148,0.03)]"
|
|
130
130
|
:class="[
|
|
131
131
|
size === 'sm' && 'py-7px !px-12px',
|
|
132
132
|
disabled && '!bg-gray-50 cursor-not-allowed color-gray-600',
|
|
@@ -137,8 +137,8 @@ defineExpose({
|
|
|
137
137
|
flex items-center
|
|
138
138
|
@click="$el.querySelector(isTextarea ? 'textarea' : 'input')?.focus()"
|
|
139
139
|
>
|
|
140
|
-
<div v-if="icon" flex mr-
|
|
141
|
-
<TelaIcon :name="icon" size="
|
|
140
|
+
<div v-if="icon" flex mr-8px>
|
|
141
|
+
<TelaIcon :name="icon" size="13px" text="icon-tertiary" />
|
|
142
142
|
</div>
|
|
143
143
|
<div
|
|
144
144
|
flex="~ col" grow align-center h-full
|
|
@@ -155,7 +155,6 @@ defineExpose({
|
|
|
155
155
|
align-center
|
|
156
156
|
:class="[disabled && 'cursor-not-allowed', props.labelClass]"
|
|
157
157
|
>
|
|
158
|
-
|
|
159
158
|
<slot name="label-leading" />
|
|
160
159
|
{{ label }}
|
|
161
160
|
</label>
|
|
@@ -175,13 +174,13 @@ defineExpose({
|
|
|
175
174
|
bg-transparent
|
|
176
175
|
z-0
|
|
177
176
|
h-full
|
|
178
|
-
|
|
177
|
+
body-14-regular
|
|
178
|
+
class="placeholder-text-tertiary focus-visible:outline-none!"
|
|
179
179
|
resize-none
|
|
180
180
|
:disabled="disabled"
|
|
181
181
|
:tabindex="tabindex"
|
|
182
182
|
:class="[
|
|
183
183
|
disabled && 'cursor-not-allowed',
|
|
184
|
-
size === 'sm' && 'leading-20px body-14-regular placeholder:body-14-regular',
|
|
185
184
|
props.inputFontClass ? props.inputFontClass : 'text-14px',
|
|
186
185
|
!isTextarea && '!h-1.7em',
|
|
187
186
|
]"
|
|
@@ -22,7 +22,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
|
22
22
|
<MenubarItem
|
|
23
23
|
v-bind="forwarded"
|
|
24
24
|
:class="cn(
|
|
25
|
-
'relative flex cursor-pointer select-none items-center rounded-xl px-3 py-1.5
|
|
25
|
+
'relative flex cursor-pointer select-none items-center rounded-xl px-3 py-1.5 body-14-medium text-primary outline-none focus:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-40',
|
|
26
26
|
inset && 'pl-8',
|
|
27
27
|
props.class,
|
|
28
28
|
)"
|
|
@@ -17,7 +17,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
|
|
17
17
|
v-bind="forwardedProps"
|
|
18
18
|
:class="
|
|
19
19
|
cn(
|
|
20
|
-
'flex items-center gap-2 cursor-pointer select-none px-2 py-1.5 text-sm font-medium outline-none rounded-lg hover:bg-
|
|
20
|
+
'flex items-center gap-2 cursor-pointer select-none px-2 py-1.5 text-sm font-medium outline-none rounded-lg hover:bg-muted data-[state=open]:bg-muted',
|
|
21
21
|
props.class,
|
|
22
22
|
)
|
|
23
23
|
"
|
|
@@ -1,34 +1,43 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { ScrollAreaRootProps } from 'reka-ui'
|
|
3
|
+
import type { HTMLAttributes } from 'vue'
|
|
4
|
+
|
|
5
|
+
import { computed, onMounted, useTemplateRef } from 'vue'
|
|
6
|
+
|
|
2
7
|
import {
|
|
3
8
|
ScrollAreaCorner,
|
|
4
9
|
ScrollAreaRoot,
|
|
5
|
-
|
|
6
10
|
ScrollAreaViewport,
|
|
7
11
|
} from 'reka-ui'
|
|
8
|
-
|
|
9
|
-
import { computed } from 'vue'
|
|
10
|
-
import type { HTMLAttributes } from 'vue'
|
|
12
|
+
|
|
11
13
|
import ScrollBar from './scroll-bar.vue'
|
|
12
14
|
|
|
13
15
|
const props = withDefaults(
|
|
14
16
|
defineProps<ScrollAreaRootProps
|
|
15
|
-
& { class?: HTMLAttributes['class'], orientation?: 'vertical' | 'horizontal' | 'both', scrollThumbClass?: HTMLAttributes['class'] }>(),
|
|
17
|
+
& { class?: HTMLAttributes['class'], orientation?: 'vertical' | 'horizontal' | 'both', scrollThumbClass?: HTMLAttributes['class'], disableViewportFocus?: boolean }>(),
|
|
16
18
|
{
|
|
17
19
|
orientation: 'vertical',
|
|
18
|
-
|
|
20
|
+
disableViewportFocus: false,
|
|
19
21
|
},
|
|
20
22
|
)
|
|
21
23
|
|
|
22
24
|
const delegatedProps = computed(() => {
|
|
23
|
-
const { class: _, ...delegated } = props
|
|
25
|
+
const { class: _, disableViewportFocus: __, ...delegated } = props
|
|
24
26
|
|
|
25
27
|
return delegated
|
|
26
28
|
})
|
|
29
|
+
|
|
30
|
+
const viewportRef = useTemplateRef<InstanceType<typeof ScrollAreaViewport>>('viewportRef')
|
|
31
|
+
|
|
32
|
+
onMounted(() => {
|
|
33
|
+
if (props.disableViewportFocus)
|
|
34
|
+
viewportRef.value?.viewportElement?.setAttribute('tabindex', '-1')
|
|
35
|
+
})
|
|
27
36
|
</script>
|
|
28
37
|
|
|
29
38
|
<template>
|
|
30
39
|
<ScrollAreaRoot v-bind="delegatedProps" :class="cn('relative overflow-hidden', props.class)">
|
|
31
|
-
<ScrollAreaViewport class="
|
|
40
|
+
<ScrollAreaViewport ref="viewportRef" class="size-full rounded-[inherit] focus-visible:outline-border-strong">
|
|
32
41
|
<slot />
|
|
33
42
|
</ScrollAreaViewport>
|
|
34
43
|
<ScrollBar v-if="props.orientation === 'vertical' || props.orientation === 'both'" orientation="vertical" :class="props.scrollThumbClass" />
|
|
@@ -7,39 +7,54 @@ const props = defineProps<{
|
|
|
7
7
|
to?: string
|
|
8
8
|
onClick?: () => void
|
|
9
9
|
isActive: boolean
|
|
10
|
+
disabled?: boolean
|
|
10
11
|
}>()
|
|
11
12
|
|
|
12
13
|
const iconName = computed(() => props.isActive ? `${props.icon}-fill` : props.icon)
|
|
14
|
+
|
|
15
|
+
const rootIs = computed(() => props.disabled || !props.to ? 'button' : NuxtLink)
|
|
16
|
+
|
|
17
|
+
const rootAttrs = computed(() => {
|
|
18
|
+
if (props.disabled || !props.to) {
|
|
19
|
+
return {
|
|
20
|
+
type: 'button',
|
|
21
|
+
disabled: props.disabled || undefined,
|
|
22
|
+
...(!props.disabled && props.onClick ? { onClick: props.onClick } : {}),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { to: props.to }
|
|
26
|
+
})
|
|
13
27
|
</script>
|
|
14
28
|
|
|
15
29
|
<template>
|
|
16
30
|
<component
|
|
17
|
-
:is="
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class="group"
|
|
31
|
+
:is="rootIs"
|
|
32
|
+
v-bind="rootAttrs"
|
|
33
|
+
class="group disabled:opacity-60 disabled:cursor-not-allowed"
|
|
21
34
|
flex="~ col" items-center justify-center gap-2px outline-none
|
|
22
|
-
:data-active="isActive"
|
|
23
|
-
v-bind="!to && onClick ? { onClick } : {}"
|
|
35
|
+
:data-active="isActive && !props.disabled"
|
|
24
36
|
>
|
|
25
37
|
<div relative size-40px flex items-center justify-center rounded-10px>
|
|
26
38
|
<TelaIcon
|
|
27
39
|
:name="iconName"
|
|
28
40
|
size="20px"
|
|
29
41
|
relative z-1
|
|
30
|
-
|
|
42
|
+
color="icon-tertiary duration-150 ease-out group-[:hover:not(:disabled)]:icon group-focus-visible:icon group-data-[active=true]:icon"
|
|
31
43
|
/>
|
|
32
44
|
<div
|
|
33
45
|
:class="cn(
|
|
34
|
-
'absolute inset-0 size-full rounded-[14px] z-0 border-[0.5px] border-transparent',
|
|
35
|
-
|
|
46
|
+
'absolute inset-0 size-full rounded-[14px] z-0 border-[0.5px] border-transparent duration-150 ease-out origin-center group-disabled:scale-0',
|
|
47
|
+
'group-data-[active=false]:bg group-data-[active=false]:scale-10 group-data-[active=false]:opacity-0',
|
|
48
|
+
'group-data-[active=true]:bg-neutral-200 group-focus-visible:border-strong group-[[data-active=false]:hover]:border-strong group-hover:scale-100 group-hover:opacity-100',
|
|
49
|
+
'group-focus-visible:border-strong group-focus-visible:scale-100 group-focus-visible:opacity-100',
|
|
36
50
|
)"
|
|
37
51
|
/>
|
|
38
52
|
</div>
|
|
39
53
|
<p
|
|
40
54
|
:class="cn(
|
|
41
|
-
'text-[11px] leading-[12px] -tracking-0.2px',
|
|
42
|
-
|
|
55
|
+
'text-[11px] leading-[12px] -tracking-0.2px font-460 text-tertiary duration-150 ease-out',
|
|
56
|
+
'group-[:hover:not(:disabled)]:text-primary group-focus-visible:text-primary',
|
|
57
|
+
'group-data-[active=true]:text-primary group-data-[active=true]:font-550',
|
|
43
58
|
)"
|
|
44
59
|
>
|
|
45
60
|
{{ label }}
|
|
@@ -57,6 +57,10 @@ A composable sidebar navigation system built from focused sub-components. Fixed
|
|
|
57
57
|
|
|
58
58
|
<Canvas of={SidebarStories.NoActiveItem} />
|
|
59
59
|
|
|
60
|
+
### Disabled Items
|
|
61
|
+
|
|
62
|
+
<Canvas of={SidebarStories.DisabledItems} />
|
|
63
|
+
|
|
60
64
|
### Individual Item States
|
|
61
65
|
|
|
62
66
|
<Canvas of={SidebarStories.SingleItem} />
|
|
@@ -98,6 +102,7 @@ interface TelaSidebarItemProps {
|
|
|
98
102
|
isActive: boolean // Highlights the item as the current route
|
|
99
103
|
to?: string // Route path — renders as a link
|
|
100
104
|
onClick?: () => void // Click handler when not using `to`
|
|
105
|
+
disabled?: boolean // Renders as a non-interactive button with reduced opacity
|
|
101
106
|
}
|
|
102
107
|
```
|
|
103
108
|
|
|
@@ -168,6 +168,66 @@ export const ActivityActive: Story = {
|
|
|
168
168
|
}),
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
export const DisabledItems: Story = {
|
|
172
|
+
parameters: {
|
|
173
|
+
docs: {
|
|
174
|
+
description: {
|
|
175
|
+
story: 'Disabled items render as non-interactive buttons with reduced opacity. The `to` prop is ignored when `disabled` is `true`.',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
render: () => ({
|
|
180
|
+
components,
|
|
181
|
+
setup() {
|
|
182
|
+
return { userActions }
|
|
183
|
+
},
|
|
184
|
+
template: `
|
|
185
|
+
<TelaSidebar>
|
|
186
|
+
<TelaSidebarHeader>
|
|
187
|
+
<TelaSidebarLogo src="/tela-logo-black.svg" alt="Tela Logo" />
|
|
188
|
+
</TelaSidebarHeader>
|
|
189
|
+
|
|
190
|
+
<TelaSidebarContent>
|
|
191
|
+
<TelaSidebarItem
|
|
192
|
+
icon="i-ph-house"
|
|
193
|
+
label="Home"
|
|
194
|
+
to="/"
|
|
195
|
+
:is-active="true"
|
|
196
|
+
/>
|
|
197
|
+
<TelaSidebarItem
|
|
198
|
+
icon="i-ph-graph"
|
|
199
|
+
label="Workflows"
|
|
200
|
+
to="/workflows"
|
|
201
|
+
:is-active="false"
|
|
202
|
+
disabled
|
|
203
|
+
/>
|
|
204
|
+
<TelaSidebarItem
|
|
205
|
+
icon="i-ph-database"
|
|
206
|
+
label="Data"
|
|
207
|
+
to="/data"
|
|
208
|
+
:is-active="false"
|
|
209
|
+
disabled
|
|
210
|
+
/>
|
|
211
|
+
<TelaSidebarItem
|
|
212
|
+
icon="i-ph-gear"
|
|
213
|
+
label="Settings"
|
|
214
|
+
to="/settings"
|
|
215
|
+
:is-active="false"
|
|
216
|
+
/>
|
|
217
|
+
</TelaSidebarContent>
|
|
218
|
+
|
|
219
|
+
<TelaSidebarFooter>
|
|
220
|
+
<TelaSidebarUser
|
|
221
|
+
name="Username"
|
|
222
|
+
email="user@example.com"
|
|
223
|
+
:actions="userActions"
|
|
224
|
+
/>
|
|
225
|
+
</TelaSidebarFooter>
|
|
226
|
+
</TelaSidebar>
|
|
227
|
+
`,
|
|
228
|
+
}),
|
|
229
|
+
}
|
|
230
|
+
|
|
171
231
|
export const SingleItem: Story = {
|
|
172
232
|
parameters: {
|
|
173
233
|
layout: 'centered',
|
|
@@ -97,7 +97,9 @@ function clearAll() {
|
|
|
97
97
|
</template>
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
###
|
|
100
|
+
### Non-Editable (selection only)
|
|
101
|
+
|
|
102
|
+
Pass `:is-editable="false"` to hide the create button (`+`) and the per-tag edit pencil. Users can still select/deselect existing tags, but cannot create new ones or modify existing ones.
|
|
101
103
|
|
|
102
104
|
```vue
|
|
103
105
|
<script setup>
|
|
@@ -112,6 +114,7 @@ const tags = ref([
|
|
|
112
114
|
<TelaTagsSelect
|
|
113
115
|
:model-value="tags"
|
|
114
116
|
:options="tags"
|
|
117
|
+
:is-editable="false"
|
|
115
118
|
/>
|
|
116
119
|
</template>
|
|
117
120
|
```
|
|
@@ -143,6 +146,7 @@ type TagsSelectProps = {
|
|
|
143
146
|
addNewNamePlaceholder?: string
|
|
144
147
|
createButtonLabel?: string
|
|
145
148
|
saveChangesButtonLabel?: string
|
|
149
|
+
isEditable?: boolean // Default: true. When false, hides the create (+) button and the per-tag edit pencil.
|
|
146
150
|
}
|
|
147
151
|
```
|
|
148
152
|
|
|
@@ -24,6 +24,7 @@ const props = withDefaults(defineProps<{
|
|
|
24
24
|
assignLabel?: string
|
|
25
25
|
showLabel?: boolean
|
|
26
26
|
alwaysShowEmpty?: boolean
|
|
27
|
+
isEditable?: boolean
|
|
27
28
|
}>(), {
|
|
28
29
|
modelValue: () => [],
|
|
29
30
|
disabled: false,
|
|
@@ -41,6 +42,7 @@ const props = withDefaults(defineProps<{
|
|
|
41
42
|
tagPlural: 'tags',
|
|
42
43
|
showLabel: true,
|
|
43
44
|
alwaysShowEmpty: false,
|
|
45
|
+
isEditable: true,
|
|
44
46
|
})
|
|
45
47
|
|
|
46
48
|
const emit = defineEmits<{
|
|
@@ -141,7 +143,7 @@ function resolveColor(color: string, lightColor = false): string {
|
|
|
141
143
|
const allCreatedTags = ref<Tag[]>([])
|
|
142
144
|
const localSelectedTags = ref<Tag[]>(props.modelValue || [])
|
|
143
145
|
const popoverOpen = ref(false)
|
|
144
|
-
const selectedContent = ref<ContentType>(allCreatedTags.value.length > 0 ? 'existing-tag' : 'new-tag')
|
|
146
|
+
const selectedContent = ref<ContentType>(allCreatedTags.value.length > 0 || !props.isEditable ? 'existing-tag' : 'new-tag')
|
|
145
147
|
const newTagName = ref<string>('')
|
|
146
148
|
const selectedColorsForNewTag = ref<string | null>(ALL_COLORS[0])
|
|
147
149
|
const selectedTagsForApply = ref<Set<string>>(new Set())
|
|
@@ -247,7 +249,7 @@ watch(() => props.modelValue, (newTags) => {
|
|
|
247
249
|
|
|
248
250
|
watch(popoverOpen, (isOpen) => {
|
|
249
251
|
if (isOpen) {
|
|
250
|
-
selectedContent.value = hasTags.value ? 'existing-tag' : 'new-tag'
|
|
252
|
+
selectedContent.value = hasTags.value || !props.isEditable ? 'existing-tag' : 'new-tag'
|
|
251
253
|
selectedTagsForApply.value = getTagKeys(localSelectedTags.value)
|
|
252
254
|
}
|
|
253
255
|
else {
|
|
@@ -574,7 +576,7 @@ updateAllCreatedTags()
|
|
|
574
576
|
<h5 heading-h5-semibold>
|
|
575
577
|
{{ allCreatedTags.length }} {{ allCreatedTags.length > 1 ? props.tagPlural : props.tagSingular }}
|
|
576
578
|
</h5>
|
|
577
|
-
<button flex items-center justify-center w-24px h-24px rounded-6px hover:bg-background-muted mr--4px @click="handleCreateMore">
|
|
579
|
+
<button v-if="props.isEditable" flex items-center justify-center w-24px h-24px rounded-6px hover:bg-background-muted mr--4px @click="handleCreateMore">
|
|
578
580
|
<TelaIcon name="i-ph-plus" size="16px" color="icon" />
|
|
579
581
|
</button>
|
|
580
582
|
</div>
|
|
@@ -588,6 +590,7 @@ updateAllCreatedTags()
|
|
|
588
590
|
</div>
|
|
589
591
|
<div flex items-center gap-4px>
|
|
590
592
|
<button
|
|
593
|
+
v-if="props.isEditable"
|
|
591
594
|
class="group opacity-0 group-hover/tag:opacity-100" flex items-center justify-center w-17px h-17px rounded-5px hover:bg-background-lowered
|
|
592
595
|
@click.stop="handleEditTag(tag)"
|
|
593
596
|
>
|
package/css/reset.css
CHANGED