main
vue 188 lines 3.51 KB
Raw
1 <template>
2 <component
3 :is="!!href ? 'a' : 'div'"
4 class="badge"
5 :href
6 :class="[type, color, { 'cursor-help': hintCursor, cursor: pointCursor, fluid, bright }, `badge-size-${size}`]"
7 >
8 <span v-if="$slots.label || $slots.iconLeft || $slots.iconRight" class="flex items-center gap-2">
9 <slot name="iconLeft"></slot>
10 <slot name="label"></slot>
11 <slot name="iconRight"></slot>
12 </span>
13 <span v-if="$slots.value" class="flex items-center gap-2">
14 <slot name="value"></slot>
15 </span>
16 </component>
17 </template>
18
19 <script setup lang="ts">
20 export type BadgeColor = "danger" | "warning" | "success" | "primary"
21
22 // TODO-FE: refactor
23 const { type, hintCursor, pointCursor, color, href, fluid, size } = defineProps<{
24 type?: "splitted" | "muted" | "active" | "cursor"
25 hintCursor?: boolean
26 pointCursor?: boolean
27 fluid?: boolean
28 bright?: boolean
29 color?: BadgeColor
30 href?: string
31 size?: "small" | "medium"
32 }>()
33 </script>
34
35 <style lang="scss" scoped>
36 .badge {
37 border-radius: var(--border-radius);
38 border: 1px solid var(--border-color);
39 display: flex;
40 align-items: center;
41 font-size: 14px;
42 padding: 0px 6px;
43 height: 28px;
44 line-height: 1;
45 gap: 6px;
46 transition: all 0.3s var(--bezier-ease);
47
48 &.muted {
49 span,
50 i {
51 opacity: 0.5;
52 }
53 }
54
55 &.active {
56 color: var(--success-color);
57 background-color: rgba(var(--success-color-rgb) / 0.05);
58 border-color: var(--success-color);
59 }
60
61 &.cursor {
62 cursor: pointer;
63
64 &:hover {
65 color: var(--primary-color);
66 border-color: var(--primary-color);
67 }
68 }
69
70 span:not(:last-child) {
71 border-right: 1px solid var(--border-color);
72 padding-right: 8px;
73 }
74
75 &.splitted {
76 padding: 0px;
77 gap: 0;
78 overflow: hidden;
79
80 & > span {
81 padding: 0px 8px;
82 height: 100%;
83 line-height: 24px;
84
85 &:first-child {
86 background-color: rgba(var(--border-color-rgb) / 0.05);
87 white-space: nowrap;
88 }
89 &:last-child {
90 font-family: var(--font-family-mono);
91 font-size: 0.9em;
92 }
93 }
94
95 &.danger {
96 & > span {
97 &:first-child {
98 background-color: rgba(var(--error-color-rgb) / 0.1);
99 }
100 }
101 }
102 &.warning {
103 & > span {
104 &:first-child {
105 background-color: rgba(var(--warning-color-rgb) / 0.1);
106 }
107 }
108 }
109 &.success {
110 & > span {
111 &:first-child {
112 background-color: rgba(var(--success-color-rgb) / 0.1);
113 }
114 }
115 }
116 &.primary {
117 & > span {
118 &:first-child {
119 background-color: rgba(var(--primary-color-rgb) / 0.1);
120 }
121 }
122 }
123
124 &.bright {
125 &.danger {
126 border-color: rgba(var(--error-color-rgb) / 0.3);
127
128 & > span {
129 &:first-child {
130 background-color: rgba(var(--error-color-rgb) / 0.2);
131 }
132 }
133 }
134 &.warning {
135 border-color: rgba(var(--warning-color-rgb) / 0.3);
136
137 & > span {
138 &:first-child {
139 background-color: rgba(var(--warning-color-rgb) / 0.2);
140 }
141 }
142 }
143 &.success {
144 border-color: rgba(var(--success-color-rgb) / 0.3);
145
146 & > span {
147 &:first-child {
148 background-color: rgba(var(--success-color-rgb) / 0.2);
149 }
150 }
151 }
152 &.primary {
153 border-color: rgba(var(--primary-color-rgb) / 0.3);
154
155 & > span {
156 &:first-child {
157 background-color: rgba(var(--primary-color-rgb) / 0.2);
158 }
159 }
160 }
161 }
162 }
163
164 &.fluid {
165 min-height: 28px;
166 height: unset;
167
168 &.splitted {
169 & > span {
170 &:last-child {
171 line-height: 1.1;
172 padding-top: 2px;
173 padding-bottom: 2px;
174 display: flex;
175 align-items: center;
176 }
177 }
178 }
179 }
180
181 &.badge-size-small {
182 font-size: 12px;
183 height: 22px;
184 min-height: 22px;
185 border-radius: var(--border-radius-small);
186 }
187 }
188 </style>