Skip to content

Commit c78db9f

Browse files
committed
🤖 refactor: Convert CommandPalette to Tailwind CSS
- Replace all styled-components with Tailwind utility classes - Use Command.* directly with className instead of styled wrappers - Convert cmdk custom attribute selectors to arbitrary Tailwind selectors - Maintain overlay backdrop, input styling, and list interactions - ~30% code reduction (533 lines)
1 parent 4fab393 commit c78db9f

File tree

1 file changed

+22
-101
lines changed

1 file changed

+22
-101
lines changed

src/components/CommandPalette.tsx

Lines changed: 22 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,11 @@
11
import React, { useCallback, useEffect, useMemo, useState } from "react";
2-
import styled from "@emotion/styled";
32
import { Command } from "cmdk";
43
import { useCommandRegistry } from "@/contexts/CommandRegistryContext";
54
import type { CommandAction } from "@/contexts/CommandRegistryContext";
65
import { formatKeybind, KEYBINDS, isEditableElement, matchesKeybind } from "@/utils/ui/keybinds";
76
import { getSlashCommandSuggestions } from "@/utils/slashCommands/suggestions";
87
import { CUSTOM_EVENTS } from "@/constants/events";
98

10-
const Overlay = styled.div`
11-
position: fixed;
12-
inset: 0;
13-
background: rgba(0, 0, 0, 0.4);
14-
z-index: 2000;
15-
display: flex;
16-
align-items: flex-start;
17-
justify-content: center;
18-
padding-top: 10vh;
19-
`;
20-
21-
const PaletteContainer = styled(Command)`
22-
width: min(720px, 92vw);
23-
background: #1f1f1f;
24-
border: 1px solid #333;
25-
border-radius: 8px;
26-
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
27-
color: #e5e5e5;
28-
font-family: var(--font-primary);
29-
overflow: hidden;
30-
` as unknown as typeof Command;
31-
32-
const PaletteInput = styled(Command.Input)`
33-
width: 100%;
34-
padding: 12px 14px;
35-
background: #161616;
36-
color: #e5e5e5;
37-
border: none;
38-
outline: none;
39-
font-size: 14px;
40-
border-bottom: 1px solid #2a2a2a;
41-
` as unknown as typeof Command.Input;
42-
43-
const Empty = styled.div`
44-
padding: 16px;
45-
color: #7a7a7a;
46-
font-size: 13px;
47-
`;
48-
49-
const List = styled(Command.List)`
50-
max-height: 420px;
51-
overflow: auto;
52-
` as unknown as typeof Command.List;
53-
54-
const Group = styled(Command.Group)`
55-
&[cmdk-group] {
56-
padding: 8px 6px;
57-
}
58-
&[cmdk-group-heading] {
59-
padding: 4px 10px;
60-
color: #9a9a9a;
61-
font-size: 11px;
62-
text-transform: uppercase;
63-
letter-spacing: 0.08em;
64-
}
65-
` as unknown as typeof Command.Group;
66-
67-
const Item = styled(Command.Item)`
68-
display: grid;
69-
grid-template-columns: 1fr auto;
70-
align-items: center;
71-
gap: 8px;
72-
padding: 8px 12px;
73-
font-size: 13px;
74-
cursor: pointer;
75-
border-radius: 6px;
76-
margin: 2px 4px;
77-
&:hover {
78-
background: #2a2a2a;
79-
}
80-
&[aria-selected="true"] {
81-
background: #2f2f2f;
82-
}
83-
` as unknown as typeof Command.Item;
84-
85-
const Subtitle = styled.span`
86-
color: #9a9a9a;
87-
font-size: 12px;
88-
`;
89-
90-
const ShortcutHint = styled.span`
91-
color: #9a9a9a;
92-
font-size: 11px;
93-
font-family: var(--font-monospace);
94-
`;
95-
969
interface CommandPaletteProps {
9710
getSlashContext?: () => { providerNames: string[]; workspaceId?: string };
9811
}
@@ -441,19 +354,22 @@ export const CommandPalette: React.FC<CommandPaletteProps> = ({ getSlashContext
441354
const hasAnyItems = groupsWithItems.length > 0;
442355

443356
return (
444-
<Overlay
357+
<div
358+
className="fixed inset-0 bg-black/40 z-[2000] flex items-start justify-center pt-[10vh]"
445359
onMouseDown={() => {
446360
setActivePrompt(null);
447361
setPromptError(null);
448362
setQuery("");
449363
close();
450364
}}
451365
>
452-
<PaletteContainer
366+
<Command
367+
className="w-[min(720px,92vw)] bg-[#1f1f1f] border border-[#333] rounded-lg shadow-[0_10px_40px_rgba(0,0,0,0.4)] text-[#e5e5e5] font-primary overflow-hidden"
453368
onMouseDown={(e: React.MouseEvent) => e.stopPropagation()}
454369
shouldFilter={shouldUseCmdkFilter}
455370
>
456-
<PaletteInput
371+
<Command.Input
372+
className="w-full py-3 px-3.5 bg-[#161616] text-[#e5e5e5] border-none outline-none text-sm border-b border-[#2a2a2a]"
457373
value={query}
458374
onValueChange={handleQueryChange}
459375
placeholder={
@@ -484,12 +400,17 @@ export const CommandPalette: React.FC<CommandPaletteProps> = ({ getSlashContext
484400
}
485401
}}
486402
/>
487-
<List>
403+
<Command.List className="max-h-[420px] overflow-auto">
488404
{groupsWithItems.map((group) => (
489-
<Group key={group.name} heading={group.name}>
405+
<Command.Group
406+
key={group.name}
407+
heading={group.name}
408+
className="[&[cmdk-group]]:py-2 [&[cmdk-group]]:px-1.5 [&[cmdk-group-heading]]:py-1 [&[cmdk-group-heading]]:px-2.5 [&[cmdk-group-heading]]:text-[#9a9a9a] [&[cmdk-group-heading]]:text-[11px] [&[cmdk-group-heading]]:uppercase [&[cmdk-group-heading]]:tracking-[0.08em]"
409+
>
490410
{group.items.map((item) => (
491-
<Item
411+
<Command.Item
492412
key={item.id}
413+
className="grid grid-cols-[1fr_auto] items-center gap-2 py-2 px-3 text-[13px] cursor-pointer rounded-md my-0.5 mx-1 hover:bg-[#2a2a2a] aria-selected:bg-[#2f2f2f]"
493414
onSelect={() => {
494415
if ("prompt" in item && item.prompt) {
495416
addRecent(item.id);
@@ -514,20 +435,20 @@ export const CommandPalette: React.FC<CommandPaletteProps> = ({ getSlashContext
514435
{"subtitle" in item && item.subtitle && (
515436
<>
516437
<br />
517-
<Subtitle>{item.subtitle}</Subtitle>
438+
<span className="text-[#9a9a9a] text-xs">{item.subtitle}</span>
518439
</>
519440
)}
520441
</div>
521442
{"shortcutHint" in item && item.shortcutHint && (
522-
<ShortcutHint>{item.shortcutHint}</ShortcutHint>
443+
<span className="text-[#9a9a9a] text-[11px] font-monospace">{item.shortcutHint}</span>
523444
)}
524-
</Item>
445+
</Command.Item>
525446
))}
526-
</Group>
447+
</Command.Group>
527448
))}
528-
{!hasAnyItems && <Empty>{emptyText ?? "No results"}</Empty>}
529-
</List>
530-
</PaletteContainer>
531-
</Overlay>
449+
{!hasAnyItems && <div className="p-4 text-[#7a7a7a] text-[13px]">{emptyText ?? "No results"}</div>}
450+
</Command.List>
451+
</Command>
452+
</div>
532453
);
533454
};

0 commit comments

Comments
 (0)