vueless
Version:
Vue Styleless UI Component Library, powered by Tailwind CSS.
216 lines (195 loc) • 5.63 kB
text/typescript
import { ref } from "vue";
import {
getArgTypes,
getSlotNames,
getSlotsFragment,
getDocsDescription,
} from "../../utils/storybook.ts";
import UDataList from "../../ui.data-list/UDataList.vue";
import UIcon from "../../ui.image-icon/UIcon.vue";
import UButton from "../../ui.button/UButton.vue";
import URow from "../../ui.container-row/URow.vue";
import UBadge from "../../ui.text-badge/UBadge.vue";
import UAvatar from "../../ui.image-avatar/UAvatar.vue";
import UHeader from "../../ui.text-header/UHeader.vue";
import ULoader from "../../ui.loader/ULoader.vue";
import tooltip from "../../directives/tooltip/vTooltip.ts";
import type { Meta, StoryFn } from "@storybook/vue3";
import type { Props, DataListItem } from "../types.ts";
interface UDataListArgs extends Props {
slotTemplate?: string;
enum: "size";
}
export default {
id: "7020",
title: "Data / Data List",
component: UDataList,
args: {
list: [
{
label: "Expenses",
id: 1,
nesting: true,
children: [
{ label: "Office Supplies", id: 1.1 },
{ label: "Travel & Lodging", id: 1.2 },
{ label: "Utilities", id: 1.3 },
],
},
{
label: "Revenue Streams",
id: 2,
nesting: true,
children: [
{ label: "Product Sales", id: 2.1 },
{ label: "Subscription Services", id: 2.2 },
{ label: "Consulting", id: 2.3 },
],
},
{
label: "Departments",
id: 3,
nesting: true,
children: [
{ label: "Engineering", id: 3.1 },
{ label: "Marketing", id: 3.2 },
{ label: "Finance", id: 3.3 },
],
},
],
},
argTypes: {
...getArgTypes(UDataList.__name),
},
parameters: {
docs: {
...getDocsDescription(UDataList.__name),
},
},
} as Meta;
const DefaultTemplate: StoryFn<UDataListArgs> = (args: UDataListArgs) => ({
components: { UDataList, UIcon, URow, UButton, UBadge, UAvatar, ULoader, UHeader },
directives: { tooltip },
setup() {
const slots = getSlotNames(UDataList.__name);
const avatars = [
"https://cdn-icons-png.flaticon.com/128/1999/1999625.png",
"https://cdn-icons-png.flaticon.com/128/4140/4140057.png",
"https://cdn-icons-png.flaticon.com/128/4140/4140047.png",
];
const list = ref(
args.list?.map((item, index) => ({
...item,
id: item.id,
avatar: avatars[index % avatars.length],
})),
);
function removeItem(targetItem: DataListItem) {
list.value = list.value?.filter((listItem) => listItem.id !== targetItem.id);
return alert(`Removed item: ${JSON.stringify(targetItem, null, 2)}`);
}
function editItem(targetItem: DataListItem) {
alert(`Edit item: ${JSON.stringify(targetItem, null, 2)}`);
}
return { args, slots, removeItem, editItem, list };
},
template: `
<UDataList v-bind="args" :list="args.slotTemplate ? list : args.list">
${args.slotTemplate || getSlotsFragment("")}
</UDataList>
`,
});
const EnumVariantTemplate: StoryFn<UDataListArgs> = (args: UDataListArgs, { argTypes }) => ({
components: { URow, UDataList, UHeader },
setup() {
return {
args,
options: argTypes?.[args.enum]?.options,
};
},
template: `
<div v-for="(option, index) in options" :key="index">
<UHeader :label="option" size="xs" />
<UDataList v-bind="args" :[args.enum]="option" class="mb-4" />
</div>
`,
});
export const Default = DefaultTemplate.bind({});
Default.args = {};
export const EmptyState = DefaultTemplate.bind({});
EmptyState.args = { list: [] };
export const Nesting = DefaultTemplate.bind({});
Nesting.args = { nesting: true };
export const Size = EnumVariantTemplate.bind({});
Size.args = { enum: "size" };
export const SlotLabel = DefaultTemplate.bind({});
SlotLabel.args = {
slotTemplate: `
<template
<UBadge :label="item.label" />
</template>
`,
};
export const SlotEmpty = DefaultTemplate.bind({});
SlotEmpty.args = {
list: [],
config: {
wrapper: "flex flex-col items-center justify-center py-10 gap-4",
i18n: {
emptyTitle: "Fetching data...",
emptyDescription: "Please wait until data is received.",
},
},
slotTemplate: `
<template
<ULoader loading size="lg" />
<UHeader :label="emptyTitle" size="xs" />
<p>{{ emptyDescription }}</p>
</template>
`,
};
SlotEmpty.parameters = {
docs: {
description: {
story:
"You can customize the `empty` slot's props (`emptyTitle` and `emptyDescription`) using the `i18n` config key.",
},
},
};
export const SlotDrag = DefaultTemplate.bind({});
SlotDrag.args = {
list: [
{ label: "John Doe (Engineering)", id: 1 },
{ label: "Michael Johnson (Finance)", id: 2 },
{ label: "Emma Smith (Marketing)", id: 3 },
],
slotTemplate: `
<template
<UAvatar :src="item.avatar" rounded="full" />
</template>
`,
};
export const SlotActions = DefaultTemplate.bind({});
SlotActions.args = {
slotTemplate: `
<template
<UButton label="Export" size="xs" />
<UIcon
name="delete"
size="sm"
color="red"
interactive
v-tooltip="'Delete'"
@click="removeItem(item)"
/>
<UIcon
name="edit_note"
size="sm"
color="grayscale"
interactive
v-tooltip="'Edit'"
@click="editItem(item)"
/>
</template>
`,
};