Skip to content

fix: improve UI scaling when sidebar width is reduced (#2678) #5917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion webview-ui/src/components/chat/ChatTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
placeholder={displayName}
options={getApiConfigOptions}
onChange={handleApiConfigChange}
triggerClassName="w-full text-ellipsis overflow-hidden"
triggerClassName="w-full text-ellipsis overflow-hidden min-w-0"
itemClassName="group"
renderItem={renderApiConfigItem}
/>
Expand Down
25 changes: 6 additions & 19 deletions webview-ui/src/components/modes/ModesView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -663,29 +663,16 @@ const ModesView = ({ onDone }: ModesViewProps) => {
setOpen(false)
}}
data-testid={`mode-option-${modeConfig.slug}`}>
<div className="flex items-center justify-between w-full">
<div className="flex items-center justify-between w-full min-w-0">
<span
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
flex: 2,
minWidth: 0,
}}>
className="truncate flex-1 min-w-0 mr-2"
title={modeConfig.name}>
{modeConfig.name}
</span>
<span
className="text-foreground"
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
direction: "rtl",
textAlign: "right",
flex: 1,
minWidth: 0,
marginLeft: "0.5em",
}}>
className="text-foreground text-xs opacity-70 truncate flex-shrink-0 max-w-[40%]"
style={{ textAlign: "right" }}
title={modeConfig.slug}>
{modeConfig.slug}
</span>
</div>
Expand Down
79 changes: 44 additions & 35 deletions webview-ui/src/components/settings/ApiConfigManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ const ApiConfigManager = ({
</div>
) : (
<>
<div className="flex items-center gap-1">
<div className="flex items-center gap-1 min-w-0">
<SearchableSelect
value={currentApiConfigName}
onValueChange={handleSelectConfig}
Expand All @@ -247,42 +247,51 @@ const ApiConfigManager = ({
placeholder={t("settings:common.select")}
searchPlaceholder={t("settings:providers.searchPlaceholder")}
emptyMessage={t("settings:providers.noMatchFound")}
className="grow"
className="grow min-w-0"
data-testid="select-component"
/>
<StandardTooltip content={t("settings:providers.addProfile")}>
<Button variant="ghost" size="icon" onClick={handleAdd} data-testid="add-profile-button">
<span className="codicon codicon-add" />
</Button>
</StandardTooltip>
{currentApiConfigName && (
<>
<StandardTooltip content={t("settings:providers.renameProfile")}>
<Button
variant="ghost"
size="icon"
onClick={handleStartRename}
data-testid="rename-profile-button">
<span className="codicon codicon-edit" />
</Button>
</StandardTooltip>
<StandardTooltip
content={
isOnlyProfile
? t("settings:providers.cannotDeleteOnlyProfile")
: t("settings:providers.deleteProfile")
}>
<Button
variant="ghost"
size="icon"
onClick={handleDelete}
data-testid="delete-profile-button"
disabled={isOnlyProfile}>
<span className="codicon codicon-trash" />
</Button>
</StandardTooltip>
</>
)}
<div className="flex items-center gap-0.5 flex-shrink-0 ml-1">
<StandardTooltip content={t("settings:providers.addProfile")}>
<Button
variant="ghost"
size="icon"
onClick={handleAdd}
data-testid="add-profile-button"
className="flex-shrink-0 min-w-[32px]">
<span className="codicon codicon-add" />
</Button>
</StandardTooltip>
{currentApiConfigName && (
<>
<StandardTooltip content={t("settings:providers.renameProfile")}>
<Button
variant="ghost"
size="icon"
onClick={handleStartRename}
data-testid="rename-profile-button"
className="flex-shrink-0 min-w-[32px]">
<span className="codicon codicon-edit" />
</Button>
</StandardTooltip>
<StandardTooltip
content={
isOnlyProfile
? t("settings:providers.cannotDeleteOnlyProfile")
: t("settings:providers.deleteProfile")
}>
<Button
variant="ghost"
size="icon"
onClick={handleDelete}
data-testid="delete-profile-button"
disabled={isOnlyProfile}
className="flex-shrink-0 min-w-[32px]">
<span className="codicon codicon-trash" />
</Button>
</StandardTooltip>
</>
)}
</div>
</div>
<div className="text-vscode-descriptionForeground text-sm mt-1">
{t("settings:providers.description")}
Expand Down
4 changes: 2 additions & 2 deletions webview-ui/src/components/settings/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,8 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t

const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
// If container width is less than 500px, switch to compact mode
setIsCompactMode(entry.contentRect.width < 500)
// If container width is less than 600px, switch to compact mode
setIsCompactMode(entry.contentRect.width < 600)
}
})

Expand Down
154 changes: 154 additions & 0 deletions webview-ui/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,47 @@ vscode-dropdown::part(listbox) {
min-height: 16px;
}

/* Ensure checkbox containers don't squeeze */
.vscrui-checkbox {
flex-shrink: 0;
min-width: fit-content;
}

/* Prevent checkbox label text from wrapping inappropriately */
.vscrui-checkbox label {
display: flex;
align-items: center;
gap: 0.5rem;
min-width: 0;
}

/* Ensure checkbox input maintains size */
.vscrui-checkbox input[type="checkbox"] {
flex-shrink: 0;
min-width: 16px;
min-height: 16px;
}

/* VSCode checkbox specific styles to prevent squeezing */
vscode-checkbox {
flex-shrink: 0;
min-width: fit-content;
display: inline-flex;
align-items: center;
}

/* Ensure VSCode checkbox internals don't squeeze */
vscode-checkbox::part(control) {
flex-shrink: 0;
min-width: 16px;
min-height: 16px;
}

vscode-checkbox::part(label) {
min-width: 0;
margin-left: 0.5rem;
}

/**
* @shadcn/ui Overrides / Hacks
*/
Expand Down Expand Up @@ -479,3 +520,116 @@ input[cmdk-input]:focus {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}

/* Responsive utilities for narrow containers */
@media (max-width: 640px) {
.responsive-text {
font-size: 0.875rem;
}

.responsive-gap {
gap: 0.25rem;
}

.responsive-padding {
padding: 0.5rem;
}
}

/* Container query support for components */
@container (max-width: 600px) {
.container-compact {
flex-direction: column;
gap: 0.5rem;
}

.container-compact .settings-tab {
min-width: auto;
flex: 1;
}
}

/* Improved flex utilities for narrow containers */
.flex-responsive {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}

.flex-responsive > * {
min-width: 0;
flex: 1 1 auto;
}

/* Better text truncation for dropdowns and selectors */
.dropdown-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
max-width: 100%;
}

