Rebrand to Reforge with Lyra theme and ScrollArea#29
Conversation
- Rebrand from "smo" to "Reforge" across all pages and components - Apply shadcn Stone base + Blue theme (HSL CSS variables) - Lyra style: JetBrains Mono font, radius 0, boxy/sharp look - Add shadcn ScrollArea component, replace native overflow scrollbars - Add sidebar/chart CSS variables for future use - Add ReforgeLogo component and SVG logo - Remove duplicate docker-compose.dev.yml, keep docker-compose.yml - Update README with new branding and correct compose references - Enable SummarizationMiddleware in agent for long conversations - Remove hardcoded VERTEX_AI_MODEL from deploy workflow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR rebrands the frontend to “Reforge”, applies a Stone/Blue (Lyra-like) shadcn theme (JetBrains Mono, radius 0), replaces several native scroll containers with a shared Radix ScrollArea, updates dev/prod docs/compose usage, and enables agent-side conversation summarization for long threads.
Changes:
- Rebrand UI (logo, favicon/title, gradients, copy) and adjust core UI component styling to the new theme tokens.
- Introduce
ScrollArea(Radix) and migrate multiple scrollable regions to it (chat/messages, file tree, agent logs, settings modal, etc.). - Enable
SummarizationMiddlewarein the agent and update README / dev compose references.
Reviewed changes
Copilot reviewed 34 out of 36 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/tailwind.config.js | Adds JetBrains Mono and new theme color tokens (brand/sidebar/chart) and radius variables. |
| frontend/src/pages/RegisterPage.tsx | Updates branding/styles and refines error UI text. |
| frontend/src/pages/ProjectsPage.tsx | Applies Reforge header branding and theme tokens across the page. |
| frontend/src/pages/ProjectDetailPage.tsx | Switches layout styling to new theme and adopts ScrollArea for task list section. |
| frontend/src/pages/LoginPage.tsx | Updates branding (logo/tagline) and applies brand gradient + theme tokens. |
| frontend/src/pages/CreateProjectPage.tsx | Applies theme tokens and updates warning copy styling. |
| frontend/src/index.css | Replaces palette variables (stone/blue), sets radius=0, adds brand gradient utilities, adjusts scrollbar fallback. |
| frontend/src/components/ui/toast.tsx | Updates toast colors to align with brand-blue and theme text tokens. |
| frontend/src/components/ui/textarea.tsx | Updates dark-mode tokens to match new theme variables. |
| frontend/src/components/ui/scroll-area.tsx | Adds shared Radix ScrollArea component for consistent scrollbars. |
| frontend/src/components/ui/input.tsx | Updates dark-mode tokens to match new theme variables. |
| frontend/src/components/ui/dialog.tsx | Updates dialog colors/borders to theme variables. |
| frontend/src/components/ui/card.tsx | Updates dark-mode card colors to use theme variables. |
| frontend/src/components/ui/button.tsx | Rethemes button variants to use brand-blue in dark mode. |
| frontend/src/components/ui/badge.tsx | Adjusts badge radius and dark-mode colors to theme variables. |
| frontend/src/components/ui/ErrorState.tsx | Updates error state background/text tokens. |
| frontend/src/components/ui/EmptyState.tsx | Updates empty state text tokens. |
| frontend/src/components/project/ProjectSettingsModal.tsx | Applies new theme and wraps modal body in ScrollArea. |
| frontend/src/components/layout/PanelHeader.tsx | Updates panel header border/text to theme tokens. |
| frontend/src/components/file/FileViewer.tsx | Rethemes file viewer container and tab styling. |
| frontend/src/components/file/FileTree.tsx | Wraps tree in ScrollArea and rethemes selection/hover states. |
| frontend/src/components/common/ModelSelector.tsx | Rethemes selector and wraps dropdown list in ScrollArea. |
| frontend/src/components/chat/ChatSessionList.tsx | Rethemes session list and wraps sessions in ScrollArea. |
| frontend/src/components/chat/ChatPanel.tsx | Rethemes chat panel, wraps messages in ScrollArea, adds toast-based long-thread warnings. |
| frontend/src/components/brand/ReforgeLogo.tsx | Adds new reusable brand logo component. |
| frontend/src/components/agent/TaskList.tsx | Rethemes task list colors and in-progress highlighting. |
| frontend/src/components/agent/AgentRunPanel.tsx | Rethemes agent run UI and wraps tasks/logs in ScrollArea. |
| frontend/public/reforge-logo.svg | Adds Reforge SVG logo asset. |
| frontend/package.json | Renames package and adds Radix scroll-area dependency. |
| frontend/package-lock.json | Locks new package name and Radix scroll-area dependency tree. |
| frontend/index.html | Updates favicon/title and loads JetBrains Mono from Google Fonts. |
| frontend/components.json | Switches shadcn style/baseColor and enables CSS variables. |
| devops/docker-compose.dev.yml | Removes duplicate dev compose file. |
| agent/deep_agent.py | Enables SummarizationMiddleware with message-count trigger/keep settings. |
| README.md | Updates branding and adjusts Docker Compose commands and docs structure. |
| .github/workflows/deploy-gce.yml | Removes VERTEX_AI_MODEL env usage note (model now passed via API parameter). |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)
frontend/tailwind.config.js:95
- With
--radiusset to0rem, the Tailwind borderRadius extensions computemd/smascalc(var(--radius) - 2px)/- 4px, which yields negative radii. Negative border-radius values are invalid and rely on browser clamping behavior. Setmd/smto0as well (or clamp viamax()), to guarantee consistent sharp corners without invalid CSS.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <ScrollArea className="flex-1"> | ||
| <div className="p-2 space-y-1"> | ||
| {sessions.length === 0 ? ( | ||
| <div className="text-[10px] text-muted-foreground">No sessions</div> | ||
| ) : ( |
There was a problem hiding this comment.
ChatSessionList now wraps the sessions list in a ScrollArea with className="flex-1", but this component’s root isn’t a flex container, so flex-1 won’t constrain height and the list can grow unbounded (reducing space for content below). Add an explicit height/max-height (e.g., keep a max-h-*) and/or make the container flex flex-col so the ScrollArea can actually scroll within a bounded area.
| <ScrollArea className="absolute bottom-full left-0 mb-1 w-72 max-h-80 bg-secondary border border-border rounded-lg shadow-xl z-50"> | ||
| {Object.entries(grouped).map(([provider, providerModels]) => ( | ||
| <div key={provider}> | ||
| <div className="px-3 py-1.5 text-[10px] font-semibold text-gray-500 uppercase tracking-wider sticky top-0 bg-gray-800"> | ||
| <div className="px-3 py-1.5 text-[10px] font-semibold text-muted-foreground uppercase tracking-wider sticky top-0 bg-secondary"> | ||
| {provider} |
There was a problem hiding this comment.
ModelSelector dropdown uses ScrollArea with only max-h-80 on the root. Because the ScrollArea viewport is h-full, scrolling may not activate unless the root has a definite height. Consider adding an explicit h-80 (or similar) alongside max-h-80, or adjust the ScrollArea implementation/usage so the viewport can size to the max-height and scroll reliably.
| ? 'bg-background text-white' | ||
| : 'bg-background text-muted-foreground hover:bg-background' |
There was a problem hiding this comment.
FileViewer tab classes now use bg-background for both active and inactive tabs, and the hover state also uses hover:bg-background, so there’s almost no visual affordance for hover/active background changes. Consider using a contrasting token (e.g., secondary/muted) for inactive/hover to keep tabs discoverable and improve visual separation.
| ? 'bg-background text-white' | |
| : 'bg-background text-muted-foreground hover:bg-background' | |
| ? 'bg-background text-foreground' | |
| : 'bg-muted text-muted-foreground hover:bg-muted/80' |
| default: "bg-primary text-primary-foreground hover:bg-primary/90 bg-slate-900 text-white hover:bg-slate-800 dark:bg-brand-blue-500 dark:hover:bg-brand-blue-600", | ||
| destructive: | ||
| "bg-destructive text-destructive-foreground hover:bg-destructive/90 bg-red-500 text-white hover:bg-red-600 dark:bg-red-600 dark:hover:bg-red-700", | ||
| outline: | ||
| "border border-input bg-background hover:bg-accent hover:text-accent-foreground border-slate-300 hover:bg-slate-100 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700 dark:bg-transparent", | ||
| "border border-input bg-background hover:bg-accent hover:text-accent-foreground border-slate-300 hover:bg-slate-100 dark:border-border dark:text-secondary-foreground dark:hover:bg-secondary dark:bg-transparent", |
There was a problem hiding this comment.
Button default variant includes both theme-token classes (bg-primary text-primary-foreground) and hard-coded colors (bg-slate-900 text-white). The hard-coded classes will override the CSS-variable theme (Stone/Blue) in light mode, undermining theming consistency. Remove the hard-coded slate/text classes (or split into a separate variant) so theme tokens control appearance.
| middleware = [ | ||
| SummarizationMiddleware( | ||
| model=self.model, | ||
| # 當訊息數量超過 50 條時觸發壓縮 | ||
| trigger=("messages", 50), |
There was a problem hiding this comment.
SummarizationMiddleware is enabled unconditionally and uses self.model for summarization. This can materially increase token usage/latency (summarization calls compete with the main agent model) and may not be desired in all environments. Consider making summarization enablement + trigger/keep thresholds configurable via env/config, and optionally using a cheaper/faster model for summarization.
| {/* Tasks */} | ||
| {tasks.length > 0 && ( | ||
| <div className="flex-shrink-0 border-b border-gray-800 max-h-48 overflow-y-auto"> | ||
| <ScrollArea className="flex-shrink-0 border-b border-border max-h-48"> |
There was a problem hiding this comment.
AgentRunPanel wraps the tasks section in ScrollArea with only max-h-48 on the root. Since the ScrollArea viewport is h-full, scrolling may not engage unless the root has a definite height. Consider adding an explicit height (e.g., h-48) or adjusting ScrollArea usage so this section reliably scrolls when tasks exceed the max height.
| <ScrollArea className="flex-shrink-0 border-b border-border max-h-48"> | |
| <ScrollArea className="flex-shrink-0 border-b border-border h-48 max-h-48"> |
| <div className="fixed top-4 right-4 z-50 space-y-2"> | ||
| {toast.toasts.map((t) => ( | ||
| <Toast key={t.id} {...t} /> | ||
| ))} | ||
| </div> |
There was a problem hiding this comment.
ChatPanel introduces its own useToast state + fixed-position toast rendering, but ProjectDetailPage already renders ToastContainer from a separate useToast instance. This creates two independent toast systems and ChatPanel warnings won’t appear in the existing container (and the new container also lacks ToastContainer’s pointer-events handling). Prefer lifting these warnings to the existing toast instance (pass toast methods as props / use shared context) and render via ToastContainer only once.
Summary
ScrollAreacomponent, replace all nativeoverflow-y-autoscrollbarsdocker-compose.dev.yml, update READMESummarizationMiddlewarein agent for long conversationsTest plan
docker-compose -f devops/docker-compose.yml up -dstarts correctlynpm run buildpasses without errors🤖 Generated with Claude Code