Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
3dc4c54
πŸ€– feat: Add Tailwind CSS and Shadcn UI foundation
kylecarbs Oct 22, 2025
61f668b
πŸ€– refactor: Convert ToggleGroup and ErrorMessage to Tailwind
kylecarbs Oct 22, 2025
170df51
πŸ€– docs: Add comprehensive Tailwind migration status
kylecarbs Oct 22, 2025
1792bc8
πŸ€– refactor: Convert StatusIndicator, Tooltip, ChatToggles, Context1MC…
kylecarbs Oct 22, 2025
81e656c
πŸ€– refactor: Convert Modal and all modal components to Tailwind
kylecarbs Oct 22, 2025
824f0ac
πŸ€– refactor: Convert DirectorySelectModal and ToolPrimitives to Tailwind
kylecarbs Oct 22, 2025
367c029
πŸ€– refactor: Convert HistoryHiddenMessage and TerminalOutput to Tailwind
kylecarbs Oct 22, 2025
ba25510
πŸ€– refactor: Convert CompactingMessageContent and TypewriterMarkdown
kylecarbs Oct 22, 2025
d17c24e
πŸ“Š docs: Update migration status to 20% complete (13/64 components)
kylecarbs Oct 22, 2025
66dcef1
πŸ€– refactor: Convert LeftSidebar to Tailwind
kylecarbs Oct 22, 2025
7d920ed
πŸ€– refactor: Convert ErrorBoundary to Tailwind
kylecarbs Oct 22, 2025
dffb762
πŸ“Š docs: Update final migration status - 23% complete (15/64)
kylecarbs Oct 22, 2025
82ee5ed
πŸ€– refactor: Convert RefreshButton to Tailwind
kylecarbs Oct 22, 2025
2790773
πŸ€– refactor: Convert ModelDisplay to Tailwind
kylecarbs Oct 22, 2025
ff9703d
πŸ€– refactor: Convert BaseBarrier to Tailwind
kylecarbs Oct 22, 2025
1db6429
πŸ€– refactor: Convert PinnedTodoList to Tailwind
kylecarbs Oct 22, 2025
0e8c955
πŸ€– refactor: Convert UserMessage to Tailwind
kylecarbs Oct 22, 2025
cd16a6a
πŸ€– refactor: Convert RetryBarrier to Tailwind
kylecarbs Oct 22, 2025
61f9ceb
πŸ€– refactor: Convert StreamingBarrier to Tailwind
kylecarbs Oct 22, 2025
39f9728
πŸ€– refactor: Convert ReasoningMessage to Tailwind
kylecarbs Oct 22, 2025
8488c3b
πŸ€– refactor: Convert StreamErrorMessage to Tailwind
kylecarbs Oct 22, 2025
cfc0bf5
πŸ€– refactor: Convert CompactionBackground to Tailwind
kylecarbs Oct 22, 2025
a309862
πŸ€– refactor: Convert GitStatusIndicatorView to Tailwind
kylecarbs Oct 22, 2025
640fa2d
πŸ€– refactor: Convert WorkspaceListItem to Tailwind
kylecarbs Oct 22, 2025
a82abde
πŸ€– refactor: Convert ImageAttachments, TitleBar, TodoList to Tailwind
kylecarbs Oct 22, 2025
6eff57e
πŸ€– refactor: Convert ThinkingSlider to Tailwind with CSS variables
kylecarbs Oct 22, 2025
3ee4465
πŸ€– refactor: Convert ChatInputToast to Tailwind
kylecarbs Oct 22, 2025
9830bbc
πŸ€– refactor: Convert ForceDeleteModal and TipsCarousel to Tailwind
kylecarbs Oct 22, 2025
6bf2135
πŸ€– refactor: Convert BashToolCall and FileReadToolCall to Tailwind
kylecarbs Oct 22, 2025
10bd559
πŸ€– refactor: Convert FileEditToolCall to Tailwind
kylecarbs Oct 22, 2025
661e6c4
πŸ€– refactor: Convert CommandSuggestions to Tailwind
kylecarbs Oct 22, 2025
221a272
πŸ€– refactor: Convert ProposePlanToolCall to Tailwind CSS
kylecarbs Oct 22, 2025
b7c4025
πŸ€– refactor: Convert MarkdownRenderer to Tailwind CSS
kylecarbs Oct 22, 2025
c401fdb
πŸ€– refactor: Convert AssistantMessage to Tailwind CSS
kylecarbs Oct 22, 2025
f7b85e9
πŸ€– refactor: Convert MessageWindow to Tailwind CSS
kylecarbs Oct 22, 2025
3f7075b
πŸ€– refactor: Convert SecretsModal to Tailwind CSS
kylecarbs Oct 22, 2025
c4e19fc
πŸ€– refactor: Convert NewWorkspaceModal to Tailwind CSS
kylecarbs Oct 22, 2025
dfc0c74
πŸ€– refactor: Convert StartHereModal to Tailwind CSS
kylecarbs Oct 22, 2025
05c6754
πŸ€– refactor: Convert TokenMeter to Tailwind CSS
kylecarbs Oct 22, 2025
230919d
πŸ€– refactor: Convert VerticalTokenMeter to Tailwind CSS
kylecarbs Oct 22, 2025
7678e8e
πŸ€– refactor: Convert RightSidebar components to Tailwind CSS
kylecarbs Oct 22, 2025
be30b09
πŸ€– refactor: Convert UntrackedStatus to Tailwind CSS
kylecarbs Oct 22, 2025
948297b
πŸ€– refactor: Convert ReviewControls to Tailwind CSS
kylecarbs Oct 22, 2025
d422b1b
πŸ€– refactor: Convert HunkViewer to Tailwind CSS
kylecarbs Oct 22, 2025
ce8a1cb
πŸ€– refactor: Convert CommandPalette to Tailwind CSS
kylecarbs Oct 22, 2025
d012024
πŸ€– refactor: Convert ModelSelector to Tailwind CSS
kylecarbs Oct 22, 2025
a9b1087
πŸ€– refactor: Convert KebabMenu to Tailwind CSS
kylecarbs Oct 22, 2025
bc21dd7
πŸ€– refactor: Convert VimTextArea to Tailwind CSS
kylecarbs Oct 22, 2025
2895a74
πŸ€– refactor: Convert DiffRenderer to Tailwind CSS
kylecarbs Oct 22, 2025
585efa5
πŸ€– refactor: Convert AIView to Tailwind CSS
kylecarbs Oct 22, 2025
c78729b
πŸ€– refactor: Convert App.tsx to Tailwind CSS
kylecarbs Oct 22, 2025
d7eecbd
πŸ€– refactor: Convert ChatInput to Tailwind CSS
kylecarbs Oct 22, 2025
e6a0b73
πŸ€– refactor: Convert story files to Tailwind CSS and remove emotion
kylecarbs Oct 22, 2025
77b8f36
πŸ€– refactor: Remove temporary migration documentation file
kylecarbs Oct 22, 2025
211681b
πŸ€– refactor: Remove temporary migration scripts
kylecarbs Oct 22, 2025
e629bc4
πŸ€– fix: Restore properly converted Tailwind files after rebase
kylecarbs Oct 22, 2025
f1c51bf
πŸ€– fix: Remove unused imports and fix linting issues
kylecarbs Oct 22, 2025
8136f29
πŸ€– fix: Add --color-* CSS variable aliases for backwards compatibility
kylecarbs Oct 22, 2025
70d367a
πŸ€– fix: Correct font-family class names in Tailwind conversions
kylecarbs Oct 22, 2025
2915e39
πŸ€– Fix: Define font CSS variables and add font-primary class
kylecarbs Oct 22, 2025
04bfcf6
πŸ€– Fix: Remove quotes from font CSS variables
kylecarbs Oct 22, 2025
cd72e04
πŸ€– Fix: Remove font-mono from AIView container
kylecarbs Oct 22, 2025
5f65c60
πŸ€– WIP: Migrate to Tailwind CSS v4
kylecarbs Oct 22, 2025
19e0356
πŸ€– Fix: Tailwind v4 migration - fix CSS syntax
kylecarbs Oct 22, 2025
488a40c
πŸ€– Tailwind v4 migration complete (dev mode working)
kylecarbs Oct 22, 2025
321bc8f
πŸ€– fix: Update Tailwind CSS to v4.1.15 and fix components.json config
kylecarbs Oct 22, 2025
9ae71fa
πŸ€– Trigger CI re-run for E2E tests
kylecarbs Oct 22, 2025
11df5c6
πŸ€– Fix: Remove config bypassing in renameWorkspace tests
kylecarbs Oct 22, 2025
6df1ee2
Revert "πŸ€– Fix: Remove config bypassing in renameWorkspace tests"
kylecarbs Oct 22, 2025
8009896
πŸ€– Fix worker.plugins syntax for Vite 7 compatibility
kylecarbs Oct 22, 2025
94de92a
πŸ€– Configure Tailwind to exclude worker files
kylecarbs Oct 22, 2025
7f9a2e1
πŸ€– Retrigger CI
kylecarbs Oct 22, 2025
9042265
πŸ€– Prevent Tailwind plugin from applying to worker builds
kylecarbs Oct 22, 2025
aa8dfcd
πŸ€– Simplify vite config - remove apply() filter
kylecarbs Oct 22, 2025
99b278e
Fix vite config
kylecarbs Oct 22, 2025
6a06258
πŸ€– Fix worker plugins - use array syntax to match main
kylecarbs Oct 22, 2025
f0a46ad
πŸ€– Fix mode toggle visibility - correct container query breakpoint
kylecarbs Oct 22, 2025
fc9c414
πŸ€– Remove git conflict markers from ProjectSidebar
kylecarbs Oct 23, 2025
00e5b17
πŸ€– Restore ReviewPanel and FileTree from good state
kylecarbs Oct 23, 2025
a34751b
πŸ€– Port changes from main commits 0a1aea1 and f147297
kylecarbs Oct 23, 2025
1241a08
Make the UI more consistent with current
kylecarbs Oct 23, 2025
bd39955
Fix markdown content
kylecarbs Oct 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import type { Preview } from "@storybook/react";
import { GlobalColors } from "../src/styles/colors";
import { GlobalFonts } from "../src/styles/fonts";
import { GlobalScrollbars } from "../src/styles/scrollbars";
import "../src/styles/globals.css";

