@youcan/celeste 0.6.39 → 0.6.41
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/celeste.css +137 -22
- package/dist/cjs/chunks/index.js +211 -0
- package/dist/cjs/chunks/radio-group-item.vue_vue_type_style_index_0_lang.js +34 -0
- package/dist/cjs/chunks/radio-group.vue_vue_type_style_index_0_lang.js +39 -0
- package/dist/cjs/digit-input-slot.js +1 -1
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/modal-content.js +1 -1
- package/dist/cjs/radio-group-item.js +3 -0
- package/dist/cjs/radio-group.js +3 -0
- package/dist/cjs/tag.js +39 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/radio-group/index.d.ts +4 -0
- package/dist/components/radio-group/radio-group-item.d.ts +7 -0
- package/dist/components/radio-group/radio-group.d.ts +26 -0
- package/dist/components/tag/index.d.ts +2 -0
- package/dist/components/tag/tag.d.ts +26 -0
- package/dist/es/button.js +1 -1
- package/dist/es/checkbox-label.js +1 -1
- package/dist/es/chunks/index.js +275 -64
- package/dist/es/chunks/index3.js +1 -1
- package/dist/es/chunks/radio-group-item.vue_vue_type_style_index_0_lang.js +35 -0
- package/dist/es/chunks/radio-group.vue_vue_type_style_index_0_lang.js +40 -0
- package/dist/es/combobox-group.js +1 -1
- package/dist/es/combobox-input.js +1 -1
- package/dist/es/combobox-item.js +1 -1
- package/dist/es/combobox-list.js +1 -1
- package/dist/es/combobox-root.js +1 -1
- package/dist/es/combobox-separator.js +1 -1
- package/dist/es/combobox-trigger.js +1 -1
- package/dist/es/command-group.js +1 -1
- package/dist/es/command-input.js +1 -1
- package/dist/es/command-item.js +1 -1
- package/dist/es/command-list.js +1 -1
- package/dist/es/command-root.js +1 -1
- package/dist/es/command-separator.js +1 -1
- package/dist/es/compact-button.js +1 -1
- package/dist/es/digit-input-group.js +1 -1
- package/dist/es/digit-input-slot.js +2 -2
- package/dist/es/digit-input.js +1 -1
- package/dist/es/dropdown-menu-content.js +1 -1
- package/dist/es/dropdown-menu-group.js +1 -1
- package/dist/es/dropdown-menu-item.js +1 -1
- package/dist/es/dropdown-menu-label.js +1 -1
- package/dist/es/dropdown-menu-separator.js +1 -1
- package/dist/es/dropdown-menu-sub-content.js +1 -1
- package/dist/es/dropdown-menu-sub-trigger.js +1 -1
- package/dist/es/dropdown-menu-trigger.js +1 -1
- package/dist/es/dropdown-menu.js +1 -1
- package/dist/es/dropdown.js +1 -1
- package/dist/es/fancy-button.js +1 -1
- package/dist/es/index.js +24 -18
- package/dist/es/label.js +1 -1
- package/dist/es/link-button.js +1 -1
- package/dist/es/modal-content.js +2 -2
- package/dist/es/modal-header.js +1 -1
- package/dist/es/popover-content.js +1 -1
- package/dist/es/popover-trigger.js +1 -1
- package/dist/es/progress-bar.js +1 -1
- package/dist/es/progress-circle.js +1 -1
- package/dist/es/radio-group-item.js +4 -0
- package/dist/es/radio-group.js +4 -0
- package/dist/es/segmented-control-item.js +1 -1
- package/dist/es/segmented-control.js +1 -1
- package/dist/es/select-content.js +1 -1
- package/dist/es/select-item.js +1 -1
- package/dist/es/select-trigger.js +1 -1
- package/dist/es/select-value.js +1 -1
- package/dist/es/social-button.js +1 -1
- package/dist/es/tab-menu-content.js +1 -1
- package/dist/es/tab-menu-item.js +1 -1
- package/dist/es/tab-menu-list.js +1 -1
- package/dist/es/tab-menu.js +1 -1
- package/dist/es/tag.js +40 -0
- package/dist/es/text-input.js +1 -1
- package/dist/es/tooltip.js +1 -1
- package/package.json +3 -4
- package/src/components/digit-input/digit-input-slot.vue +4 -3
- package/src/components/digit-input/stories/digit-input.stories.ts +8 -8
- package/src/components/index.ts +1 -0
- package/src/components/modal/modal-content.vue +2 -2
- package/src/components/radio-group/index.ts +5 -0
- package/src/components/radio-group/radio-group-item.vue +83 -0
- package/src/components/radio-group/radio-group.vue +30 -0
- package/src/components/radio-group/stories/radio-group.stories.ts +48 -0
- package/src/components/tag/index.ts +2 -0
- package/src/components/tag/stories/tag.stories.ts +162 -0
- package/src/components/tag/tag.vue +125 -0
|
@@ -57,7 +57,7 @@ export const Default: Story = {
|
|
|
57
57
|
return { args, value };
|
|
58
58
|
},
|
|
59
59
|
template: `
|
|
60
|
-
<DigitInput v-bind="args" v-model="value">
|
|
60
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
61
61
|
<DigitInputGroup>
|
|
62
62
|
<DigitInputSlot v-for="(item, index) in 4" :key="index" :index="index" />
|
|
63
63
|
</DigitInputGroup>
|
|
@@ -78,7 +78,7 @@ export const WithPlaceholder: Story = {
|
|
|
78
78
|
return { args, value };
|
|
79
79
|
},
|
|
80
80
|
template: `
|
|
81
|
-
<DigitInput v-bind="args" v-model="value">
|
|
81
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
82
82
|
<DigitInputGroup>
|
|
83
83
|
<DigitInputSlot v-for="(item, index) in 6" :key="index" :index="index" />
|
|
84
84
|
</DigitInputGroup>
|
|
@@ -101,7 +101,7 @@ export const OTPInput: Story = {
|
|
|
101
101
|
return { args, value };
|
|
102
102
|
},
|
|
103
103
|
template: `
|
|
104
|
-
<DigitInput v-bind="args" v-model="value">
|
|
104
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
105
105
|
<DigitInputGroup>
|
|
106
106
|
<DigitInputSlot v-for="(item, index) in 6" :key="index" :index="index" />
|
|
107
107
|
</DigitInputGroup>
|
|
@@ -124,7 +124,7 @@ export const PasswordInput: Story = {
|
|
|
124
124
|
return { args, value };
|
|
125
125
|
},
|
|
126
126
|
template: `
|
|
127
|
-
<DigitInput v-bind="args" v-model="value">
|
|
127
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
128
128
|
<DigitInputGroup>
|
|
129
129
|
<DigitInputSlot v-for="(item, index) in 4" :key="index" :index="index" />
|
|
130
130
|
</DigitInputGroup>
|
|
@@ -146,7 +146,7 @@ export const Disabled: Story = {
|
|
|
146
146
|
return { args, value };
|
|
147
147
|
},
|
|
148
148
|
template: `
|
|
149
|
-
<DigitInput v-bind="args" v-model="value">
|
|
149
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
150
150
|
<DigitInputGroup>
|
|
151
151
|
<DigitInputSlot v-for="(item, index) in 4" :key="index" :index="index" />
|
|
152
152
|
</DigitInputGroup>
|
|
@@ -167,7 +167,7 @@ export const LongerInput: Story = {
|
|
|
167
167
|
return { args, value };
|
|
168
168
|
},
|
|
169
169
|
template: `
|
|
170
|
-
<DigitInput v-bind="args" v-model="value">
|
|
170
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
171
171
|
<DigitInputGroup>
|
|
172
172
|
<DigitInputSlot v-for="(item, index) in 8" :key="index" :index="index" />
|
|
173
173
|
</DigitInputGroup>
|
|
@@ -188,7 +188,7 @@ export const PrefilledValue: Story = {
|
|
|
188
188
|
return { args, value };
|
|
189
189
|
},
|
|
190
190
|
template: `
|
|
191
|
-
<DigitInput v-bind="args" v-model="value">
|
|
191
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
192
192
|
<DigitInputGroup>
|
|
193
193
|
<DigitInputSlot v-for="(item, index) in 4" :key="index" :index="index" />
|
|
194
194
|
</DigitInputGroup>
|
|
@@ -210,7 +210,7 @@ export const ErrorState: Story = {
|
|
|
210
210
|
return { args, value };
|
|
211
211
|
},
|
|
212
212
|
template: `
|
|
213
|
-
<DigitInput v-bind="args" v-model="value">
|
|
213
|
+
<DigitInput v-bind="args" v-model="value" style="max-width: 640px;">
|
|
214
214
|
<DigitInputGroup>
|
|
215
215
|
<DigitInputSlot v-for="(item, index) in 4" :key="index" :index="index" />
|
|
216
216
|
</DigitInputGroup>
|
package/src/components/index.ts
CHANGED
|
@@ -41,13 +41,13 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
|
41
41
|
.celeste-modal-content {
|
|
42
42
|
position: fixed;
|
|
43
43
|
z-index: 51;
|
|
44
|
+
top: 50%;
|
|
45
|
+
left: 50%;
|
|
44
46
|
border: 1px solid var(--color-stroke-soft-200);
|
|
45
47
|
border-radius: var(--radius-20);
|
|
46
48
|
background: var(--color-bg-white-0);
|
|
47
49
|
box-shadow: var(--shadow-regular-md);
|
|
48
50
|
translate: -50% -50%;
|
|
49
|
-
inset-block-start: 50%;
|
|
50
|
-
inset-inline-start: 50%;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
.fade-enter-active,
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'vue';
|
|
3
|
+
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { RadioGroupIndicator, RadioGroupItem, type RadioGroupItemProps, useForwardPropsEmits } from 'radix-vue';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<RadioGroupItemProps & { class?: HTMLAttributes['class'] }>();
|
|
8
|
+
const delegatedProps = useDelegatedProps(props, 'class');
|
|
9
|
+
const forwarded = useForwardPropsEmits(delegatedProps);
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<RadioGroupItem
|
|
14
|
+
v-bind="forwarded"
|
|
15
|
+
:class="clsx('celeste-radio-item', props.class)"
|
|
16
|
+
>
|
|
17
|
+
<RadioGroupIndicator class="celeste-radio-indicator" />
|
|
18
|
+
</RadioGroupItem>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<style lang="scss">
|
|
22
|
+
.celeste-radio-item {
|
|
23
|
+
--celeste-radio-border: var(--color-stroke-soft-200);
|
|
24
|
+
|
|
25
|
+
all: unset;
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
flex-shrink: 0;
|
|
28
|
+
width: 16px;
|
|
29
|
+
height: 16px;
|
|
30
|
+
padding: var(--spacing-0);
|
|
31
|
+
transition: box-shadow var(--animation-extra-fast) ease-out;
|
|
32
|
+
border-radius: var(--radius-full);
|
|
33
|
+
background-color: var(--color-bg-white-0);
|
|
34
|
+
box-shadow:
|
|
35
|
+
inset 0 0 0 1.5px var(--celeste-radio-border),
|
|
36
|
+
var(--shadow-regular-xs);
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
|
|
39
|
+
&:hover:not([data-disabled]) {
|
|
40
|
+
--celeste-radio-border: var(--color-stroke-sub-300);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&:focus:not([data-disabled]) {
|
|
44
|
+
--celeste-radio-border: var(--color-primary-base);
|
|
45
|
+
|
|
46
|
+
outline: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&[data-disabled] {
|
|
50
|
+
background-color: var(--color-bg-soft-200);
|
|
51
|
+
pointer-events: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&[data-state='checked']:not([data-disabled]) {
|
|
55
|
+
--celeste-radio-border: transparent;
|
|
56
|
+
|
|
57
|
+
background-color: var(--color-primary-base);
|
|
58
|
+
|
|
59
|
+
&:hover,
|
|
60
|
+
&:focus {
|
|
61
|
+
background-color: var(--color-primary-darker);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.celeste-radio-indicator {
|
|
67
|
+
display: flex;
|
|
68
|
+
position: relative;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: 100%;
|
|
73
|
+
|
|
74
|
+
&::after {
|
|
75
|
+
content: '';
|
|
76
|
+
display: block;
|
|
77
|
+
width: 8px;
|
|
78
|
+
height: 8px;
|
|
79
|
+
border-radius: var(--radius-full);
|
|
80
|
+
background-color: var(--color-static-white);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'vue';
|
|
3
|
+
import { useDelegatedProps } from '@/composables/use-delegated-props';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { RadioGroupRoot, type RadioGroupRootEmits, type RadioGroupRootProps, useForwardPropsEmits } from 'radix-vue';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<RadioGroupRootProps & { class?: HTMLAttributes['class'] }>();
|
|
8
|
+
const emits = defineEmits<RadioGroupRootEmits>();
|
|
9
|
+
|
|
10
|
+
const delegatedProps = useDelegatedProps(props, 'class');
|
|
11
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<RadioGroupRoot
|
|
16
|
+
:class="clsx('celeste-radio-wrapper', props.class)"
|
|
17
|
+
v-bind="forwarded"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
20
|
+
</RadioGroupRoot>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<style lang="scss">
|
|
24
|
+
.celeste-radio-wrapper {
|
|
25
|
+
&[data-orientation='vertical'] {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import RadioGroupItem from '../radio-group-item.vue';
|
|
3
|
+
import RadioGroup from '../radio-group.vue';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof RadioGroup> = {
|
|
6
|
+
title: 'Components/Radio Group',
|
|
7
|
+
component: RadioGroup,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
|
|
12
|
+
type Story = StoryObj<typeof RadioGroup>;
|
|
13
|
+
|
|
14
|
+
export const Default: Story = {
|
|
15
|
+
args: {
|
|
16
|
+
defaultValue: 'option2',
|
|
17
|
+
orientation: 'vertical',
|
|
18
|
+
disabled: false,
|
|
19
|
+
name: 'radio-group',
|
|
20
|
+
modelValue: '',
|
|
21
|
+
dir: 'ltr',
|
|
22
|
+
loop: true,
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
render: args => ({
|
|
27
|
+
components: { RadioGroup, RadioGroupItem },
|
|
28
|
+
setup() {
|
|
29
|
+
return { args };
|
|
30
|
+
},
|
|
31
|
+
template: `
|
|
32
|
+
<RadioGroup v-bind="args" v-model="option2" style="display: flex; gap: 20px;">
|
|
33
|
+
<div style="display: flex; align-items: center;">
|
|
34
|
+
<RadioGroupItem id="r1" value="option1"></RadioGroupItem>
|
|
35
|
+
<label for="r1" style="padding-inline-start: 10px;">Option 1</label>
|
|
36
|
+
</div>
|
|
37
|
+
<div style="display: flex; align-items: center;">
|
|
38
|
+
<RadioGroupItem id="r2" value="option2"></RadioGroupItem>
|
|
39
|
+
<label for="r2" style="padding-inline-start: 10px;">Option 2</label>
|
|
40
|
+
</div>
|
|
41
|
+
<div style="display: flex; align-items: center;">
|
|
42
|
+
<RadioGroupItem id="r3" value="option3"></RadioGroupItem>
|
|
43
|
+
<label for="r3" style="padding-inline-start: 10px;">Option 3</label>
|
|
44
|
+
</div>
|
|
45
|
+
</RadioGroup>
|
|
46
|
+
`,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
import Tag from '../tag.vue';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Tag> = {
|
|
6
|
+
title: 'Components/Tag',
|
|
7
|
+
component: Tag,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
variant: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: ['stroke', 'gray'],
|
|
15
|
+
description: 'Visual variant of the tag',
|
|
16
|
+
},
|
|
17
|
+
dismissable: {
|
|
18
|
+
control: { type: 'boolean' },
|
|
19
|
+
description: 'Whether the tag can be dismissed with a close button',
|
|
20
|
+
},
|
|
21
|
+
disabled: {
|
|
22
|
+
control: { type: 'boolean' },
|
|
23
|
+
description: 'Whether the tag is in a disabled state',
|
|
24
|
+
},
|
|
25
|
+
class: {
|
|
26
|
+
control: { type: 'text' },
|
|
27
|
+
description: 'Additional CSS classes to apply',
|
|
28
|
+
},
|
|
29
|
+
onDismiss: {
|
|
30
|
+
action: 'dismiss',
|
|
31
|
+
description: 'Event emitted when the dismiss button is clicked',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
args: {
|
|
35
|
+
variant: 'stroke',
|
|
36
|
+
dismissable: false,
|
|
37
|
+
disabled: false,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default meta;
|
|
42
|
+
type Story = StoryObj<typeof Tag>;
|
|
43
|
+
|
|
44
|
+
export const Default: Story = {
|
|
45
|
+
args: {},
|
|
46
|
+
render: args => ({
|
|
47
|
+
components: { Tag },
|
|
48
|
+
setup() {
|
|
49
|
+
return { args };
|
|
50
|
+
},
|
|
51
|
+
template: `
|
|
52
|
+
<Tag v-bind="args">
|
|
53
|
+
Tag
|
|
54
|
+
</Tag>
|
|
55
|
+
`,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Variants: Story = {
|
|
60
|
+
render: () => ({
|
|
61
|
+
components: { Tag },
|
|
62
|
+
template: `
|
|
63
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
64
|
+
<Tag variant="stroke">Stroke Variant</Tag>
|
|
65
|
+
<Tag variant="gray">Gray Variant</Tag>
|
|
66
|
+
</div>
|
|
67
|
+
`,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const Dismissable: Story = {
|
|
72
|
+
render: args => ({
|
|
73
|
+
components: { Tag },
|
|
74
|
+
setup() {
|
|
75
|
+
function handleDismiss(): void {};
|
|
76
|
+
return { args, handleDismiss };
|
|
77
|
+
},
|
|
78
|
+
template: `
|
|
79
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
80
|
+
<Tag variant="stroke" dismissable @dismiss="handleDismiss">Dismissable Stroke</Tag>
|
|
81
|
+
<Tag variant="gray" dismissable @dismiss="handleDismiss">Dismissable Gray</Tag>
|
|
82
|
+
</div>
|
|
83
|
+
`,
|
|
84
|
+
}),
|
|
85
|
+
args: {
|
|
86
|
+
dismissable: true,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const Disabled: Story = {
|
|
91
|
+
render: () => ({
|
|
92
|
+
components: { Tag },
|
|
93
|
+
template: `
|
|
94
|
+
<div style="display: flex; gap: 12px; align-items: center;">
|
|
95
|
+
<Tag disabled variant="stroke">Disabled Stroke</Tag>
|
|
96
|
+
<Tag disabled variant="gray">Disabled Gray</Tag>
|
|
97
|
+
<Tag disabled dismissable variant="stroke">Disabled Dismissable</Tag>
|
|
98
|
+
</div>
|
|
99
|
+
`,
|
|
100
|
+
}),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const TagList: Story = {
|
|
104
|
+
render: () => ({
|
|
105
|
+
components: { Tag },
|
|
106
|
+
setup() {
|
|
107
|
+
const tags = ref([
|
|
108
|
+
{ id: 1, text: 'Facebook' },
|
|
109
|
+
{ id: 2, text: 'Google Analytics' },
|
|
110
|
+
{ id: 3, text: 'Snap' },
|
|
111
|
+
{ id: 4, text: 'TikTok' },
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
const removeTag = (id: number): void => {
|
|
115
|
+
tags.value = tags.value.filter(tag => tag.id !== id);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
return { tags, removeTag };
|
|
119
|
+
},
|
|
120
|
+
template: `
|
|
121
|
+
<div style="display: flex; gap: 8px; align-items: center; flex-wrap: wrap; min-height: 32px;">
|
|
122
|
+
<Tag
|
|
123
|
+
v-for="tag in tags"
|
|
124
|
+
:key="tag.id"
|
|
125
|
+
:variant="tag.variant"
|
|
126
|
+
dismissable
|
|
127
|
+
@dismiss="removeTag(tag.id)"
|
|
128
|
+
>
|
|
129
|
+
{{ tag.text }}
|
|
130
|
+
</Tag>
|
|
131
|
+
</div>
|
|
132
|
+
`,
|
|
133
|
+
}),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const WithIcon: Story = {
|
|
137
|
+
render: () => ({
|
|
138
|
+
components: { Tag },
|
|
139
|
+
template: `
|
|
140
|
+
<Tag variant="stroke">
|
|
141
|
+
<i class="i-celeste-star-line" />
|
|
142
|
+
Star
|
|
143
|
+
</Tag>
|
|
144
|
+
`,
|
|
145
|
+
}),
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const WithImage: Story = {
|
|
149
|
+
render: () => ({
|
|
150
|
+
components: { Tag },
|
|
151
|
+
template: `
|
|
152
|
+
<Tag variant="stroke">
|
|
153
|
+
<img
|
|
154
|
+
width="16"
|
|
155
|
+
height="16"
|
|
156
|
+
style="object-fit: fill; clip-path: circle()"
|
|
157
|
+
src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Flag_of_the_United_States.png/1024px-Flag_of_the_United_States.png" alt="USA" />
|
|
158
|
+
United States of America
|
|
159
|
+
</Tag>
|
|
160
|
+
`,
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'vue';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<TagProps>(), {
|
|
6
|
+
variant: 'stroke',
|
|
7
|
+
dismissable: false,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
defineEmits<TagEmits>();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
export interface TagProps {
|
|
15
|
+
variant?: 'stroke' | 'gray';
|
|
16
|
+
class?: HTMLAttributes['class'];
|
|
17
|
+
dismissable?: boolean;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface TagEmits {
|
|
22
|
+
dismiss: [];
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<div
|
|
28
|
+
:class="clsx('celeste-tag', props.class)"
|
|
29
|
+
:data-tag-variant="variant"
|
|
30
|
+
:aria-disabled="disabled"
|
|
31
|
+
>
|
|
32
|
+
<slot />
|
|
33
|
+
<button
|
|
34
|
+
v-if="dismissable"
|
|
35
|
+
:disabled="disabled"
|
|
36
|
+
class="celeste-tag-dismiss-button"
|
|
37
|
+
aria-label="dismiss"
|
|
38
|
+
@click.prevent.stop="$emit('dismiss')"
|
|
39
|
+
>
|
|
40
|
+
<i class="i-celeste-close-line" />
|
|
41
|
+
</button>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<style scoped lang="scss">
|
|
46
|
+
.celeste-tag {
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
padding: var(--spacing-4) var(--spacing-8);
|
|
51
|
+
transition: background-color, border-color;
|
|
52
|
+
transition-duration: var(--animation-fast);
|
|
53
|
+
transition-timing-function: ease-out;
|
|
54
|
+
border: 1px solid transparent;
|
|
55
|
+
border-radius: var(--radius-6);
|
|
56
|
+
color: var(--color-text-sub-600);
|
|
57
|
+
font: var(--label-xs);
|
|
58
|
+
gap: var(--spacing-4);
|
|
59
|
+
|
|
60
|
+
&[data-tag-variant='stroke']:not([aria-disabled='true']) {
|
|
61
|
+
border-color: var(--color-stroke-soft-200);
|
|
62
|
+
background-color: var(--color-bg-white-0);
|
|
63
|
+
|
|
64
|
+
&:hover {
|
|
65
|
+
border-color: transparent;
|
|
66
|
+
background-color: var(--color-bg-weak-50);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
&[data-tag-variant='gray']:not([aria-disabled='true']) {
|
|
71
|
+
border-color: transparent;
|
|
72
|
+
background-color: var(--color-bg-weak-50);
|
|
73
|
+
|
|
74
|
+
&:hover {
|
|
75
|
+
border-color: var(--color-stroke-soft-200);
|
|
76
|
+
background-color: var(--color-bg-white-0);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.celeste-tag-dismiss-button {
|
|
81
|
+
--size: 16px;
|
|
82
|
+
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
width: var(--size);
|
|
87
|
+
height: var(--size);
|
|
88
|
+
margin-inline-end: calc(var(--spacing-4) * -1);
|
|
89
|
+
padding: var(--spacing-0);
|
|
90
|
+
border: none;
|
|
91
|
+
border-radius: calc(var(--radius-4) / 2);
|
|
92
|
+
background-color: transparent;
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
|
|
95
|
+
i {
|
|
96
|
+
transition: background-color var(--animation-fast) ease-out;
|
|
97
|
+
background-color: var(--color-icon-soft-400);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&:disabled {
|
|
101
|
+
cursor: auto;
|
|
102
|
+
|
|
103
|
+
i {
|
|
104
|
+
background-color: var(--color-icon-disabled-300);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&:focus:not([aria-disabled='true']) {
|
|
109
|
+
outline: none;
|
|
110
|
+
box-shadow: var(--shadow-buttons-important-focus);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&:not(:disabled):hover {
|
|
114
|
+
i {
|
|
115
|
+
background-color: var(--color-icon-sub-600);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
&[aria-disabled='true'] {
|
|
121
|
+
background-color: var(--color-bg-weak-50);
|
|
122
|
+
color: var(--color-text-disabled-300);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
</style>
|