diff --git a/.storybook/README.md b/.storybook/README.md index f35753d27c..eff19a67db 100644 --- a/.storybook/README.md +++ b/.storybook/README.md @@ -93,6 +93,44 @@ export const WithVariant: Story = { ## Development Tips +## ComfyUI Storybook Guidelines + +### Scope – When to Create Stories +- **PrimeVue components**: + No need to create stories. Just refer to the official PrimeVue documentation. +- **Custom shared components (design system components)**: + Always create stories. These components are built in collaboration with designers, and Storybook serves as both documentation and a communication tool. +- **Container components (logic-heavy)**: + Do not create stories. Only the underlying pure UI components should be included in Storybook. + +### Maintenance Philosophy +- Stories are lightweight and generally stable. + Once created, they rarely need updates unless: + - The design changes + - New props (e.g. size, color variants) are introduced +- For existing usage patterns, simply copy real code examples into Storybook to create stories. + +### File Placement +- Keep `*.stories.ts` files at the **same level as the component** (similar to test files). +- This makes it easier to check usage examples without navigating to another directory. + +### Developer/Designer Workflow +- **UI vs Container**: Separate pure UI components from container components. + Only UI components should live in Storybook. +- **Communication Tool**: Storybook is not just about code quality—it enables designers and developers to see: + - Which props exist + - What cases are covered + - How variants (e.g. size, colors) look in isolation +- **Example**: + `PackActionButton.vue` wraps a PrimeVue button with additional logic. + → Only create a story for the base UI button, not for the wrapper. + +### Suggested Workflow +1. Use PrimeVue docs for standard components +2. Use Storybook for **shared/custom components** that define our design system +3. Keep story files alongside components +4. When in doubt, focus on components reused across the app or those that need to be showcased to designers + ### Best Practices 1. **Keep Stories Simple**: Each story should demonstrate one specific use case @@ -135,6 +173,7 @@ export const WithLongText: Story = { - **`main.ts`**: Core Storybook configuration and Vite integration - **`preview.ts`**: Global decorators, parameters, and Vue app setup - **`manager.ts`**: Storybook UI customization (if needed) +- **`preview-head.html`**: Injects custom HTML into the `` of every Storybook iframe (used for global styles, fonts, or fixes for iframe-specific issues) ## Chromatic Visual Testing @@ -170,4 +209,4 @@ This Storybook setup includes: - PrimeVue component library integration - Proper alias resolution for `@/` imports -For component-specific examples, see the NodePreview stories in `src/components/node/`. \ No newline at end of file +For component-specific examples, see the NodePreview stories in `src/components/node/`. diff --git a/browser_tests/README.md b/browser_tests/README.md index 91f2f0a46b..ede6a303a9 100644 --- a/browser_tests/README.md +++ b/browser_tests/README.md @@ -392,16 +392,6 @@ Option 2 - Generate local baselines for comparison: npx playwright test --update-snapshots ``` -### Getting Test Artifacts from GitHub Actions - -When tests fail in CI, you can download screenshots and traces: - -1. Go to the failed workflow run in GitHub Actions -2. Scroll to "Artifacts" section at the bottom -3. Download `playwright-report` or `test-results` -4. Extract and open the HTML report locally -5. View actual vs expected screenshots and execution traces - ### Creating New Screenshot Baselines For PRs from `Comfy-Org/ComfyUI_frontend` branches: @@ -412,17 +402,19 @@ For PRs from `Comfy-Org/ComfyUI_frontend` branches: > **Note:** Fork PRs cannot auto-commit screenshots. A maintainer will need to commit the screenshots manually for you (don't worry, they'll do it). -## CI/CD Integration +## Viewing Test Reports ### Automated Test Deployment -The project automatically deploys Playwright test reports to Cloudflare Pages for every PR and push to main branches. This provides: +The project automatically deploys Playwright test reports to Cloudflare Pages for every PR and push to main branches. -- **Live test reports** with interactive HTML views -- **Cross-browser testing** across chromium, mobile-chrome, and different viewport sizes -- **Real-time PR comments** with test status and links to detailed reports +### Accessing Test Reports -#### How it works: +- **From PR comments**: Click the "View Report" links for each browser +- **Direct URLs**: Reports are available at `https://[branch].comfyui-playwright-[browser].pages.dev` (branch-specific deployments) +- **From GitHub Actions**: Download artifacts from failed runs + +### How It Works 1. **Test execution**: All browser tests run in parallel across multiple browsers 2. **Report generation**: HTML reports are generated for each browser configuration @@ -437,21 +429,6 @@ The project automatically deploys Playwright test reports to Cloudflare Pages fo - Direct links to interactive test reports - Real-time progress updates as tests complete -#### Accessing test reports: - -- **From PR comments**: Click the "View Report" links for each browser -- **From GitHub Actions**: Download artifacts from failed runs -- **Direct URLs**: Reports are available at `https://[branch].comfyui-playwright-[browser].pages.dev` (branch-specific deployments) - -#### Report features: - -- **Interactive HTML reports** with test results, screenshots, and traces -- **Detailed failure analysis** with before/after screenshots -- **Test execution videos** for failed tests -- **Network logs** and console output for debugging - -This integration ensures that test results are easily accessible to reviewers and maintainers, making it simple to verify that changes don't break existing functionality across different browsers and viewport sizes. - ## Resources - [Playwright UI Mode](https://playwright.dev/docs/test-ui-mode) - Interactive test debugging diff --git a/src/assets/icons/custom/workflow.svg b/src/assets/icons/custom/workflow.svg index 72f90c1a4f..043d24e7b5 100644 --- a/src/assets/icons/custom/workflow.svg +++ b/src/assets/icons/custom/workflow.svg @@ -1,7 +1,3 @@ - - - - - - + + diff --git a/src/components/graph/SelectionToolbox.vue b/src/components/graph/SelectionToolbox.vue index d4cf408fcf..bbbeadef94 100644 --- a/src/components/graph/SelectionToolbox.vue +++ b/src/components/graph/SelectionToolbox.vue @@ -12,7 +12,6 @@ - @@ -35,7 +34,6 @@ import BypassButton from '@/components/graph/selectionToolbox/BypassButton.vue' import ColorPickerButton from '@/components/graph/selectionToolbox/ColorPickerButton.vue' import ConvertToSubgraphButton from '@/components/graph/selectionToolbox/ConvertToSubgraphButton.vue' import DeleteButton from '@/components/graph/selectionToolbox/DeleteButton.vue' -import EditModelButton from '@/components/graph/selectionToolbox/EditModelButton.vue' import ExecuteButton from '@/components/graph/selectionToolbox/ExecuteButton.vue' import ExtensionCommandButton from '@/components/graph/selectionToolbox/ExtensionCommandButton.vue' import HelpButton from '@/components/graph/selectionToolbox/HelpButton.vue' diff --git a/src/components/graph/selectionToolbox/EditModelButton.vue b/src/components/graph/selectionToolbox/EditModelButton.vue deleted file mode 100644 index d9f515ddd4..0000000000 --- a/src/components/graph/selectionToolbox/EditModelButton.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/src/components/input/MultiSelect.vue b/src/components/input/MultiSelect.vue index 2dd01dcb57..d1d02a4f16 100644 --- a/src/components/input/MultiSelect.vue +++ b/src/components/input/MultiSelect.vue @@ -9,6 +9,41 @@ :max-selected-labels="0" :pt="pt" > +
+ +
+ + {{ + selectedCount > 0 + ? $t('g.itemsSelected', { selectedCount }) + : $t('g.itemSelected', { selectedCount }) + }} + + +
+
+
+ + - +
() +import SearchBox from '@/components/input/SearchBox.vue' -const selectedItems = defineModel<{ name: string; value: string }[]>({ +import TextButton from '../button/TextButton.vue' + +type Option = { name: string; value: string } + +interface Props { + /** Input label shown on the trigger button */ + label?: string + /** Static options for the multiselect (when not using async search) */ + options: Option[] + /** Show search box in the panel header */ + hasSearchBox?: boolean + /** Show selected count text in the panel header */ + showSelectedCount?: boolean + /** Show "Clear all" action in the panel header */ + hasClearButton?: boolean + /** Placeholder for the search input */ + searchPlaceholder?: string +} +const { + label, + options, + hasSearchBox = false, + showSelectedCount = false, + hasClearButton = false, + searchPlaceholder = 'Search...' +} = defineProps() + +const selectedItems = defineModel({ required: true }) - +const searchQuery = defineModel('searchQuery') const selectedCount = computed(() => selectedItems.value.length) -/** - * Pure unstyled mode using only the PrimeVue PT API. - * All PrimeVue built-in checkboxes/headers are hidden via PT (no :deep hacks). - * Visual output matches the previous version exactly. - */ const pt = computed(() => ({ root: ({ props }: MultiSelectPassThroughMethodOptions) => ({ class: [ @@ -97,19 +151,19 @@ const pt = computed(() => ({ dropdown: { class: 'flex shrink-0 cursor-pointer items-center justify-center px-3' }, - header: { class: 'hidden' }, - + header: () => ({ + class: + hasSearchBox || showSelectedCount || hasClearButton ? 'block' : 'hidden' + }), // Overlay & list visuals unchanged overlay: - 'mt-2 bg-white dark-theme:bg-zinc-800 text-neutral dark-theme:text-white rounded-lg border border-solid border-zinc-100', + 'mt-2 bg-white dark-theme:bg-zinc-800 text-neutral dark-theme:text-white rounded-lg border border-solid border-zinc-100 dark-theme:border-zinc-700', list: { class: 'flex flex-col gap-1 p-0 list-none border-none text-xs' }, - // Option row hover tone identical option: 'flex gap-1 items-center p-2 hover:bg-neutral-100/50 dark-theme:hover:bg-zinc-700/50', - // Hide built-in checkboxes entirely via PT (no :deep) pcHeaderCheckbox: { root: { class: 'hidden' }, diff --git a/src/components/input/SearchBox.vue b/src/components/input/SearchBox.vue index 08075b18b1..462668a123 100644 --- a/src/components/input/SearchBox.vue +++ b/src/components/input/SearchBox.vue @@ -1,8 +1,6 @@