const preview: Preview = {
decorators: [
(Story) => (
<>
<GlobalColors />
<GlobalFonts />
<GlobalScrollbars />
<Story />
</>
),
Expand Down
412 changes: 289 additions & 123 deletions bun.lock

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/styles/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}

25 changes: 18 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,20 @@
"docs:watch": "make docs-watch",
"storybook": "make storybook",
"storybook:build": "make storybook-build",
"test:storybook": "make test-storybook",
"chromatic": "make chromatic"
"test:storybook": "make test-storybook"
},
"dependencies": {
"@ai-sdk/anthropic": "^2.0.29",
"@ai-sdk/openai": "^2.0.52",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"ai": "^5.0.72",
"ai-tokenizer": "^1.0.3",
"chalk": "^5.6.2",
Expand All @@ -68,9 +76,6 @@
"zod-to-json-schema": "^3.24.6"
},
"devDependencies": {
"@emotion/babel-plugin": "^11.13.5",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@eslint/js": "^9.36.0",
"@playwright/test": "^1.56.0",
"@storybook/addon-essentials": "^8.6.14",
Expand All @@ -80,6 +85,7 @@
"@storybook/react": "^8.6.14",
"@storybook/react-vite": "^8.6.14",
"@storybook/test-runner": "^0.23.0",
"@tailwindcss/vite": "^4.1.15",
"@testing-library/react": "^16.3.0",
"@types/bun": "^1.2.23",
"@types/cors": "^2.8.19",
Expand All @@ -98,8 +104,10 @@
"@typescript-eslint/parser": "^8.44.1",
"@typescript/native-preview": "^7.0.0-dev.20251014.1",
"@vitejs/plugin-react": "^4.0.0",
"autoprefixer": "^10.4.21",
"babel-plugin-react-compiler": "^1.0.0",
"chromatic": "^13.3.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"concurrently": "^8.2.0",
"dotenv": "^17.2.3",
Expand All @@ -114,6 +122,7 @@
"jest": "^30.1.3",
"mermaid": "^11.12.0",
"playwright": "^1.56.0",
"postcss": "^8.5.6",
"posthog-js": "^1.276.0",
"prettier": "^3.6.2",
"react": "^18.2.0",
Expand All @@ -129,11 +138,13 @@
"remark-math": "^6.0.0",
"shiki": "^3.13.0",
"storybook": "^8.6.14",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.15",
"ts-jest": "^29.4.4",
"tsc-alias": "^1.8.16",
"typescript": "^5.1.3",
"typescript-eslint": "^8.45.0",
"vite": "^4.4.0",
"vite": "^7.1.11",
"vite-plugin-svgr": "^4.5.0",
"vite-plugin-top-level-await": "^1.6.0"
},
Expand Down
217 changes: 18 additions & 199 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { useState, useEffect, useCallback, useRef } from "react";
import styled from "@emotion/styled";
import { Global, css } from "@emotion/react";
import { GlobalColors } from "./styles/colors";
import { GlobalFonts } from "./styles/fonts";
import { GlobalScrollbars } from "./styles/scrollbars";
import "./styles/globals.css";
import type { ProjectConfig } from "./config";
import type { WorkspaceSelection } from "./components/ProjectSidebar";
import type { FrontendWorkspaceMetadata } from "./types/workspace";
Expand Down Expand Up @@ -37,187 +33,6 @@ import { useTelemetry } from "./hooks/useTelemetry";

