Skip to content

feat(web): add v2 interface built on shadcn/ui as an opt-in preference - #401

Open
YSamed wants to merge 24 commits into
Devlaner:mainfrom
YSamed:feat/shadcn-design-system
Open

feat(web): add v2 interface built on shadcn/ui as an opt-in preference#401
YSamed wants to merge 24 commits into
Devlaner:mainfrom
YSamed:feat/shadcn-design-system

Conversation

@YSamed

@YSamed YSamed commented Aug 13, 2026

Copy link
Copy Markdown

Feature summary

Adds a second Devlane web interface ("v2") built on shadcn/ui, which a user opts into from Settings. Both interfaces answer the same URLs, so a link shared between users opens in whichever interface each of them prefers.

Linked issues / discussion

Design discussion: #400

User-facing behavior

Settings gains an interface switch. Flipping it to v2 stores devlane-interface-version in localStorage and re-renders the app with the shadcn-based shell, navigation, and pages — same routes, same data, same permissions. Flipping it back restores v1 exactly. Nothing about v2 is visible to a user who hasn't opted in.

The v2 surface covers workspace home, projects, work items (list, detail, creation), epics, cycles, modules, views, pages, drafts, archives, intake, analytics, notifications, settings, and the full auth flow (login, sign-up, invite accept, forgot/reset/set password). Turkish is available alongside English.

What changed

API (apps/api/)

  • internal/handler/user.goGetActivity now also returns verb, field, old_value, and new_value for activity rows that have no free-text comment, so the client can compose the sentence in the user's own language instead of rendering a pre-built English description. description is still sent and unchanged; the added fields are additive and existing consumers are unaffected.
  • No new endpoints, env vars, or instance settings.

