@code-coaching/vuetiful 0.17.1 → 0.18.1
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/README.md +1 -1
- package/dist/style.css +1 -1
- package/dist/styles/all.css +103 -5
- package/dist/types/components/molecules/VTabs/VTab.test.d.ts +1 -0
- package/dist/types/components/molecules/VTabs/VTab.vue.d.ts +14 -0
- package/dist/types/components/molecules/VTabs/VTabPanel.test.d.ts +1 -0
- package/dist/types/components/molecules/VTabs/VTabPanel.vue.d.ts +2 -0
- package/dist/types/components/molecules/VTabs/VTabs.test.d.ts +1 -0
- package/dist/types/components/molecules/VTabs/VTabs.vue.d.ts +86 -0
- package/dist/types/components/molecules/index.d.ts +6 -3
- package/dist/vuetiful.es.mjs +645 -308
- package/dist/vuetiful.umd.js +12 -12
- package/package.json +1 -1
- package/src/components/molecules/VListbox/VListbox.vue +3 -1
- package/src/components/molecules/VTabs/VTab.test.ts +122 -0
- package/src/components/molecules/VTabs/VTab.vue +39 -0
- package/src/components/molecules/VTabs/VTabPanel.test.ts +23 -0
- package/src/components/molecules/VTabs/VTabPanel.vue +9 -0
- package/src/components/molecules/VTabs/VTabs.test.ts +90 -0
- package/src/components/molecules/VTabs/VTabs.vue +84 -0
- package/src/components/molecules/index.ts +15 -7
package/package.json
CHANGED
|
@@ -101,7 +101,9 @@ const showText = computed(() => {
|
|
|
101
101
|
v-model="parentModelValue"
|
|
102
102
|
>
|
|
103
103
|
<v-listbox-label v-if="labelText" :class="labelClasses">{{ labelText }}</v-listbox-label>
|
|
104
|
-
<v-listbox-button data-test="v-listbox-button"
|
|
104
|
+
<v-listbox-button data-test="v-listbox-button" :class="`${background} ${text}`">
|
|
105
|
+
{{ showText }}
|
|
106
|
+
</v-listbox-button>
|
|
105
107
|
<!-- TODO: Add configurable transition -->
|
|
106
108
|
<transition
|
|
107
109
|
enter-active-class="transition duration-150 ease-in-out"
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { mount } from "@vue/test-utils";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
import { VTab, VTabs } from "..";
|
|
4
|
+
|
|
5
|
+
describe("VTab", () => {
|
|
6
|
+
test("defaults", async () => {
|
|
7
|
+
const wrapper = mount({
|
|
8
|
+
template: /*html*/ `
|
|
9
|
+
<v-tabs>
|
|
10
|
+
<template v-slot="tabs">
|
|
11
|
+
<v-tab data-test="vuetiful">Vuetiful</v-tab>
|
|
12
|
+
</template>
|
|
13
|
+
</v-tabs>
|
|
14
|
+
`,
|
|
15
|
+
components: {
|
|
16
|
+
"v-tabs": VTabs,
|
|
17
|
+
"v-tab": VTab,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const vuetiful = wrapper.find("[data-test='vuetiful']");
|
|
22
|
+
const slotContainer = vuetiful.find("[data-test='slot-container']");
|
|
23
|
+
expect(vuetiful.classes()).toEqual(["flex", "flex-col"]);
|
|
24
|
+
expect(slotContainer.classes()).toEqual([
|
|
25
|
+
"text-base",
|
|
26
|
+
"rounded-token",
|
|
27
|
+
"w-full",
|
|
28
|
+
"px-4",
|
|
29
|
+
"py-2",
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("vertical", async () => {
|
|
34
|
+
const wrapper = mount({
|
|
35
|
+
template: /*html*/ `
|
|
36
|
+
<v-tabs vertical>
|
|
37
|
+
<template v-slot="tabs">
|
|
38
|
+
<v-tab data-test="vuetiful">Vuetiful</v-tab>
|
|
39
|
+
</template>
|
|
40
|
+
</v-tabs>
|
|
41
|
+
`,
|
|
42
|
+
components: {
|
|
43
|
+
"v-tabs": VTabs,
|
|
44
|
+
"v-tab": VTab,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const vuetiful = wrapper.find("[data-test='vuetiful']");
|
|
49
|
+
expect(vuetiful.classes()).toEqual(["flex", "flex-row", "justify-between"]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("class-tab", async () => {
|
|
53
|
+
const wrapper = mount({
|
|
54
|
+
template: /*html*/ `
|
|
55
|
+
<v-tabs class-tab="my-custom-class">
|
|
56
|
+
<template v-slot="tabs">
|
|
57
|
+
<v-tab data-test="vuetiful">Vuetiful</v-tab>
|
|
58
|
+
</template>
|
|
59
|
+
</v-tabs>
|
|
60
|
+
`,
|
|
61
|
+
components: {
|
|
62
|
+
"v-tabs": VTabs,
|
|
63
|
+
"v-tab": VTab,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const vuetiful = wrapper.find("[data-test='vuetiful']");
|
|
68
|
+
const slotContainer = vuetiful.find("[data-test='slot-container']");
|
|
69
|
+
expect(slotContainer.classes()).toEqual(["text-base", "rounded-token", "my-custom-class"]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("hover/active", async () => {
|
|
73
|
+
const wrapper = mount({
|
|
74
|
+
template: /*html*/ `
|
|
75
|
+
<v-tabs active="my-custom-active-class">
|
|
76
|
+
<template v-slot="tabs">
|
|
77
|
+
<v-tab data-test="vuetiful">Vuetiful</v-tab>
|
|
78
|
+
<v-tab data-test="is">Is</v-tab>
|
|
79
|
+
<v-tab data-test="beautiful">Beautiful</v-tab>
|
|
80
|
+
</template>
|
|
81
|
+
</v-tabs>
|
|
82
|
+
`,
|
|
83
|
+
components: {
|
|
84
|
+
"v-tabs": VTabs,
|
|
85
|
+
"v-tab": VTab,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const vuetifulSlotContainer = wrapper
|
|
90
|
+
.find("[data-test='vuetiful']")
|
|
91
|
+
.find("[data-test='slot-container']");
|
|
92
|
+
const isSlotContainer = wrapper.find("[data-test='is']").find("[data-test='slot-container']");
|
|
93
|
+
const beautifulSlotContainer = wrapper
|
|
94
|
+
.find("[data-test='beautiful']")
|
|
95
|
+
.find("[data-test='slot-container']");
|
|
96
|
+
|
|
97
|
+
expect(vuetifulSlotContainer.classes()).toEqual([
|
|
98
|
+
"text-base",
|
|
99
|
+
"rounded-token",
|
|
100
|
+
"my-custom-active-class",
|
|
101
|
+
"w-full",
|
|
102
|
+
"px-4",
|
|
103
|
+
"py-2",
|
|
104
|
+
]);
|
|
105
|
+
expect(isSlotContainer.classes()).toEqual([
|
|
106
|
+
"text-base",
|
|
107
|
+
"rounded-token",
|
|
108
|
+
"hover:variant-ghost",
|
|
109
|
+
"w-full",
|
|
110
|
+
"px-4",
|
|
111
|
+
"py-2",
|
|
112
|
+
]);
|
|
113
|
+
expect(beautifulSlotContainer.classes()).toEqual([
|
|
114
|
+
"text-base",
|
|
115
|
+
"rounded-token",
|
|
116
|
+
"hover:variant-ghost",
|
|
117
|
+
"w-full",
|
|
118
|
+
"px-4",
|
|
119
|
+
"py-2",
|
|
120
|
+
]);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Tab } from "@headlessui/vue";
|
|
3
|
+
import { computed, inject } from "vue";
|
|
4
|
+
|
|
5
|
+
defineProps({
|
|
6
|
+
disabled: {
|
|
7
|
+
type: Boolean,
|
|
8
|
+
default: false,
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const activeClass = inject("active") as string;
|
|
13
|
+
const hoverClass = inject("hover") as string;
|
|
14
|
+
const vertical = inject("vertical") as boolean;
|
|
15
|
+
const classTab = inject("classTab") as string;
|
|
16
|
+
const hideSeparator = inject("hideSeparator") as boolean;
|
|
17
|
+
|
|
18
|
+
const tabClass = computed(() => {
|
|
19
|
+
return classTab ? classTab : "w-full px-4 py-2";
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<Tab
|
|
25
|
+
:disabled="disabled"
|
|
26
|
+
v-slot="{ selected }"
|
|
27
|
+
:class="`flex ${vertical ? 'flex-row justify-between' : 'flex-col'}`"
|
|
28
|
+
>
|
|
29
|
+
<div data-test="slot-container" :class="`text-base rounded-token ${selected ? activeClass : hoverClass} ${tabClass}`">
|
|
30
|
+
<slot />
|
|
31
|
+
</div>
|
|
32
|
+
<div
|
|
33
|
+
v-show="selected && !hideSeparator"
|
|
34
|
+
:class="`z-10 border-surface-900-50-token ${
|
|
35
|
+
vertical ? 'mr-[-2px] h-full border-r-2' : 'mb-[-2px] border-b-2'
|
|
36
|
+
}`"
|
|
37
|
+
></div>
|
|
38
|
+
</Tab>
|
|
39
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TabGroup } from "@headlessui/vue";
|
|
2
|
+
import { mount } from "@vue/test-utils";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { VTabPanel } from "..";
|
|
5
|
+
|
|
6
|
+
describe("VTabs", () => {
|
|
7
|
+
test("default props", () => {
|
|
8
|
+
const wrapper = mount({
|
|
9
|
+
template: /*html*/ `
|
|
10
|
+
<TabGroup>
|
|
11
|
+
<v-tab-panel data-test='tab-panel'>John Duck</v-tab-panel>
|
|
12
|
+
</TabGroup>
|
|
13
|
+
`,
|
|
14
|
+
components: {
|
|
15
|
+
TabGroup: TabGroup,
|
|
16
|
+
"v-tab-panel": VTabPanel,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const tabPanel = wrapper.find("[data-test='tab-panel']");
|
|
21
|
+
expect(tabPanel.text()).toEqual("John Duck");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { mount } from "@vue/test-utils";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
import { VTab, VTabPanel, VTabs } from "..";
|
|
4
|
+
|
|
5
|
+
describe("VTabs", () => {
|
|
6
|
+
test("hide separator", () => {
|
|
7
|
+
const wrapper = mount({
|
|
8
|
+
template: /*html*/ `
|
|
9
|
+
<v-tabs hide-separator></v-tabs>
|
|
10
|
+
`,
|
|
11
|
+
components: {
|
|
12
|
+
"v-tabs": VTabs,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const separator = wrapper.find("[data-test='vuetiful-separator']");
|
|
17
|
+
expect(separator.exists()).toBeFalsy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("default props", () => {
|
|
21
|
+
const wrapper = mount({
|
|
22
|
+
template: /*html*/ `
|
|
23
|
+
<v-tabs>
|
|
24
|
+
<template v-slot="tabs">
|
|
25
|
+
<v-tab>John Duck</v-tab>
|
|
26
|
+
</template>
|
|
27
|
+
<v-tab-panel>John Duck Panel</v-tab-panel>
|
|
28
|
+
</v-tabs>
|
|
29
|
+
`,
|
|
30
|
+
components: {
|
|
31
|
+
"v-tabs": VTabs,
|
|
32
|
+
"v-tab": VTab,
|
|
33
|
+
"v-tab-panel": VTabPanel,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const tabList = wrapper.find("[data-test='vuetiful-tab-list']");
|
|
38
|
+
expect(tabList.classes()).toEqual([
|
|
39
|
+
"vuetiful-tab-list",
|
|
40
|
+
"flex",
|
|
41
|
+
"!rounded-bl-none",
|
|
42
|
+
"!rounded-br-none",
|
|
43
|
+
"rounded-container-token",
|
|
44
|
+
]);
|
|
45
|
+
expect(tabList.classes()).not.toContain("flex-col");
|
|
46
|
+
|
|
47
|
+
const tabPanels = wrapper.find("[data-test='vuetiful-tab-panels']");
|
|
48
|
+
expect(tabPanels.classes()).toEqual([
|
|
49
|
+
"vuetiful-tab-panels",
|
|
50
|
+
"!rounded-tl-none",
|
|
51
|
+
"!rounded-tr-none",
|
|
52
|
+
"rounded-container-token",
|
|
53
|
+
]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("vertical", () => {
|
|
57
|
+
const wrapper = mount({
|
|
58
|
+
template: /*html*/ `
|
|
59
|
+
<v-tabs vertical>
|
|
60
|
+
<template v-slot="tabs">
|
|
61
|
+
<v-tab>Tab 1</v-tab>
|
|
62
|
+
</template>
|
|
63
|
+
<v-tab-panel>Panel 1</v-tab-panel>
|
|
64
|
+
</v-tabs>
|
|
65
|
+
`,
|
|
66
|
+
components: {
|
|
67
|
+
"v-tabs": VTabs,
|
|
68
|
+
"v-tab": VTab,
|
|
69
|
+
"v-tab-panel": VTabPanel,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
const tabList = wrapper.find("[data-test='vuetiful-tab-list']");
|
|
73
|
+
expect(tabList.classes()).toEqual([
|
|
74
|
+
"vuetiful-tab-list",
|
|
75
|
+
"flex",
|
|
76
|
+
"flex-col",
|
|
77
|
+
"!rounded-br-none",
|
|
78
|
+
"!rounded-tr-none",
|
|
79
|
+
"rounded-container-token",
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
const tabPanels = wrapper.find("[data-test='vuetiful-tab-panels']");
|
|
83
|
+
expect(tabPanels.classes()).toEqual([
|
|
84
|
+
"vuetiful-tab-panels",
|
|
85
|
+
"!rounded-bl-none",
|
|
86
|
+
"!rounded-tl-none",
|
|
87
|
+
"rounded-container-token",
|
|
88
|
+
]);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { TabGroup, TabList, TabPanels } from "@headlessui/vue";
|
|
3
|
+
import { provide } from "vue";
|
|
4
|
+
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
hideSeparator: {
|
|
7
|
+
type: Boolean,
|
|
8
|
+
default: false,
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
vertical: {
|
|
12
|
+
type: Boolean,
|
|
13
|
+
default: false,
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
active: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: "",
|
|
19
|
+
},
|
|
20
|
+
hover: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: "hover:variant-ghost",
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
classPanels: {
|
|
26
|
+
type: String,
|
|
27
|
+
default: "",
|
|
28
|
+
},
|
|
29
|
+
classTabs: {
|
|
30
|
+
type: String,
|
|
31
|
+
default: "",
|
|
32
|
+
},
|
|
33
|
+
classTab: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: "",
|
|
36
|
+
},
|
|
37
|
+
classSeparator: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: "border border-surface-400-500-token",
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
defaultIndex: {
|
|
43
|
+
type: Number,
|
|
44
|
+
default: 0,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
provide("active", props.active);
|
|
49
|
+
provide("hover", props.hover);
|
|
50
|
+
provide("vertical", props.vertical);
|
|
51
|
+
provide("classTab", props.classTab);
|
|
52
|
+
provide("hideSeparator", props.hideSeparator);
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<TabGroup
|
|
57
|
+
as="div"
|
|
58
|
+
:vertical="vertical"
|
|
59
|
+
:defaultIndex="defaultIndex"
|
|
60
|
+
:class="`${vertical ? 'flex' : ''}`"
|
|
61
|
+
>
|
|
62
|
+
<TabList
|
|
63
|
+
data-test="vuetiful-tab-list"
|
|
64
|
+
:class="`vuetiful-tab-list flex ${vertical ? 'flex-col' : ''} ${
|
|
65
|
+
vertical ? '!rounded-br-none !rounded-tr-none' : '!rounded-bl-none !rounded-br-none'
|
|
66
|
+
} rounded-container-token ${classTabs}`"
|
|
67
|
+
>
|
|
68
|
+
<slot name="tabs" />
|
|
69
|
+
</TabList>
|
|
70
|
+
<div
|
|
71
|
+
data-test="vuetiful-tab-separator"
|
|
72
|
+
v-if="!hideSeparator"
|
|
73
|
+
:class="`${classSeparator}`"
|
|
74
|
+
></div>
|
|
75
|
+
<TabPanels
|
|
76
|
+
data-test="vuetiful-tab-panels"
|
|
77
|
+
:class="`vuetiful-tab-panels ${
|
|
78
|
+
vertical ? '!rounded-bl-none !rounded-tl-none' : '!rounded-tl-none !rounded-tr-none'
|
|
79
|
+
} rounded-container-token ${classPanels}`"
|
|
80
|
+
>
|
|
81
|
+
<slot />
|
|
82
|
+
</TabPanels>
|
|
83
|
+
</TabGroup>
|
|
84
|
+
</template>
|
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import VDrawer from "./VDrawer.vue";
|
|
2
|
+
import VPreview from "./VPreview.vue";
|
|
2
3
|
import VRail from "./VRail.vue";
|
|
3
4
|
import VRailTile from "./VRailTile.vue";
|
|
4
5
|
import VShell from "./VShell.vue";
|
|
5
|
-
|
|
6
|
+
|
|
6
7
|
import VListbox from "./VListbox/VListbox.vue";
|
|
8
|
+
import VListboxButton from "./VListbox/VListboxButton.vue";
|
|
7
9
|
import VListboxItem from "./VListbox/VListboxItem.vue";
|
|
8
10
|
import VListboxItems from "./VListbox/VListboxItems.vue";
|
|
9
11
|
import VListboxLabel from "./VListbox/VListboxLabel.vue";
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
import VTab from "./VTabs/VTab.vue";
|
|
14
|
+
import VTabPanel from "./VTabs/VTabPanel.vue";
|
|
15
|
+
import VTabs from "./VTabs/VTabs.vue";
|
|
11
16
|
|
|
12
17
|
export {
|
|
13
|
-
VRail,
|
|
14
|
-
VRailTile,
|
|
15
|
-
VShell,
|
|
16
18
|
VDrawer,
|
|
17
|
-
VPreview,
|
|
18
19
|
VListbox,
|
|
20
|
+
VListboxButton,
|
|
19
21
|
VListboxItem,
|
|
20
22
|
VListboxItems,
|
|
21
23
|
VListboxLabel,
|
|
22
|
-
|
|
24
|
+
VPreview,
|
|
25
|
+
VRail,
|
|
26
|
+
VRailTile,
|
|
27
|
+
VShell,
|
|
28
|
+
VTab,
|
|
29
|
+
VTabPanel,
|
|
30
|
+
VTabs,
|
|
23
31
|
};
|