/* Settings view specific responsive adjustments */
@container (max-width: 400px) {
/* Reduce button sizes in very narrow containers */
.settings-view button[class*="size-icon"] {
width: 2rem;
height: 2rem;
padding: 0.25rem;
}

/* Adjust gap between elements */
.settings-view .flex.gap-1 {
gap: 0.25rem;
}
}

/* Ensure profile selector doesn't overflow */
.profile-selector-container {
min-width: 0;
overflow: hidden;
}

/* Prevent icon buttons from shrinking */
button[class*="codicon"] {
flex-shrink: 0;
}

/* Additional responsive adjustments for very narrow sidebars */
@media (max-width: 350px) {
/* Ensure button groups stay visible */
.flex-shrink-0 {
overflow-x: auto;
overflow-y: hidden;
scrollbar-width: thin;
}

/* Minimum width for button containers */
.flex-shrink-0:has(button) {
min-width: fit-content;
}
}

/* Ensure all settings checkboxes don't squeeze */
.settings-view vscode-checkbox,
[class*="settings"] vscode-checkbox,
[class*="Settings"] vscode-checkbox {
flex-shrink: 0;
min-width: fit-content;
display: inline-flex;
align-items: center;
}

/* Ensure proper text wrapping and overflow handling */
.text-wrap {
word-wrap: break-word;
overflow-wrap: break-word;
}

.text-ellipsis-safe {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}