feat(web): add preview badge to empty hero
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
- button "Settings":
|
- button "Settings":
|
||||||
- img
|
- img
|
||||||
- text: Settings
|
- text: Settings
|
||||||
- text: Let's start building
|
- text: Let's start building Preview
|
||||||
- button "Choose workspace":
|
- button "Choose workspace":
|
||||||
- img
|
- img
|
||||||
- text: workspace
|
- text: workspace
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
- button "Settings":
|
- button "Settings":
|
||||||
- img
|
- img
|
||||||
- text: Settings
|
- text: Settings
|
||||||
- text: Let's start building
|
- text: Let's start building Preview
|
||||||
- button "Choose workspace":
|
- button "Choose workspace":
|
||||||
- img
|
- img
|
||||||
- text: workspace
|
- text: workspace
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export const zh = {
|
|||||||
'access.confirm.cancel': '取消',
|
'access.confirm.cancel': '取消',
|
||||||
'access.confirm.enable': '启用 Full access',
|
'access.confirm.enable': '启用 Full access',
|
||||||
'hero.headline': '开始构建吧',
|
'hero.headline': '开始构建吧',
|
||||||
|
'hero.preview': '预览版',
|
||||||
'hero.chooseWorkspace': '选择工作区',
|
'hero.chooseWorkspace': '选择工作区',
|
||||||
'session.hierarchy': '会话层级',
|
'session.hierarchy': '会话层级',
|
||||||
'details.title': '详情',
|
'details.title': '详情',
|
||||||
@@ -144,6 +145,7 @@ export const en = {
|
|||||||
'access.confirm.cancel': 'Cancel',
|
'access.confirm.cancel': 'Cancel',
|
||||||
'access.confirm.enable': 'Enable Full access',
|
'access.confirm.enable': 'Enable Full access',
|
||||||
'hero.headline': 'Let\'s start building',
|
'hero.headline': 'Let\'s start building',
|
||||||
|
'hero.preview': 'Preview',
|
||||||
'hero.chooseWorkspace': 'Choose workspace',
|
'hero.chooseWorkspace': 'Choose workspace',
|
||||||
'session.hierarchy': 'Session hierarchy',
|
'session.hierarchy': 'Session hierarchy',
|
||||||
'details.title': 'Details',
|
'details.title': 'Details',
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ export function HeroShell({ t, children }: HeroShellProps) {
|
|||||||
<div className={css.headline}>
|
<div className={css.headline}>
|
||||||
{/* figma 34:10412: fish 34×25 leading the headline, gap 10. */}
|
{/* figma 34:10412: fish 34×25 leading the headline, gap 10. */}
|
||||||
<FishLogo size={34} className={css.fish} />
|
<FishLogo size={34} className={css.fish} />
|
||||||
{t('hero.headline')}
|
<span className={css.headlineText}>{t('hero.headline')}</span>
|
||||||
|
<span className={css.previewBadge}>{t('hero.preview')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={css.body}>
|
<div className={css.body}>
|
||||||
{/* The resident composer (ConversationRoot wrapActiveBody seat; the
|
{/* The resident composer (ConversationRoot wrapActiveBody seat; the
|
||||||
|
|||||||
@@ -23,21 +23,44 @@
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* figma 34:10411: fish + title, gap 10, centered; 26/32 wt500. */
|
/* Fish + title stay centered as one unit; the preview badge aligns with the
|
||||||
|
title's leading edge on the second row. */
|
||||||
.headline {
|
.headline {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: 34px auto;
|
||||||
|
column-gap: 10px;
|
||||||
|
row-gap: 4px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 10px;
|
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--dsw-alias-label-primary);
|
color: var(--dsw-alias-label-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.headlineText {
|
||||||
|
grid-row: 1;
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previewBadge {
|
||||||
|
grid-row: 2;
|
||||||
|
grid-column: 2;
|
||||||
|
justify-self: start;
|
||||||
|
padding: 0 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--dsw-alias-state-business-tertiary);
|
||||||
|
color: var(--dsw-alias-state-business-primary);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* figma fish fill rides business blue. */
|
/* figma fish fill rides business blue. */
|
||||||
.fish {
|
.fish {
|
||||||
flex: none;
|
grid-row: 1;
|
||||||
|
grid-column: 1;
|
||||||
color: var(--dsw-alias-state-business-primary);
|
color: var(--dsw-alias-state-business-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ import type {
|
|||||||
import type { ConversationRootProps } from '../src/client/skeleton/ConversationRoot.tsx'
|
import type { ConversationRootProps } from '../src/client/skeleton/ConversationRoot.tsx'
|
||||||
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
|
||||||
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
|
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
|
||||||
|
import { en as commonEn } from '@deepseek-ai/dsh-client-locale/src/locales/en.ts'
|
||||||
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
|
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
|
||||||
import { createChatStore } from '../src/client/stores.ts'
|
import { createChatStore } from '../src/client/stores.ts'
|
||||||
import { SessionInputShell } from '../src/client/input/facade.ts'
|
import { SessionInputShell } from '../src/client/input/facade.ts'
|
||||||
import { zh } from '../src/client/locales.ts'
|
import { en, zh } from '../src/client/locales.ts'
|
||||||
import { ConversationRoot } from '../src/client/skeleton/ConversationRoot.tsx'
|
import { ConversationRoot } from '../src/client/skeleton/ConversationRoot.tsx'
|
||||||
import { ConversationSession } from '../src/client/skeleton/ConversationSession.tsx'
|
import { ConversationSession } from '../src/client/skeleton/ConversationSession.tsx'
|
||||||
|
import { HeroShell } from '../src/client/skeleton/EmptyHero.tsx'
|
||||||
import { InputBar } from '../src/client/skeleton/InputBar.tsx'
|
import { InputBar } from '../src/client/skeleton/InputBar.tsx'
|
||||||
import type { InputBarProps } from '../src/client/skeleton/InputBar.tsx'
|
import type { InputBarProps } from '../src/client/skeleton/InputBar.tsx'
|
||||||
import type {
|
import type {
|
||||||
@@ -214,6 +216,12 @@ function mount(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('ConversationRoot resident composer', () => {
|
describe('ConversationRoot resident composer', () => {
|
||||||
|
it('renders the English preview badge through the hero locale seat', () => {
|
||||||
|
const view = render(<HeroShell t={makeTranslate(en, commonEn)} />)
|
||||||
|
expect(view.getByText('Let\'s start building')).toBeTruthy()
|
||||||
|
expect(view.getByText('Preview')).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
it('keeps composer text in the machine, mirrors to the chat store, and submits through the sink', () => {
|
it('keeps composer text in the machine, mirrors to the chat store, and submits through the sink', () => {
|
||||||
const b = mount(conversationSnapshot())
|
const b = mount(conversationSnapshot())
|
||||||
const box = b.view.getByRole('textbox')
|
const box = b.view.getByRole('textbox')
|
||||||
@@ -273,6 +281,7 @@ describe('ConversationRoot resident composer', () => {
|
|||||||
expect(host).not.toBeNull()
|
expect(host).not.toBeNull()
|
||||||
expect(header?.getAttribute('aria-hidden')).toBe('true')
|
expect(header?.getAttribute('aria-hidden')).toBe('true')
|
||||||
expect(b.view.getByText('开始构建吧')).toBeTruthy()
|
expect(b.view.getByText('开始构建吧')).toBeTruthy()
|
||||||
|
expect(b.view.getByText('预览版')).toBeTruthy()
|
||||||
expect(b.view.queryByTestId('view-chat')).toBeNull()
|
expect(b.view.queryByTestId('view-chat')).toBeNull()
|
||||||
// The same machine-backed textarea is live in the hero, and the
|
// The same machine-backed textarea is live in the hero, and the
|
||||||
// persistence mirror stays bound (ConversationSession mounts chrome-hidden
|
// persistence mirror stays bound (ConversationSession mounts chrome-hidden
|
||||||
|
|||||||
Reference in New Issue
Block a user