const THINKING_LEVELS: ThinkingLevel[] = ["off", "low", "medium", "high"];

// Global Styles with nice fonts
const globalStyles = css`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

html,
body,
#root {
height: 100vh;
overflow: hidden;
background: #1e1e1e;
color: #fff;
font-family: var(--font-primary);
font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

/* Mobile: Improve touch interactions */
@media (max-width: 768px) {
html {
/* Prevent text size adjustment on orientation change */
-webkit-text-size-adjust: 100%;
}

body {
/* Slightly larger font for better readability on mobile */
font-size: 15px;
}

/* Make buttons and interactive elements easier to tap */
button,
a,
[role="button"] {
min-height: 44px;
min-width: 44px;
/* Improve tap responsiveness on buttons only */
touch-action: manipulation;
}

/* Ensure input elements allow default touch behavior for iOS keyboard */
input,
textarea,
select {
touch-action: auto;
}
}

code {
font-family: var(--font-monospace);
}

/* Enable native tooltips */
[title] {
position: relative;
}

[title]:hover::after {
content: attr(title);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
margin-bottom: 8px;
padding: 6px 10px;
background: #2d2d30;
color: #cccccc;
border: 1px solid #464647;
border-radius: 4px;
font-size: 11px;
white-space: nowrap;
z-index: 1000;
pointer-events: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

[title]:hover::before {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
margin-bottom: 3px;
border-width: 5px;
border-style: solid;
border-color: #2d2d30 transparent transparent transparent;
z-index: 1000;
pointer-events: none;
}

/* Search term highlighting - global for consistent styling across components */
/* Applied to <mark> for plain text and <span> for Shiki-highlighted code */
mark.search-highlight,
span.search-highlight {
background: rgba(255, 215, 0, 0.3);
color: inherit;
padding: 0;
border-radius: 2px;
}

/* Override Shiki theme background to use our global color */
.shiki,
.shiki pre {
background: var(--color-code-bg) !important;
}

/* Global styling for markdown code blocks */
pre code {
display: block;
background: var(--color-code-bg);
margin: 1em 0;
border-radius: 4px;
font-size: 12px;
padding: 12px;
overflow: auto;
}
`;

