mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-28 18:22:40 +00:00
Asset Browser Modal Component (#5607)
* [ci] ignore playwright mcp directory * [feat] add AssetBrowserModal And all related sub components * [feat] reactive filter functions * [ci] clean up storybook config * [feat] add sematic AssetCard * [fix] i love lucide * [fix] AssetCard layout issues * [fix] add AssetBadge type * [fix] simplify useAssetBrowser * [fix] modal layout * [fix] simplify useAssetBrowserDialog * [fix] add tailwind back to storybook * [fix] better reponsive layout * [fix] missed i18n string * [fix] missing i18n translations * [fix] remove erroneous prevent on keyboard.space * [feat] add asset metadata validation utilities * [fix] remove erroneous test code * [fix] remove forced min and max width on AssetCard * [fix] import statement nits
This commit is contained in:
178
src/platform/assets/components/AssetBrowserModal.stories.ts
Normal file
178
src/platform/assets/components/AssetBrowserModal.stories.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
import AssetBrowserModal from '@/platform/assets/components/AssetBrowserModal.vue'
|
||||
import {
|
||||
createMockAssets,
|
||||
mockAssets
|
||||
} from '@/platform/assets/fixtures/ui-mock-assets'
|
||||
|
||||
// Story arguments interface
|
||||
interface StoryArgs {
|
||||
nodeType: string
|
||||
inputName: string
|
||||
currentValue: string
|
||||
showLeftPanel?: boolean
|
||||
}
|
||||
|
||||
const meta: Meta<StoryArgs> = {
|
||||
title: 'Platform/Assets/AssetBrowserModal',
|
||||
component: AssetBrowserModal,
|
||||
parameters: {
|
||||
layout: 'fullscreen'
|
||||
},
|
||||
argTypes: {
|
||||
nodeType: {
|
||||
control: 'select',
|
||||
options: ['CheckpointLoaderSimple', 'VAELoader', 'ControlNetLoader'],
|
||||
description: 'ComfyUI node type for context'
|
||||
},
|
||||
inputName: {
|
||||
control: 'select',
|
||||
options: ['ckpt_name', 'vae_name', 'control_net_name'],
|
||||
description: 'Widget input name'
|
||||
},
|
||||
currentValue: {
|
||||
control: 'text',
|
||||
description: 'Current selected asset value'
|
||||
},
|
||||
showLeftPanel: {
|
||||
control: 'boolean',
|
||||
description: 'Whether to show the left panel with categories'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
// Modal Layout Stories
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
nodeType: 'CheckpointLoaderSimple',
|
||||
inputName: 'ckpt_name',
|
||||
currentValue: '',
|
||||
showLeftPanel: false
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { AssetBrowserModal },
|
||||
setup() {
|
||||
const onAssetSelect = (asset: any) => {
|
||||
console.log('Selected asset:', asset)
|
||||
}
|
||||
const onClose = () => {
|
||||
console.log('Modal closed')
|
||||
}
|
||||
|
||||
return {
|
||||
...args,
|
||||
onAssetSelect,
|
||||
onClose,
|
||||
assets: mockAssets
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="flex items-center justify-center min-h-screen bg-stone-200 dark-theme:bg-stone-200 p-4">
|
||||
<AssetBrowserModal
|
||||
:node-type="nodeType"
|
||||
:input-name="inputName"
|
||||
:show-left-panel="showLeftPanel"
|
||||
:assets="assets"
|
||||
@asset-select="onAssetSelect"
|
||||
@close="onClose"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
}
|
||||
|
||||
// Story demonstrating single asset type (auto-hides left panel)
|
||||
export const SingleAssetType: Story = {
|
||||
args: {
|
||||
nodeType: 'CheckpointLoaderSimple',
|
||||
inputName: 'ckpt_name',
|
||||
currentValue: '',
|
||||
showLeftPanel: false
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { AssetBrowserModal },
|
||||
setup() {
|
||||
const onAssetSelect = (asset: any) => {
|
||||
console.log('Selected asset:', asset)
|
||||
}
|
||||
const onClose = () => {
|
||||
console.log('Modal closed')
|
||||
}
|
||||
|
||||
// Create assets with only one type (checkpoints)
|
||||
const singleTypeAssets = createMockAssets(15).map((asset) => ({
|
||||
...asset,
|
||||
type: 'checkpoint'
|
||||
}))
|
||||
|
||||
return { ...args, onAssetSelect, onClose, assets: singleTypeAssets }
|
||||
},
|
||||
template: `
|
||||
<div class="flex items-center justify-center min-h-screen bg-stone-200 dark-theme:bg-stone-200 p-4">
|
||||
<AssetBrowserModal
|
||||
:node-type="nodeType"
|
||||
:input-name="inputName"
|
||||
:show-left-panel="showLeftPanel"
|
||||
:assets="assets"
|
||||
@asset-select="onAssetSelect"
|
||||
@close="onClose"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
}),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
'Modal with assets of only one type (checkpoint) - left panel auto-hidden.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Story with left panel explicitly hidden
|
||||
export const NoLeftPanel: Story = {
|
||||
args: {
|
||||
nodeType: 'CheckpointLoaderSimple',
|
||||
inputName: 'ckpt_name',
|
||||
currentValue: '',
|
||||
showLeftPanel: false
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { AssetBrowserModal },
|
||||
setup() {
|
||||
const onAssetSelect = (asset: any) => {
|
||||
console.log('Selected asset:', asset)
|
||||
}
|
||||
const onClose = () => {
|
||||
console.log('Modal closed')
|
||||
}
|
||||
|
||||
return { ...args, onAssetSelect, onClose, assets: mockAssets }
|
||||
},
|
||||
template: `
|
||||
<div class="flex items-center justify-center min-h-screen bg-stone-200 dark-theme:bg-stone-200 p-4">
|
||||
<AssetBrowserModal
|
||||
:node-type="nodeType"
|
||||
:input-name="inputName"
|
||||
:show-left-panel="showLeftPanel"
|
||||
:assets="assets"
|
||||
@asset-select="onAssetSelect"
|
||||
@close="onClose"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
}),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
'Modal with left panel explicitly disabled via showLeftPanel=false.'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user