@dpa-id-components/dpa-shared-components 20.0.6 → 20.0.7
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/src/components/DpaMediaItem/DpaMediaItem.spec.ts +123 -0
- package/dist/src/components/DpaMediaItem/DpaMediaItem.stories.ts +140 -0
- package/dist/src/components/UiAutocomplete/UiAutocomplete.spec.ts +39 -0
- package/dist/src/components/UiAutocomplete/UiAutocomplete.stories.ts +46 -0
- package/dist/src/components/UiBadge/UiBadge.spec.ts +32 -0
- package/dist/src/components/UiBadge/UiBadge.stories.ts +80 -0
- package/dist/src/components/UiButton/UiButton.spec.ts +136 -0
- package/dist/src/components/UiButton/UiButton.stories.ts +57 -0
- package/dist/src/components/UiButtonGroup/UiButtonGroup.spec.ts +16 -0
- package/dist/src/components/UiButtonGroup/UiButtonGroup.stories.ts +50 -0
- package/dist/src/components/UiCard/UiCard.spec.ts +16 -0
- package/dist/src/components/UiCard/UiCard.stories.ts +30 -0
- package/dist/src/components/UiCheckBoxGroup/UiCheckBoxGroup.spec.ts +67 -0
- package/dist/src/components/UiCheckBoxGroup/UiCheckBoxGroup.stories.ts +59 -0
- package/dist/src/components/UiCheckbox/UiCheckbox.spec.ts +173 -0
- package/dist/src/components/UiCheckbox/UiCheckbox.stories.ts +99 -0
- package/dist/src/components/UiChip/UiChip.spec.ts +75 -0
- package/dist/src/components/UiChip/UiChip.stories.ts +39 -0
- package/dist/src/components/UiCollapseNavigation/UiCollapseNavigation.spec.ts +21 -0
- package/dist/src/components/UiCollapseNavigation/UiCollapseNavigation.stories.ts +66 -0
- package/dist/src/components/UiColorPicker/UiColorPicker.spec.ts +52 -0
- package/dist/src/components/UiColorPicker/UiColorPicker.stories.ts +44 -0
- package/dist/src/components/UiDatePicker/UiDatePicker.spec.ts +335 -0
- package/dist/src/components/UiDatePicker/UiDatePicker.stories.ts +273 -0
- package/dist/src/components/UiDialog/UiDialog.spec.ts +160 -0
- package/dist/src/components/UiDialog/UiDialog.stories.ts +79 -0
- package/dist/src/components/UiFilterBadge/UiFilterBadge.spec.ts +17 -0
- package/dist/src/components/UiFilterBadge/UiFilterBadge.stories.ts +44 -0
- package/dist/src/components/UiFilterBadgeButton/UiFilterBadgeButton.spec.ts +41 -0
- package/dist/src/components/UiFilterBadgeButton/UiFilterBadgeButton.stories.ts +55 -0
- package/dist/src/components/UiFilterButton/UiFilterButton.spec.ts +79 -0
- package/dist/src/components/UiFilterButton/UiFilterButton.stories.ts +88 -0
- package/dist/src/components/UiIcon/IconOverview.stories.vue +23 -0
- package/dist/src/components/UiIcon/UiIcon.spec.ts +56 -0
- package/dist/src/components/UiIcon/UiIcon.stories.ts +48 -0
- package/dist/src/components/UiIconButton/UiIconButton.spec.ts +78 -0
- package/dist/src/components/UiIconButton/UiIconButton.stories.ts +63 -0
- package/dist/src/components/UiInfoContent/UiInfoContent.spec.ts +43 -0
- package/dist/src/components/UiInfoContent/UiInfoContent.stories.ts +56 -0
- package/dist/src/components/UiInput/UiInput.spec.ts +239 -0
- package/dist/src/components/UiInput/UiInput.stories.ts +127 -0
- package/dist/src/components/UiList/UiList.spec.ts +22 -0
- package/dist/src/components/UiList/UiList.stories.ts +64 -0
- package/dist/src/components/UiListItem/UiListItem.spec.ts +99 -0
- package/dist/src/components/UiListItem/UiListItem.stories.ts +83 -0
- package/dist/src/components/UiMenu/UiMenu.spec.ts +319 -0
- package/dist/src/components/UiMenu/UiMenu.stories.ts +634 -0
- package/dist/src/components/UiOverlay/UiOverlay.spec.ts +16 -0
- package/dist/src/components/UiOverlay/UiOverlay.stories.ts +22 -0
- package/dist/src/components/UiOverlayMenu/UiOverlayMenu.spec.ts +32 -0
- package/dist/src/components/UiOverlayMenu/UiOverlayMenu.stories.ts +39 -0
- package/dist/src/components/UiRadioInputGroup/UiRadioInputGroup.spec.ts +66 -0
- package/dist/src/components/UiRadioInputGroup/UiRadioInputGroup.stories.ts +70 -0
- package/dist/src/components/UiSearchBar/UiSearchBar.spec.ts +82 -0
- package/dist/src/components/UiSearchBar/UiSearchBar.stories.ts +191 -0
- package/dist/src/components/UiSearchInput/UiSearchInput.spec.ts +45 -0
- package/dist/src/components/UiSearchInput/UiSearchInput.stories.ts +61 -0
- package/dist/src/components/UiSection/UiSection.spec.ts +49 -0
- package/dist/src/components/UiSection/UiSection.stories.ts +61 -0
- package/dist/src/components/UiSectionDivider/UiSectionDivider.spec.ts +19 -0
- package/dist/src/components/UiSectionDivider/UiSectionDivider.stories.ts +48 -0
- package/dist/src/components/UiSelect/UIiSelect.spec.ts +102 -0
- package/dist/src/components/UiSelect/UiSelect.stories.ts +94 -0
- package/dist/src/components/UiSimpleInput/UiSimpleInput.spec.ts +58 -0
- package/dist/src/components/UiSimpleInput/UiSimpleInput.stories.ts +53 -0
- package/dist/src/components/UiSkeletonBox/UiSkeletonBox.spec.ts +15 -0
- package/dist/src/components/UiSkeletonBox/UiSkeletonBox.stories.ts +33 -0
- package/dist/src/components/UiSnackbar/UiSnackbar.spec.ts +63 -0
- package/dist/src/components/UiSnackbar/UiSnackbar.stories.ts +65 -0
- package/dist/src/components/UiSpinner/UiSpinner.spec.ts +30 -0
- package/dist/src/components/UiSpinner/UiSpinner.stories.ts +48 -0
- package/dist/src/components/UiTextButton/UiTextButton.spec.ts +99 -0
- package/dist/src/components/UiTextButton/UiTextButton.stories.ts +60 -0
- package/dist/src/components/UiToggleButton/UiToggleButton.spec.ts +89 -0
- package/dist/src/components/UiToggleButton/UiToggleButton.stories.ts +102 -0
- package/dist/src/components/UiTooltip/UiTooltip.spec.ts +139 -0
- package/dist/src/components/UiTooltip/UiTooltip.stories.ts +107 -0
- package/dist/src/compositions/useBreakpoints/UseBreakpoints.stories.ts +23 -0
- package/dist/src/compositions/useBreakpoints/UseBreakpoints.stories.vue +12 -0
- package/dist/src/utils/index.spec.ts +12 -0
- package/package.json +5 -4
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { mount } from "@vue/test-utils";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import UiTextButton from "./UiTextButton.vue";
|
|
5
|
+
|
|
6
|
+
describe("UiTextButton", () => {
|
|
7
|
+
it("should render defaults", () => {
|
|
8
|
+
const wrapper = mount(UiTextButton);
|
|
9
|
+
expect(wrapper.classes("font-normal")).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should render semibold font-weight", () => {
|
|
13
|
+
const wrapper = mount(UiTextButton, {
|
|
14
|
+
props: {
|
|
15
|
+
weight: "semibold",
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
expect(wrapper.classes("font-semibold")).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should render xsmall font-size", () => {
|
|
22
|
+
const wrapper = mount(UiTextButton, {
|
|
23
|
+
props: {
|
|
24
|
+
size: "xsmall",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
expect(wrapper.classes("text-xs")).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should render small font-size", () => {
|
|
31
|
+
const wrapper = mount(UiTextButton, {
|
|
32
|
+
props: {
|
|
33
|
+
size: "small",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
expect(wrapper.classes("text-sm")).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should render medium font-size", () => {
|
|
40
|
+
const wrapper = mount(UiTextButton, {
|
|
41
|
+
props: {
|
|
42
|
+
size: "medium",
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
expect(wrapper.classes("text-base")).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should render blue text color", () => {
|
|
49
|
+
const wrapper = mount(UiTextButton, {
|
|
50
|
+
props: {
|
|
51
|
+
color: "blue",
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
expect(wrapper.classes("text-blue-default")).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should render gray text color", () => {
|
|
58
|
+
const wrapper = mount(UiTextButton, {
|
|
59
|
+
props: {
|
|
60
|
+
color: "gray",
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
expect(wrapper.classes("text-gray-700")).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should render iconLeft", () => {
|
|
67
|
+
const iconLeft = "alert";
|
|
68
|
+
const wrapper = mount(UiTextButton, {
|
|
69
|
+
props: {
|
|
70
|
+
iconLeft,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
expect(wrapper.findComponent({ name: "UiIcon" }).props()).toMatchObject({
|
|
74
|
+
name: iconLeft,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should render iconRight", () => {
|
|
79
|
+
const iconRight = "alert";
|
|
80
|
+
const wrapper = mount(UiTextButton, {
|
|
81
|
+
props: {
|
|
82
|
+
iconRight,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
expect(wrapper.findComponent({ name: "UiIcon" }).props()).toMatchObject({
|
|
86
|
+
name: iconRight,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should change gray text color when placement is oncanvas", () => {
|
|
91
|
+
const wrapper = mount(UiTextButton, {
|
|
92
|
+
props: {
|
|
93
|
+
color: "gray",
|
|
94
|
+
placement: "oncanvas",
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
expect(wrapper.classes("text-gray-800")).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
|
|
3
|
+
import { icons } from "../UiIcon/icons.js";
|
|
4
|
+
import UiTextButton from "./UiTextButton.vue";
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Ui/UiTextButton",
|
|
8
|
+
component: UiTextButton,
|
|
9
|
+
argTypes: {
|
|
10
|
+
color: {
|
|
11
|
+
control: "select",
|
|
12
|
+
options: ["blue", "gray"],
|
|
13
|
+
},
|
|
14
|
+
href: { control: "text" },
|
|
15
|
+
linkTarget: { control: "text" },
|
|
16
|
+
iconLeft: {
|
|
17
|
+
control: "select",
|
|
18
|
+
options: Object.keys(icons),
|
|
19
|
+
},
|
|
20
|
+
iconRight: {
|
|
21
|
+
control: "select",
|
|
22
|
+
options: Object.keys(icons),
|
|
23
|
+
},
|
|
24
|
+
placement: {
|
|
25
|
+
control: "select",
|
|
26
|
+
options: ["onsurface", "oncanvas"],
|
|
27
|
+
},
|
|
28
|
+
size: {
|
|
29
|
+
control: "select",
|
|
30
|
+
options: ["xsmall", "small", "medium"],
|
|
31
|
+
},
|
|
32
|
+
weight: {
|
|
33
|
+
control: "select",
|
|
34
|
+
options: ["regular", "semibold"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
args: {
|
|
38
|
+
color: "blue",
|
|
39
|
+
href: undefined,
|
|
40
|
+
iconLeft: undefined,
|
|
41
|
+
iconRight: undefined,
|
|
42
|
+
placement: "onsurface",
|
|
43
|
+
size: "medium",
|
|
44
|
+
weight: "regular",
|
|
45
|
+
linkTarget: undefined,
|
|
46
|
+
},
|
|
47
|
+
} satisfies Meta<typeof UiTextButton>;
|
|
48
|
+
|
|
49
|
+
export default meta;
|
|
50
|
+
type Story = StoryObj<typeof meta>;
|
|
51
|
+
|
|
52
|
+
export const Default: Story = {
|
|
53
|
+
render: (args) => ({
|
|
54
|
+
setup() {
|
|
55
|
+
return { args };
|
|
56
|
+
},
|
|
57
|
+
components: { UiTextButton },
|
|
58
|
+
template: "<UiTextButton v-bind='args'>Link</UiTextButton>",
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { mount } from "@vue/test-utils";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import UiToggleButton from "./UiToggleButton.vue";
|
|
5
|
+
|
|
6
|
+
describe("UiToggleButton", () => {
|
|
7
|
+
const labelText = "Foo";
|
|
8
|
+
const wrapper = mount(UiToggleButton, {
|
|
9
|
+
props: {
|
|
10
|
+
modelValue: false,
|
|
11
|
+
disabled: false,
|
|
12
|
+
labelText: labelText,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("shows correct label text ", () => {
|
|
17
|
+
expect(wrapper.text()).toContain(labelText);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("emits correct event when clicked", async () => {
|
|
21
|
+
const input = wrapper.find("[data-testid='toggleButton']");
|
|
22
|
+
|
|
23
|
+
await input.trigger("click");
|
|
24
|
+
await wrapper.vm.$nextTick();
|
|
25
|
+
expect(wrapper.emitted()["update:modelValue"]).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should render correct colors when checked", async () => {
|
|
29
|
+
await wrapper.setProps({
|
|
30
|
+
modelValue: true,
|
|
31
|
+
color: "green",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const dot = wrapper.find(".dot");
|
|
35
|
+
const line = wrapper.find(".line");
|
|
36
|
+
expect((dot.element as HTMLInputElement).className).toContain(
|
|
37
|
+
"translate-x-full bg-green-primary",
|
|
38
|
+
);
|
|
39
|
+
expect((line.element as HTMLInputElement).className).toContain(
|
|
40
|
+
"opacity-50",
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should render correct size when size=small", async () => {
|
|
45
|
+
await wrapper.setProps({
|
|
46
|
+
modelValue: true,
|
|
47
|
+
size: "small",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const dot = wrapper.find(".dot");
|
|
51
|
+
const line = wrapper.find(".line");
|
|
52
|
+
expect((dot.element as HTMLInputElement).className).toContain("h-4 w-4");
|
|
53
|
+
expect((line.element as HTMLInputElement).className).toContain("h-3 w-6");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should render correct size when size=large", async () => {
|
|
57
|
+
await wrapper.setProps({
|
|
58
|
+
modelValue: true,
|
|
59
|
+
size: "large",
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const dot = wrapper.find(".dot");
|
|
63
|
+
const line = wrapper.find(".line");
|
|
64
|
+
expect((dot.element as HTMLInputElement).className).toContain("h-6 w-6");
|
|
65
|
+
expect((line.element as HTMLInputElement).className).toContain("h-4 w-10");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should show correct disabled value when props are set", async () => {
|
|
69
|
+
await wrapper.setProps({
|
|
70
|
+
disabled: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const input = wrapper.find("[data-testid='toggleButton']");
|
|
74
|
+
expect((input.element as HTMLInputElement).disabled).toBeTruthy();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should render slot content", () => {
|
|
78
|
+
const wrapperWithSlotContent = mount(UiToggleButton, {
|
|
79
|
+
props: {
|
|
80
|
+
modelValue: false,
|
|
81
|
+
disabled: false,
|
|
82
|
+
},
|
|
83
|
+
slots: {
|
|
84
|
+
default: "Slot Label",
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
expect(wrapperWithSlotContent.text()).toContain("Slot Label");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
|
|
4
|
+
import UiIcon from "../UiIcon/UiIcon.vue";
|
|
5
|
+
import UiToggleButton from "./UiToggleButton.vue";
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Ui/UiToggleButton",
|
|
9
|
+
component: UiToggleButton,
|
|
10
|
+
argTypes: {
|
|
11
|
+
color: {
|
|
12
|
+
control: { type: "select" },
|
|
13
|
+
options: ["blue", "green"],
|
|
14
|
+
},
|
|
15
|
+
size: {
|
|
16
|
+
control: { type: "select" },
|
|
17
|
+
options: ["small", "large"],
|
|
18
|
+
},
|
|
19
|
+
modelValue: {
|
|
20
|
+
control: "boolean",
|
|
21
|
+
},
|
|
22
|
+
disabled: {
|
|
23
|
+
control: "boolean",
|
|
24
|
+
},
|
|
25
|
+
labelText: {
|
|
26
|
+
control: "text",
|
|
27
|
+
},
|
|
28
|
+
labelSpace: {
|
|
29
|
+
control: "select",
|
|
30
|
+
options: ["default", "xl"],
|
|
31
|
+
},
|
|
32
|
+
labelPosition: {
|
|
33
|
+
control: "select",
|
|
34
|
+
options: ["left", "right"],
|
|
35
|
+
},
|
|
36
|
+
labelTextSize: {
|
|
37
|
+
control: "select",
|
|
38
|
+
options: ["xs", "sm", "md", "lg"],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
args: {
|
|
42
|
+
color: "blue",
|
|
43
|
+
size: "small",
|
|
44
|
+
modelValue: false,
|
|
45
|
+
disabled: false,
|
|
46
|
+
labelSpace: "default",
|
|
47
|
+
labelTextSize: "xs",
|
|
48
|
+
labelPosition: "left",
|
|
49
|
+
},
|
|
50
|
+
} satisfies Meta<typeof UiToggleButton>;
|
|
51
|
+
|
|
52
|
+
export default meta;
|
|
53
|
+
type Story = StoryObj<typeof meta>;
|
|
54
|
+
|
|
55
|
+
export const Default: Story = {
|
|
56
|
+
render: (args) => ({
|
|
57
|
+
setup() {
|
|
58
|
+
const isChecked = ref(args.modelValue);
|
|
59
|
+
return { args, isChecked };
|
|
60
|
+
},
|
|
61
|
+
components: { UiToggleButton },
|
|
62
|
+
template: `
|
|
63
|
+
<UiToggleButton v-bind='args' v-model='isChecked'>
|
|
64
|
+
Label
|
|
65
|
+
</UiToggleButton>
|
|
66
|
+
`,
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const MultipleToggles: Story = {
|
|
71
|
+
render: (args) => ({
|
|
72
|
+
setup() {
|
|
73
|
+
const isChecked = ref(args.modelValue);
|
|
74
|
+
const secondToggle = ref(true);
|
|
75
|
+
return { args, isChecked, secondToggle };
|
|
76
|
+
},
|
|
77
|
+
components: { UiToggleButton },
|
|
78
|
+
template: `
|
|
79
|
+
<UiToggleButton label-text="first" v-bind='args' v-model='isChecked' />
|
|
80
|
+
<UiToggleButton label-text="second" color="green" v-model='secondToggle' />
|
|
81
|
+
`,
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const WithSlot: Story = {
|
|
86
|
+
args: {
|
|
87
|
+
color: "green",
|
|
88
|
+
},
|
|
89
|
+
render: (args) => ({
|
|
90
|
+
setup() {
|
|
91
|
+
const isChecked = ref(args.modelValue);
|
|
92
|
+
return { args, isChecked };
|
|
93
|
+
},
|
|
94
|
+
components: { UiToggleButton, UiIcon },
|
|
95
|
+
template: `
|
|
96
|
+
<UiToggleButton v-bind="args" v-model="isChecked">
|
|
97
|
+
<div class="flex items-center text-gray-800">
|
|
98
|
+
<UiIcon size="small" name="flag-filled" />
|
|
99
|
+
<span class="pl-1.5">Label</span></div>
|
|
100
|
+
</UiToggleButton>`,
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { mount } from "@vue/test-utils";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import UiTooltip from "./UiTooltip.vue";
|
|
5
|
+
|
|
6
|
+
document.body.innerHTML = `
|
|
7
|
+
<div id="app"></div>
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
describe("UiTooltip", () => {
|
|
11
|
+
it("shows correct content", () => {
|
|
12
|
+
const wrapper = mount(UiTooltip, {
|
|
13
|
+
props: {
|
|
14
|
+
fixed: false,
|
|
15
|
+
},
|
|
16
|
+
slots: {
|
|
17
|
+
default: "tooltip content",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
expect(wrapper.text()).toBe("tooltip content");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("uses the structured tooltip", () => {
|
|
24
|
+
const wrapper = mount(UiTooltip, {
|
|
25
|
+
props: {
|
|
26
|
+
fixed: false,
|
|
27
|
+
structuredLayout: true,
|
|
28
|
+
structuredInfo: [
|
|
29
|
+
{
|
|
30
|
+
title: "Typ",
|
|
31
|
+
description: "Termine",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
title: "Ressort",
|
|
35
|
+
description: "Wirtschaft",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const firstEl = wrapper.findAll("li")[0];
|
|
41
|
+
const secondEl = wrapper.findAll("li")[1];
|
|
42
|
+
expect(firstEl.text()).toBe("TypTermine");
|
|
43
|
+
expect(secondEl.text()).toBe("RessortWirtschaft");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("is not rendered without mouseover", () => {
|
|
47
|
+
const wrapper = mount(UiTooltip, {
|
|
48
|
+
props: {
|
|
49
|
+
fixed: false,
|
|
50
|
+
},
|
|
51
|
+
slots: {
|
|
52
|
+
activator: "<button>activate</button>",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(
|
|
57
|
+
wrapper.find('[data-testid="tooltipElement"]').isVisible(),
|
|
58
|
+
).toBeFalsy();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("is rendered upon mouseover", async () => {
|
|
62
|
+
const wrapper = mount(UiTooltip, {
|
|
63
|
+
props: {
|
|
64
|
+
fixed: false,
|
|
65
|
+
},
|
|
66
|
+
slots: {
|
|
67
|
+
activator: "<button>Hover me</button>",
|
|
68
|
+
default: "I'm a tooltip",
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
const activator = wrapper.find('[data-testid="activator"]');
|
|
72
|
+
await activator.trigger("mouseenter");
|
|
73
|
+
|
|
74
|
+
expect(wrapper.find('[data-testid="tooltip"]').classes("hidden")).toBe(
|
|
75
|
+
false,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
expect(wrapper.find('[data-testid="tooltipElement"]').text()).toBe(
|
|
79
|
+
"I'm a tooltip",
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("is rendered in the correct position", async () => {
|
|
84
|
+
const wrapper = mount(UiTooltip, {
|
|
85
|
+
props: {
|
|
86
|
+
fixed: false,
|
|
87
|
+
position: "right",
|
|
88
|
+
},
|
|
89
|
+
slots: {
|
|
90
|
+
activator: "<button>Hover me</button>",
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const activator = wrapper.find('[data-testid="activator"]');
|
|
94
|
+
await activator.trigger("mouseenter");
|
|
95
|
+
|
|
96
|
+
expect(
|
|
97
|
+
wrapper.find('[data-testid="tooltip"]').attributes("data-placement"),
|
|
98
|
+
).toBe("right");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("is in a fixed position", () => {
|
|
102
|
+
const wrapper = mount(UiTooltip, {
|
|
103
|
+
props: {
|
|
104
|
+
fixed: true,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Find Tooltip that is teleported to the body
|
|
109
|
+
const tooltip = document.querySelector(
|
|
110
|
+
'[data-testid="tooltip"]',
|
|
111
|
+
) as HTMLElement;
|
|
112
|
+
|
|
113
|
+
expect(tooltip).not.toBeNull();
|
|
114
|
+
expect(tooltip?.style.position).toBe("fixed");
|
|
115
|
+
|
|
116
|
+
// Cleanup after the test
|
|
117
|
+
wrapper.unmount();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("shows no tooltip content when disabled", async () => {
|
|
121
|
+
const wrapper = mount(UiTooltip, {
|
|
122
|
+
props: {
|
|
123
|
+
disabled: true,
|
|
124
|
+
fixed: false,
|
|
125
|
+
},
|
|
126
|
+
slots: {
|
|
127
|
+
activator: "<button>Hover me</button>",
|
|
128
|
+
default: "I'm a Tooltip",
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const activator = wrapper.find('[data-testid="activator"]');
|
|
133
|
+
|
|
134
|
+
expect(activator.exists()).toBe(true);
|
|
135
|
+
await activator.trigger("mouseenter");
|
|
136
|
+
|
|
137
|
+
expect(wrapper.find('[data-testid="tooltipElement"]').exists()).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { shift } from "@floating-ui/vue";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
3
|
+
|
|
4
|
+
import UiTooltip from "./UiTooltip.vue";
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Ui/UiTooltip",
|
|
8
|
+
component: UiTooltip,
|
|
9
|
+
argTypes: {
|
|
10
|
+
position: {
|
|
11
|
+
control: { type: "select" },
|
|
12
|
+
options: [
|
|
13
|
+
"top-start",
|
|
14
|
+
"top",
|
|
15
|
+
"top-end",
|
|
16
|
+
"right",
|
|
17
|
+
"bottom-end",
|
|
18
|
+
"bottom",
|
|
19
|
+
"bottom-start",
|
|
20
|
+
"left",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
structuredLayout: {
|
|
24
|
+
control: "boolean",
|
|
25
|
+
},
|
|
26
|
+
structuredInfo: {
|
|
27
|
+
control: "object",
|
|
28
|
+
},
|
|
29
|
+
fixed: {
|
|
30
|
+
control: "boolean",
|
|
31
|
+
},
|
|
32
|
+
multilines: {
|
|
33
|
+
control: "boolean",
|
|
34
|
+
},
|
|
35
|
+
enterActiveClasses: {
|
|
36
|
+
control: "text",
|
|
37
|
+
},
|
|
38
|
+
leaveActiveClasses: {
|
|
39
|
+
control: "text",
|
|
40
|
+
},
|
|
41
|
+
disabled: {
|
|
42
|
+
control: "boolean",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
args: {
|
|
46
|
+
position: "bottom",
|
|
47
|
+
structuredLayout: false,
|
|
48
|
+
structuredInfo: [],
|
|
49
|
+
fixed: false,
|
|
50
|
+
multilines: false,
|
|
51
|
+
enterActiveClasses:
|
|
52
|
+
"motion-safe:transition motion-safe:duration-300 motion-safe:delay-500",
|
|
53
|
+
leaveActiveClasses: "motion-safe:transition",
|
|
54
|
+
disabled: false,
|
|
55
|
+
},
|
|
56
|
+
render: (args) => ({
|
|
57
|
+
setup() {
|
|
58
|
+
return { args };
|
|
59
|
+
},
|
|
60
|
+
components: { UiTooltip },
|
|
61
|
+
template: `
|
|
62
|
+
<div style="margin-top: 50px; margin-left: 120px; max-width: max-content;">
|
|
63
|
+
<UiTooltip v-bind="args">
|
|
64
|
+
<template v-slot:activator>
|
|
65
|
+
<button>Target</button>
|
|
66
|
+
</template>
|
|
67
|
+
Tooltip Content
|
|
68
|
+
</UiTooltip>
|
|
69
|
+
</div>
|
|
70
|
+
`,
|
|
71
|
+
}),
|
|
72
|
+
} satisfies Meta<typeof UiTooltip>;
|
|
73
|
+
|
|
74
|
+
export default meta;
|
|
75
|
+
type Story = StoryObj<typeof meta>;
|
|
76
|
+
|
|
77
|
+
export const Default: Story = {};
|
|
78
|
+
|
|
79
|
+
export const Structured: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
structuredLayout: true,
|
|
82
|
+
structuredInfo: [
|
|
83
|
+
{
|
|
84
|
+
title: "Typ",
|
|
85
|
+
description: "Termine",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: "Ressort",
|
|
89
|
+
description: "Wirtschaft",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
title: "Veranstaltungsort",
|
|
93
|
+
description: "Hamburg",
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const CustomFloatingUi: Story = {
|
|
100
|
+
args: {
|
|
101
|
+
animate: true,
|
|
102
|
+
floatingUiOptions: {
|
|
103
|
+
middleware: [shift()],
|
|
104
|
+
},
|
|
105
|
+
position: "bottom-end",
|
|
106
|
+
},
|
|
107
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
|
|
3
|
+
import UseBreakpoints from "./UseBreakpoints.stories.vue";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "tailwind/UseBreakpoints.ts",
|
|
7
|
+
component: UseBreakpoints,
|
|
8
|
+
argTypes: {},
|
|
9
|
+
parameters: {},
|
|
10
|
+
} satisfies Meta<typeof UseBreakpoints>;
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: (args) => ({
|
|
17
|
+
setup() {
|
|
18
|
+
return { args };
|
|
19
|
+
},
|
|
20
|
+
components: { UseBreakpoints },
|
|
21
|
+
template: `<div><UseBreakpoints /></div>`,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UiButton v-if="lg">Button for LG</UiButton>
|
|
3
|
+
<UiIconButton v-else title="Button" icon-name="emoji" />
|
|
4
|
+
</template>
|
|
5
|
+
|
|
6
|
+
<script setup lang="ts">
|
|
7
|
+
import UiButton from "../../components/UiButton/UiButton.vue";
|
|
8
|
+
import UiIconButton from "../../components/UiIconButton/UiIconButton.vue";
|
|
9
|
+
import { useBreakpoints } from "./useBreakpoints.js";
|
|
10
|
+
|
|
11
|
+
const { lg } = useBreakpoints();
|
|
12
|
+
</script>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { cn } from "./cn.js";
|
|
4
|
+
|
|
5
|
+
describe("cn", () => {
|
|
6
|
+
test.each<[Parameters<typeof cn>, ReturnType<typeof cn>]>([
|
|
7
|
+
[["items-center", "items-start"], "items-start"],
|
|
8
|
+
[["items-center", undefined], "items-center"],
|
|
9
|
+
])("works", (parameters, expected) => {
|
|
10
|
+
expect(cn(...parameters)).toBe(expected);
|
|
11
|
+
});
|
|
12
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dpa-id-components/dpa-shared-components",
|
|
3
|
-
"version": "20.0.
|
|
3
|
+
"version": "20.0.7",
|
|
4
4
|
"description": "Shared Vue components library for dpa projects",
|
|
5
5
|
"files": [
|
|
6
6
|
"src",
|
|
@@ -63,12 +63,12 @@
|
|
|
63
63
|
"npm-run-all2": "8.0.4",
|
|
64
64
|
"prettier": "3.8.1",
|
|
65
65
|
"rimraf": "6.1.3",
|
|
66
|
+
"rollup-plugin-copy": "3.5.0",
|
|
66
67
|
"storybook": "10.3.3",
|
|
67
68
|
"tailwindcss": "4.2.2",
|
|
68
69
|
"typescript": "5.9.3",
|
|
69
70
|
"vite": "8.0.2",
|
|
70
71
|
"vite-plugin-dts": "4.5.4",
|
|
71
|
-
"vite-plugin-static-copy": "4.0.0",
|
|
72
72
|
"vitest": "4.1.1",
|
|
73
73
|
"vue": "3.5.30",
|
|
74
74
|
"vue-router": "5.0.4",
|
|
@@ -91,9 +91,10 @@
|
|
|
91
91
|
"vue-eslint-parser": "^10.4.0"
|
|
92
92
|
},
|
|
93
93
|
"peerDependencies": {
|
|
94
|
+
"@eslint/js": "^9.39.2 || ^10.0.1",
|
|
94
95
|
"@tailwindcss/typography": "^0.5.16",
|
|
95
|
-
"eslint": "
|
|
96
|
-
"prettier": "
|
|
96
|
+
"eslint": "^9.39.2 || ^10.1.0",
|
|
97
|
+
"prettier": "^3.8.1",
|
|
97
98
|
"tailwindcss": "^4.1.11",
|
|
98
99
|
"vue": "^3.5.0",
|
|
99
100
|
"vue-router": "^4.6.4 || ^5.0.0"
|