From 3cadd955079c995d82147e261f1f4766a4662583 Mon Sep 17 00:00:00 2001 From: Innei Date: Wed, 9 Sep 2026 15:24:27 +0800 Subject: [PATCH 01/27] feat(ui): add @lody/ui with StyleX tokens and Base UI Button (#305) * feat(ui): add @lody/ui with StyleX tokens and Base UI Button Introduce packages/ui as the Base UI + StyleX home for shared primitives. It ships colour, scale, shadow and motion tokens tuned to the two palettes the app renders (Lody Light and Vesper), squircle per-size radii, forced light/dark themes, and a Button with primary/secondary/ghost/destructive/link variants, mini..large sizes, tone, pill shape and icon layout. Wire the StyleX unplugin into the Electron renderer, site-docs and Storybook, pin one cascade layer order (theme, base, stylex, components, utilities) so Tailwind preflight sits below component styles and utilities above them, and inject the dev stylesheet into the TanStack Start root head. Replace every packages/components Button import and buttonVariants user with @lody/ui/button, delete the Radix button, and give AlertDialog action and cancel their children back with a variant prop instead of red utilities. Model: claude-fable-5-1 Claude-Session: https://claude.ai/code/session_01KJL8hsY2LscFcvxHFDzwxt * fix(ui): use button tokens for composer actions Model: gpt-6 --------- Co-authored-by: Wibus Wu <62133302+wibus-wee@users.noreply.github.com> --- .agents/docs/components-package.md | 6 + ...2026-09-08-ui-button-migration-takeover.md | 68 ++ README.md | 1 + README.zh-CN.md | 1 + apps/electron/electron.vite.config.ts | 3 + apps/electron/package.json | 2 + apps/electron/tsconfig.web.json | 3 + packages/components/.storybook/main.cjs | 3 + packages/components/package.json | 2 + .../ai-gui/chat-failed-detail-dialog.tsx | 6 +- .../ai-gui/mermaid-diagram-viewer.tsx | 18 +- .../components/ai-gui/message-selection.tsx | 8 +- .../ai-gui/session-file-preview-dialog.tsx | 20 +- .../components/ai-gui/user-message-editor.tsx | 16 +- .../components/src/components/ai-gui/view.tsx | 45 +- .../src/components/archive/archive-view.tsx | 27 +- .../components/archive/web-archive-screen.tsx | 22 +- .../bug-report/bug-report-dialog.tsx | 4 +- .../components/chat/attachment-add-menu.tsx | 6 +- .../src/components/chat/chat-composer.tsx | 12 +- .../src/components/chat/chat-landing-view.tsx | 14 +- .../src/components/chat/chat-landing.tsx | 26 +- .../chat/machine-pairing-dialog.tsx | 12 +- .../codex-reset-forecast-dialog.tsx | 4 +- .../components/error-boundary-fallback.tsx | 16 +- .../add-local-project-dialog.tsx | 34 +- .../mobile-add-local-project-flow.tsx | 7 +- .../components/src/components/login-page.tsx | 34 +- .../src/components/loro-app-sidebar.tsx | 4 +- .../src/components/loro-sidebar.tsx | 4 +- .../mobile/mobile-about-settings.tsx | 10 +- .../mobile/mobile-account-settings.tsx | 72 +- .../mobile/mobile-acp-history-sheet.tsx | 15 +- .../mobile/mobile-archive-screen.tsx | 28 +- .../mobile/mobile-chat-landing-screen.tsx | 12 +- .../components/mobile/mobile-chat-list.tsx | 2 +- .../mobile/mobile-create-workspace-sheet.tsx | 4 +- .../mobile/mobile-delete-workspace-sheet.tsx | 15 +- .../mobile/mobile-file-viewer-drawer.tsx | 6 +- .../mobile/mobile-integrations-settings.tsx | 10 +- .../mobile-remove-local-project-sheet.tsx | 4 +- .../components/src/components/not-found.tsx | 6 +- .../onboarding/ceremony/intro-sequence.tsx | 6 +- .../onboarding/onboarding-shell.tsx | 8 +- .../onboarding/screens/first-task-screen.tsx | 9 +- .../onboarding/screens/invite-screen.tsx | 14 +- .../onboarding/screens/login-screen.tsx | 4 +- .../onboarding/screens/projects-screen.tsx | 9 +- .../onboarding/screens/providers-screen.tsx | 37 +- .../onboarding/screens/summary-screen.tsx | 7 +- .../onboarding/screens/workspace-screen.tsx | 14 +- .../src/components/organization-switcher.tsx | 11 +- .../components/page-headers/base-header.tsx | 4 +- .../pages/accept-invitation-page.tsx | 14 +- .../components/pages/complete-email-page.tsx | 4 +- .../pages/create-workspace-page.tsx | 8 +- .../pages/desktop-checkout-return-page.tsx | 11 +- .../pages/desktop-github-install-page.tsx | 8 +- .../src/components/pages/device-auth-page.tsx | 2 +- .../components/pages/email-verified-page.tsx | 2 +- .../components/pages/forgot-password-page.tsx | 2 +- .../components/pages/reset-password-page.tsx | 2 +- .../pages/workspace-join-request-page.tsx | 11 +- .../visual-annotation-draft-composer.tsx | 14 +- .../sessions/ask-user-question-card.tsx | 28 +- .../components/sessions/auto-review-info.tsx | 10 +- .../sessions/auto-review-status.tsx | 27 +- .../sessions/chat-share-image-dialog.tsx | 4 +- .../sessions/components/file-tree-view.tsx | 2 +- .../sessions/floating-permission-request.tsx | 6 +- .../sessions/managed-preview-surface.tsx | 9 +- .../notification-permission-prompt.tsx | 13 +- .../components/sessions/paged-file-viewer.tsx | 8 +- .../components/sessions/pr-merge-button.tsx | 15 +- .../src/components/sessions/pr-tab-view.tsx | 173 ++--- .../sessions/rename-session-dialog.tsx | 6 +- .../sessions/session-browser-panel.tsx | 62 +- .../sessions/session-browser-toolbar.tsx | 6 +- .../sessions/session-chat-input-area.tsx | 27 +- .../sessions/session-chat-interface.tsx | 36 +- .../components/sessions/session-detail.tsx | 31 +- .../sessions/session-file-content-view.tsx | 24 +- .../sessions/session-file-error-state.tsx | 8 +- .../sessions/session-goal-banner.tsx | 17 +- .../sessions/session-info-chips.tsx | 7 +- .../components/sessions/session-not-found.tsx | 4 +- .../src/components/sessions/session-pin.tsx | 9 +- .../sessions/session-usage-popover.tsx | 9 +- .../src/components/settings/about-setting.tsx | 19 +- .../settings/account-machines-overview.tsx | 22 +- .../settings/account-setting-pure.tsx | 56 +- .../settings/acp-authentication-panel.tsx | 24 +- .../settings/agent-config-dialog.tsx | 32 +- .../components/settings/agent-role-form.tsx | 16 +- .../settings/agent-roles-setting.tsx | 20 +- .../settings/billing-setting-pure.tsx | 16 +- .../components/settings/billing-setting.tsx | 3 +- .../settings/change-password-button.tsx | 39 +- .../src/components/settings/clear-cache.tsx | 2 +- .../settings/cli-daemon-setting.tsx | 13 +- .../settings/device-resource-monitor.tsx | 12 +- .../components/settings/general-setting.tsx | 4 +- .../settings/integrations-setting.tsx | 17 +- .../settings/invite-member-dialog.tsx | 10 +- .../settings/join-community-dialog.tsx | 2 +- .../settings/keyboard-shortcuts-setting.tsx | 24 +- .../settings/linked-accounts-list.tsx | 34 +- .../settings/machine-agent-settings.tsx | 9 +- .../settings/machine-detail-pane.tsx | 58 +- .../components/settings/machine-tab-list.tsx | 15 +- .../settings/mcp-connection-form.tsx | 29 +- .../src/components/settings/mcp-setting.tsx | 16 +- .../my-machine-connected-resources.tsx | 4 +- .../open-source-attributions-dialog.tsx | 5 +- .../settings/path-launchers-setting.tsx | 12 +- .../components/settings/project-settings.tsx | 25 +- .../settings/project-skills-tab.tsx | 14 +- .../settings/provider-progress-button.tsx | 11 +- .../src/components/settings/provider-row.tsx | 13 +- .../settings/provider-setup-row.tsx | 14 +- .../settings/review-policy-setting.tsx | 12 +- .../components/settings/settings-header.tsx | 4 +- .../settings/usage-calendar-visualization.tsx | 23 +- .../workspace-join-requests-settings.tsx | 21 +- .../settings/workspace-ownership-transfer.tsx | 8 +- .../components/shared/acp-session-select.tsx | 11 +- .../src/components/shared/option-selector.tsx | 4 +- .../shared/session-relation-card.tsx | 8 +- .../shared/workdir-mode-selector.tsx | 13 +- .../src/components/sidebar-filter-popover.tsx | 7 +- .../src/components/sidebar-update-banner.tsx | 6 +- .../components/stuck-connection-banner.tsx | 13 +- .../tasks/task-attach-session-dialog.tsx | 12 +- .../tasks/task-body-editor-fallback.tsx | 6 +- .../tasks/task-body-editor-surface.tsx | 4 +- .../tasks/task-detail-actions-menu.tsx | 9 +- .../src/components/tasks/task-detail-view.tsx | 6 +- .../components/tasks/task-launch-controls.tsx | 15 +- .../tasks/task-properties-panel.tsx | 37 +- .../components/tasks/task-proposal-notice.tsx | 8 +- .../tasks/task-quick-add-dialog.tsx | 19 +- .../src/components/tasks/task-thread.tsx | 14 +- .../src/components/tasks/tasks-workspace.tsx | 15 +- .../components/update-changelog-dialog.tsx | 4 +- .../stories/AddLocalProjectDialog.stories.tsx | 2 +- .../AssistantTurnAlignment.stories.tsx | 9 - .../src/stories/BaseHeader.stories.tsx | 22 +- .../src/stories/ChatComposer.stories.tsx | 28 +- .../ChatFailedDetailDialog.stories.tsx | 1 - .../ChatLandingAttachments.stories.tsx | 14 +- .../src/stories/ChatLandingView.stories.tsx | 3 - .../stories/ChatMessageSelection.stories.tsx | 8 +- .../CodeCollabMarkdownPreview.stories.tsx | 12 - .../CodeCollabMonacoEditor.stories.tsx | 2 - ...rsationOutlineArrivalIntentLab.stories.tsx | 30 +- .../DesktopSessionDetailLayout.stories.tsx | 6 +- .../stories/ErrorBoundaryFallback.stories.tsx | 1 - .../src/stories/FileTreeStates.stories.tsx | 4 +- .../stories/JoinCommunityDialog.stories.tsx | 4 +- .../stories/LocalProjectRemovalUX.stories.tsx | 8 +- .../src/stories/MarkdownRenderer.stories.tsx | 101 --- .../MobileChatLandingScreen.stories.tsx | 9 +- .../stories/MobileInlinePicker.stories.tsx | 20 +- .../stories/MobileNewChatSheet.stories.tsx | 9 +- .../stories/MobileProjectSkills.stories.tsx | 2 - .../stories/MobileSidebarDrawer.stories.tsx | 2 +- .../stories/MobileWorkspaceLayout.stories.tsx | 10 +- .../MobileWorkspaceSwitcherSheet.stories.tsx | 2 +- .../src/stories/OnboardingShell.stories.tsx | 12 +- .../src/stories/PrTabView.stories.tsx | 5 - .../src/stories/ProjectSkillsTab.stories.tsx | 4 - .../ReviewAgentSetupDialog.stories.tsx | 2 +- .../src/stories/SessionChatSearch.stories.tsx | 1 - .../SessionConversationPage.stories.tsx | 13 - .../SessionForkDestinationPopover.stories.tsx | 10 +- .../SessionSidePanelTabBar.stories.tsx | 6 +- .../src/stories/SettingsHeader.stories.tsx | 6 +- .../stories/SkillMarkdownFallback.stories.tsx | 10 - .../src/stories/TaskTabBar.stories.tsx | 4 +- .../src/stories/TerminalComponent.stories.tsx | 1 - .../src/stories/Toaster.stories.tsx | 22 +- .../stories/UpdateChangelogDialog.stories.tsx | 3 - .../src/stories/VSCodeThemeProbe.stories.tsx | 6 +- ...isualAnnotationCommentsOverlay.stories.tsx | 8 +- .../VisualAnnotationInspector.stories.tsx | 37 +- .../stories/ZoomableImageViewer.stories.tsx | 2 +- packages/components/src/tailwind/index.css | 1 + packages/components/src/theme-provider.tsx | 7 +- packages/components/src/ui/alert-dialog.tsx | 24 +- packages/components/src/ui/button.tsx | 50 -- packages/components/src/ui/calendar.tsx | 14 +- .../components/src/ui/collapsible-card.tsx | 9 +- packages/components/src/ui/copy-button.tsx | 6 +- .../src/ui/diff-viewer/diff-viewer.tsx | 8 +- .../ui/diff-viewer/github-comment-thread.tsx | 11 +- .../ui/diff-viewer/session-comment-draft.tsx | 10 +- packages/components/src/ui/index.ts | 3 +- packages/components/src/ui/pagination.tsx | 46 +- packages/components/src/ui/sidebar.tsx | 9 +- packages/components/src/ui/workspace-list.tsx | 13 +- packages/components/vitest.config.ts | 10 +- packages/ui/AGENTS.md | 28 + packages/ui/CLAUDE.md | 1 + packages/ui/README.md | 25 + packages/ui/package.json | 38 + .../ui/src/button/button.tokens.stylex.ts | 28 + packages/ui/src/button/button.tsx | 178 +++++ packages/ui/src/index.ts | 10 + packages/ui/src/theme/theme.tsx | 33 + packages/ui/src/tokens/RULES.md | 62 ++ packages/ui/src/tokens/colors.stylex.ts | 129 ++++ packages/ui/src/tokens/scales.stylex.ts | 62 ++ packages/ui/stylex-options.ts | 10 + packages/ui/test/button.test.tsx | 38 + packages/ui/test/tokens.test.tsx | 36 + packages/ui/tsconfig.json | 7 + packages/ui/vitest.config.ts | 11 + pnpm-lock.yaml | 655 ++++++++++++------ site-docs/app/global.css | 1 + site-docs/components/landing-app-preview.tsx | 66 +- .../components/landing-mobile-preview.tsx | 275 ++++---- .../components/landing-preview-panel.tsx | 24 +- site-docs/package.json | 2 + site-docs/src/routes/__root.tsx | 1 + site-docs/types/lody-app-components.d.ts | 17 - site-docs/vite.config.ts | 3 + specs/ui-primitives.md | 51 ++ 227 files changed, 2677 insertions(+), 2019 deletions(-) create mode 100644 .agents/notes/implemented/architecture/2026-09-08-ui-button-migration-takeover.md delete mode 100644 packages/components/src/ui/button.tsx create mode 100644 packages/ui/AGENTS.md create mode 120000 packages/ui/CLAUDE.md create mode 100644 packages/ui/README.md create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/button/button.tokens.stylex.ts create mode 100644 packages/ui/src/button/button.tsx create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/src/theme/theme.tsx create mode 100644 packages/ui/src/tokens/RULES.md create mode 100644 packages/ui/src/tokens/colors.stylex.ts create mode 100644 packages/ui/src/tokens/scales.stylex.ts create mode 100644 packages/ui/stylex-options.ts create mode 100644 packages/ui/test/button.test.tsx create mode 100644 packages/ui/test/tokens.test.tsx create mode 100644 packages/ui/tsconfig.json create mode 100644 packages/ui/vitest.config.ts create mode 100644 specs/ui-primitives.md diff --git a/.agents/docs/components-package.md b/.agents/docs/components-package.md index a370ca77c..5abb0ed09 100644 --- a/.agents/docs/components-package.md +++ b/.agents/docs/components-package.md @@ -58,6 +58,12 @@ button for a file the machine will refuse, and the user would lose the edit at s ## Theming and fields +Reusable visual primitives and semantic design tokens are owned by +[`@lody/ui`](../../packages/ui/README.md). `@lody/components` composes those +primitives into product surfaces and may add layout or interaction constraints, +while the primitive's props remain the owner of its visual variant, size, tone, +and shape. + `--input` is the theme's raw `input.background` and doubles as a muted chip/composer slab, so in a light theme it can sit below the page color and read as a disabled field. `--input-field` is derived in `lib/vscode-theme/vscode-theme-css.ts` as the lighter of diff --git a/.agents/notes/implemented/architecture/2026-09-08-ui-button-migration-takeover.md b/.agents/notes/implemented/architecture/2026-09-08-ui-button-migration-takeover.md new file mode 100644 index 000000000..30fc939bd --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-09-08-ui-button-migration-takeover.md @@ -0,0 +1,68 @@ +# UI Button migration takeover + +Status: implemented +Translation: pending +Issue: https://github.com/LodyAI/Lody/issues/304 +Original PR: https://github.com/LodyAI/Lody/pull/305 + +## Abstract + +PR #305 redesigns Lody buttons around `@lody/ui`, Base UI, and StyleX tokens, +but its September 2 branch no longer merged cleanly with current `main`. The +takeover keeps that redesign as the visual authority, preserves business behavior +added on `main`, and migrates newer Button consumers to the author's public API. +It does not provide a compatibility layer for the deleted Button or restore its +appearance through caller classes. Surface-specific accessibility and layout +requirements remain explicit at their owning call sites. + +## Decision + +Update the author's branch by merging current `main` into its existing commit. +Resolve overlapping product files by retaining current navigation, session, +onboarding, machine, and Skills behavior, then express their controls using the +new Button variants, sizes, tones, shapes, and icon flag. + +New Button consumers added after the PR base follow the same API used by the +author's migration. They do not select sizes by matching the removed component's +pixel dimensions. Mermaid viewer controls keep their existing 44 px touch target +because that surface has an independent mobile accessibility requirement; the +new Button still owns their appearance. + +`@lody/ui` owns primitive visuals and semantic tokens. Product packages compose +those primitives and may pass classes for layout or interaction constraints. +Caller classes must not recreate the deleted Button's colors, typography, +shadows, radii, or state styling. + +Composer submit and stop actions use the Button's `primary`, `medium`, `pill`, +and icon choices directly. Their former `ghost` variant plus Tailwind color, +size, radius, shadow, and press-state overrides bypassed the primitive and could +leave the stop glyph with insufficient contrast. Landing, session, mobile-sheet, +and Storybook compositions now select the same token-owned control treatment. + +## Integration evidence + +The original PR is commit `11ef421f86c29fe50773c6c101bf129839368c3c`, +based on `947affd0741e35b3644622c841e8457a26133a95`. Current `main` is merged as +the second parent so the author's commit and authorship remain intact. Conflict +resolution retains the current package dependencies and application handlers, +adds `@lody/ui` where needed, and regenerates the lockfile from the merged +manifests. + +Verification used the repository's supported Node 22 runtime. The complete +`pnpm check` suite passed after disabling commit signing for its synthetic Git +repository, and the focused `@lody/ui` test suite passed all eight tests. The +Electron application, documentation site, and component Storybook production +builds completed with StyleX compiling the package source. A source scan found no +remaining imports of the deleted Button module or uses of its old size and variant +props. + +Interactive browser screenshot comparison was unavailable in the takeover +environment. The production application and Storybook builds provide compiler +and integration coverage, but a maintainer should still inspect the PR preview as +the final visual acceptance step. + +## Limits + +This migration establishes the Button and token foundation described in the +linked draft Spec. Other primitives remain in `@lody/components` until a later +migration gives each one an explicit `@lody/ui` contract. diff --git a/README.md b/README.md index 113350c05..6eaf09bf3 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Lody is still moving toward full local-first support. - `apps/cli` — Connect machines and run coding agents - `apps/electron` — Lody desktop app - `packages/components` — Shared workspace UI +- `packages/ui` — Base UI primitives and StyleX design tokens - `packages/platform` — Platform capabilities and integrations - `packages/shared` — Shared schemas, protocols, and utilities - `packages/cloud-api` — Optional-cloud protocol names and DTOs diff --git a/README.zh-CN.md b/README.zh-CN.md index c492777e9..262ce6988 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -161,6 +161,7 @@ Lody 仍在走向完整的 local-first 支持。 - `apps/cli` — 连接机器并运行 Coding Agents - `apps/electron` — Lody 桌面应用 - `packages/components` — 工作空间共享 UI +- `packages/ui` — Base UI 基础组件与 StyleX 设计令牌 - `packages/platform` — 平台能力与集成 - `packages/shared` — 共享 Schema、协议与工具 - `site-docs` — 官网、文档与博客 diff --git a/apps/electron/electron.vite.config.ts b/apps/electron/electron.vite.config.ts index e5cd6bbe5..295002520 100644 --- a/apps/electron/electron.vite.config.ts +++ b/apps/electron/electron.vite.config.ts @@ -6,6 +6,7 @@ import type { Plugin } from 'vite' import react from '@vitejs/plugin-react' import wasm from 'vite-plugin-wasm' import tailwindcss from '@tailwindcss/vite' +import stylex from '@stylexjs/unplugin' import { loroCrdtBundlerAlias, loroCrdtWasmUrlWorkaround @@ -17,6 +18,7 @@ import { rendererBundleAliasPlugin, rendererBundleAliases } from '../../packages/components/vite-renderer-bundle-aliases' +import { stylexOptions } from '../../packages/ui/stylex-options' import { emojibaseAssetsPlugin } from '../../packages/components/vite-emojibase-assets' function getGitCommitHash(): string { @@ -187,6 +189,7 @@ export default defineConfig(({ mode }) => { plugins: [ previewPublicBaseDomainHtmlPlugin(previewPublicBaseDomain), tailwindcss(), + stylex.vite(stylexOptions), loroCrdtWasmUrlWorkaround(), react(), wasm(), diff --git a/apps/electron/package.json b/apps/electron/package.json index 6ed410786..33fbf4544 100644 --- a/apps/electron/package.json +++ b/apps/electron/package.json @@ -54,10 +54,12 @@ "react-dom": "catalog:" }, "devDependencies": { + "@stylexjs/unplugin": "0.19.0", "@electron-toolkit/eslint-config-prettier": "^3.0.0", "@electron-toolkit/eslint-config-ts": "^3.1.0", "@electron-toolkit/tsconfig": "^2.0.0", "@lody/components": "workspace:*", + "@lody/ui": "workspace:*", "@lody/configs": "workspace:*", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/vite": "^4.3.0", diff --git a/apps/electron/tsconfig.web.json b/apps/electron/tsconfig.web.json index 80f817eb0..75e57ef6e 100644 --- a/apps/electron/tsconfig.web.json +++ b/apps/electron/tsconfig.web.json @@ -19,6 +19,9 @@ "react/jsx-dev-runtime": ["./node_modules/@types/react/jsx-dev-runtime"], "@lody/components": ["../../packages/components/src"], "@lody/components/*": ["../../packages/components/src/*"], + "@lody/ui": ["../../packages/ui/src"], + "@lody/ui/tokens/*": ["../../packages/ui/src/tokens/*"], + "@lody/ui/theme": ["../../packages/ui/src/theme/theme"], "@/ui": ["../../packages/components/src/ui"], "@/ui/*": ["../../packages/components/src/ui/*"], "@/components": ["../../packages/components/src/components"], diff --git a/packages/components/.storybook/main.cjs b/packages/components/.storybook/main.cjs index 251e4bdcf..342284c8b 100644 --- a/packages/components/.storybook/main.cjs +++ b/packages/components/.storybook/main.cjs @@ -1,4 +1,6 @@ const tailwindcss = require('@tailwindcss/vite').default; +const stylex = require('@stylexjs/unplugin').default; +const { stylexOptions } = require('../../ui/stylex-options.ts'); const { loadEnv } = require('vite'); const { resolve } = require('node:path'); const wasm = require('vite-plugin-wasm').default; @@ -33,6 +35,7 @@ const config = { return true; }); viteConfig.plugins.push(tailwindcss()); + viteConfig.plugins.push(stylex.vite(stylexOptions)); viteConfig.worker = { ...(viteConfig.worker ?? {}), diff --git a/packages/components/package.json b/packages/components/package.json index 9023024de..80e9f6af6 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -70,6 +70,7 @@ "build-storybook": "storybook build" }, "dependencies": { + "@lody/ui": "workspace:*", "@zumer/snapdom": "^2.24.15", "@assistant-ui/react": "^0.10.39", "@assistant-ui/react-markdown": "^0.10.8", @@ -196,6 +197,7 @@ "zod": "catalog:" }, "devDependencies": { + "@stylexjs/unplugin": "0.19.0", "@lody/configs": "workspace:*", "@playwright/test": "^1.58.2", "@radix-ui/react-avatar": "^1.1.10", diff --git a/packages/components/src/components/ai-gui/chat-failed-detail-dialog.tsx b/packages/components/src/components/ai-gui/chat-failed-detail-dialog.tsx index fe3ee3a39..0ec23890c 100644 --- a/packages/components/src/components/ai-gui/chat-failed-detail-dialog.tsx +++ b/packages/components/src/components/ai-gui/chat-failed-detail-dialog.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; import { AlertCircle, Check, Copy } from 'lucide-react'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Dialog, DialogClose, @@ -128,11 +128,11 @@ export function ChatFailedDetailDialog({ - - - - diff --git a/packages/components/src/components/ai-gui/session-file-preview-dialog.tsx b/packages/components/src/components/ai-gui/session-file-preview-dialog.tsx index 945649250..bc40d5f66 100644 --- a/packages/components/src/components/ai-gui/session-file-preview-dialog.tsx +++ b/packages/components/src/components/ai-gui/session-file-preview-dialog.tsx @@ -4,7 +4,7 @@ import { toast } from 'sonner'; import { Check, Copy, Download, FileWarning, Loader2, X } from 'lucide-react'; import type { SessionFilePayload } from '@lody/shared'; import { Dialog, DialogClose, DialogContentWithoutClose, DialogTitle } from '@/ui/dialog'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Tabs, TabsList, TabsTrigger } from '@/ui/tabs'; import { formatFileSize } from '@/lib/session-file-presentation'; import { MarkdownRenderer } from './markdown-renderer'; @@ -100,8 +100,8 @@ export function SessionFilePreviewPanel({ @@ -153,8 +153,8 @@ export function SessionFilePreviewPanel({ diff --git a/packages/components/src/components/ai-gui/user-message-editor.tsx b/packages/components/src/components/ai-gui/user-message-editor.tsx index 553d64824..bdc57e6a0 100644 --- a/packages/components/src/components/ai-gui/user-message-editor.tsx +++ b/packages/components/src/components/ai-gui/user-message-editor.tsx @@ -2,7 +2,7 @@ import { useCallback, useLayoutEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { Loader2 } from 'lucide-react'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Textarea } from '@/ui/textarea'; import { cn } from '@/lib/utils'; import type { ConversationFontSize } from '@/atoms/settings'; @@ -101,24 +101,20 @@ export function UserMessageEditor({ @@ -1520,12 +1515,7 @@ export function ArchiveView() {
- ) : null} {isMultiSelectMode ? ( <> - @@ -102,22 +98,20 @@ export function WebArchiveScreen({
- @@ -6118,19 +6119,15 @@ function WorkspaceChatLanding({ primaryAction={ diff --git a/packages/components/src/components/chat/machine-pairing-dialog.tsx b/packages/components/src/components/chat/machine-pairing-dialog.tsx index a07585b36..3cc2b0308 100644 --- a/packages/components/src/components/chat/machine-pairing-dialog.tsx +++ b/packages/components/src/components/chat/machine-pairing-dialog.tsx @@ -15,7 +15,7 @@ import { toast } from 'sonner'; import { useConvexErrorMessage } from '@/hooks/use-convex-error-message'; import { writeTextToClipboard } from '@/lib/clipboard'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Dialog, DialogContent, @@ -164,7 +164,7 @@ export function MachinePairingDialog({

{t('machinePairing.createFailed', 'Could not create a connection request.')}

-
@@ -187,7 +187,7 @@ export function MachinePairingDialog({

- @@ -223,8 +223,8 @@ export function MachinePairingDialog({ diff --git a/packages/components/src/components/codex-reset/codex-reset-forecast-dialog.tsx b/packages/components/src/components/codex-reset/codex-reset-forecast-dialog.tsx index 2bc1b30e5..0ba6bd648 100644 --- a/packages/components/src/components/codex-reset/codex-reset-forecast-dialog.tsx +++ b/packages/components/src/components/codex-reset/codex-reset-forecast-dialog.tsx @@ -5,7 +5,7 @@ import { enUS, zhCN } from 'date-fns/locale'; import { ExternalLink, Loader2, TimerReset } from 'lucide-react'; import { Badge } from '@/ui/badge'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/ui/dialog'; import { openExternalUrl } from '@/lib/native-browser'; import { cn } from '@/lib/utils'; @@ -139,7 +139,7 @@ function RetryButton({ onRetry }: { onRetry: () => void }) { const { t } = useTranslation(); return ( - ); diff --git a/packages/components/src/components/error-boundary-fallback.tsx b/packages/components/src/components/error-boundary-fallback.tsx index 6fa46a989..3cfc02042 100644 --- a/packages/components/src/components/error-boundary-fallback.tsx +++ b/packages/components/src/components/error-boundary-fallback.tsx @@ -10,7 +10,7 @@ import { Trash2, } from 'lucide-react'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { AlertDialog, AlertDialogAction, @@ -207,14 +207,14 @@ export function ErrorBoundaryFallback({ ) : null}
- - @@ -472,8 +467,8 @@ function BrowseStep({
- @@ -386,7 +386,8 @@ function MobileBrowse({ controller: c }: { controller: RemoteDirectoryPickerCont ) : null}
- ) : ( @@ -615,9 +610,10 @@ export function MobileAccountSettings({ {isEditable && ( {!hasGeneratedCliApiKey && ( @@ -61,22 +55,20 @@ export function MobileArchiveScreen({
diff --git a/packages/components/src/components/mobile/mobile-chat-landing-screen.tsx b/packages/components/src/components/mobile/mobile-chat-landing-screen.tsx index eccf8afc4..5140d72d6 100644 --- a/packages/components/src/components/mobile/mobile-chat-landing-screen.tsx +++ b/packages/components/src/components/mobile/mobile-chat-landing-screen.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from 'react'; import { PanelLeft } from 'lucide-react'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { cn } from '@/lib/utils'; export type MobileChatLandingScreenProps = { @@ -31,14 +31,12 @@ export function MobileChatLandingScreen({
{title} diff --git a/packages/components/src/components/mobile/mobile-chat-list.tsx b/packages/components/src/components/mobile/mobile-chat-list.tsx index e78604f37..8f6fdc409 100644 --- a/packages/components/src/components/mobile/mobile-chat-list.tsx +++ b/packages/components/src/components/mobile/mobile-chat-list.tsx @@ -1383,7 +1383,7 @@ export function MobileChatList({ void handleDelete(); }} disabled={isDeleting} - className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + variant="destructive" > {selectionLabels?.confirmDelete ?? '删除'} diff --git a/packages/components/src/components/mobile/mobile-create-workspace-sheet.tsx b/packages/components/src/components/mobile/mobile-create-workspace-sheet.tsx index 2fc411cc4..730d392ce 100644 --- a/packages/components/src/components/mobile/mobile-create-workspace-sheet.tsx +++ b/packages/components/src/components/mobile/mobile-create-workspace-sheet.tsx @@ -5,7 +5,7 @@ import { cloudOperations } from '@/lib/cloud-api-operations'; import { useCloudQuery } from '@lody/platform/react'; import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerTitle } from '@/ui/drawer'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Input } from '@/ui/input'; import { Label } from '@/ui/label'; import { useOrganization } from '../../hooks/useOrganization'; @@ -244,7 +244,7 @@ export function MobileCreateWorkspaceSheet({ > - diff --git a/packages/components/src/components/onboarding/ceremony/intro-sequence.tsx b/packages/components/src/components/onboarding/ceremony/intro-sequence.tsx index 941785ff1..d03fec258 100644 --- a/packages/components/src/components/onboarding/ceremony/intro-sequence.tsx +++ b/packages/components/src/components/onboarding/ceremony/intro-sequence.tsx @@ -5,7 +5,7 @@ import quietWork from '@/assets/onboarding/intro/quiet-work.png'; import continuousScroll from '@/assets/onboarding/intro/continuous-scroll.png'; import readyToBegin from '@/assets/onboarding/intro/ready-to-begin.png'; import { cn } from '@/lib/utils'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { WINDOW_DRAG_EXEMPT_CLASS } from '@/ui/window-drag-region'; import type { AudioLayers } from './use-onboarding-audio'; import { playClick, playCut, playReveal, playSelect } from './ui-sounds'; @@ -395,10 +395,10 @@ export function IntroSequence({
{beat.final ? ( } primaryAction={
-
- @@ -132,9 +131,10 @@ export function InviteScreenView({ ) : ( } primaryAction={
-
@@ -142,7 +142,7 @@ export function AcceptInvitationPage({ />

) : null} - @@ -168,10 +168,10 @@ export function AcceptInvitationPage({ /> {roleLabel ? : null} - - @@ -186,7 +186,7 @@ export function AcceptInvitationPage({ 'For security, verify the email address named by this invitation before accepting it.' )} - @@ -212,7 +212,7 @@ export function AcceptInvitationPage({ {errorMessage || t('invite.error.notFound', 'Invitation not found or expired.')} - diff --git a/packages/components/src/components/pages/complete-email-page.tsx b/packages/components/src/components/pages/complete-email-page.tsx index d6df6cca1..7557df940 100644 --- a/packages/components/src/components/pages/complete-email-page.tsx +++ b/packages/components/src/components/pages/complete-email-page.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { Loader2, Mail } from 'lucide-react'; import { Alert, AlertDescription } from '@/ui/alert'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/ui/card'; import { Input } from '@/ui/input'; import { Label } from '@/ui/label'; @@ -42,7 +42,7 @@ export function CompleteEmailPage({
- diff --git a/packages/components/src/components/pages/desktop-github-install-page.tsx b/packages/components/src/components/pages/desktop-github-install-page.tsx index 922641e42..5d9303411 100644 --- a/packages/components/src/components/pages/desktop-github-install-page.tsx +++ b/packages/components/src/components/pages/desktop-github-install-page.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'; import { motion } from 'framer-motion'; import { Github, Loader2 } from 'lucide-react'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/ui/card'; import lodyLogo from '@/assets/lody-icon.png'; @@ -41,11 +41,11 @@ export function DesktopGithubInstallPage({ deepLink }: DesktopGithubInstallPageP {deepLink ? ( - ) : ( - )} diff --git a/packages/components/src/components/pages/device-auth-page.tsx b/packages/components/src/components/pages/device-auth-page.tsx index e696ca3d0..7d2330180 100644 --- a/packages/components/src/components/pages/device-auth-page.tsx +++ b/packages/components/src/components/pages/device-auth-page.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { AlertCircle, CheckCircle2, Loader2 } from 'lucide-react'; import { Alert, AlertDescription } from '@/ui/alert'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/ui/card'; import { Input } from '@/ui/input'; diff --git a/packages/components/src/components/pages/email-verified-page.tsx b/packages/components/src/components/pages/email-verified-page.tsx index 142a0311d..d5101faf9 100644 --- a/packages/components/src/components/pages/email-verified-page.tsx +++ b/packages/components/src/components/pages/email-verified-page.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/ui/card'; import lodyLogo from '@/assets/lody-icon.png'; diff --git a/packages/components/src/components/pages/forgot-password-page.tsx b/packages/components/src/components/pages/forgot-password-page.tsx index 2c4095ba5..36dbe772d 100644 --- a/packages/components/src/components/pages/forgot-password-page.tsx +++ b/packages/components/src/components/pages/forgot-password-page.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { CheckCircle2, Loader2, Mail } from 'lucide-react'; import { Alert, AlertDescription } from '@/ui/alert'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/ui/card'; import { Input } from '@/ui/input'; import { Label } from '@/ui/label'; diff --git a/packages/components/src/components/pages/reset-password-page.tsx b/packages/components/src/components/pages/reset-password-page.tsx index 4281f83fa..f05603776 100644 --- a/packages/components/src/components/pages/reset-password-page.tsx +++ b/packages/components/src/components/pages/reset-password-page.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { CheckCircle2, KeyRound, Loader2 } from 'lucide-react'; import { Alert, AlertDescription } from '@/ui/alert'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/ui/card'; import { Label } from '@/ui/label'; import { PasswordInput } from '@/ui/password-input'; diff --git a/packages/components/src/components/pages/workspace-join-request-page.tsx b/packages/components/src/components/pages/workspace-join-request-page.tsx index a9eb0b38c..a2b4b0a4c 100644 --- a/packages/components/src/components/pages/workspace-join-request-page.tsx +++ b/packages/components/src/components/pages/workspace-join-request-page.tsx @@ -1,6 +1,6 @@ import { Loader2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Textarea } from '@/ui/textarea'; import workspaceAvatarPlaceholder from '@/assets/icon-transparent.png'; @@ -86,7 +86,7 @@ export function WorkspaceJoinRequestPage({ 'Sign in or create an account to request access. You can use any verified email.' )} - @@ -98,7 +98,7 @@ export function WorkspaceJoinRequestPage({ email: currentEmail || '', })} - @@ -134,7 +134,8 @@ export function WorkspaceJoinRequestPage({ })}

diff --git a/packages/components/src/components/preview/visual-annotation-draft-composer.tsx b/packages/components/src/components/preview/visual-annotation-draft-composer.tsx index b9cc30f49..eebd54fca 100644 --- a/packages/components/src/components/preview/visual-annotation-draft-composer.tsx +++ b/packages/components/src/components/preview/visual-annotation-draft-composer.tsx @@ -3,7 +3,7 @@ import { Loader2, Send, X } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { cn } from '@/lib/utils'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Textarea } from '@/ui/textarea'; export type VisualAnnotationDraftComposerProps = { @@ -50,8 +50,9 @@ export function VisualAnnotationDraftComposer({ @@ -141,12 +139,7 @@ export function AutoReviewStatus({ {run.state === 'paused' && onResume ? (
- @@ -170,8 +163,8 @@ export function AutoReviewStatus({ {onFixFinding && canFixManually ? ( diff --git a/packages/components/src/components/sessions/floating-permission-request.tsx b/packages/components/src/components/sessions/floating-permission-request.tsx index 6b6b34634..1657993d6 100644 --- a/packages/components/src/components/sessions/floating-permission-request.tsx +++ b/packages/components/src/components/sessions/floating-permission-request.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { ChevronDown, ChevronRight, Loader2 } from 'lucide-react'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/ui/card'; import { ScrollArea } from '@/ui/scroll-area'; import { cn } from '@/lib/utils'; @@ -275,12 +275,12 @@ export function PermissionRequestCard({ return ( @@ -148,9 +148,10 @@ export function NotificationPermissionPrompt({
{onOpenExternal ? ( - ) : null} diff --git a/packages/components/src/components/sessions/pr-merge-button.tsx b/packages/components/src/components/sessions/pr-merge-button.tsx index 8de173de4..e07e22a43 100644 --- a/packages/components/src/components/sessions/pr-merge-button.tsx +++ b/packages/components/src/components/sessions/pr-merge-button.tsx @@ -2,7 +2,7 @@ import { Check, ChevronDown, GitMerge, Loader2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import type { GitHubMergeMethod } from '@lody/shared'; import { cn } from '@/lib/utils'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { DropdownMenu, DropdownMenuContent, @@ -71,7 +71,7 @@ export function PrMergeButton({ const { t } = useTranslation(); const isDisabled = disabled || isMerging || !onMerge; const buttonVariant = - tone === 'ready' ? 'default' : tone === 'conflict' ? 'destructive' : 'outline'; + tone === 'ready' ? 'primary' : tone === 'conflict' ? 'destructive' : 'secondary'; // The full (non-compact) ready button uses GitHub's green so "merge" reads as // the positive terminal action, matching the compact info-bar merge control. const readyGreen = tone === 'ready' && !compact; @@ -108,11 +108,11 @@ export function PrMergeButton({ ) : ( @@ -131,14 +131,11 @@ export function PrMergeButton({ ) : ( diff --git a/packages/components/src/components/sessions/pr-tab-view.tsx b/packages/components/src/components/sessions/pr-tab-view.tsx index dd1efa071..26100c5eb 100644 --- a/packages/components/src/components/sessions/pr-tab-view.tsx +++ b/packages/components/src/components/sessions/pr-tab-view.tsx @@ -40,7 +40,7 @@ import { isPullRequestMergeabilityPending, } from '@/lib/github-pr-details-state'; import { Avatar, AvatarFallback, AvatarImage } from '@/ui/avatar'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { ScrollArea } from '@/ui/scroll-area'; import { Skeleton } from '@/ui/skeleton'; import { Textarea } from '@/ui/textarea'; @@ -314,13 +314,7 @@ function ChecksPermissionNotice({

{onGrantChecksPermission && ( - @@ -342,7 +336,7 @@ function MergeStatusNotice({ kind }: { kind: 'conflict' | 'blocked' | 'checking'

{t( 'sessions.prTab.mergeConflictNotice', - "This branch has conflicts with the base branch — resolve them before it can be merged." + 'This branch has conflicts with the base branch — resolve them before it can be merged.' )}

@@ -700,10 +694,10 @@ function PrHeaderActionButton({
@@ -733,7 +727,11 @@ function PrHeaderActionButton({ onValueChange={(value) => onSelectMergeMethod?.(value as GitHubMergeMethod)} > {HEADER_MERGE_METHODS.map((method) => ( - +
{t(method.labelKey, method.labelFallback)} @@ -771,12 +769,12 @@ function PrHeaderActionButton({
@@ -821,11 +818,11 @@ function PrHeaderActionButton({
@@ -863,10 +859,10 @@ function PrHeaderActionButton({
@@ -902,8 +898,8 @@ function PrHeaderActionButton({ return ( @@ -1081,31 +1071,31 @@ function BranchRow({ pr }: { pr: GitHubPullRequestDetails }) {
- - {t('sessions.prTab.base', 'base')} + + {t('sessions.prTab.base', 'base')} + + + {pr.baseRef} + + - - {pr.baseRef} - - - - - ← - - - - {t('sessions.prTab.head', 'head')} + + ← - - {pr.headRef} - - + + + {t('sessions.prTab.head', 'head')} + + + {pr.headRef} + +
@@ -1176,13 +1166,7 @@ export const PrTabView = memo(function PrTabView({
{onRefresh && ( - )} @@ -1267,9 +1251,9 @@ export const PrTabView = memo(function PrTabView({ data && )} - {(mergeKind === 'conflict' || - mergeKind === 'blocked' || - mergeKind === 'checking') && } + {(mergeKind === 'conflict' || mergeKind === 'blocked' || mergeKind === 'checking') && ( + + )}
{conversation.length > 0 && ( @@ -1326,19 +1310,12 @@ export const PrTabView = memo(function PrTabView({ onDeleteBranch={onDeleteBranch} onResolveConflicts={onResolveConflicts} isResolvingConflicts={isResolvingConflicts} - menuContentClassName={ - embedded ? 'lody-app-preview-portal-dark' : undefined - } + menuContentClassName={embedded ? 'lody-app-preview-portal-dark' : undefined} /> ) : null; return ( -
+
{embedded ? ( /* Landing: slim bar — badge + merge only (no branch row / github chrome). */
@@ -1363,8 +1340,8 @@ export const PrTabView = memo(function PrTabView({ {mergeAction}
diff --git a/packages/components/src/components/sessions/rename-session-dialog.tsx b/packages/components/src/components/sessions/rename-session-dialog.tsx index 7c39385ed..d57ee1358 100644 --- a/packages/components/src/components/sessions/rename-session-dialog.tsx +++ b/packages/components/src/components/sessions/rename-session-dialog.tsx @@ -10,7 +10,7 @@ import { DialogHeader, DialogTitle, } from '@/ui/dialog'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Textarea } from '@/ui/textarea'; import { useSessionActions } from '@/hooks/use-session-actions'; import { isImeComposingKeyboardEvent } from '@/lib/ime'; @@ -159,11 +159,11 @@ export function RenameSessionDialogView({
-
) : null; - /* Keep desktop actions compact while preserving the mobile touch target. */ - const primaryActionSizeClassName = isMobile ? 'h-8 w-8' : 'h-7 w-7'; const primaryActionNode = showStopButton ? ( diff --git a/packages/components/src/components/sessions/session-detail.tsx b/packages/components/src/components/sessions/session-detail.tsx index 13639ab0b..8832a38cc 100644 --- a/packages/components/src/components/sessions/session-detail.tsx +++ b/packages/components/src/components/sessions/session-detail.tsx @@ -23,7 +23,7 @@ import { Users, } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { useRouter } from '@tanstack/react-router'; import { useComposerNavigationFocus } from '../chat/submission/use-composer-navigation-focus'; import { usePostHog } from '@posthog/react'; @@ -673,12 +673,13 @@ const TerminalDockToggleButton = memo(function TerminalDockToggleButton() { @@ -4572,7 +4573,7 @@ const SessionDetail = ({

{t('sessions.tabWaitingForSync', 'Waiting for this conversation to sync…')}

- @@ -4598,7 +4599,7 @@ const SessionDetail = ({ - @@ -5660,10 +5662,11 @@ const SessionDetail = ({ diff --git a/packages/components/src/components/sessions/session-file-content-view.tsx b/packages/components/src/components/sessions/session-file-content-view.tsx index 9fcc7d9a1..7856c3e77 100644 --- a/packages/components/src/components/sessions/session-file-content-view.tsx +++ b/packages/components/src/components/sessions/session-file-content-view.tsx @@ -81,7 +81,7 @@ import { type SessionFileLiveSyncStatus, type SessionFileSaveStatus, } from '@/hooks/use-code-collab-save-text'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/ui/tooltip'; import { useCodeCollabLsp, type CodeCollabLspState } from '@/hooks/use-code-collab-lsp'; import { useLatestRef } from '@/hooks/use-latest-ref'; @@ -1983,18 +1983,12 @@ export function SessionFileConflictActionRow({ {pendingOverride ? ( <> -
diff --git a/packages/components/src/components/sessions/session-file-error-state.tsx b/packages/components/src/components/sessions/session-file-error-state.tsx index 7b69bc8f6..bf284f1ee 100644 --- a/packages/components/src/components/sessions/session-file-error-state.tsx +++ b/packages/components/src/components/sessions/session-file-error-state.tsx @@ -5,7 +5,7 @@ import { cn } from '@/lib/utils'; // The action model is shared with the file tree context menu and the side // panel ⋯ menu; the card is one consumer of it, not its owner. import type { SessionFileErrorActions } from '@/lib/session-file-actions'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; type Translation = (key: string, defaultValue: string, options?: Record) => string; @@ -304,7 +304,7 @@ export function SessionFileErrorState({ {localHost ? ( <> diff --git a/packages/components/src/components/sessions/session-info-chips.tsx b/packages/components/src/components/sessions/session-info-chips.tsx index 8b63ac331..dc6f1bdc1 100644 --- a/packages/components/src/components/sessions/session-info-chips.tsx +++ b/packages/components/src/components/sessions/session-info-chips.tsx @@ -32,7 +32,7 @@ import { type SessionPullRequestMeta, } from '@lody/shared'; import { cn } from '@/lib/utils'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { writeTextToClipboard } from '@/lib/clipboard'; import { getGoalStatusPresentation } from '@/lib/session-goal-status'; import { formatDurationCompact, type DurationUnitLabels } from '@/lib/format-duration'; @@ -273,11 +273,12 @@ export function GoalChip({ diff --git a/packages/components/src/components/sessions/session-not-found.tsx b/packages/components/src/components/sessions/session-not-found.tsx index 66139c885..6e532d19f 100644 --- a/packages/components/src/components/sessions/session-not-found.tsx +++ b/packages/components/src/components/sessions/session-not-found.tsx @@ -1,5 +1,5 @@ import { useRouter } from '@tanstack/react-router'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { ArrowLeft, MessageSquareOff } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useAtomValue } from 'jotai'; @@ -54,7 +54,7 @@ export function SessionNotFound({ onBack }: SessionNotFoundProps) { )}

- diff --git a/packages/components/src/components/sessions/session-pin.tsx b/packages/components/src/components/sessions/session-pin.tsx index 33d054a7b..59544dce3 100644 --- a/packages/components/src/components/sessions/session-pin.tsx +++ b/packages/components/src/components/sessions/session-pin.tsx @@ -1,7 +1,7 @@ import { memo, useCallback, useMemo } from 'react'; import { Pin, X } from 'lucide-react'; import { cn } from '@/lib/utils'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import type { SessionHistoryParsed } from '@lody/shared'; import { useTranslation } from 'react-i18next'; import { ConversationColumn } from '@/components/shared/conversation-column'; @@ -61,7 +61,7 @@ export const SessionPin = memo(function SessionPin({ - @@ -202,8 +197,7 @@ export function AboutSettingsComponent() { )} {isDownloaded ? ( ) : ( {!hasGeneratedCliApiKey && (
- @@ -588,8 +588,8 @@ export function AcpAuthenticationPanel({ ) : (
@@ -2452,11 +2452,11 @@ export function AgentConfigDialog(props: AgentConfigDialogProps) { - @@ -390,8 +396,8 @@ function AgentRoleEmojiField({ @@ -144,7 +138,7 @@ export function AgentRolesSetting() {
{onCancelExternalCheckout ? ( - ) : null} @@ -463,10 +463,10 @@ export function BillingSettingsView({
@@ -792,8 +792,8 @@ export function BillingSettingsView({

) : ( <> - @@ -316,15 +315,15 @@ export function ChangePasswordButton({ diff --git a/packages/components/src/components/settings/integrations-setting.tsx b/packages/components/src/components/settings/integrations-setting.tsx index 3cbc197e1..a48fa06fc 100644 --- a/packages/components/src/components/settings/integrations-setting.tsx +++ b/packages/components/src/components/settings/integrations-setting.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { AlertCircle, Book, @@ -144,9 +144,9 @@ export function GitHubPersonalIdentitySettingsCard({ {!authorizationReady && canAuthorize && ( ) ) : ( - diff --git a/packages/components/src/components/settings/join-community-dialog.tsx b/packages/components/src/components/settings/join-community-dialog.tsx index 41efa3bcf..5f16ae101 100644 --- a/packages/components/src/components/settings/join-community-dialog.tsx +++ b/packages/components/src/components/settings/join-community-dialog.tsx @@ -100,7 +100,7 @@ export function JoinCommunityButton() { return ( <> - diff --git a/packages/components/src/components/settings/keyboard-shortcuts-setting.tsx b/packages/components/src/components/settings/keyboard-shortcuts-setting.tsx index 09d178a9a..a1e7e8eac 100644 --- a/packages/components/src/components/settings/keyboard-shortcuts-setting.tsx +++ b/packages/components/src/components/settings/keyboard-shortcuts-setting.tsx @@ -6,7 +6,7 @@ import { type GlobalShortcutId, type GlobalShortcutSetError, } from '@lody/shared'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { cn } from '@/lib/utils'; import { canonicalizeBinding, @@ -93,13 +93,7 @@ export function KeyboardShortcutsSetting() {

{t('settings.keyboardShortcuts.description')}

- @@ -227,15 +221,16 @@ function GlobalShortcutRow({ {!recording && binding && ( )} @@ -355,12 +350,13 @@ function ShortcutRow({ {!recording && primary && ( )} diff --git a/packages/components/src/components/settings/linked-accounts-list.tsx b/packages/components/src/components/settings/linked-accounts-list.tsx index c90041d87..d8366fd7f 100644 --- a/packages/components/src/components/settings/linked-accounts-list.tsx +++ b/packages/components/src/components/settings/linked-accounts-list.tsx @@ -6,7 +6,7 @@ import type { IconType } from 'react-icons'; import { SiApple, SiDiscord, SiGithub } from 'react-icons/si'; import { FcGoogle } from 'react-icons/fc'; import { cn } from '@/lib/utils'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { Dialog, DialogContent, @@ -49,10 +49,25 @@ const PROVIDERS: { * Kept as literal strings so Tailwind's JIT emits them. */ hoverClassName?: string; }[] = [ - { id: 'github', Icon: SiGithub, boundClassName: 'text-foreground', hoverClassName: 'group-hover:text-foreground' }, + { + id: 'github', + Icon: SiGithub, + boundClassName: 'text-foreground', + hoverClassName: 'group-hover:text-foreground', + }, { id: 'google', Icon: FcGoogle, flat: true }, - { id: 'apple', Icon: SiApple, boundClassName: 'text-foreground', hoverClassName: 'group-hover:text-foreground' }, - { id: 'discord', Icon: SiDiscord, boundClassName: 'text-[#5865F2]', hoverClassName: 'group-hover:text-[#5865F2]' }, + { + id: 'apple', + Icon: SiApple, + boundClassName: 'text-foreground', + hoverClassName: 'group-hover:text-foreground', + }, + { + id: 'discord', + Icon: SiDiscord, + boundClassName: 'text-[#5865F2]', + hoverClassName: 'group-hover:text-[#5865F2]', + }, ]; export function LinkedAccountsList({ @@ -67,7 +82,10 @@ export function LinkedAccountsList({ const boundProviders = new Set(accounts.map((account) => account.providerId)); const providerLabel = (providerId: string): string => - t(`settings.profile.providers.${providerId}`, providerId.charAt(0).toUpperCase() + providerId.slice(1)); + t( + `settings.profile.providers.${providerId}`, + providerId.charAt(0).toUpperCase() + providerId.slice(1) + ); const iconClassName = ( bound: boolean, @@ -185,15 +203,15 @@ export function LinkedAccountsList({ @@ -447,12 +447,7 @@ export function MachineDetailPane(props: MachineDetailPaneProps) { /> ) : externalAccordionHeader ? ( manageableOwnMachine ? ( - @@ -471,8 +466,9 @@ export function MachineDetailPane(props: MachineDetailPaneProps) { {!isMobile && manageableOwnMachine && ( diff --git a/packages/components/src/components/settings/machine-tab-list.tsx b/packages/components/src/components/settings/machine-tab-list.tsx index b5d4041d8..380cf7d06 100644 --- a/packages/components/src/components/settings/machine-tab-list.tsx +++ b/packages/components/src/components/settings/machine-tab-list.tsx @@ -4,7 +4,7 @@ import { ChevronRight, ListFilter, LockKeyhole, Users } from 'lucide-react'; import { type MachineId, type MachineViewMeta } from '@lody/shared'; import type { MachineSettingsFilter } from '@/atoms/settings-machine-tab'; import type { MachineVisibilityAccess } from '@/hooks/use-visible-machine-metas'; -import { Button } from '@/ui/button'; +import { Button } from '@lody/ui/button'; import { DropdownMenu, DropdownMenuCheckboxItem, @@ -120,8 +120,7 @@ export function MachineTabList({