feat(settings): 开关改为可点击卡片 — 高亮即启用
- 清单项(侧边栏内容/文件预览)、嵌套相关设置与「新会话默认打开」 全部从复选框行改为 <button aria-pressed> 卡片:整卡点击切换, 视觉状态即状态(启用 = 品牌描边 + 交互选中填充 + 勾选徽标; 禁用 = 中性 hairline + 文字降级),悬停仅在禁用卡上显示 - 嵌套相关设置渲染为更小的缩进卡片(仍仅父级启用时显示); 宽度输入保持原生设置行(数值非开关) - 设置导航齿轮为宿主 shell navIcon 硬编码(无插件注入点), 按用户选择不改宿主、保持现状 - 新增 settingsGeneralTitle 文案;规格测试改为断言 aria-pressed - 文档(README/AGENTS.md/设计文档偏差记录)同步
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
/**
|
||||
* Side card settings section render tests: the section is DECLARATIVE —
|
||||
* every row (icon, title, type id, extensions, enable switch) derives from
|
||||
* every card (icon, title, type id, extensions, on/off state) derives from
|
||||
* the sidebar service's tab/viewer registries instead of hardcoded copy.
|
||||
* These specs pin that derivation with a fake store + a small registry:
|
||||
* The toggles are CARDS: the whole card is the switch, the visual state IS
|
||||
* the state (highlighted = enabled), announced via `aria-pressed`. These
|
||||
* specs pin that derivation with a fake store + a small registry:
|
||||
* registered tabs/viewers appear with their declared icon/title/settings,
|
||||
* disabled states render unchecked, and a disabled tab hides its declared
|
||||
* nested toggles.
|
||||
* disabled states render pressed=false, and a disabled tab hides its
|
||||
* declared nested cards.
|
||||
*
|
||||
* Rendered with renderToString (mount effects — the settings RPC sync — do
|
||||
* not run in SSR; the initial store prefs are the render input).
|
||||
@@ -60,58 +62,61 @@ function renderSection(store: SidebarStore, service: BetterSidebarService): stri
|
||||
))
|
||||
}
|
||||
|
||||
/** Count `aria-pressed` occurrences of one value in the rendered HTML. */
|
||||
function pressedCount(html: string, value: string): number {
|
||||
return html.match(new RegExp(`aria-pressed="${value}"`, 'g'))?.length ?? 0
|
||||
}
|
||||
|
||||
describe('SideCardSection declarative inventory', () => {
|
||||
it('renders one row per registered tab: icon + title + type id + switch', () => {
|
||||
it('renders one card per registered tab: icon + title + type id + pressed state', () => {
|
||||
const { store, service } = mount()
|
||||
const html = renderSection(store, service)
|
||||
expect(html).toContain('data-icon="explorer"')
|
||||
expect(html).toContain('>Explorer<')
|
||||
// The type id is the row's desc (the declarative "type" surface).
|
||||
// The type id is the card's desc (the declarative "type" surface).
|
||||
expect(html).toContain('>explorer<')
|
||||
expect(html).toContain('data-icon="subagent"')
|
||||
expect(html).toContain('>Subagents<')
|
||||
// Both tabs are enabled by default: their switches render checked.
|
||||
expect(html.match(/type="checkbox"/g)?.length).toBeGreaterThanOrEqual(4)
|
||||
// Default prefs: openByDefault + both tabs + the nested auto-open + the
|
||||
// image viewer are all enabled → 5 cards pressed, none pressed=false.
|
||||
expect(pressedCount(html, 'true')).toBe(5)
|
||||
expect(pressedCount(html, 'false')).toBe(0)
|
||||
})
|
||||
|
||||
it('renders the declared nested toggle under an enabled tab', () => {
|
||||
it('renders the declared nested card under an enabled tab', () => {
|
||||
const { store, service } = mount()
|
||||
const html = renderSection(store, service)
|
||||
// The subagent tab's declared related setting appears while enabled,
|
||||
// bound to its prefs key (default true → checked).
|
||||
// bound to its prefs key (default true → pressed).
|
||||
expect(html).toContain('Auto-open Subagents')
|
||||
expect(html).toContain('Expand on new subagent')
|
||||
})
|
||||
|
||||
it('hides the nested toggles while the parent tab is disabled', () => {
|
||||
it('hides the nested cards while the parent tab is disabled', () => {
|
||||
const { store, service } = mount()
|
||||
store.setPrefs({ ...store.getPrefs(), tabsEnabled: { subagent: false } })
|
||||
const html = renderSection(store, service)
|
||||
// The parent row stays (so the user can re-enable it) but unchecked.
|
||||
// The parent card stays (so the user can re-enable it) but pressed=false.
|
||||
expect(html).toContain('>Subagents<')
|
||||
expect(html).not.toContain('Auto-open Subagents')
|
||||
expect(pressedCount(html, 'false')).toBe(1)
|
||||
})
|
||||
|
||||
it('renders one row per registered viewer: icon + title + exts + switch', () => {
|
||||
it('renders one card per registered viewer: icon + title + exts', () => {
|
||||
const { store, service } = mount()
|
||||
const html = renderSection(store, service)
|
||||
expect(html).toContain('data-icon="image"')
|
||||
expect(html).toContain('>Image<')
|
||||
// The covered extensions are the row's desc.
|
||||
// The covered extensions are the card's desc.
|
||||
expect(html).toContain('png · jpg')
|
||||
})
|
||||
|
||||
it('a disabled viewer renders unchecked', () => {
|
||||
it('a disabled viewer renders pressed=false', () => {
|
||||
const { store, service } = mount()
|
||||
store.setPrefs({ ...store.getPrefs(), viewersEnabled: { image: false } })
|
||||
const html = renderSection(store, service)
|
||||
expect(html).toContain('>Image<')
|
||||
})
|
||||
|
||||
it('a disabled tab renders unchecked (its switch reflects the prefs map)', () => {
|
||||
const { store, service } = mount()
|
||||
store.setPrefs({ ...store.getPrefs(), tabsEnabled: { explorer: false } })
|
||||
const html = renderSection(store, service)
|
||||
expect(html).toContain('>explorer<')
|
||||
expect(pressedCount(html, 'false')).toBe(1)
|
||||
expect(pressedCount(html, 'true')).toBe(4)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user