HH-789 / HH-793: align theme tokens and BrowserList contract (#16)

This commit is contained in:
2026-08-28 18:58:39 +08:00
parent 60eda8f39e
commit d57fa68866
3 changed files with 32 additions and 6 deletions
+3 -2
View File
@@ -30,8 +30,9 @@ const statusLabels = {
}
function Status({ state }) {
const label = statusLabels[state]
const color = state === 'running' ? 'success.main' : state === 'exited' ? 'warning.main' : 'text.secondary'
return <Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 1, color, fontWeight: 650 }}><Box sx={{ width: 8, height: 8, borderRadius: '50%', bgcolor: 'currentColor' }} />{statusLabels[state] || state}</Box>
return <Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 1, color, fontWeight: 650 }}><Box sx={{ width: 8, height: 8, borderRadius: '50%', bgcolor: 'currentColor' }} /><Box><Typography component="span" fontWeight="inherit">{label || '未知状态'}</Typography>{label ? null : <Typography component="span" variant="caption" color="text.secondary" sx={{ display: 'block' }}>{state}</Typography>}</Box></Box>
}
function RuntimeActions({ runtime, busy, onAction }) {
@@ -67,7 +68,7 @@ function RuntimeTable({ runtimes, busy, onAction }) {
}
function RuntimeCards({ runtimes, busy, onAction }) {
return <Stack spacing={2} sx={{ display: { xs: 'flex', md: 'none' } }}>{runtimes.map(runtime => <Paper key={runtime.id} variant="outlined" sx={{ p: 2.5 }}><Stack spacing={1.5}><Box><Typography fontWeight={700}>{runtime.name}</Typography><Typography variant="caption" color="text.secondary">{runtime.status}</Typography></Box><Status state={runtime.state} /><Typography component="code" variant="body2" sx={{ overflowWrap: 'anywhere' }}>{runtime.profile}</Typography><RuntimeActions runtime={runtime} busy={busy === runtime.name} onAction={onAction} /></Stack></Paper>)}</Stack>
return <Stack spacing={2} sx={{ display: { xs: 'flex', md: 'none' } }}>{runtimes.map(runtime => <Paper key={runtime.id} variant="outlined" sx={{ p: 2.5 }}><Stack spacing={1.5}><Box><Typography fontWeight={700}>{runtime.name}</Typography><Typography variant="caption" color="text.secondary">{runtime.status}</Typography></Box><Status state={runtime.state} /><Typography component="code" variant="body2" sx={{ overflowWrap: 'anywhere' }}>{runtime.profile}</Typography><Box><Typography variant="caption" color="text.secondary">CDP</Typography><Typography component="code" variant="body2" sx={{ display: 'block', overflowWrap: 'anywhere' }}>{runtime.endpoint}</Typography></Box><RuntimeActions runtime={runtime} busy={busy === runtime.name} onAction={onAction} /></Stack></Paper>)}</Stack>
}
export function BrowserList() {
+25
View File
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { CoreAdminContext } from 'ra-core'
import { BrowserList } from './BrowserList'
import { theme } from './theme'
afterEach(cleanup)
@@ -21,6 +22,30 @@ function provider(overrides = {}) {
}
describe('BrowserList', () => {
it('uses the semantic design colors', () => {
expect(theme.palette.text.secondary).toBe('#475467')
expect(theme.palette.success.main).toBe('#067647')
expect(theme.palette.warning.main).toBe('#B54708')
expect(theme.palette.error.main).toBe('#B42318')
})
it('keeps CDP data in desktop and mobile views', async () => {
render(<CoreAdminContext dataProvider={provider()}><BrowserList /></CoreAdminContext>)
expect(await screen.findAllByText('http://account-a:9222')).toHaveLength(2)
expect(screen.getAllByText('CDP')).toHaveLength(3)
})
it('shows unknown states with their raw value as secondary evidence', async () => {
const unknownRuntime = { ...runtimes[0], state: 'dead' }
render(<CoreAdminContext dataProvider={provider({ getList: vi.fn().mockResolvedValue({ data: [unknownRuntime], total: 1 }) })}><BrowserList /></CoreAdminContext>)
expect(await screen.findAllByText('未知状态')).toHaveLength(2)
const rawStates = screen.getAllByText('dead')
expect(rawStates).toHaveLength(2)
expect(rawStates[0].className).toContain('MuiTypography-caption')
})
it('disables invalid lifecycle actions and sends explicit domain actions', async () => {
const dataProvider = provider()
render(<CoreAdminContext dataProvider={dataProvider}><BrowserList /></CoreAdminContext>)
+4 -4
View File
@@ -6,11 +6,11 @@ export const theme = createTheme({
primary: { main: '#0866ef', dark: '#0759d4' },
secondary: { main: '#061a38' },
background: { default: '#ffffff', paper: '#ffffff' },
text: { primary: '#111827', secondary: '#667085' },
text: { primary: '#111827', secondary: '#475467' },
divider: '#d7dde7',
success: { main: '#079455' },
warning: { main: '#d97706' },
error: { main: '#dc2626' },
success: { main: '#067647' },
warning: { main: '#B54708' },
error: { main: '#B42318' },
},
shape: { borderRadius: 8 },
typography: {