Unverified 提交 efcc2958 authored 作者: wwwillchen-bot's avatar wwwillchen-bot 提交者: GitHub

refactor(ProModeSelector): wrap build mode settings in accordion (#2555)

## Summary - Refactored the ProModeSelector component to group build mode settings (Web Access, Turbo Edits, Smart Context) inside a collapsible accordion - Improves UI organization by reducing visual clutter in the popover ## Test plan - Open the Pro Mode selector in the app - Verify the "Build mode settings" accordion is present - Expand/collapse the accordion and verify all settings (Web Access, Turbo Edits, Smart Context) are accessible - Test toggling each setting within the accordion 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2555" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Grouped Pro build mode settings (Web Access, Turbo Edits, Smart Context) into a collapsible accordion in ProModeSelector to declutter the popover. No behavior changes; tests now expand the accordion before toggling these settings. - **Refactors** - Wrapped the three settings under a "Build mode settings" accordion with smoother height transitions using Base UI’s panel API. - Updated rules to clarify our Accordion uses Base UI (not Radix/shadcn) and added E2E guidance for accordion-wrapped settings. - **Bug Fixes** - E2E helper now expands the accordion before changing Smart Context or Turbo Edits. <sup>Written for commit 025d159d427e8f9c59372f71374da18a6420ff00. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarWill Chen <willchen90@gmail.com> Co-authored-by: 's avatarClaude Opus 4.5 <noreply@anthropic.com> Co-authored-by: 's avatarclaude[bot] <41898282+claude[bot]@users.noreply.github.com>
上级 1b64ee3f
...@@ -11,7 +11,17 @@ export class ProModesDialog { ...@@ -11,7 +11,17 @@ export class ProModesDialog {
public close: () => Promise<void>, public close: () => Promise<void>,
) {} ) {}
async expandBuildModeSettings() {
const trigger = this.page.getByRole("button", {
name: "Build mode settings",
});
if ((await trigger.getAttribute("aria-expanded")) !== "true") {
await trigger.click();
}
}
async setSmartContextMode(mode: "balanced" | "off" | "deep") { async setSmartContextMode(mode: "balanced" | "off" | "deep") {
await this.expandBuildModeSettings();
await this.page await this.page
.getByTestId("smart-context-selector") .getByTestId("smart-context-selector")
.getByRole("button", { .getByRole("button", {
...@@ -21,6 +31,7 @@ export class ProModesDialog { ...@@ -21,6 +31,7 @@ export class ProModesDialog {
} }
async setTurboEditsMode(mode: "off" | "classic" | "search-replace") { async setTurboEditsMode(mode: "off" | "classic" | "search-replace") {
await this.expandBuildModeSettings();
await this.page await this.page
.getByTestId("turbo-edits-selector") .getByTestId("turbo-edits-selector")
.getByRole("button", { .getByRole("button", {
......
...@@ -14,3 +14,12 @@ ...@@ -14,3 +14,12 @@
- Wrapping `ToggleGroupItem` in `TooltipTrigger` without `render` also breaks `:first-child`/`:last-child` CSS selectors for rounded corners on the group. - Wrapping `ToggleGroupItem` in `TooltipTrigger` without `render` also breaks `:first-child`/`:last-child` CSS selectors for rounded corners on the group.
- For drag handles and resize rails, prefer the native `title` attribute over `Tooltip` — tooltips appear immediately on hover and interfere with drag interactions, while `title` has a built-in delay. - For drag handles and resize rails, prefer the native `title` attribute over `Tooltip` — tooltips appear immediately on hover and interfere with drag interactions, while `title` has a built-in delay.
## Accordion (Base UI vs Radix/shadcn)
The `Accordion` component in `src/components/ui/accordion.tsx` wraps `@base-ui/react/accordion`, **not** Radix or shadcn. The APIs differ:
- **No `type` or `collapsible` props** — these are Radix/shadcn-only. Reviewers may suggest `type="single" collapsible` but these props don't exist on Base UI's Accordion.
- Use `multiple` (boolean, default `false`) to allow multiple items open at once.
- Use `defaultValue` (array of item values) to control which items start expanded.
- Items are collapsible by default — no extra prop needed.
...@@ -69,6 +69,10 @@ Snapshots must be **deterministic** and **platform-agnostic**. They must not con ...@@ -69,6 +69,10 @@ Snapshots must be **deterministic** and **platform-agnostic**. They must not con
If the output under test contains non-deterministic or platform-specific content, add sanitization logic in the test helper (e.g. in `test_helper.ts`) to normalize it before snapshotting. If the output under test contains non-deterministic or platform-specific content, add sanitization logic in the test helper (e.g. in `test_helper.ts`) to normalize it before snapshotting.
## Accordion-wrapped settings in E2E tests
The Pro mode build settings (Web Access, Turbo Edits, Smart Context) are inside a collapsed `<Accordion>` in `ProModeSelector`. E2E test helpers must expand the accordion before interacting with elements inside it. The `ProModesDialog` class in `e2e-tests/helpers/page-objects/dialogs/ProModesDialog.ts` has an `expandBuildModeSettings()` method that handles this — call it before clicking any build mode setting buttons.
## E2E test fixtures with .dyad directories ## E2E test fixtures with .dyad directories
When adding E2E test fixtures that need a `.dyad` directory for testing: When adding E2E test fixtures that need a `.dyad` directory for testing:
......
...@@ -12,6 +12,12 @@ import { ...@@ -12,6 +12,12 @@ import {
TooltipTrigger, TooltipTrigger,
TooltipContent, TooltipContent,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import {
Accordion,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from "@/components/ui/accordion";
import { useSettings } from "@/hooks/useSettings"; import { useSettings } from "@/hooks/useSettings";
import { ipc } from "@/ipc/types"; import { ipc } from "@/ipc/types";
import { hasDyadProKey, type UserSettings } from "@/lib/schemas"; import { hasDyadProKey, type UserSettings } from "@/lib/schemas";
...@@ -95,7 +101,7 @@ export function ProModeSelector() { ...@@ -95,7 +101,7 @@ export function ProModeSelector() {
</a> </a>
</div> </div>
)} )}
<div className="flex flex-col gap-5"> <div className="flex flex-col gap-3">
<SelectorRow <SelectorRow
id="pro-enabled" id="pro-enabled"
label="Enable Dyad Pro" label="Enable Dyad Pro"
...@@ -104,25 +110,39 @@ export function ProModeSelector() { ...@@ -104,25 +110,39 @@ export function ProModeSelector() {
settingEnabled={Boolean(settings?.enableDyadPro)} settingEnabled={Boolean(settings?.enableDyadPro)}
toggle={toggleProEnabled} toggle={toggleProEnabled}
/> />
<SelectorRow <Accordion>
id="web-search" <AccordionItem
label="Web Access" value="build-mode-settings"
tooltip="Allows Dyad to access the web (e.g. search for information)" className="rounded-lg border border-border/60 bg-muted/30 px-3 border-b-0"
isTogglable={proModeTogglable} >
settingEnabled={Boolean(settings?.enableProWebSearch)} <AccordionTrigger className="cursor-pointer py-2 text-foreground/80 hover:text-foreground hover:no-underline">
toggle={toggleWebSearch} Build mode settings
/> </AccordionTrigger>
<AccordionContent className="pb-3">
<div className="flex flex-col gap-5 pt-2">
<SelectorRow
id="web-search"
label="Web Access"
tooltip="Allows Dyad to access the web (e.g. search for information)"
isTogglable={proModeTogglable}
settingEnabled={Boolean(settings?.enableProWebSearch)}
toggle={toggleWebSearch}
/>
<TurboEditsSelector <TurboEditsSelector
isTogglable={proModeTogglable} isTogglable={proModeTogglable}
settings={settings} settings={settings}
onValueChange={handleTurboEditsChange} onValueChange={handleTurboEditsChange}
/> />
<SmartContextSelector <SmartContextSelector
isTogglable={proModeTogglable} isTogglable={proModeTogglable}
settings={settings} settings={settings}
onValueChange={handleSmartContextChange} onValueChange={handleSmartContextChange}
/> />
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</div> </div>
</div> </div>
</PopoverContent> </PopoverContent>
......
...@@ -53,7 +53,7 @@ function AccordionContent({ ...@@ -53,7 +53,7 @@ function AccordionContent({
return ( return (
<AccordionPrimitive.Panel <AccordionPrimitive.Panel
data-slot="accordion-content" data-slot="accordion-content"
className="data-closed:animate-accordion-up data-open:animate-accordion-down overflow-hidden text-sm" className="h-[var(--accordion-panel-height)] overflow-hidden text-sm transition-[height] duration-200 ease-out data-[ending-style]:h-0 data-[starting-style]:h-0"
{...props} {...props}
> >
<div className={cn("pt-0 pb-4", className)}>{children}</div> <div className={cn("pt-0 pb-4", className)}>{children}</div>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论