UI (apps/web/)

  • src/v2/** — the entire v2 interface (148 of the 174 changed files): ~40 shadcn/ui primitives under src/v2/components/ui, plus contexts, hooks, layout shell, domain components, and ~31 pages. src/v2/ mirrors src/, so a v2 page carries the same filename and export name as the v1 page it replaces.
  • src/routes/index.tsx — each path is still declared once; the element is chosen by <Variant v1={…} v2={…} /> (src/routes/InterfaceVariant.tsx), which reads the preference from src/v2/contexts/InterfaceContext. Setup and instance-admin stay v1-only.
  • src/routes/InterfaceSwitch.tsx — the Settings toggle. Its single call site in src/pages/SettingsPage.tsx is the only v2-aware line in any v1 file.
  • eslint.config.js — forbids importing from src/v2 outside src/v2/ and src/routes/, so the isolation is enforced by the build rather than by convention.
  • i18n: i18next-parser.config.cjs plus English and Turkish resources.
  • components.json (new-york, slate, lucide, @/v2/components/ui), tsconfig path aliases, and the @ alias in vite.config.ts.
  • AGENTS.md documents the v2 design direction and its reference sources; CLAUDE.md gains a section describing the isolation rules above.

Database

No schema changes.

Why this design

Refactoring the existing UI in place would mean touching every page of a UI that people already use, with regressions landing directly on them and no way back. Shipping v2 as a parallel, opt-in surface means v1 is bit-for-bit what it would be without this PR, the two can be compared side by side by the same user on the same URL, and the work can land incrementally instead of as one flag day.

Making it a preference rather than a /v2/ route prefix was the other significant choice: a route prefix forks every URL in the product, breaks links pasted between users on different interfaces, and would have required v2 copies of the route tree. Keying off a stored preference keeps one route table and one set of URLs.

The ESLint boundary matters more than it looks: without it, a v1 file importing one v2 component would quietly make v2's CSS and dependencies part of the v1 bundle, and the isolation claim above would stop being true within a release or two.

Test plan

  • npm run validate — web typecheck, eslint --max-warnings=0, and prettier --check all pass; go vet ./... passes. go test ./... was not run locally (the suite needs Docker for testcontainers-postgres, which isn't available on this machine); CI covers it, and this PR changes one Go file.
  • Manual end-to-end walkthrough:
    1. Toggle to v2 in Settings, reload, confirm the shell, sidebar, and navigation render.
    2. Open work items list, work item detail, cycles, and settings from v1 URLs.
    3. Toggle back to v1 and confirm the original interface is unchanged.
  • Tested with both light and dark theme (1440×900)
  • Tested at narrow viewport (390×844): the sidebar collapses to a toggle and the toolbar and table scroll inside their own containers — the page body itself never scrolls horizontally. Usable, but the small-screen layout isn't polished; see follow-ups.
  • Migration on a fresh DB — not applicable, no migration

Screenshots / recording

Before (v1) After (v2)

Out of scope (follow-ups)

  • v1-only surfaces: instance setup and the instance-admin tree still render v1 regardless of preference.
  • The preference is per-browser (localStorage), not stored on the user record — it doesn't follow a user across devices.
  • Turkish covers the v2 surface; v1 strings are untouched.
  • No automated tests for the v2 components yet.
  • Small-screen polish: list toolbars and the work-item table rely on horizontal scrolling below ~640px rather than reflowing into a layout designed for that width.

Rollout notes

Opt-in and off by default — no flag day, and no action needed at deploy time. The API and UI can deploy in either order: the added activity fields are additive, and the v2 client falls back to description when they're absent.

AI assistance

  • AI tools were used — tool(s): Claude Code — and AI-assisted commits include a Co-Authored-By: trailer

Checklist

  • PR title follows Conventional Commits and is ≤ 100 chars
  • Trailing slashes on new routes match neighboring routes
  • New env vars documented in internal/config/config.go — none added
  • New instance settings reachable from the admin UI — none added
  • No --no-verify bypass
  • Acceptance criteria from the linked issue are all met — no linked issue; discussion above sets the scope

YSamed and others added 18 commits August 14, 2026 00:22
Introduce a full shadcn-based preview surface in the web app: new login/signup v2 pages, an AppShell v2 with sidebar/navigation, and a projects v2 page with toolbar filters and create-project dialog wired to existing services. This also adds vendored shadcn primitives, theme bridge/reference/v4 styles, new routes, shared project-list filtering logic, and alias/lint config updates needed to support the new component structure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds a full AppShell v2 surface across workspace, project, analytics, and detail pages, including new v2 routes, header context wiring, and sidebar/navigation updates. Introduces reusable shadcn-based toolbars, dialogs, and UI primitives (charts, tables, tabs, toggles, popovers, progress) to support filtering, view management, and work-item creation/edit flows. Also updates supporting shared helpers and bumps web charting deps to enable the new analytics/chart components.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reworks the v2 sidebar to better match the new app layout: navigation is split into primary and workspace sections, and a translated Favorites section now renders the workspace favorites tree in the sidebar. It also updates `NavMain` and `NavProjects` to use cleaner collapsible triggers with inline chevrons, and removes extra project-menu complexity (hover actions, dropdown, and "more" truncation) so all projects and their subpages are directly accessible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reworks the v2 Projects and Notifications pages into fully responsive, shadcn-based experiences with richer controls: body-level projects toolbar (search/filter chips/view toggle/scope segments), grid+table project views, better loading/error/empty states, and a master-detail inbox with unread tab, search, mobile sheet detail, and inline action handling.

Adds a new shadcn NotificationSnoozeMenu, introduces a shared project refresh event to keep sidebar/project lists in sync after mutations, passes workspace members into project creation/toolbar to avoid duplicate fetches, and fixes project access filtering to use the project network value. Also expands EN/AZ i18n strings for the new UI and makes V2 home stickies follow theme changes in real time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add repo guidance for the v2 web surface in `CLAUDE.md` and `apps/web/README.md`, pointing contributors to the shadcn/ui docs, source repo, and AdminCN reference before changing v2 components.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Introduces shared `useProjectIssuesController` and `useProjectCyclesController` hooks, then rewires both legacy and v2 pages to use the same data/filter/grouping logic so behavior stays aligned across designs. Adds a full v2 work-items experience (filters/display menus, bulk actions, row/context actions, inline editing, board/calendar/gantt/spreadsheet layouts) plus expanded v2 cycles and views toolbars.

Also adds new shadcn primitives (alert dialog, calendar, checkbox, command, context menu, scroll area, sonner, etc.), wires v2 toast support, pre-bundles lazy-only deps in Vite to avoid runtime dynamic-import failures, and fixes project list view defaults to table-first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaced v2 usage of the legacy create modal with the new shadcn work-item dialog, adding richer fields (including parent selection), inline label creation, improved responsive layout, and safer submit/close behavior so failed saves keep the composer open with errors visible. Added a shared helper to attach cycle/module relations after creation using partial-success handling, with toast warnings when relation links fail. Updated workspace views and toolbar to support in-page work item creation, improved list/table accessibility and responsiveness, localized static view/display labels, and refined default v2 display state and column ordering (including state).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Introduces shared v2 primitives (`PageHeading`, `ListPageSkeleton`, `DetailPageSkeleton`, `ProjectListToolbar`) and migrates pages to use them, moving list controls out of the shell header and into consistent in-page toolbars. Updates archives, drafts, analytics, profile, issue detail, and project list pages with richer loading/error/empty states, improved accessibility labels, and responsive table layouts; also replaces `project-search-toolbar`, adds a shadcn-based work-item subscribe button, updates nav-user actions/sign-out flow, and expands EN/AZ translations to cover the new UI copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Builds a complete v2 settings surface across account, workspace, and project scopes, including new reusable settings shell/panel primitives and dedicated sections for profile, preferences, security, notifications, members, tokens, exports, automations, labels, and states.

Adds new `/app-v2/settings` routes (including account and per-project paths), wires project-level settings entry points in navigation, and keeps settings navigation inside the v2 shell.

Also standardizes several v2 page section/scope controls by replacing Tabs usage with ToggleGroup-based segmented controls for consistent behavior and styling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Introduces Turkish (`tr`) as a supported UI language end-to-end: parser config, i18n bootstrap, docs, dynamic key notes, and a full Turkish translation catalog, alongside many new/normalized English keys. The v2 sidebar navigation now uses translated labels via `t()`.

For the v2 shell preview, switches from the `shadcn-v4` class to a new scoped `shadcn-app` class so shadcn border defaults apply without forcing the stock v4 palette. This keeps Devlane theme tokens (including pink), aligns portalled dropdown borders, and updates related style/docs comments to clarify intended usage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Introduces a shared `AuthPageShellV2` and new v2 auth/onboarding flows: forgot/reset password, set password, invite accept/sign-up, and create workspace. Adds reusable password-field primitives (strength, match, show/hide) and refactors signup/login to reuse them and remove duplicated layout logic.

Routes are wired for all new `*-v2` pages, including protected v2 routes with a configurable `signInPath` so expired sessions redirect to `/login-v2` instead of v1 pages. Also updates related links and adds shared auth hero localization keys in English and Turkish.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Introduces a global InterfaceContext (persisted in localStorage) and an InterfaceGate that automatically redirects v1 routes to v2 when users opt into the new interface. Adds bidirectional path mappers for static and workspace routes, preserving query strings and navigation state. Exposes the interface toggle in both settings UIs (legacy and shadcn v2 account preferences) and adds matching EN/TR translations.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Switches the v2 AppShell wrapper from `shadcn-app` to `shadcn-v4` on both `document.body` and `SidebarProvider`. This makes the preview use the stock upstream shadcn new-york-v4 palette consistently, and updates the inline docs to clarify that this intentionally bypasses Devlane’s token bridge/theme picker (including pink) for pixel-faithful comparison.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nder src/v2

v2 used to be a second route tree under /:workspaceSlug/app-v2, reached by
bouncing v1 URLs through a 350-line path mapper. Both interfaces now answer to
the same URLs: routes/index.tsx declares each path once and picks the element
with <Variant v1={...} v2={...} />, which reads the stored interface preference.
Switching no longer navigates — the page re-renders in place.
Routing:
- Drop lib/interfaceRedirect.ts, components/InterfaceGate.tsx and every *-v2
  path (login-v2, invite-v2, the whole app-v2 subtree).
- v2 links now use the shipped URL shapes; a project's work items live at
  /projects/:id/issues, and v2 redirects /board to issues?layout=board.
- Both shells mount on the :workspaceSlug route and render an <Outlet />, so
  child routes are shared.
Isolation:
- Move the entire v2 interface under src/v2/, mirroring src/: a v2 page carries
  the same filename and export name as the v1 page it replaces
  (v2/pages/IssueListPage.tsx <-> pages/IssueListPage.tsx). components.json now
  aliases @/v2/components.
- Restore every v1 file to its pre-v2 state, including IssueListPage and
  CyclesPage; the controllers they had been refactored into move to
  src/v2/hooks. The only v2-aware line left in v1 is <InterfaceSwitch /> in
  SettingsPage, implemented in routes/InterfaceSwitch.tsx.
- Add a no-restricted-imports rule: nothing outside src/v2 and src/routes may
  import from src/v2.
- v2 styles become their own Tailwind entry imported by the v2 shells, so the
  global index.css stays untouched and a v1 reader never downloads them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Expose structured activity metadata from the API (`verb`, `field`, `old_value`, `new_value`) for non-free-text issue activity rows, then render localized activity text on the client via a new `describeActivity` helper in both v1 and v2 settings activity panels. Add the related i18n keys/translations (en/tr/az), including notification row labels/descriptions and activity field/action phrases. Also move scoped shadcn border-color defaults into `@layer base` so utility `border-*` colors in v2 are no longer unintentionally overridden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Improve the v2 navigation experience by rendering a v2-specific Suspense fallback and adding an animated page-enter transition in the v2 AppShell. Also import `tw-animate-css` (and add it to dependencies) so shadcn animation utility classes like `animate-in`, `fade-in-*`, and `slide-in-*` actually work in Tailwind v4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cap the popover panels at the available height the popper reports and
stack the work item grouping toggles vertically so the three full-sentence
labels no longer spill out of the panel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 196 files, which is 96 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 760232f5-847c-46d2-a61b-4d731be757cc

📥 Commits

Reviewing files that changed from the base of the PR and between 7719dca and a7251fa.

⛔ Files ignored due to path filters (1)
  • apps/web/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (196)
  • .gitignore
  • AGENTS.md
  • CLAUDE.md
  • apps/api/internal/handler/user.go
  • apps/web/README.md
  • apps/web/components.json
  • apps/web/eslint.config.js
  • apps/web/i18next-parser.config.cjs
  • apps/web/package.json
  • apps/web/src/api/types.ts
  • apps/web/src/components/CreateWorkItemModal.tsx
  • apps/web/src/i18n/README.md
  • apps/web/src/i18n/dynamicKeys.ts
  • apps/web/src/i18n/index.ts
  • apps/web/src/i18n/locales/az/translation.json
  • apps/web/src/i18n/locales/en/translation.json
  • apps/web/src/i18n/locales/tr/translation.json
  • apps/web/src/lib/activityDescription.ts
  • apps/web/src/pages/SettingsPage.tsx
  • apps/web/src/routes/InterfaceSwitch.tsx
  • apps/web/src/routes/InterfaceVariant.tsx
  • apps/web/src/routes/PageFallback.tsx
  • apps/web/src/routes/index.tsx
  • apps/web/src/v2/README.md
  • apps/web/src/v2/components/app-sidebar.tsx
  • apps/web/src/v2/components/archives-toolbar.tsx
  • apps/web/src/v2/components/auth-page-shell.tsx
  • apps/web/src/v2/components/create-cycle-dialog.tsx
  • apps/web/src/v2/components/create-epic-dialog.tsx
  • apps/web/src/v2/components/create-module-dialog.tsx
  • apps/web/src/v2/components/create-page-dialog.tsx
  • apps/web/src/v2/components/create-project-dialog.tsx
  • apps/web/src/v2/components/create-project-view-dialog.tsx
  • apps/web/src/v2/components/create-view-dialog.tsx
  • apps/web/src/v2/components/create-work-item-dialog.tsx
  • apps/web/src/v2/components/create-workspace-form.tsx
  • apps/web/src/v2/components/cycles-filters-menu.tsx
  • apps/web/src/v2/components/detail-page-skeleton.tsx
  • apps/web/src/v2/components/drafts-toolbar.tsx
  • apps/web/src/v2/components/forgot-password-form.tsx
  • apps/web/src/v2/components/invite-accept-form.tsx
  • apps/web/src/v2/components/invite-signup-form.tsx
  • apps/web/src/v2/components/layout/AppShell.tsx
  • apps/web/src/v2/components/list-filter-chips.tsx
  • apps/web/src/v2/components/list-filters-menu.tsx
  • apps/web/src/v2/components/list-page-skeleton.tsx
  • apps/web/src/v2/components/list-sort-menu.tsx
  • apps/web/src/v2/components/login-form.tsx
  • apps/web/src/v2/components/nav-main.tsx
  • apps/web/src/v2/components/nav-projects.tsx
  • apps/web/src/v2/components/nav-secondary.tsx
  • apps/web/src/v2/components/nav-user.tsx
  • apps/web/src/v2/components/notification-snooze-menu.tsx
  • apps/web/src/v2/components/page-fallback.tsx
  • apps/web/src/v2/components/page-heading.tsx
  • apps/web/src/v2/components/page-transition.tsx
  • apps/web/src/v2/components/password-field.tsx
  • apps/web/src/v2/components/project-list-toolbar.tsx
  • apps/web/src/v2/components/projects-toolbar.tsx
  • apps/web/src/v2/components/reset-password-form.tsx
  • apps/web/src/v2/components/set-password-form.tsx
  • apps/web/src/v2/components/settings/account/account-activity-panel.tsx
  • apps/web/src/v2/components/settings/account/account-preferences-panel.tsx
  • apps/web/src/v2/components/settings/account/account-profile-panel.tsx
  • apps/web/src/v2/components/settings/account/account-security-panel.tsx
  • apps/web/src/v2/components/settings/api-tokens-panel.tsx
  • apps/web/src/v2/components/settings/invite-members-dialog.tsx
  • apps/web/src/v2/components/settings/member-role-select.tsx
  • apps/web/src/v2/components/settings/notification-preferences-panel.tsx
  • apps/web/src/v2/components/settings/project/project-automations-panel.tsx
  • apps/web/src/v2/components/settings/project/project-features-panel.tsx
  • apps/web/src/v2/components/settings/project/project-general-panel.tsx
  • apps/web/src/v2/components/settings/project/project-item-dialog.tsx
  • apps/web/src/v2/components/settings/project/project-labels-panel.tsx
  • apps/web/src/v2/components/settings/project/project-members-panel.tsx
  • apps/web/src/v2/components/settings/project/project-states-panel.tsx
  • apps/web/src/v2/components/settings/settings-panel.tsx
  • apps/web/src/v2/components/settings/settings-shell.tsx
  • apps/web/src/v2/components/settings/timezone-combobox.tsx
  • apps/web/src/v2/components/settings/workspace/workspace-exports-panel.tsx
  • apps/web/src/v2/components/settings/workspace/workspace-general-panel.tsx
  • apps/web/src/v2/components/settings/workspace/workspace-members-panel.tsx
  • apps/web/src/v2/components/signup-form.tsx
  • apps/web/src/v2/components/ui/alert-dialog.tsx
  • apps/web/src/v2/components/ui/alert.tsx
  • apps/web/src/v2/components/ui/avatar.tsx
  • apps/web/src/v2/components/ui/badge.tsx
  • apps/web/src/v2/components/ui/breadcrumb.tsx
  • apps/web/src/v2/components/ui/button.tsx
  • apps/web/src/v2/components/ui/calendar.tsx
  • apps/web/src/v2/components/ui/card.tsx
  • apps/web/src/v2/components/ui/chart.tsx
  • apps/web/src/v2/components/ui/checkbox.tsx
  • apps/web/src/v2/components/ui/collapsible.tsx
  • apps/web/src/v2/components/ui/command.tsx
  • apps/web/src/v2/components/ui/context-menu.tsx
  • apps/web/src/v2/components/ui/dialog.tsx
  • apps/web/src/v2/components/ui/dithered-logo.tsx
  • apps/web/src/v2/components/ui/dropdown-menu.tsx
  • apps/web/src/v2/components/ui/empty.tsx
  • apps/web/src/v2/components/ui/field.tsx
  • apps/web/src/v2/components/ui/hero-geometric.tsx
  • apps/web/src/v2/components/ui/hover-card.tsx
  • apps/web/src/v2/components/ui/input.tsx
  • apps/web/src/v2/components/ui/label.tsx
  • apps/web/src/v2/components/ui/pagination.tsx
  • apps/web/src/v2/components/ui/popover.tsx
  • apps/web/src/v2/components/ui/prism-gradient.tsx
  • apps/web/src/v2/components/ui/progress.tsx
  • apps/web/src/v2/components/ui/scroll-area.tsx
  • apps/web/src/v2/components/ui/select.tsx
  • apps/web/src/v2/components/ui/separator.tsx
  • apps/web/src/v2/components/ui/sheet.tsx
  • apps/web/src/v2/components/ui/sidebar.tsx
  • apps/web/src/v2/components/ui/skeleton.tsx
  • apps/web/src/v2/components/ui/sonner.tsx
  • apps/web/src/v2/components/ui/switch.tsx
  • apps/web/src/v2/components/ui/table.tsx
  • apps/web/src/v2/components/ui/tabs.tsx
  • apps/web/src/v2/components/ui/textarea.tsx
  • apps/web/src/v2/components/ui/toggle-group.tsx
  • apps/web/src/v2/components/ui/toggle.tsx
  • apps/web/src/v2/components/ui/tooltip.tsx
  • apps/web/src/v2/components/views-toolbar.tsx
  • apps/web/src/v2/components/work-item-inline-cells.tsx
  • apps/web/src/v2/components/work-item-layouts/work-items-board-layout.tsx
  • apps/web/src/v2/components/work-item-layouts/work-items-calendar-layout.tsx
  • apps/web/src/v2/components/work-item-layouts/work-items-gantt-layout.tsx
  • apps/web/src/v2/components/work-item-layouts/work-items-spreadsheet-layout.tsx
  • apps/web/src/v2/components/work-item-row-actions.tsx
  • apps/web/src/v2/components/work-item-subscribe-button.tsx
  • apps/web/src/v2/components/work-items-bulk-bar.tsx
  • apps/web/src/v2/components/work-items-display-menu.tsx
  • apps/web/src/v2/components/work-items-filters-menu.tsx
  • apps/web/src/v2/contexts/AccentColorContext.tsx
  • apps/web/src/v2/contexts/AppShellHeaderContext.tsx
  • apps/web/src/v2/contexts/InterfaceContext.tsx
  • apps/web/src/v2/contexts/ProjectSavedViewDisplayContext.tsx
  • apps/web/src/v2/contexts/WorkspaceViewsStateProvider.tsx
  • apps/web/src/v2/hooks/use-mobile.ts
  • apps/web/src/v2/hooks/useIsDarkTheme.ts
  • apps/web/src/v2/hooks/useListViewPreferences.ts
  • apps/web/src/v2/hooks/usePersistedChoice.ts
  • apps/web/src/v2/hooks/usePersistedSearchParams.ts
  • apps/web/src/v2/hooks/useProjectCyclesController.ts
  • apps/web/src/v2/hooks/useProjectIssuesController.ts
  • apps/web/src/v2/hooks/useProjectsListPreferences.ts
  • apps/web/src/v2/hooks/useWorkspaceViewPreferences.ts
  • apps/web/src/v2/lib/filterProjectsList.ts
  • apps/web/src/v2/lib/lastWorkspaceView.ts
  • apps/web/src/v2/lib/listControls.ts
  • apps/web/src/v2/lib/project.ts
  • apps/web/src/v2/lib/projectIssuesFiltersStorage.ts
  • apps/web/src/v2/lib/projectListEvents.ts
  • apps/web/src/v2/lib/workItemRelations.ts
  • apps/web/src/v2/lib/workspaceViewFiltersApply.ts
  • apps/web/src/v2/lib/workspaceViewParams.ts
  • apps/web/src/v2/pages/AnalyticsOverviewPage.tsx
  • apps/web/src/v2/pages/AnalyticsWorkItemsPage.tsx
  • apps/web/src/v2/pages/ArchivesPage.tsx
  • apps/web/src/v2/pages/CreateWorkspacePage.tsx
  • apps/web/src/v2/pages/CycleDetailPage.tsx
  • apps/web/src/v2/pages/CyclesPage.tsx
  • apps/web/src/v2/pages/DraftsPage.tsx
  • apps/web/src/v2/pages/EpicDetailPage.tsx
  • apps/web/src/v2/pages/EpicsPage.tsx
  • apps/web/src/v2/pages/ForgotPasswordPage.tsx
  • apps/web/src/v2/pages/IntakePage.tsx
  • apps/web/src/v2/pages/InviteAcceptPage.tsx
  • apps/web/src/v2/pages/InviteSignUpPage.tsx
  • apps/web/src/v2/pages/IssueDetailPage.tsx
  • apps/web/src/v2/pages/IssueListPage.tsx
  • apps/web/src/v2/pages/LoginPage.tsx
  • apps/web/src/v2/pages/ModuleDetailPage.tsx
  • apps/web/src/v2/pages/ModulesPage.tsx
  • apps/web/src/v2/pages/NotificationsPage.tsx
  • apps/web/src/v2/pages/PageDetailPage.tsx
  • apps/web/src/v2/pages/PagesPage.tsx
  • apps/web/src/v2/pages/ProfilePage.tsx
  • apps/web/src/v2/pages/ProjectsListPage.tsx
  • apps/web/src/v2/pages/ResetPasswordPage.tsx
  • apps/web/src/v2/pages/SetPasswordPage.tsx
  • apps/web/src/v2/pages/SettingsPage.tsx
  • apps/web/src/v2/pages/SignUpPage.tsx
  • apps/web/src/v2/pages/ViewDetailPage.tsx
  • apps/web/src/v2/pages/ViewsPage.tsx
  • apps/web/src/v2/pages/WorkspaceHomePage.tsx
  • apps/web/src/v2/pages/WorkspaceViewsPage.tsx
  • apps/web/src/v2/styles/index.css
  • apps/web/src/v2/styles/shadcn-bridge.css
  • apps/web/src/v2/styles/shadcn-reference-theme.css
  • apps/web/src/v2/styles/shadcn-v4-theme.css
  • apps/web/src/v2/styles/v2-color-themes.css
  • apps/web/tsconfig.app.json
  • apps/web/tsconfig.json
  • apps/web/vite.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@YSamed
YSamed marked this pull request as ready for review August 13, 2026 21:52
@YSamed
YSamed requested a review from a team as a code owner August 13, 2026 21:52
@YSamed

YSamed commented Aug 13, 2026

Copy link
Copy Markdown
Author

Out of draft and ready for review. All three checks are green.

Context and the design rationale live in discussion #400#400 — including screenshots and the two open questions (should v2 stay opt-in, and what the long-term plan for v1 is). Neither question blocks review: v2 is off by default, and v1 is unchanged apart from a single <InterfaceSwitch /> line in SettingsPage.tsx.

One note for reviewers: CodeRabbit skipped its automated pass because the PR has 173 files and its limit is 100. 148 of those files are new files under apps/web/src/v2/, and the shared surface is small — the route table, the settings switch, an ESLint rule, and one additive change in apps/api/internal/handler/user.go. Starting there should give the fastest read on whether the approach is right.

Happy to split this into a series of smaller PRs (primitives and shell first, then pages in batches) if that reviews better — just say the word.

YSamed and others added 6 commits August 14, 2026 10:38
Adjusts v2 cycle/work-item filter and display popovers to use explicit ScrollArea height calculations instead of flex growth. This prevents Radix ScrollArea viewports from expanding to full content height (and not scrolling) when constrained by available popover space, while accounting for headers and borders in each panel.
Adds shared v2 list UX primitives (filter menu/chips, sort menu) and wires them into epics, modules, pages, views, intake, drafts, archives, and projects with URL/localStorage-backed preferences. Introduces create dialogs for cycles, epics, modules, pages, and project views, plus project issues/workspace view persistence helpers and last-opened workspace view routing in the sidebar.

Also updates v2 shell/sidebar visuals (dithered logo, toolbar/layout refinements), adds optional mock-data infrastructure for v2 development, and significantly refreshes the v2 profile page layout and interactions. Translation keys were expanded in en/tr/az to support the new controls, dialogs, and profile copy.
The v2 mock data module and its hook were never imported by any page.
They also broke CI: the underscore-prefixed parameters tripped
@typescript-eslint/no-unused-vars, which has no argsIgnorePattern in
this repo's ESLint config.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Prevents v2 UI state from being overwritten during initial hydration and route changes by gating writes until localStorage/URL restores have actually landed. This adds restore-tracking guards for saved view display settings, project issue display state, and workspace URL-sync state (including StrictMode double-effect behavior). It also makes the v2 shell read the sidebar cookie for `defaultOpen` so collapse state persists correctly in the SPA.
Adds a new v2 accent color system with persisted presets (default, blue, violet, green, orange, rose) and CSS token overrides that only recolor primary actions and focus rings in both light and dark modes. Updates the v2 account preferences UI to separate appearance into mode + accent controls, wires accent state into the AppShell (including portal content), and adds new i18n strings for EN/TR/AZ.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant