Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ body,

--shadow-app-card: 0 18px 45px rgb(29 37 31 / 9%);
--shadow-app-panel: 0 22px 60px rgb(29 37 31 / 12%);
--shadow-app-composer-focus: 0 18px 48px rgb(29 37 31 / 14%);
--shadow-app-page: 0 26px 80px rgb(29 37 31 / 10%);
--shadow-app-header: inset 0 1px 0 rgb(255 255 255 / 55%);
--shadow-app-menu: 0 8px 24px rgb(29 37 31 / 10%);
Expand Down
33 changes: 20 additions & 13 deletions frontend/src/pages/quick-start/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,6 @@ describe('QuickStartPage', () => {
expect(screen.getByRole('button', { name: /16-bit 日式 RPG/u })).toBeTruthy()
expect(screen.getByRole('button', { name: /暗黑哥特像素/u })).toBeTruthy()
expect(screen.getByRole('button', { name: /温暖手绘像素/u })).toBeTruthy()
expect(screen.getByRole('button', { name: '像素守夜人' })).toBeTruthy()
expect(screen.getByRole('button', { name: '轻装信使' })).toBeTruthy()

fireEvent.change(screen.getByRole('textbox', { name: '创作指令' }), {
target: { value: '戴银色面具的游侠' },
Expand All @@ -350,18 +348,27 @@ describe('QuickStartPage', () => {
expect(screen.queryByRole('button', { name: /暗黑哥特像素/u })).toBeNull()
})

it('keeps the original Quick Start prompt shortcuts functional', () => {
const view = renderAt('/quick-start', serviceFor(null))
fireEvent.click(screen.getByRole('button', { name: '像素守夜人' }))
expect((screen.getByRole('textbox', { name: '创作指令' }) as HTMLTextAreaElement).value).toBe(
'一位提着风灯、披深色斗篷的像素守夜人',
it('offers style prompts only, without the retired role-example shortcuts', () => {
renderAt('/quick-start', serviceFor(null))

// 入口只保留三张风格卡:角色样例会让人误以为这些形象是现成资产。
expect(screen.queryByRole('button', { name: '像素守夜人' })).toBeNull()
expect(screen.queryByRole('button', { name: '轻装信使' })).toBeNull()

fireEvent.click(screen.getByRole('button', { name: /16-bit 日式 RPG/u }))
expect((screen.getByRole('textbox', { name: '创作指令' }) as HTMLInputElement).value).toBe(
'16-bit 日式 RPG 像素风,清晰轮廓,明亮配色',
)
})

view.unmount()
it('keeps the entry composer on a single line', () => {
renderAt('/quick-start', serviceFor(null))
fireEvent.click(screen.getByRole('button', { name: '轻装信使' }))
expect((screen.getByRole('textbox', { name: '创作指令' }) as HTMLTextAreaElement).value).toBe(
'轻装信使,侧视像素风,轮廓清晰,动作轻快',
const composer = screen.getByRole('textbox', { name: '创作指令' })

expect(composer.tagName).toBe('INPUT')
expect(composer.className).toContain('h-10')
expect(composer.closest('form')?.className).toContain(
'focus-within:shadow-[var(--shadow-app-composer-focus)]',
)
})

Expand Down Expand Up @@ -748,7 +755,7 @@ describe('QuickStartPage', () => {

expect(screen.getByRole('textbox', { name: '创作指令' })).toBeTruthy()
fireEvent.click(screen.getByRole('button', { name: /16-bit 日式 RPG/u }))
expect((screen.getByRole('textbox') as HTMLTextAreaElement).value).toBe(
expect((screen.getByRole('textbox') as HTMLInputElement).value).toBe(
'16-bit 日式 RPG 像素风,清晰轮廓,明亮配色',
)
expect(screen.queryByRole('button', { name: /暗黑哥特像素/u })).toBeNull()
Expand Down Expand Up @@ -846,7 +853,7 @@ describe('QuickStartPage', () => {
fireEvent.change(screen.getByLabelText('上传角色母版'), { target: { files: [file] } })

const composer = screen.getByLabelText('创作指令').closest('form')
expect(screen.getByLabelText('创作指令').tagName).toBe('TEXTAREA')
expect(screen.getByLabelText('创作指令').tagName).toBe('INPUT')
expect(composer?.textContent).toContain('hero.png')
expect(screen.getByRole('button', { name: '移除图片' }).closest('form')).toBe(composer)
expect(composer?.querySelector('[data-layout="quick-start-attachment-row"]')).toBeNull()
Expand Down
41 changes: 4 additions & 37 deletions frontend/src/pages/quick-start/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,17 +241,6 @@ function QuickStartInput({
const hasPrompt = Boolean(prompt.trim())
const showStylePrompts = !hasPrompt && !templateFile

const originalPromptShortcuts = [
{
label: '像素守夜人',
prompt: '一位提着风灯、披深色斗篷的像素守夜人',
},
{
label: '轻装信使',
prompt: '轻装信使,侧视像素风,轮廓清晰,动作轻快',
},
] as const

useEffect(
() => () => {
submitAbortController.current?.abort()
Expand Down Expand Up @@ -361,47 +350,25 @@ function QuickStartInput({
</button>
))}
</div>
<div
data-layout="quick-start-original-shortcuts"
data-presence={showStylePrompts ? 'visible' : 'hidden'}
aria-hidden={!showStylePrompts}
className={`flex flex-wrap justify-center gap-2 transition-[opacity,transform,filter] duration-[460ms] motion-reduce:transition-none ${
showStylePrompts
? 'translate-y-0 opacity-100 blur-0'
: 'pointer-events-none -translate-y-1 opacity-0 blur-[4px]'
}`}
>
{originalPromptShortcuts.map((shortcut) => (
<button
key={shortcut.label}
type="button"
disabled={!showStylePrompts}
onClick={() => setPrompt(shortcut.prompt)}
className="rounded-full border border-app-line px-3 py-1.5 text-xs font-medium text-app-muted transition hover:border-app-line-strong hover:text-app-accent"
>
{shortcut.label}
</button>
))}
</div>
</div>

<div data-layout="quick-start-composer" className="mx-auto w-full max-w-3xl self-end">
<form
onSubmit={(event) => void submit(event)}
className="grid items-center gap-1.5 rounded-xl border border-app-line-strong bg-app-surface-raised p-1.5 shadow-app-panel transition-shadow focus-within:border-app-accent sm:grid-cols-[1fr_auto_auto]"
className="grid items-center gap-1.5 rounded-xl border border-app-line-strong bg-app-surface-raised p-1.5 shadow-app-panel transition-shadow focus-within:border-app-accent focus-within:shadow-[var(--shadow-app-composer-focus)] sm:grid-cols-[1fr_auto_auto]"
>
<label className="min-w-0" htmlFor="quick-start-prompt">
<span className="sr-only">创作指令</span>
<textarea
<input
id="quick-start-prompt"
type="text"
aria-label="创作指令"
value={prompt}
onChange={(event) => setPrompt(event.target.value)}
rows={2}
placeholder={
templateFile ? '描述动作,可留空生成待机动作…' : '描述角色的外形、身份和气质…'
}
className="min-h-10 w-full min-w-0 resize-none border-0 bg-transparent px-3 py-2 text-[15px] leading-6 text-app-ink outline-none placeholder:text-app-faint"
className="h-10 w-full min-w-0 border-0 bg-transparent px-3 text-[15px] text-app-ink outline-none placeholder:text-app-faint"
/>
</label>

Expand Down
Loading