-
Notifications
You must be signed in to change notification settings - Fork 53
Redesign image generation node with unified headers and Next.js Image migration #2051
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f0a689d
300072e
e09f670
78bddf4
52ddd5a
c7d5d36
1626ca4
7032d98
a0f56d7
6aaf58a
4574188
c1882c5
466fcb0
d97b444
502a220
2ca9501
9da0d1a
bf40ba3
b756e36
febe6da
5390930
cd4ac7a
55421dc
5712004
858ff1e
7e99fef
350a3b6
f5ebc1b
25cd72f
8208db9
2ad3c15
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -186,36 +186,35 @@ export function ModelPicker({ | |
| {group.label} | ||
| </div> | ||
| ) : null} | ||
| {group.models.map((m) => ( | ||
| <button | ||
| key={`${group.provider}-${m.id}`} | ||
| type="button" | ||
| disabled={m.disabled} | ||
| onClick={() => { | ||
| if (m.disabled) return; | ||
| onSelect(group.provider, m.id); | ||
| setOpen(false); | ||
| }} | ||
| className={clsx( | ||
| "flex gap-[12px] items-center p-[4px] rounded-[4px] text-left", | ||
| "hover:bg-white/5 focus:bg-white/5 cursor-pointer", | ||
| "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:focus:bg-transparent", | ||
| )} | ||
| title={ | ||
| m.disabled | ||
| ? (m.disabledReason ?? | ||
| "Upgrade to Pro to use this model.") | ||
| : undefined | ||
| } | ||
| > | ||
| <div className="flex items-center gap-[8px]"> | ||
| <p className="text-[14px] text-left text-nowrap"> | ||
| {m.label || m.id} | ||
| </p> | ||
| {m.badge} | ||
| </div> | ||
| </button> | ||
| ))} | ||
| {group.models.map((m) => { | ||
| const isDisabled = Boolean(m.disabled); | ||
| return ( | ||
| <button | ||
| key={`${group.provider}-${m.id}`} | ||
| type="button" | ||
| onClick={() => { | ||
| if (isDisabled) return; | ||
| onSelect(group.provider, m.id); | ||
| setOpen(false); | ||
| }} | ||
| aria-disabled={isDisabled} | ||
| className={clsx( | ||
| "flex gap-[12px] items-center p-[4px] rounded-[4px] text-left", | ||
| isDisabled | ||
| ? "opacity-50 cursor-not-allowed" | ||
| : "hover:bg-white/5 focus:bg-white/5 cursor-pointer", | ||
| )} | ||
| > | ||
| <div className="flex items-center gap-[8px]"> | ||
| <p className="text-[14px] text-left text-nowrap"> | ||
| {m.label || m.id} | ||
| </p> | ||
| {m.badge} | ||
| </div> | ||
| {/* disabled reason text intentionally not shown (design: gray-out only) */} | ||
| </button> | ||
| ); | ||
| })} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Disabled Buttons Still Keyboard AccessibleDisabled model picker buttons are still focusable and keyboard-activatable (Enter/Space) because the |
||
| </div> | ||
| ))} | ||
| </div> | ||
|
|
||
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,78 +4,68 @@ import { | |||||||||||
| useWorkflowDesigner, | ||||||||||||
| } from "@giselle-sdk/giselle/react"; | ||||||||||||
| import clsx from "clsx/lite"; | ||||||||||||
| import { Maximize2 } from "lucide-react"; | ||||||||||||
| import { useCallback } from "react"; | ||||||||||||
| import { GenerateImageIcon } from "../../../icons"; | ||||||||||||
| import { EmptyState } from "../../../ui/empty-state"; | ||||||||||||
| import { GenerationView } from "../../../ui/generation-view"; | ||||||||||||
|
|
||||||||||||
| function Empty({ onGenerate }: { onGenerate?: () => void }) { | ||||||||||||
| function Empty() { | ||||||||||||
| return ( | ||||||||||||
| <div className="bg-inverse/10 h-full rounded-[8px] flex justify-center items-center text-black-400"> | ||||||||||||
| <div className="relative bg-inverse/10 min-h-[250px] rounded-[8px] flex justify-center items-center text-black-400"> | ||||||||||||
| <EmptyState | ||||||||||||
| icon={<GenerateImageIcon width={24} height={24} />} | ||||||||||||
| title="Nothing generated yet." | ||||||||||||
| description="Generate with the current Prompt or adjust the Prompt and the results will be displayed." | ||||||||||||
| description="Generate or adjust the Prompt to see results." | ||||||||||||
| className="text-black-400" | ||||||||||||
| > | ||||||||||||
| {onGenerate && ( | ||||||||||||
| <button | ||||||||||||
| type="button" | ||||||||||||
| onClick={onGenerate} | ||||||||||||
| className="flex items-center justify-center px-[24px] py-[12px] mt-[16px] bg-[#141519] text-white rounded-[9999px] border border-border/15 transition-all hover:bg-[#1e1f26] hover:border-border/25 hover:translate-y-[-1px] cursor-pointer font-sans font-[500] text-[14px]" | ||||||||||||
| > | ||||||||||||
| <span className="mr-[8px] generate-star">✦</span> | ||||||||||||
| Generate with the Current Prompt | ||||||||||||
| </button> | ||||||||||||
| )} | ||||||||||||
| <style jsx>{` | ||||||||||||
| .generate-star { | ||||||||||||
| display: inline-block; | ||||||||||||
| } | ||||||||||||
| button:hover .generate-star { | ||||||||||||
| animation: rotateStar 0.7s ease-in-out; | ||||||||||||
| } | ||||||||||||
| @keyframes rotateStar { | ||||||||||||
| 0% { | ||||||||||||
| transform: rotate(0deg) scale(1); | ||||||||||||
| } | ||||||||||||
| 50% { | ||||||||||||
| transform: rotate(180deg) scale(1.5); | ||||||||||||
| } | ||||||||||||
| 100% { | ||||||||||||
| transform: rotate(360deg) scale(1); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| `}</style> | ||||||||||||
| </EmptyState> | ||||||||||||
| /> | ||||||||||||
| </div> | ||||||||||||
| ); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| export function GenerationPanel({ | ||||||||||||
| node, | ||||||||||||
| onClickGenerateButton, | ||||||||||||
| onExpand, | ||||||||||||
| isExpanded, | ||||||||||||
| }: { | ||||||||||||
| node: ImageGenerationNode; | ||||||||||||
| onClickGenerateButton?: () => void; | ||||||||||||
| onExpand?: () => void; | ||||||||||||
| isExpanded?: boolean; | ||||||||||||
| }) { | ||||||||||||
|
Comment on lines
26
to
36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify: Is the generate CTA intentionally removed from the empty state?
Also applies to: 49-51 🏁 Script executed: #!/bin/bash
# Find usages of GenerationPanel and check if onClickGenerateButton is still passed.
rg -nP --type=ts --type=tsx -C2 '\bGenerationPanel\s*\('
rg -nP --type=ts --type=tsx -C2 'onClickGenerateButton='Length of output: 55 </script> 🏁 Script executed: #!/bin/bash
# Search for GenerationPanel usages without --type flag
rg -nP '\bGenerationPanel\s*\(' -g '*.ts' -g '*.tsx' -C2
echo "---"
# Search for onClickGenerateButton parameter passing
rg -nP 'onClickGenerateButton=' -g '*.ts' -g '*.tsx' -C2
echo "---"
# Inspect the file to see lines 49-51
cat internal-packages/workflow-designer-ui/src/editor/properties-panel/image-generation-node-properties-panel/generation-panel.tsx | sed -n '1,60p'Length of output: 8156 </script> 🏁 Script executed: #!/bin/bash
# Get full file content to see where _handleGenerate is used
wc -l internal-packages/workflow-designer-ui/src/editor/properties-panel/image-generation-node-properties-panel/generation-panel.tsx
echo "---Full File---"
cat internal-packages/workflow-designer-ui/src/editor/properties-panel/image-generation-node-properties-panel/generation-panel.tsx
echo "---"
# Search for _handleGenerate usage
rg '_handleGenerate' internal-packages/workflow-designer-ui/src/editor/properties-panel/image-generation-node-properties-panel/generation-panel.tsx -n
echo "---"
# Check GenerationView component definition
fd GenerationView.tsx -g '*.tsx' | head -5Length of output: 3004 Remove unused The
🤖 Prompt for AI Agents |
||||||||||||
| const { data } = useWorkflowDesigner(); | ||||||||||||
| const { currentGeneration } = useNodeGenerations({ | ||||||||||||
| nodeId: node.id, | ||||||||||||
| origin: { type: "studio", workspaceId: data.id }, | ||||||||||||
| }); | ||||||||||||
|
|
||||||||||||
| const handleGenerate = useCallback(() => { | ||||||||||||
| const _handleGenerate = useCallback(() => { | ||||||||||||
| if (onClickGenerateButton) { | ||||||||||||
| onClickGenerateButton(); | ||||||||||||
| } | ||||||||||||
| }, [onClickGenerateButton]); | ||||||||||||
|
Comment on lines
+43
to
47
|
||||||||||||
| const _handleGenerate = useCallback(() => { | |
| if (onClickGenerateButton) { | |
| onClickGenerateButton(); | |
| } | |
| }, [onClickGenerateButton]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
disabledattribute instead ofaria-disabledfor better accessibility.The current implementation uses
aria-disabledwhile still keeping the button focusable and in the keyboard tab order. WhenisDisabledis true, keyboard users can focus the button but activation does nothing, creating a confusing experience.According to WAI-ARIA best practices,
aria-disabledshould only be used when an element needs to remain in the tab order for context. For truly non-interactive items, the HTMLdisabledattribute is more appropriate as it removes the element from the tab order entirely.Apply this diff to use the native
disabledattribute:{group.models.map((m) => { const isDisabled = Boolean(m.disabled); return ( <button key={`${group.provider}-${m.id}`} type="button" + disabled={isDisabled} onClick={() => { - if (isDisabled) return; onSelect(group.provider, m.id); setOpen(false); }} - aria-disabled={isDisabled} className={clsx( "flex gap-[12px] items-center p-[4px] rounded-[4px] text-left", isDisabled - ? "opacity-50 cursor-not-allowed" - : "hover:bg-white/5 focus:bg-white/5 cursor-pointer", + ? "opacity-50 cursor-not-allowed disabled:pointer-events-none" + : "hover:bg-white/5 focus:bg-white/5 cursor-pointer enabled:hover:bg-white/5", )} >Note: If you need disabled items to remain in tab order for specific UX reasons, please document that decision and ensure proper keyboard event handling (Enter/Space keys) is implemented.
📝 Committable suggestion
🤖 Prompt for AI Agents