mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 22:39:39 +00:00
feat(tailwind): add lucide icon support via iconify plugin (#5453)
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import { Bell, Download, Heart, Settings, Trophy, X } from 'lucide-vue-next'
|
||||
|
||||
import IconButton from './IconButton.vue'
|
||||
|
||||
@@ -33,13 +32,13 @@ type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Primary: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconButton, Trophy },
|
||||
components: { IconButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconButton v-bind="args">
|
||||
<Trophy :size="16" />
|
||||
<i class="icon-[lucide--trophy] size-4" />
|
||||
</IconButton>
|
||||
`
|
||||
}),
|
||||
@@ -51,13 +50,13 @@ export const Primary: Story = {
|
||||
|
||||
export const Secondary: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconButton, Settings },
|
||||
components: { IconButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconButton v-bind="args">
|
||||
<Settings :size="16" />
|
||||
<i class="icon-[lucide--settings] size-4" />
|
||||
</IconButton>
|
||||
`
|
||||
}),
|
||||
@@ -69,13 +68,13 @@ export const Secondary: Story = {
|
||||
|
||||
export const Transparent: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconButton, X },
|
||||
components: { IconButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconButton v-bind="args">
|
||||
<X :size="16" />
|
||||
<i class="icon-[lucide--x] size-4" />
|
||||
</IconButton>
|
||||
`
|
||||
}),
|
||||
@@ -87,13 +86,13 @@ export const Transparent: Story = {
|
||||
|
||||
export const Small: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconButton, Bell },
|
||||
components: { IconButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconButton v-bind="args">
|
||||
<Bell :size="12" />
|
||||
<i class="icon-[lucide--bell] size-3" />
|
||||
</IconButton>
|
||||
`
|
||||
}),
|
||||
@@ -105,42 +104,42 @@ export const Small: Story = {
|
||||
|
||||
export const AllVariants: Story = {
|
||||
render: () => ({
|
||||
components: { IconButton, Trophy, Settings, X, Bell, Heart, Download },
|
||||
components: { IconButton },
|
||||
template: `
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconButton type="primary" size="sm" @click="() => {}">
|
||||
<Trophy :size="12" />
|
||||
<i class="icon-[lucide--trophy] size-3" />
|
||||
</IconButton>
|
||||
<IconButton type="primary" size="md" @click="() => {}">
|
||||
<Trophy :size="16" />
|
||||
<i class="icon-[lucide--trophy] size-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconButton type="secondary" size="sm" @click="() => {}">
|
||||
<Settings :size="12" />
|
||||
<i class="icon-[lucide--settings] size-3" />
|
||||
</IconButton>
|
||||
<IconButton type="secondary" size="md" @click="() => {}">
|
||||
<Settings :size="16" />
|
||||
<i class="icon-[lucide--settings] size-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconButton type="transparent" size="sm" @click="() => {}">
|
||||
<X :size="12" />
|
||||
<i class="icon-[lucide--x] size-3" />
|
||||
</IconButton>
|
||||
<IconButton type="transparent" size="md" @click="() => {}">
|
||||
<X :size="16" />
|
||||
<i class="icon-[lucide--x] size-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconButton type="primary" size="md" @click="() => {}">
|
||||
<Bell :size="16" />
|
||||
<i class="icon-[lucide--bell] size-4" />
|
||||
</IconButton>
|
||||
<IconButton type="secondary" size="md" @click="() => {}">
|
||||
<Heart :size="16" />
|
||||
<i class="icon-[lucide--heart] size-4" />
|
||||
</IconButton>
|
||||
<IconButton type="transparent" size="md" @click="() => {}">
|
||||
<Download :size="16" />
|
||||
<i class="icon-[lucide--download] size-4" />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import { Download, ExternalLink, Heart } from 'lucide-vue-next'
|
||||
|
||||
import IconButton from './IconButton.vue'
|
||||
import IconGroup from './IconGroup.vue'
|
||||
@@ -17,17 +16,17 @@ type Story = StoryObj<typeof IconGroup>
|
||||
|
||||
export const Basic: Story = {
|
||||
render: () => ({
|
||||
components: { IconGroup, IconButton, Download, ExternalLink, Heart },
|
||||
components: { IconGroup, IconButton },
|
||||
template: `
|
||||
<IconGroup>
|
||||
<IconButton @click="console.log('Hello World!!')">
|
||||
<Heart :size="16" />
|
||||
<i class="icon-[lucide--heart] size-4" />
|
||||
</IconButton>
|
||||
<IconButton @click="console.log('Hello World!!')">
|
||||
<Download :size="16" />
|
||||
<i class="icon-[lucide--download] size-4" />
|
||||
</IconButton>
|
||||
<IconButton @click="console.log('Hello World!!')">
|
||||
<ExternalLink :size="16" />
|
||||
<i class="icon-[lucide--external-link] size-4" />
|
||||
</IconButton>
|
||||
</IconGroup>
|
||||
`
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Download,
|
||||
Package,
|
||||
Save,
|
||||
Settings,
|
||||
Trash2,
|
||||
X
|
||||
} from 'lucide-vue-next'
|
||||
|
||||
import IconTextButton from './IconTextButton.vue'
|
||||
|
||||
@@ -49,14 +39,14 @@ type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Primary: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconTextButton, Package },
|
||||
components: { IconTextButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconTextButton v-bind="args">
|
||||
<template #icon>
|
||||
<Package :size="16" />
|
||||
<i class="icon-[lucide--package] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
`
|
||||
@@ -70,14 +60,14 @@ export const Primary: Story = {
|
||||
|
||||
export const Secondary: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconTextButton, Settings },
|
||||
components: { IconTextButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconTextButton v-bind="args">
|
||||
<template #icon>
|
||||
<Settings :size="16" />
|
||||
<i class="icon-[lucide--settings] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
`
|
||||
@@ -91,14 +81,14 @@ export const Secondary: Story = {
|
||||
|
||||
export const Transparent: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconTextButton, X },
|
||||
components: { IconTextButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconTextButton v-bind="args">
|
||||
<template #icon>
|
||||
<X :size="16" />
|
||||
<i class="icon-[lucide--x] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
`
|
||||
@@ -112,14 +102,14 @@ export const Transparent: Story = {
|
||||
|
||||
export const WithIconRight: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconTextButton, ChevronRight },
|
||||
components: { IconTextButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconTextButton v-bind="args">
|
||||
<template #icon>
|
||||
<ChevronRight :size="16" />
|
||||
<i class="icon-[lucide--chevron-right] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
`
|
||||
@@ -134,14 +124,14 @@ export const WithIconRight: Story = {
|
||||
|
||||
export const Small: Story = {
|
||||
render: (args) => ({
|
||||
components: { IconTextButton, Save },
|
||||
components: { IconTextButton },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: `
|
||||
<IconTextButton v-bind="args">
|
||||
<template #icon>
|
||||
<Save :size="12" />
|
||||
<i class="icon-[lucide--save] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
`
|
||||
@@ -156,66 +146,60 @@ export const Small: Story = {
|
||||
export const AllVariants: Story = {
|
||||
render: () => ({
|
||||
components: {
|
||||
IconTextButton,
|
||||
Download,
|
||||
Settings,
|
||||
Trash2,
|
||||
ChevronRight,
|
||||
ChevronLeft,
|
||||
Save
|
||||
IconTextButton
|
||||
},
|
||||
template: `
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconTextButton label="Download" type="primary" size="sm" @click="() => {}">
|
||||
<template #icon>
|
||||
<Download :size="12" />
|
||||
<i class="icon-[lucide--download] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton label="Download" type="primary" size="md" @click="() => {}">
|
||||
<template #icon>
|
||||
<Download :size="16" />
|
||||
<i class="icon-[lucide--download] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconTextButton label="Settings" type="secondary" size="sm" @click="() => {}">
|
||||
<template #icon>
|
||||
<Settings :size="12" />
|
||||
<i class="icon-[lucide--settings] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton label="Settings" type="secondary" size="md" @click="() => {}">
|
||||
<template #icon>
|
||||
<Settings :size="16" />
|
||||
<i class="icon-[lucide--settings] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconTextButton label="Delete" type="transparent" size="sm" @click="() => {}">
|
||||
<template #icon>
|
||||
<Trash2 :size="12" />
|
||||
<i class="icon-[lucide--trash-2] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton label="Delete" type="transparent" size="md" @click="() => {}">
|
||||
<template #icon>
|
||||
<Trash2 :size="16" />
|
||||
<i class="icon-[lucide--trash-2] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</div>
|
||||
<div class="flex gap-2 items-center">
|
||||
<IconTextButton label="Next" type="primary" size="md" iconPosition="right" @click="() => {}">
|
||||
<template #icon>
|
||||
<ChevronRight :size="16" />
|
||||
<i class="icon-[lucide--chevron-right] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton label="Previous" type="secondary" size="md" @click="() => {}">
|
||||
<template #icon>
|
||||
<ChevronLeft :size="16" />
|
||||
<i class="icon-[lucide--chevron-left] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
<IconTextButton label="Save File" type="primary" size="md" @click="() => {}">
|
||||
<template #icon>
|
||||
<Save :size="16" />
|
||||
<i class="icon-[lucide--save] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import { Download, ScrollText } from 'lucide-vue-next'
|
||||
|
||||
import IconTextButton from './IconTextButton.vue'
|
||||
import MoreButton from './MoreButton.vue'
|
||||
@@ -18,7 +17,7 @@ type Story = StoryObj<typeof MoreButton>
|
||||
|
||||
export const Basic: Story = {
|
||||
render: () => ({
|
||||
components: { MoreButton, IconTextButton, Download, ScrollText },
|
||||
components: { MoreButton, IconTextButton },
|
||||
template: `
|
||||
<div style="height: 200px; display: flex; align-items: center; justify-content: center;">
|
||||
<MoreButton>
|
||||
@@ -29,7 +28,7 @@ export const Basic: Story = {
|
||||
@click="() => { close() }"
|
||||
>
|
||||
<template #icon>
|
||||
<Download :size="16" />
|
||||
<i class="icon-[lucide--download] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
|
||||
@@ -39,7 +38,7 @@ export const Basic: Story = {
|
||||
@click="() => { close() }"
|
||||
>
|
||||
<template #icon>
|
||||
<ScrollText :size="16" />
|
||||
<i class="icon-[lucide--scroll-text] size-4" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</template>
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import {
|
||||
Download,
|
||||
Folder,
|
||||
Heart,
|
||||
Info,
|
||||
MoreVertical,
|
||||
Star,
|
||||
Upload
|
||||
} from 'lucide-vue-next'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import IconButton from '../button/IconButton.vue'
|
||||
@@ -149,14 +140,7 @@ const createCardTemplate = (args: CardStoryArgs) => ({
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
IconButton,
|
||||
SquareChip,
|
||||
Info,
|
||||
Folder,
|
||||
Heart,
|
||||
Download,
|
||||
Star,
|
||||
Upload,
|
||||
MoreVertical
|
||||
SquareChip
|
||||
},
|
||||
setup() {
|
||||
const favorited = ref(false)
|
||||
@@ -202,14 +186,14 @@ const createCardTemplate = (args: CardStoryArgs) => ({
|
||||
class="!bg-white/90 !text-neutral-900"
|
||||
@click="() => console.log('Info clicked')"
|
||||
>
|
||||
<Info :size="16" />
|
||||
<i class="icon-[lucide--info] size-4" />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
class="!bg-white/90"
|
||||
:class="favorited ? '!text-red-500' : '!text-neutral-900'"
|
||||
@click="toggleFavorite"
|
||||
>
|
||||
<Heart :size="16" :fill="favorited ? 'currentColor' : 'none'" />
|
||||
<i class="icon-[lucide--heart] size-4" :class="favorited ? 'fill-current' : ''" />
|
||||
</IconButton>
|
||||
</template>
|
||||
|
||||
@@ -222,7 +206,7 @@ const createCardTemplate = (args: CardStoryArgs) => ({
|
||||
<SquareChip v-if="args.showFileSize" :label="args.fileSize" />
|
||||
<SquareChip v-for="tag in args.tags" :key="tag" :label="tag">
|
||||
<template v-if="tag === 'LoRA'" #icon>
|
||||
<Folder :size="12" />
|
||||
<i class="icon-[lucide--folder] size-3" />
|
||||
</template>
|
||||
</SquareChip>
|
||||
</template>
|
||||
@@ -409,11 +393,7 @@ export const GridOfCards: Story = {
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
IconButton,
|
||||
SquareChip,
|
||||
Info,
|
||||
Folder,
|
||||
Heart,
|
||||
Download
|
||||
SquareChip
|
||||
},
|
||||
setup() {
|
||||
const cards = ref([
|
||||
@@ -500,7 +480,7 @@ export const GridOfCards: Story = {
|
||||
class="!bg-white/90 !text-neutral-900"
|
||||
@click="() => console.log('Info:', card.title)"
|
||||
>
|
||||
<Info :size="16" />
|
||||
<i class="icon-[lucide--info] size-4" />
|
||||
</IconButton>
|
||||
</template>
|
||||
|
||||
@@ -511,7 +491,7 @@ export const GridOfCards: Story = {
|
||||
:label="tag"
|
||||
>
|
||||
<template v-if="tag === 'LoRA'" #icon>
|
||||
<Folder :size="12" />
|
||||
<i class="icon-[lucide--folder] size-3" />
|
||||
</template>
|
||||
</SquareChip>
|
||||
<SquareChip :label="card.size" />
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import { ArrowUpDown } from 'lucide-vue-next'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import SingleSelect from './SingleSelect.vue'
|
||||
@@ -57,7 +56,7 @@ export const Default: Story = {
|
||||
|
||||
export const WithIcon: Story = {
|
||||
render: () => ({
|
||||
components: { SingleSelect, ArrowUpDown },
|
||||
components: { SingleSelect },
|
||||
setup() {
|
||||
const selected = ref<string | null>('popular')
|
||||
const options = sampleOptions
|
||||
@@ -67,7 +66,7 @@ export const WithIcon: Story = {
|
||||
<div>
|
||||
<SingleSelect v-model="selected" :options="options" label="Sorting Type">
|
||||
<template #icon>
|
||||
<ArrowUpDown :size="14" />
|
||||
<i class="icon-[lucide--arrow-up-down] w-3.5 h-3.5" />
|
||||
</template>
|
||||
</SingleSelect>
|
||||
<div class="mt-4 p-3 bg-gray-50 dark-theme:bg-zinc-800 rounded">
|
||||
@@ -94,7 +93,7 @@ export const Preselected: Story = {
|
||||
|
||||
export const AllVariants: Story = {
|
||||
render: () => ({
|
||||
components: { SingleSelect, ArrowUpDown },
|
||||
components: { SingleSelect },
|
||||
setup() {
|
||||
const options = sampleOptions
|
||||
const a = ref<string | null>(null)
|
||||
@@ -110,7 +109,7 @@ export const AllVariants: Story = {
|
||||
<div class="flex items-center gap-3">
|
||||
<SingleSelect v-model="b" :options="options" label="With Icon">
|
||||
<template #icon>
|
||||
<ArrowUpDown :size="14" />
|
||||
<i class="icon-[lucide--arrow-up-down] w-3.5 h-3.5" />
|
||||
</template>
|
||||
</SingleSelect>
|
||||
</div>
|
||||
|
||||
@@ -136,10 +136,6 @@
|
||||
<script setup lang="ts">
|
||||
import { provide, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import DownloadIcon from '~icons/lucide/download'
|
||||
import Grid3x3Icon from '~icons/lucide/grid-3-x-3'
|
||||
import LayersIcon from '~icons/lucide/layers'
|
||||
import TagIcon from '~icons/lucide/tag'
|
||||
|
||||
import IconButton from '@/components/button/IconButton.vue'
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
@@ -177,20 +173,20 @@ const sortOptions = ref([
|
||||
])
|
||||
|
||||
const tempNavigation = ref<(NavItemData | NavGroupData)[]>([
|
||||
{ id: 'installed', label: 'Installed', icon: DownloadIcon },
|
||||
{ id: 'installed', label: 'Installed', icon: 'icon-[lucide--download]' },
|
||||
{
|
||||
title: 'TAGS',
|
||||
items: [
|
||||
{ id: 'tag-sd15', label: 'SD 1.5', icon: TagIcon },
|
||||
{ id: 'tag-sdxl', label: 'SDXL', icon: TagIcon },
|
||||
{ id: 'tag-utility', label: 'Utility', icon: TagIcon }
|
||||
{ id: 'tag-sd15', label: 'SD 1.5', icon: 'icon-[lucide--tag]' },
|
||||
{ id: 'tag-sdxl', label: 'SDXL', icon: 'icon-[lucide--tag]' },
|
||||
{ id: 'tag-utility', label: 'Utility', icon: 'icon-[lucide--tag]' }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'CATEGORIES',
|
||||
items: [
|
||||
{ id: 'cat-models', label: 'Models', icon: LayersIcon },
|
||||
{ id: 'cat-nodes', label: 'Nodes', icon: Grid3x3Icon }
|
||||
{ id: 'cat-models', label: 'Models', icon: 'icon-[lucide--layers]' },
|
||||
{ id: 'cat-nodes', label: 'Nodes', icon: 'icon-[lucide--grid-3x3]' }
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import {
|
||||
Download,
|
||||
Filter,
|
||||
Folder,
|
||||
Info,
|
||||
PanelLeft,
|
||||
PanelLeftClose,
|
||||
PanelRight,
|
||||
PanelRightClose,
|
||||
Puzzle,
|
||||
Scroll,
|
||||
Settings,
|
||||
Upload,
|
||||
X
|
||||
} from 'lucide-vue-next'
|
||||
import { h, provide, ref } from 'vue'
|
||||
import { provide, ref } from 'vue'
|
||||
|
||||
import IconButton from '@/components/button/IconButton.vue'
|
||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||
@@ -94,20 +79,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
CardContainer,
|
||||
CardTop,
|
||||
CardBottom,
|
||||
SquareChip,
|
||||
Settings,
|
||||
Upload,
|
||||
Download,
|
||||
Scroll,
|
||||
Info,
|
||||
Filter,
|
||||
Folder,
|
||||
Puzzle,
|
||||
PanelLeft,
|
||||
PanelLeftClose,
|
||||
PanelRight,
|
||||
PanelRightClose,
|
||||
X
|
||||
SquareChip
|
||||
},
|
||||
setup() {
|
||||
const t = (k: string) => k
|
||||
@@ -121,7 +93,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
{
|
||||
id: 'installed',
|
||||
label: 'Installed',
|
||||
icon: { render: () => h(Folder, { size: 14 }) } as any
|
||||
icon: 'icon-[lucide--folder]'
|
||||
},
|
||||
{
|
||||
title: 'TAGS',
|
||||
@@ -129,17 +101,17 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
{
|
||||
id: 'tag-sd15',
|
||||
label: 'SD 1.5',
|
||||
icon: { render: () => h(Folder, { size: 14 }) } as any
|
||||
icon: 'icon-[lucide--tag]'
|
||||
},
|
||||
{
|
||||
id: 'tag-sdxl',
|
||||
label: 'SDXL',
|
||||
icon: { render: () => h(Folder, { size: 14 }) } as any
|
||||
icon: 'icon-[lucide--tag]'
|
||||
},
|
||||
{
|
||||
id: 'tag-utility',
|
||||
label: 'Utility',
|
||||
icon: { render: () => h(Folder, { size: 14 }) } as any
|
||||
icon: 'icon-[lucide--tag]'
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -149,12 +121,12 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
{
|
||||
id: 'cat-models',
|
||||
label: 'Models',
|
||||
icon: { render: () => h(Folder, { size: 14 }) } as any
|
||||
icon: 'icon-[lucide--layers]'
|
||||
},
|
||||
{
|
||||
id: 'cat-nodes',
|
||||
label: 'Nodes',
|
||||
icon: { render: () => h(Folder, { size: 14 }) } as any
|
||||
icon: 'icon-[lucide--grid-3x3]'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -205,7 +177,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
<template v-if="args.hasLeftPanel" #leftPanel>
|
||||
<LeftSidePanel v-model="selectedNavItem" :nav-items="tempNavigation">
|
||||
<template #header-icon>
|
||||
<Puzzle :size="16" class="text-neutral" />
|
||||
<i class="icon-[lucide--puzzle] size-4 text-neutral" />
|
||||
</template>
|
||||
<template #header-title>
|
||||
<span class="text-neutral text-base">Title</span>
|
||||
@@ -227,7 +199,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
<div class="flex gap-2">
|
||||
<IconTextButton type="primary" label="Upload Model" @click="() => {}">
|
||||
<template #icon>
|
||||
<Upload :size="12" />
|
||||
<i class="icon-[lucide--upload] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
|
||||
@@ -239,7 +211,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
@click="() => { close() }"
|
||||
>
|
||||
<template #icon>
|
||||
<Download :size="12" />
|
||||
<i class="icon-[lucide--download] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
|
||||
@@ -249,7 +221,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
@click="() => { close() }"
|
||||
>
|
||||
<template #icon>
|
||||
<Scroll :size="12" />
|
||||
<i class="icon-[lucide--scroll] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</template>
|
||||
@@ -280,7 +252,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
class="w-[135px]"
|
||||
>
|
||||
<template #icon>
|
||||
<Filter :size="12" />
|
||||
<i class="icon-[lucide--filter] size-3" />
|
||||
</template>
|
||||
</SingleSelect>
|
||||
</div>
|
||||
@@ -301,7 +273,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
</template>
|
||||
<template #top-right>
|
||||
<IconButton class="!bg-white !text-neutral-900" @click="() => {}">
|
||||
<Info :size="16" />
|
||||
<i class="icon-[lucide--info] size-4" />
|
||||
</IconButton>
|
||||
</template>
|
||||
<template #bottom-right>
|
||||
@@ -309,7 +281,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
<SquareChip label="1.2 MB" />
|
||||
<SquareChip label="LoRA">
|
||||
<template #icon>
|
||||
<Folder :size="12" />
|
||||
<i class="icon-[lucide--folder] size-3" />
|
||||
</template>
|
||||
</SquareChip>
|
||||
</template>
|
||||
@@ -329,7 +301,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
<template v-if="args.hasLeftPanel" #leftPanel>
|
||||
<LeftSidePanel v-model="selectedNavItem" :nav-items="tempNavigation">
|
||||
<template #header-icon>
|
||||
<Puzzle :size="16" class="text-neutral" />
|
||||
<i class="icon-[lucide--puzzle] size-4 text-neutral" />
|
||||
</template>
|
||||
<template #header-title>
|
||||
<span class="text-neutral text-base">Title</span>
|
||||
@@ -351,7 +323,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
<div class="flex gap-2">
|
||||
<IconTextButton type="primary" label="Upload Model" @click="() => {}">
|
||||
<template #icon>
|
||||
<Upload :size="12" />
|
||||
<i class="icon-[lucide--upload] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
|
||||
@@ -363,7 +335,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
@click="() => { close() }"
|
||||
>
|
||||
<template #icon>
|
||||
<Download :size="12" />
|
||||
<i class="icon-[lucide--download] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
|
||||
@@ -373,7 +345,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
@click="() => { close() }"
|
||||
>
|
||||
<template #icon>
|
||||
<Scroll :size="12" />
|
||||
<i class="icon-[lucide--scroll] size-3" />
|
||||
</template>
|
||||
</IconTextButton>
|
||||
</template>
|
||||
@@ -401,7 +373,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
class="w-[135px]"
|
||||
>
|
||||
<template #icon>
|
||||
<Filter :size="12" />
|
||||
<i class="icon-[lucide--filter] size-3" />
|
||||
</template>
|
||||
</SingleSelect>
|
||||
</div>
|
||||
@@ -422,7 +394,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
</template>
|
||||
<template #top-right>
|
||||
<IconButton class="!bg-white !text-neutral-900" @click="() => {}">
|
||||
<Info :size="16" />
|
||||
<i class="icon-[lucide--info] size-4" />
|
||||
</IconButton>
|
||||
</template>
|
||||
<template #bottom-right>
|
||||
@@ -430,7 +402,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
||||
<SquareChip label="1.2 MB" />
|
||||
<SquareChip label="LoRA">
|
||||
<template #icon>
|
||||
<Folder :size="12" />
|
||||
<i class="icon-[lucide--folder] size-3" />
|
||||
</template>
|
||||
</SquareChip>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<span v-if="icon" class="text-xs text-neutral">
|
||||
<component :is="icon" />
|
||||
</span>
|
||||
<i :class="icon" class="text-xs text-neutral" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import { Download, Folder, Grid3x3, Layers, Tag, Wrench } from 'lucide-vue-next'
|
||||
import { h } from 'vue'
|
||||
|
||||
import NavItem from './NavItem.vue'
|
||||
|
||||
@@ -34,31 +32,6 @@ const meta: Meta<typeof NavItem> = {
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Interactive: Story = {
|
||||
args: {
|
||||
icon: Folder,
|
||||
active: false,
|
||||
default: 'Navigation Item'
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { NavItem },
|
||||
setup() {
|
||||
const IconComponent = args.icon
|
||||
const WrappedIcon = {
|
||||
render() {
|
||||
return h(IconComponent, { size: 14 })
|
||||
}
|
||||
}
|
||||
return { args, WrappedIcon }
|
||||
},
|
||||
template: `
|
||||
<NavItem :icon="WrappedIcon" :active="args.active" :on-click="() => {}">
|
||||
{{ args.default }}
|
||||
</NavItem>
|
||||
`
|
||||
})
|
||||
}
|
||||
|
||||
export const InteractiveList: Story = {
|
||||
render: () => ({
|
||||
components: { NavItem },
|
||||
@@ -67,7 +40,7 @@ export const InteractiveList: Story = {
|
||||
<NavItem
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:icon="item.wrappedIcon"
|
||||
:icon="item.icon"
|
||||
:active="selectedId === item.id"
|
||||
:on-click="() => selectedId = item.id"
|
||||
>
|
||||
@@ -85,32 +58,32 @@ export const InteractiveList: Story = {
|
||||
{
|
||||
id: 'downloads',
|
||||
label: 'Downloads',
|
||||
wrappedIcon: () => h(Download, { size: 14 })
|
||||
icon: 'icon-[lucide--download]'
|
||||
},
|
||||
{
|
||||
id: 'models',
|
||||
label: 'Models',
|
||||
wrappedIcon: () => h(Layers, { size: 14 })
|
||||
icon: 'icon-[lucide--layers]'
|
||||
},
|
||||
{
|
||||
id: 'nodes',
|
||||
label: 'Nodes',
|
||||
wrappedIcon: () => h(Grid3x3, { size: 14 })
|
||||
icon: 'icon-[lucide--grid-3x3]'
|
||||
},
|
||||
{
|
||||
id: 'tags',
|
||||
label: 'Tags',
|
||||
wrappedIcon: () => h(Tag, { size: 14 })
|
||||
icon: 'icon-[lucide--tag]'
|
||||
},
|
||||
{
|
||||
id: 'settings',
|
||||
label: 'Settings',
|
||||
wrappedIcon: () => h(Wrench, { size: 14 })
|
||||
icon: 'icon-[lucide--wrench]'
|
||||
},
|
||||
{
|
||||
id: 'default',
|
||||
label: 'Default Icon',
|
||||
wrappedIcon: () => h(Folder, { size: 14 })
|
||||
icon: 'icon-[lucide--folder]'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
import {
|
||||
Download,
|
||||
Folder,
|
||||
Grid3x3,
|
||||
Layers,
|
||||
Puzzle,
|
||||
Settings,
|
||||
Tag,
|
||||
Wrench,
|
||||
Zap
|
||||
} from 'lucide-vue-next'
|
||||
import { h, ref } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import LeftSidePanel from './LeftSidePanel.vue'
|
||||
|
||||
@@ -48,22 +37,22 @@ export const Default: Story = {
|
||||
{
|
||||
id: 'installed',
|
||||
label: 'Installed',
|
||||
icon: () => h(Download, { size: 14 })
|
||||
icon: 'icon-[lucide--download]'
|
||||
},
|
||||
{
|
||||
id: 'models',
|
||||
label: 'Models',
|
||||
icon: () => h(Layers, { size: 14 })
|
||||
icon: 'icon-[lucide--layers]'
|
||||
},
|
||||
{
|
||||
id: 'nodes',
|
||||
label: 'Nodes',
|
||||
icon: () => h(Grid3x3, { size: 14 })
|
||||
icon: 'icon-[lucide--grid-3x3]'
|
||||
}
|
||||
]
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { LeftSidePanel, Puzzle },
|
||||
components: { LeftSidePanel },
|
||||
setup() {
|
||||
const selectedItem = ref(args.modelValue)
|
||||
return { args, selectedItem }
|
||||
@@ -72,7 +61,7 @@ export const Default: Story = {
|
||||
<div style="height: 500px; width: 256px;">
|
||||
<LeftSidePanel v-model="selectedItem" :nav-items="args.navItems">
|
||||
<template #header-icon>
|
||||
<Puzzle :size="16" class="text-neutral" />
|
||||
<i class="icon-[lucide--puzzle] size-4 text-neutral" />
|
||||
</template>
|
||||
<template #header-title>
|
||||
<span class="text-neutral text-base">Navigation</span>
|
||||
@@ -90,7 +79,7 @@ export const WithGroups: Story = {
|
||||
{
|
||||
id: 'installed',
|
||||
label: 'Installed',
|
||||
icon: () => h(Download, { size: 14 })
|
||||
icon: 'icon-[lucide--download]'
|
||||
},
|
||||
{
|
||||
title: 'TAGS',
|
||||
@@ -98,17 +87,17 @@ export const WithGroups: Story = {
|
||||
{
|
||||
id: 'tag-sd15',
|
||||
label: 'SD 1.5',
|
||||
icon: () => h(Tag, { size: 14 })
|
||||
icon: 'icon-[lucide--tag]'
|
||||
},
|
||||
{
|
||||
id: 'tag-sdxl',
|
||||
label: 'SDXL',
|
||||
icon: () => h(Tag, { size: 14 })
|
||||
icon: 'icon-[lucide--tag]'
|
||||
},
|
||||
{
|
||||
id: 'tag-utility',
|
||||
label: 'Utility',
|
||||
icon: () => h(Tag, { size: 14 })
|
||||
icon: 'icon-[lucide--tag]'
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -118,19 +107,19 @@ export const WithGroups: Story = {
|
||||
{
|
||||
id: 'cat-models',
|
||||
label: 'Models',
|
||||
icon: () => h(Layers, { size: 14 })
|
||||
icon: 'icon-[lucide--layers]'
|
||||
},
|
||||
{
|
||||
id: 'cat-nodes',
|
||||
label: 'Nodes',
|
||||
icon: () => h(Grid3x3, { size: 14 })
|
||||
icon: 'icon-[lucide--grid-3x3]'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { LeftSidePanel, Puzzle },
|
||||
components: { LeftSidePanel },
|
||||
setup() {
|
||||
const selectedItem = ref(args.modelValue)
|
||||
return { args, selectedItem }
|
||||
@@ -139,7 +128,7 @@ export const WithGroups: Story = {
|
||||
<div style="height: 500px; width: 256px;">
|
||||
<LeftSidePanel v-model="selectedItem" :nav-items="args.navItems">
|
||||
<template #header-icon>
|
||||
<Puzzle :size="16" class="text-neutral" />
|
||||
<i class="icon-[lucide--puzzle] size-4 text-neutral" />
|
||||
</template>
|
||||
<template #header-title>
|
||||
<span class="text-neutral text-base">Model Selector</span>
|
||||
@@ -160,27 +149,27 @@ export const DefaultIcons: Story = {
|
||||
{
|
||||
id: 'home',
|
||||
label: 'Home',
|
||||
icon: () => h(Folder, { size: 14 })
|
||||
icon: 'icon-[lucide--folder]'
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
label: 'Documents',
|
||||
icon: () => h(Folder, { size: 14 })
|
||||
icon: 'icon-[lucide--folder]'
|
||||
},
|
||||
{
|
||||
id: 'downloads',
|
||||
label: 'Downloads',
|
||||
icon: () => h(Folder, { size: 14 })
|
||||
icon: 'icon-[lucide--folder]'
|
||||
},
|
||||
{
|
||||
id: 'desktop',
|
||||
label: 'Desktop',
|
||||
icon: () => h(Folder, { size: 14 })
|
||||
icon: 'icon-[lucide--folder]'
|
||||
}
|
||||
]
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { LeftSidePanel, Folder },
|
||||
components: { LeftSidePanel },
|
||||
setup() {
|
||||
const selectedItem = ref(args.modelValue)
|
||||
return { args, selectedItem }
|
||||
@@ -189,7 +178,7 @@ export const DefaultIcons: Story = {
|
||||
<div style="height: 400px; width: 256px;">
|
||||
<LeftSidePanel v-model="selectedItem" :nav-items="args.navItems">
|
||||
<template #header-icon>
|
||||
<Folder :size="16" class="text-neutral" />
|
||||
<i class="icon-[lucide--folder] size-4 text-neutral" />
|
||||
</template>
|
||||
<template #header-title>
|
||||
<span class="text-neutral text-base">Files</span>
|
||||
@@ -207,12 +196,12 @@ export const LongLabels: Story = {
|
||||
{
|
||||
id: 'general',
|
||||
label: 'General Settings',
|
||||
icon: () => h(() => Wrench, { size: 14 })
|
||||
icon: 'icon-[lucide--wrench]'
|
||||
},
|
||||
{
|
||||
id: 'appearance',
|
||||
label: 'Appearance & Themes Configuration',
|
||||
icon: () => h(() => Wrench, { size: 14 })
|
||||
icon: 'icon-[lucide--wrench]'
|
||||
},
|
||||
{
|
||||
title: 'ADVANCED OPTIONS',
|
||||
@@ -220,19 +209,19 @@ export const LongLabels: Story = {
|
||||
{
|
||||
id: 'performance',
|
||||
label: 'Performance & Optimization Settings',
|
||||
icon: () => h(() => Zap, { size: 14 })
|
||||
icon: 'icon-[lucide--zap]'
|
||||
},
|
||||
{
|
||||
id: 'experimental',
|
||||
label: 'Experimental Features (Beta)',
|
||||
icon: () => h(() => Puzzle, { size: 14 })
|
||||
icon: 'icon-[lucide--puzzle]'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { LeftSidePanel, Settings },
|
||||
components: { LeftSidePanel },
|
||||
setup() {
|
||||
const selectedItem = ref(args.modelValue)
|
||||
return { args, selectedItem }
|
||||
@@ -241,7 +230,7 @@ export const LongLabels: Story = {
|
||||
<div style="height: 500px; width: 256px;">
|
||||
<LeftSidePanel v-model="selectedItem" :nav-items="args.navItems">
|
||||
<template #header-icon>
|
||||
<Settings :size="16" class="text-neutral" />
|
||||
<i class="icon-[lucide--settings] size-4 text-neutral" />
|
||||
</template>
|
||||
<template #header-title>
|
||||
<span class="text-neutral text-base">Settings</span>
|
||||
|
||||
Reference in New Issue
Block a user