edvoyui-component-library-test-flight 0.0.132 → 0.0.134
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/button/EUIButtonGroup.vue.d.ts +1 -1
- package/dist/library-vue-ts.cjs.js +39 -39
- package/dist/library-vue-ts.css +1 -1
- package/dist/library-vue-ts.es.js +5150 -4965
- package/dist/library-vue-ts.umd.js +36 -36
- package/dist/tabs/EUITabOutline.vue.d.ts +5 -0
- package/dist/tabs/EUITabOutline.vue.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/HelloWorld.vue +69 -0
- package/src/components/button/EUIButtonGroup.vue +32 -11
- package/src/components/index.ts +2 -0
- package/src/components/tabs/EUITabOutline.vue +263 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import _sfc_main from "/Volumes/work/repos/edvoy-ui-v2/src/components/tabs/EUITabOutline.vue?vue&type=script&setup=true&lang.ts";
|
|
2
|
+
export * from "/Volumes/work/repos/edvoy-ui-v2/src/components/tabs/EUITabOutline.vue?vue&type=script&setup=true&lang.ts";
|
|
3
|
+
import "/Volumes/work/repos/edvoy-ui-v2/src/components/tabs/EUITabOutline.vue?vue&type=style&index=0&lang.scss";
|
|
4
|
+
export default _sfc_main;
|
|
5
|
+
//# sourceMappingURL=EUITabOutline.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EUITabOutline.vue.d.ts","sourceRoot":"","sources":["../../src/components/tabs/EUITabOutline.vue"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,0GAA0G,CAAC;AACjI,cAAc,0GAA0G,CAAC;AACzH,OAAO,wGAAwG,CAAC;AAChH,eAAe,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -5,9 +5,78 @@
|
|
|
5
5
|
>
|
|
6
6
|
Edvoy User Interface
|
|
7
7
|
</h1>
|
|
8
|
+
|
|
9
|
+
<div class="mb-10">
|
|
10
|
+
<EUITabOutline
|
|
11
|
+
activeColor="purple"
|
|
12
|
+
size="sm"
|
|
13
|
+
:items="allDays"
|
|
14
|
+
:defaultActive="activeTab"
|
|
15
|
+
@update:activeTabItem="onchangeActiveTab"
|
|
16
|
+
>
|
|
17
|
+
<template v-slot:content="{ data, activeName }">
|
|
18
|
+
<div class="space-y-4">
|
|
19
|
+
<span class="text-red-400">{{ data.name }} - {{ activeName }}</span>
|
|
20
|
+
<p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Sit odio
|
|
21
|
+
quia, obcaecati suscipit, praesentium temporibus, non placeat
|
|
22
|
+
reprehenderit commodi ut adipisci consequatur laboriosam? Est
|
|
23
|
+
perspiciatis vero illo repudiandae quis explicabo.</p>
|
|
24
|
+
|
|
25
|
+
<p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Sit odio
|
|
26
|
+
quia, obcaecati suscipit, praesentium temporibus, non placeat
|
|
27
|
+
reprehenderit commodi ut adipisci consequatur laboriosam? Est
|
|
28
|
+
perspiciatis vero illo repudiandae quis explicabo.</p>
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
</EUITabOutline>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div>
|
|
35
|
+
<EUIButtonGroup
|
|
36
|
+
activeColor="purple"
|
|
37
|
+
size="sm"
|
|
38
|
+
:rounded="false"
|
|
39
|
+
:items="allDays"
|
|
40
|
+
:defaultActive="activeDays"
|
|
41
|
+
@update:activeButton="onchangeDays"
|
|
42
|
+
>
|
|
43
|
+
<template #before>
|
|
44
|
+
<div
|
|
45
|
+
class="px-2 text-sm font-normal leading-tight tracking-wide text-black me-4 font-inter"
|
|
46
|
+
>
|
|
47
|
+
Renewals due in <span class="font-bold text-red-500 text-xxs"> {{ activeDays }}</span>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
<template #default="{ data, activeName}">
|
|
51
|
+
{{ data.name }} <small :class="activeName === data.name ? 'opacity-100': 'opacity-75'">({{ data.count }})</small>
|
|
52
|
+
</template>
|
|
53
|
+
</EUIButtonGroup>
|
|
54
|
+
</div>
|
|
8
55
|
</div>
|
|
9
56
|
</template>
|
|
10
57
|
<script setup lang="ts">
|
|
58
|
+
import { ref } from "vue";
|
|
59
|
+
import EUITabOutline from "./tabs/EUITabOutline.vue";
|
|
60
|
+
import EUIButtonGroup from "./button/EUIButtonGroup.vue";
|
|
61
|
+
|
|
62
|
+
const allDays = ref([
|
|
63
|
+
{ name: "7 days", count: 5 },
|
|
64
|
+
{ name: "15 days", count: 10 },
|
|
65
|
+
{ name: "16-30 days", count: 20 },
|
|
66
|
+
{ name: "31-60 days", count: 121 },
|
|
67
|
+
{ name: "61-90 days", count: 40 },
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
const activeDays = ref(allDays.value[0].name);
|
|
71
|
+
const activeTab = ref(allDays.value[3].name)
|
|
72
|
+
|
|
73
|
+
const onchangeActiveTab = (val: any) => {
|
|
74
|
+
activeTab.value = val.name;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const onchangeDays = (val:any) => {
|
|
78
|
+
activeDays.value = val.name
|
|
79
|
+
}
|
|
11
80
|
</script>
|
|
12
81
|
<style lang="scss"></style>
|
|
13
82
|
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
<div>
|
|
3
|
+
<div
|
|
4
|
+
class="inline-flex items-center gap-2 px-2 py-2 overflow-hidden transition-all duration-200 ease-in bg-white shadow-xl w-max shadow-purple-50"
|
|
5
|
+
:class="[rounded ? 'rounded-full' : 'rounded-lg']"
|
|
6
|
+
v-bind="$attrs"
|
|
5
7
|
>
|
|
6
8
|
<slot name="before" />
|
|
7
9
|
<nav class="relative z-0 inline-flex flex-row items-center gap-2">
|
|
8
|
-
<div
|
|
10
|
+
<div
|
|
11
|
+
id="nav-indicator"
|
|
12
|
+
:class="[
|
|
13
|
+
getBtnClass(activeBtnName),
|
|
14
|
+
rounded ? 'rounded-full' : 'rounded-lg',
|
|
15
|
+
]"
|
|
16
|
+
></div>
|
|
9
17
|
<button
|
|
10
18
|
v-for="(data, index) in items"
|
|
11
19
|
:key="`data-${index}`"
|
|
12
|
-
|
|
20
|
+
v-bind="buttonAttrs"
|
|
13
21
|
:type="type"
|
|
14
22
|
:size="size"
|
|
15
23
|
:iconType="iconType"
|
|
@@ -31,7 +39,9 @@
|
|
|
31
39
|
v-if="iconType === 'icon' || iconType === 'startIcon'"
|
|
32
40
|
:class="[iconWidth]"
|
|
33
41
|
/>
|
|
34
|
-
<slot :data="data" :activeName="activeBtnName">
|
|
42
|
+
<slot :data="data" :activeName="activeBtnName">
|
|
43
|
+
{{ data?.name }}
|
|
44
|
+
</slot>
|
|
35
45
|
<component
|
|
36
46
|
:is="icon"
|
|
37
47
|
v-if="iconType === 'endIcon'"
|
|
@@ -63,6 +73,7 @@
|
|
|
63
73
|
</nav>
|
|
64
74
|
<slot name="after" />
|
|
65
75
|
</div>
|
|
76
|
+
</div>
|
|
66
77
|
</template>
|
|
67
78
|
|
|
68
79
|
<script setup lang="ts">
|
|
@@ -74,6 +85,7 @@ import {
|
|
|
74
85
|
reactive,
|
|
75
86
|
ref,
|
|
76
87
|
toRefs,
|
|
88
|
+
useAttrs,
|
|
77
89
|
} from "vue";
|
|
78
90
|
|
|
79
91
|
interface Item {
|
|
@@ -87,8 +99,8 @@ const props = defineProps({
|
|
|
87
99
|
default: () => [],
|
|
88
100
|
},
|
|
89
101
|
defaultActive: {
|
|
90
|
-
type:
|
|
91
|
-
default:
|
|
102
|
+
type:String,
|
|
103
|
+
default: '',
|
|
92
104
|
},
|
|
93
105
|
type: {
|
|
94
106
|
type: String as PropType<"button" | "submit" | "reset">,
|
|
@@ -126,8 +138,17 @@ const props = defineProps({
|
|
|
126
138
|
disabled: Boolean,
|
|
127
139
|
});
|
|
128
140
|
|
|
141
|
+
defineOptions({
|
|
142
|
+
inheritAttrs: false, // 🛑 prevents auto-inheritance of $attrs to root
|
|
143
|
+
})
|
|
144
|
+
const attrs = useAttrs()
|
|
145
|
+
const buttonAttrs = computed(() => {
|
|
146
|
+
const { class: _class, style: _style, id: _id, ...rest } = attrs;
|
|
147
|
+
return rest;
|
|
148
|
+
});
|
|
149
|
+
|
|
129
150
|
const emit = defineEmits<{
|
|
130
|
-
(event: "update:
|
|
151
|
+
(event: "update:activeButton", activeButton: Item): void;
|
|
131
152
|
}>();
|
|
132
153
|
|
|
133
154
|
const { items, defaultActive } = toRefs(props);
|
|
@@ -141,9 +162,9 @@ const marker = (el: HTMLElement) => {
|
|
|
141
162
|
}
|
|
142
163
|
};
|
|
143
164
|
|
|
144
|
-
const handleOnChange = (val:any) => {
|
|
165
|
+
const handleOnChange = (val: any) => {
|
|
145
166
|
activeBtnName.value = val?.name;
|
|
146
|
-
emit("update:
|
|
167
|
+
emit("update:activeButton", val);
|
|
147
168
|
nextTick(() => {
|
|
148
169
|
const activeBtn = document.querySelector(
|
|
149
170
|
`nav button[data-name="${activeBtnName.value}"]`
|
package/src/components/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ export { default as EUISlideover } from "./slideover/EUISlideover.vue";
|
|
|
24
24
|
export { default as EUIDatepicker } from "./datepicker/EUIDatepicker.vue";
|
|
25
25
|
|
|
26
26
|
export { default as EUITabs } from "./tabs/EUITabs.vue";
|
|
27
|
+
export { default as EUITabOutline } from "./tabs/EUITabOutline.vue";
|
|
28
|
+
|
|
27
29
|
export { default as EUIPillSelect } from "./pillSelect/EUIPillSelect.vue";
|
|
28
30
|
export { default as EUITimeLine } from "./timeLine/EUITimeLine.vue";
|
|
29
31
|
export { default as EUITag } from "./tag/EUITag.vue";
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="bg-white" v-bind="$attrs">
|
|
3
|
+
<div
|
|
4
|
+
class="relative z-10 inline-flex items-center w-full gap-2 pt-3 overflow-hidden transition-all duration-200 ease-in border border-b-0 border-solid rounded-t-xl isolate before:h-4 before:w-px before:bg-gray-200 before:-bottom-3 before:-left-px before:absolute after:h-4 after:w-px after:bg-gray-200 after:-bottom-3 after:-right-px after:absolute bg-gradient-to-b from-gray-100"
|
|
5
|
+
>
|
|
6
|
+
<nav
|
|
7
|
+
class="relative z-0 inline-flex flex-row items-center w-full gap-2 px-6"
|
|
8
|
+
>
|
|
9
|
+
<div
|
|
10
|
+
id="tab-indicator"
|
|
11
|
+
:style="{
|
|
12
|
+
'--border': allColor[activeColor],
|
|
13
|
+
}"
|
|
14
|
+
>
|
|
15
|
+
<span></span>
|
|
16
|
+
</div>
|
|
17
|
+
<button
|
|
18
|
+
v-for="(data, index) in items"
|
|
19
|
+
:key="`data-${index}`"
|
|
20
|
+
v-bind="buttonAttrs"
|
|
21
|
+
:data-tab="data.name"
|
|
22
|
+
:class="[
|
|
23
|
+
'capitalize box-border border-none inline-flex flex-row gap-x-2 items-center',
|
|
24
|
+
getBtnClass(data.name || ''),
|
|
25
|
+
activeBtnName === data.name ? 'font-semibold' : 'font-normal',
|
|
26
|
+
]"
|
|
27
|
+
:disabled="disabled"
|
|
28
|
+
:loading="loading"
|
|
29
|
+
@click="handleOnChange(data || '')"
|
|
30
|
+
style="transition: all 350ms cubic-bezier(0.15, 0.3, 0.25, 1)"
|
|
31
|
+
>
|
|
32
|
+
<component
|
|
33
|
+
:is="icon"
|
|
34
|
+
v-if="iconType === 'icon' || iconType === 'startIcon'"
|
|
35
|
+
:class="[iconWidth]"
|
|
36
|
+
/>
|
|
37
|
+
<slot :data="data" :activeName="activeBtnName">
|
|
38
|
+
{{ data?.name }}
|
|
39
|
+
</slot>
|
|
40
|
+
<component
|
|
41
|
+
:is="icon"
|
|
42
|
+
v-if="iconType === 'endIcon'"
|
|
43
|
+
:class="[iconWidth]"
|
|
44
|
+
/>
|
|
45
|
+
<svg
|
|
46
|
+
v-if="loading"
|
|
47
|
+
class="animate-spin"
|
|
48
|
+
:class="[iconWidth]"
|
|
49
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
50
|
+
fill="none"
|
|
51
|
+
viewBox="0 0 24 24"
|
|
52
|
+
>
|
|
53
|
+
<circle
|
|
54
|
+
class="opacity-25"
|
|
55
|
+
cx="12"
|
|
56
|
+
cy="12"
|
|
57
|
+
r="10"
|
|
58
|
+
stroke="currentColor"
|
|
59
|
+
stroke-width="4"
|
|
60
|
+
/>
|
|
61
|
+
<path
|
|
62
|
+
fill="currentColor"
|
|
63
|
+
class="opacity-75"
|
|
64
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
65
|
+
/>
|
|
66
|
+
</svg>
|
|
67
|
+
</button>
|
|
68
|
+
</nav>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div
|
|
72
|
+
class="relative z-0 px-4 py-4 -mt-px text-gray-500 border border-gray-200 border-solid rounded-b-xl"
|
|
73
|
+
>
|
|
74
|
+
<template v-for="(data, index) in items" :key="`data-${index}`">
|
|
75
|
+
<slot
|
|
76
|
+
v-if="data.name === activeBtnName"
|
|
77
|
+
name="content"
|
|
78
|
+
:data="data"
|
|
79
|
+
:activeName="activeBtnName"
|
|
80
|
+
>
|
|
81
|
+
{{ data.name }}
|
|
82
|
+
</slot>
|
|
83
|
+
</template>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<script setup lang="ts">
|
|
89
|
+
import {
|
|
90
|
+
computed,
|
|
91
|
+
nextTick,
|
|
92
|
+
onMounted,
|
|
93
|
+
PropType,
|
|
94
|
+
reactive,
|
|
95
|
+
ref,
|
|
96
|
+
toRefs,
|
|
97
|
+
useAttrs,
|
|
98
|
+
} from "vue";
|
|
99
|
+
|
|
100
|
+
interface Item {
|
|
101
|
+
name: string;
|
|
102
|
+
[key: string]: any;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const props = defineProps({
|
|
106
|
+
items: {
|
|
107
|
+
type: Array as () => Item[],
|
|
108
|
+
default: () => [],
|
|
109
|
+
},
|
|
110
|
+
defaultActive: {
|
|
111
|
+
type: String,
|
|
112
|
+
default: "",
|
|
113
|
+
},
|
|
114
|
+
type: {
|
|
115
|
+
type: String,
|
|
116
|
+
default: "button",
|
|
117
|
+
},
|
|
118
|
+
size: {
|
|
119
|
+
type: String as PropType<"sm" | "md" | "lg">,
|
|
120
|
+
default: "md",
|
|
121
|
+
},
|
|
122
|
+
activeColor: {
|
|
123
|
+
type: String as PropType<"success" | "black" | "purple" | "default">,
|
|
124
|
+
default: "black",
|
|
125
|
+
},
|
|
126
|
+
iconType: {
|
|
127
|
+
type: String as PropType<"startIcon" | "endIcon" | "icon">,
|
|
128
|
+
default: "",
|
|
129
|
+
},
|
|
130
|
+
icon: {
|
|
131
|
+
type: [String, Object, Function],
|
|
132
|
+
default: "",
|
|
133
|
+
},
|
|
134
|
+
loading: Boolean,
|
|
135
|
+
disabled: Boolean,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const emit = defineEmits<{
|
|
139
|
+
(event: "update:activeTabItem", activeTabItem: Item): void;
|
|
140
|
+
}>();
|
|
141
|
+
|
|
142
|
+
defineOptions({
|
|
143
|
+
inheritAttrs: false, // 🛑 prevents auto-inheritance of $attrs to root
|
|
144
|
+
});
|
|
145
|
+
const attrs = useAttrs();
|
|
146
|
+
const buttonAttrs = computed(() => {
|
|
147
|
+
const { class: _class, style: _style, id: _id, ...rest } = attrs;
|
|
148
|
+
return rest;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const { items, defaultActive } = toRefs(props);
|
|
152
|
+
const activeBtnName = ref(defaultActive.value || items.value[0]?.name || "");
|
|
153
|
+
|
|
154
|
+
const marker = (el: HTMLElement) => {
|
|
155
|
+
const indicator = document.querySelector("#tab-indicator") as HTMLElement;
|
|
156
|
+
if (indicator && el) {
|
|
157
|
+
indicator.style.left = el.offsetLeft + "px";
|
|
158
|
+
indicator.style.width = el.offsetWidth + "px";
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const handleOnChange = (val: any) => {
|
|
163
|
+
activeBtnName.value = val?.name;
|
|
164
|
+
emit("update:activeTabItem", val);
|
|
165
|
+
nextTick(() => {
|
|
166
|
+
const activeBtn = document.querySelector(
|
|
167
|
+
`nav button[data-tab="${activeBtnName.value}"]`
|
|
168
|
+
);
|
|
169
|
+
if (activeBtn) marker(activeBtn as HTMLElement);
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
onMounted(() => {
|
|
174
|
+
nextTick(() => {
|
|
175
|
+
requestAnimationFrame(() => {
|
|
176
|
+
const activeBtn = document.querySelector(
|
|
177
|
+
`nav button[data-tab="${activeBtnName.value}"]`
|
|
178
|
+
);
|
|
179
|
+
if (activeBtn) marker(activeBtn as HTMLElement);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const btnColors = {
|
|
185
|
+
default: {
|
|
186
|
+
enabled: "text-gray-500 cursor-pointer hover:text-gray-700",
|
|
187
|
+
disabled: "bg-opacity-60 cursor-not-allowed text-gray-200 bg-gray-800",
|
|
188
|
+
},
|
|
189
|
+
black: {
|
|
190
|
+
enabled: "text-black cursor-pointer",
|
|
191
|
+
disabled: "cursor-not-allowed text-gray-300",
|
|
192
|
+
},
|
|
193
|
+
success: {
|
|
194
|
+
enabled: "text-green-600 cursor-pointer",
|
|
195
|
+
disabled: "cursor-not-allowed text-green-700/60",
|
|
196
|
+
},
|
|
197
|
+
purple: {
|
|
198
|
+
enabled: "text-purple-600 cursor-pointer",
|
|
199
|
+
disabled: "cursor-not-allowed text-purple-400",
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const iconClasses = {
|
|
204
|
+
lg: props.iconType === "icon" ? "p-3" : "px-6 py-3",
|
|
205
|
+
md: props.iconType === "icon" ? "p-2" : "px-4 py-2",
|
|
206
|
+
sm: props.iconType === "icon" ? "p-1.5" : "px-4 py-1.5",
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const iconWidthClasses = reactive({
|
|
210
|
+
sm: "w-5 h-5 text-current",
|
|
211
|
+
md: "w-6 h-6 text-current",
|
|
212
|
+
lg: "w-6 h-6 text-current",
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const iconWidth = computed(() => {
|
|
216
|
+
return iconWidthClasses[props.size] || "";
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const getBtnClass = (btnName: string) => {
|
|
220
|
+
const isActive = btnName === activeBtnName.value;
|
|
221
|
+
const colorKey = isActive ? props.activeColor : "default";
|
|
222
|
+
const state = props.disabled ? "disabled" : "enabled";
|
|
223
|
+
const colorClass = btnColors[colorKey] ? btnColors[colorKey][state] : "";
|
|
224
|
+
const sizeClass = props.size === "sm" ? "text-sm" : "text-base";
|
|
225
|
+
const typeClass = iconClasses[props.size] || "";
|
|
226
|
+
return `${colorClass} ${sizeClass} ${typeClass}`;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const allColor = {
|
|
230
|
+
purple: "#7c3aed",
|
|
231
|
+
success: "#16a34a",
|
|
232
|
+
black: "#000",
|
|
233
|
+
default: "#9ca3af",
|
|
234
|
+
};
|
|
235
|
+
</script>
|
|
236
|
+
|
|
237
|
+
<style lang="scss">
|
|
238
|
+
:root {
|
|
239
|
+
--clr: theme("colors.white");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
#tab-indicator {
|
|
243
|
+
transition: all 350ms cubic-bezier(0.15, 0.3, 0.25, 1);
|
|
244
|
+
background-image: linear-gradient(90deg, #fff, #fff),
|
|
245
|
+
linear-gradient(to top, #e5e7eb, #e5e7eb, var(--border));
|
|
246
|
+
background-origin: border-box;
|
|
247
|
+
background-clip: padding-box, border-box;
|
|
248
|
+
@apply absolute left-0 w-auto h-full top-0 -z-[1] rounded-t-xl border-solid border-t-2 border bg-white p-2 border-transparent;
|
|
249
|
+
&::before {
|
|
250
|
+
content: "";
|
|
251
|
+
box-shadow: 5px 5px 0 5px var(--clr);
|
|
252
|
+
@apply absolute -bottom-px -left-3 size-3 bg-transparent border border-gray-200 border-solid border-l-0 border-t-0 rounded-br-2xl;
|
|
253
|
+
}
|
|
254
|
+
&::after {
|
|
255
|
+
content: "";
|
|
256
|
+
box-shadow: -5px 5px 0 5px var(--clr);
|
|
257
|
+
@apply absolute -bottom-px -right-3 size-3 bg-transparent border border-gray-200 border-solid border-r-0 border-t-0 rounded-bl-2xl;
|
|
258
|
+
}
|
|
259
|
+
span {
|
|
260
|
+
@apply bg-white w-full h-1 absolute -bottom-px inset-x-0 z-[1];
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
</style>
|