// Styled Components
const AppContainer = styled.div`
display: flex;
height: 100vh;
overflow: hidden;
background: #1e1e1e;

/* Mobile: Ensure content takes full width */
@media (max-width: 768px) {
flex-direction: column;
}
`;

const MainContent = styled.div`
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
min-width: 0; /* Allow content to shrink below its minimum content size */

/* Mobile: Take full width */
@media (max-width: 768px) {
width: 100%;
}
`;

const ContentArea = styled.div`
flex: 1;
display: flex;
overflow: hidden;

/* Mobile: Stack content vertically if needed */
@media (max-width: 768px) {
flex-direction: column;
}
`;

const WelcomeView = styled.div`
text-align: center;
padding: clamp(40px, 10vh, 100px) 20px;
max-width: 800px;
margin: 0 auto;
width: 100%;

h2 {
color: #fff;
font-size: clamp(24px, 5vw, 36px);
margin-bottom: 16px;
font-weight: 700;
letter-spacing: -1px;
}

p {
color: #888;
font-size: clamp(14px, 2vw, 16px);
line-height: 1.6;
}
`;

function AppInner() {
const [selectedWorkspace, setSelectedWorkspace] = usePersistedState<WorkspaceSelection | null>(
"selectedWorkspace",
Expand Down Expand Up @@ -847,11 +662,7 @@ function AppInner() {

return (
<>
<GlobalColors />
<GlobalFonts />
<GlobalScrollbars />
<Global styles={globalStyles} />
<AppContainer>
<div className="flex h-screen overflow-hidden bg-[#1e1e1e] [@media(max-width:768px)]:flex-col">
<LeftSidebar
projects={projects}
workspaceMetadata={workspaceMetadata}
Expand All @@ -871,8 +682,8 @@ function AppInner() {
sortedWorkspacesByProject={sortedWorkspacesByProject}
workspaceRecency={workspaceRecency}
/>
<MainContent>
<ContentArea>
<div className="flex-1 flex flex-col overflow-hidden min-w-0 [@media(max-width:768px)]:w-full">
<div className="flex-1 flex overflow-hidden [@media(max-width:768px)]:flex-col">
{selectedWorkspace ? (
<ErrorBoundary
workspaceInfo={`${selectedWorkspace.projectName}/${selectedWorkspace.namedWorkspacePath?.split("/").pop() ?? selectedWorkspace.workspaceId}`}
Expand All @@ -889,13 +700,21 @@ function AppInner() {
/>
</ErrorBoundary>
) : (
<WelcomeView>
<h2>Welcome to Cmux</h2>
<div
className="text-center max-w-[800px] mx-auto w-full [&_h2]:text-white [&_h2]:mb-4 [&_h2]:font-bold [&_h2]:tracking-tight [&_p]:text-[#888] [&_p]:leading-[1.6]"
style={{
padding: "clamp(40px, 10vh, 100px) 20px",
fontSize: "clamp(14px, 2vw, 16px)",
}}
>
<h2 style={{ fontSize: "clamp(24px, 5vw, 36px)", letterSpacing: "-1px" }}>
Welcome to Cmux
</h2>
<p>Select a workspace from the sidebar or add a new one to get started.</p>
</WelcomeView>
</div>
)}
</ContentArea>
</MainContent>
</div>
</div>
<CommandPalette
getSlashContext={() => ({
providerNames: [],
Expand All @@ -922,7 +741,7 @@ function AppInner() {
/>
)}
<DirectorySelectModal />
</AppContainer>
</div>
</>
);
}
Expand Down
Loading