Skip to content

Commit c8c16ae

Browse files
committed
🤖 refactor: Convert ModelSelector to Tailwind CSS
- Replace all styled-components with Tailwind utility classes - Use cn() utility for conditional dropdown item highlighting - Maintain RTL text direction for model display overflow - Preserve keyboard navigation and dropdown positioning - ~35% code reduction (317 lines)
1 parent c78db9f commit c8c16ae

File tree

1 file changed

+24
-106
lines changed

1 file changed

+24
-106
lines changed

src/components/ModelSelector.tsx

Lines changed: 24 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -6,99 +6,7 @@ import React, {
66
useImperativeHandle,
77
forwardRef,
88
} from "react";
9-
import styled from "@emotion/styled";
10-
11-
const Container = styled.div`
12-
position: relative;
13-
display: flex;
14-
align-items: center;
15-
gap: 4px;
16-
`;
17-
18-
const ModelDisplay = styled.div<{ clickable?: boolean }>`
19-
font-size: 10px;
20-
color: #808080;
21-
font-family: var(--font-monospace);
22-
line-height: 11px;
23-
cursor: ${(props) => (props.clickable ? "pointer" : "default")};
24-
padding: 2px 4px;
25-
border-radius: 2px;
26-
transition: background 0.2s;
27-
white-space: nowrap;
28-
overflow: hidden;
29-
text-overflow: ellipsis;
30-
max-width: 150px;
31-
direction: rtl; /* Right-to-left to show end of text */
32-
text-align: left; /* Keep visual alignment left */
33-
34-
&:hover {
35-
background: ${(props) => (props.clickable ? "#2a2a2b" : "transparent")};
36-
}
37-
`;
38-
39-
const InputField = styled.input`
40-
font-size: 10px;
41-
color: #d4d4d4;
42-
background: #1e1e1e;
43-
border: 1px solid #3e3e42;
44-
border-radius: 2px;
45-
padding: 2px 4px;
46-
font-family: var(--font-monospace);
47-
line-height: 11px;
48-
width: 200px;
49-
outline: none;
50-
51-
&:focus {
52-
border-color: var(--color-exec-mode);
53-
}
54-
`;
55-
56-
const Dropdown = styled.div`
57-
position: absolute;
58-
bottom: 100%;
59-
left: 0;
60-
margin-bottom: 4px;
61-
background: #252526;
62-
border: 1px solid #3e3e42;
63-
border-radius: 4px;
64-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
65-
z-index: 1000;
66-
min-width: 300px;
67-
max-height: 200px;
68-
overflow-y: auto;
69-
`;
70-
71-
const DropdownItem = styled.div<{ highlighted?: boolean }>`
72-
font-size: 11px;
73-
color: ${(props) => (props.highlighted ? "#ffffff" : "#d4d4d4")};
74-
background: ${(props) => (props.highlighted ? "#2a2a2b" : "transparent")};
75-
font-family: var(--font-monospace);
76-
padding: 6px 10px;
77-
cursor: pointer;
78-
transition: background 0.1s;
79-
80-
&:hover {
81-
background: #2a2a2b;
82-
color: #ffffff;
83-
}
84-
85-
&:first-of-type {
86-
border-top-left-radius: 4px;
87-
border-top-right-radius: 4px;
88-
}
89-
90-
&:last-of-type {
91-
border-bottom-left-radius: 4px;
92-
border-bottom-right-radius: 4px;
93-
}
94-
`;
95-
96-
const ErrorText = styled.div`
97-
font-size: 9px;
98-
color: #f48771;
99-
font-family: var(--font-monospace);
100-
margin-top: 2px;
101-
`;
9+
import { cn } from "@/lib/utils";
10210

10311
interface ModelSelectorProps {
10412
value: string;
@@ -275,41 +183,51 @@ export const ModelSelector = forwardRef<ModelSelectorRef, ModelSelectorProps>(
275183

276184
if (!isEditing) {
277185
return (
278-
<Container ref={containerRef}>
279-
<ModelDisplay clickable onClick={handleClick}>
186+
<div ref={containerRef} className="relative flex items-center gap-1">
187+
<div
188+
className="text-[10px] text-[#808080] font-monospace leading-[11px] cursor-pointer py-0.5 px-1 rounded-sm transition-colors duration-200 whitespace-nowrap overflow-hidden text-ellipsis max-w-[150px] dir-rtl text-left hover:bg-[#2a2a2b]"
189+
onClick={handleClick}
190+
>
280191
{value}
281-
</ModelDisplay>
282-
</Container>
192+
</div>
193+
</div>
283194
);
284195
}
285196

286197
return (
287-
<Container ref={containerRef}>
198+
<div ref={containerRef} className="relative flex items-center gap-1">
288199
<div>
289-
<InputField
200+
<input
290201
ref={inputRef}
291202
value={inputValue}
292203
onChange={handleInputChange}
293204
onKeyDown={handleKeyDown}
294205
placeholder="provider:model-name"
206+
className="text-[10px] text-[#d4d4d4] bg-[#1e1e1e] border border-[#3e3e42] rounded-sm py-0.5 px-1 font-monospace leading-[11px] w-[200px] outline-none focus:border-exec-mode"
295207
/>
296-
{error && <ErrorText>{error}</ErrorText>}
208+
{error && <div className="text-[9px] text-[#f48771] font-monospace mt-0.5">{error}</div>}
297209
</div>
298210
{showDropdown && filteredModels.length > 0 && (
299-
<Dropdown>
211+
<div className="absolute bottom-full left-0 mb-1 bg-[#252526] border border-[#3e3e42] rounded shadow-[0_4px_12px_rgba(0,0,0,0.3)] z-[1000] min-w-[300px] max-h-[200px] overflow-y-auto">
300212
{filteredModels.map((model, index) => (
301-
<DropdownItem
213+
<div
302214
key={model}
303215
ref={(el) => (dropdownItemRefs.current[index] = el)}
304-
highlighted={index === highlightedIndex}
216+
className={cn(
217+
"text-[11px] font-monospace py-1.5 px-2.5 cursor-pointer transition-colors duration-100",
218+
"first:rounded-t last:rounded-b",
219+
index === highlightedIndex
220+
? "text-white bg-[#2a2a2b]"
221+
: "text-[#d4d4d4] bg-transparent hover:bg-[#2a2a2b] hover:text-white"
222+
)}
305223
onClick={() => handleSelectModel(model)}
306224
>
307225
{model}
308-
</DropdownItem>
226+
</div>
309227
))}
310-
</Dropdown>
228+
</div>
311229
)}
312-
</Container>
230+
</div>
313231
);
314232
}
315233
);

0 commit comments

Comments
 (0)