Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Only write entries that are worth mentioning to users.

## Unreleased

- Web: Refine UI details including rounded corners, spacing, and layout adjustments across input group, slash command menu, and session sidebar

## 1.12.0 (2026-02-11)

- Web: Add subagent activity rendering to display subagent steps (thinking, tool calls, text) inside Task tool messages
Expand Down
2 changes: 2 additions & 0 deletions docs/en/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ This page documents the changes in each Kimi Code CLI release.

## Unreleased

- Web: Refine UI details including rounded corners, spacing, and layout adjustments across input group, slash command menu, and session sidebar

## 1.12.0 (2026-02-11)

- Web: Add subagent activity rendering to display subagent steps (thinking, tool calls, text) inside Task tool messages
Expand Down
2 changes: 2 additions & 0 deletions docs/zh/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

## 未发布

- Web:优化 UI 细节,包括输入框、斜杠命令菜单和会话侧边栏的圆角、间距和布局调整

## 1.12.0 (2026-02-11)

- Web:添加子 Agent 活动渲染,在 Task 工具消息中展示子 Agent 步骤(思考、工具调用、文本)
Expand Down
4 changes: 2 additions & 2 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ function App() {

return (
<PromptInputProvider>
<div className="box-border flex h-[100dvh] flex-col bg-background text-foreground px-[calc(0.75rem+var(--safe-left))] pr-[calc(0.75rem+var(--safe-right))] pt-[calc(0.75rem+var(--safe-top))] pb-1 lg:pb-[calc(0.75rem+var(--safe-bottom))] max-lg:h-[100svh] max-lg:overflow-hidden">
<div className="box-border flex h-dvh flex-col bg-background text-foreground px-(--safe-left) pr-(--safe-right) pt-(--safe-top) pb-1 lg:pb-(--safe-bottom) max-lg:h-svh max-lg:overflow-hidden">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Removal of base padding in root container causes zero padding on standard (non-notched) devices

The root container's padding was changed from px-[calc(0.75rem+var(--safe-left))] to px-(--safe-left), and similarly for pr, pt, and lg:pb. Since --safe-left (and the other safe-area variables) default to 0px on standard devices without notches (web/src/index.css:82-85), the app container now has zero padding on all standard desktop and laptop screens.

Root Cause and Impact

The CSS variables are defined in web/src/index.css:82-85 as:

--safe-top: env(safe-area-inset-top, 0px);
--safe-right: env(safe-area-inset-right, 0px);
--safe-bottom: env(safe-area-inset-bottom, 0px);
--safe-left: env(safe-area-inset-left, 0px);

On the vast majority of desktop browsers and non-notched mobile devices, env(safe-area-inset-*, 0px) resolves to 0px.

Old behavior: px-[calc(0.75rem+var(--safe-left))] → padding = 0.75rem + 0px = 0.75rem on standard devices. The 0.75rem provided a consistent base gutter between viewport edges and app content.

New behavior: px-(--safe-left) → padding = var(--safe-left) = 0px on standard devices. The app content (sidebar border, chat panel) is now flush against the browser viewport edges with no gap. The same applies to pr-(--safe-right) (right padding), pt-(--safe-top) (top padding), and lg:pb-(--safe-bottom) (bottom padding on large screens).

Impact: Visual layout regression on all standard (non-notched) devices — the UI loses its outer margins and sits directly against the viewport edges.

Suggested change
<div className="box-border flex h-dvh flex-col bg-background text-foreground px-(--safe-left) pr-(--safe-right) pt-(--safe-top) pb-1 lg:pb-(--safe-bottom) max-lg:h-svh max-lg:overflow-hidden">
<div className="box-border flex h-dvh flex-col bg-background text-foreground px-[calc(0.75rem+var(--safe-left))] pr-[calc(0.75rem+var(--safe-right))] pt-[calc(0.75rem+var(--safe-top))] pb-1 lg:pb-[calc(0.75rem+var(--safe-bottom))] max-lg:h-svh max-lg:overflow-hidden">
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

<div className="mx-auto flex h-full min-h-0 w-full flex-1 flex-col gap-2 max-w-none">
{isDesktop ? (
<ResizablePanelGroup
Expand Down Expand Up @@ -447,7 +447,7 @@ function App() {
searchQuery={searchQuery}
onSearchQueryChange={handleSearchQueryChange}
/>
<div className="mt-auto flex items-center justify-between pl-2 pb-2 pr-2">
<div className="mt-auto flex items-center justify-between px-3 pb-3">
<div className="flex items-center gap-2">
<ThemeToggle />
</div>
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/ai-elements/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,7 @@ export const PromptInputSubmit = ({
return (
<InputGroupButton
aria-label="Submit"
className={cn(className)}
className={cn("rounded-full",className)}
size={size}
type="submit"
variant={variant}
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/ui/input-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
data-slot="input-group"
role="group"
className={cn(
"group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-md border shadow-xs transition-[color,box-shadow] outline-none",
"group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-3xl border shadow-xs transition-[color,box-shadow] outline-none",
"h-9 min-w-0 has-[>textarea]:h-auto",

// Variants based on alignment.
Expand Down Expand Up @@ -46,9 +46,9 @@ const inputGroupAddonVariants = cva(
"inline-end":
"order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]",
"block-start":
"order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5",
"order-first w-full justify-start px-2 pt-2 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5",
"block-end":
"order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5",
"order-last w-full justify-start px-2 pb-2 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5",
},
},
defaultVariants: {
Expand Down
2 changes: 1 addition & 1 deletion web/src/features/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export const ChatWorkspace = memo(function ChatWorkspaceComponent({
/>

{currentSession && (
<div className="mt-auto flex-shrink-0 px-0 pb-0 pt-0 sm:px-3 sm:pb-3 ">
<div className="mt-auto shrink-0 px-3 pb-3 ">
<ChatPromptComposer
status={status}
onSubmit={onSubmit}
Expand Down
4 changes: 2 additions & 2 deletions web/src/features/chat/components/chat-prompt-composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ export const ChatPromptComposer = memo(function ChatPromptComposerComponent({
type="button"
onClick={handleToggleExpand}
disabled={!(canSendMessage && currentSession)}
className="absolute top-2 right-2 z-10 p-1 cursor-pointer rounded-md text-muted-foreground hover:text-foreground hover:bg-secondary/50 transition-colors disabled:opacity-50 disabled:pointer-events-none"
className="absolute top-2 right-2 z-10 p-1 cursor-pointer rounded-full text-muted-foreground hover:text-foreground hover:bg-secondary/50 transition-colors disabled:opacity-50 disabled:pointer-events-none size-8 flex items-center justify-center"
aria-label={isExpanded ? "Collapse input" : "Expand input"}
>
{isExpanded ? (
Expand Down Expand Up @@ -292,7 +292,7 @@ export const ChatPromptComposer = memo(function ChatPromptComposerComponent({
</div>
</div>
</PromptInputBody>
<PromptInputFooter className="w-full gap-2 py-1 border-none bg-transparent shadow-none">
<PromptInputFooter className="w-full gap-2 pb-2 border-none bg-transparent shadow-none">
<PromptInputTools className="flex-1 min-w-0 flex-wrap">
<GlobalConfigControls />
</PromptInputTools>
Expand Down
6 changes: 3 additions & 3 deletions web/src/features/chat/global-config-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ export function GlobalConfigControls({
<div className={cn("flex items-center gap-1", className)}>
<Button
variant="ghost"
size="icon"
className="size-9 border-0"
size="icon-sm"
className="border-0 rounded-full"
aria-label="Attach files"
onClick={() => attachments.openFileDialog()}
>
Expand All @@ -215,7 +215,7 @@ export function GlobalConfigControls({
<Button
variant="ghost"
size="sm"
className="h-9 max-w-[160px] justify-start gap-2 border-0"
className="max-w-40 justify-start gap-2 border-0 rounded-full"
aria-label="Change global model"
disabled={isLoading || isUpdating || !config}
>
Expand Down
2 changes: 1 addition & 1 deletion web/src/features/chat/slash-command-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const SlashCommandMenu = ({

return (
<div className="absolute left-0 right-0 bottom-[calc(100%+0.75rem)] z-30">
<div className="rounded-xl border border-border/80 bg-popover/95 p-2 px-1 shadow-xl backdrop-blur supports-backdrop-filter:bg-popover/80">
<div className="rounded-2xl border border-border/80 bg-popover/95 p-2 px-1 shadow-xl backdrop-blur supports-backdrop-filter:bg-popover/80">
{options.length > 0 ? (
<>
<div className="px-3 pb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
Expand Down
22 changes: 11 additions & 11 deletions web/src/features/sessions/sessions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function SessionsListComponent(
) {
const { className, ...rest } = props;
return (
<div ref={ref} className={cn("flex flex-col space-y-0.5 w-full px-2 mt-1", className)} {...rest} />
<div ref={ref} className={cn("flex flex-col gap-1 w-full px-3 pt-px!", className)} {...rest} />
);
}

Expand Down Expand Up @@ -612,7 +612,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({
<>
<aside className="flex h-full min-h-0 flex-col">
<div className="flex min-h-0 flex-1 flex-col gap-2 overflow-hidden">
<div className="flex items-center justify-between px-3 pt-2">
<div className="flex items-center justify-between p-3">
<KimiCliBrand size="sm" showVersion={true} />
{onClose && (
<button
Expand All @@ -627,7 +627,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({
</div>

{/* Sessions */}
<div className="flex items-center justify-between px-3 pt-3">
<div className="flex items-center justify-between px-3">
<h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Sessions</h4>
<div className="flex items-center gap-1">
<button
Expand Down Expand Up @@ -668,7 +668,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({

{/* Multi-select action bar */}
{isMultiSelectMode && (
<div className="mx-2 flex items-center justify-between gap-2 rounded-md bg-secondary/80 px-2 py-1.5">
<div className="mx-3 flex items-center justify-between gap-2 rounded-md bg-secondary/80 pl-2 pr-0.5 py-0.5">
{/* Left: checkbox toggle and count */}
<div className="flex items-center gap-1.5">
<button
Expand Down Expand Up @@ -774,7 +774,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({

{/* Session search and view toggle */}
{!isMultiSelectMode && (
<div className="px-2 flex items-center gap-2">
<div className="px-3 flex items-center gap-2">
<div className="relative flex-1 min-w-0">
<Search className="absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
<input
Expand Down Expand Up @@ -816,7 +816,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({
<div className="flex-1 min-h-0">
{viewMode === "grouped" ? (
<div className="flex h-full flex-col">
<div className="flex-1 overflow-y-auto overflow-x-hidden [-webkit-overflow-scrolling:touch] px-3 pb-4 pr-1">
<div className="flex-1 overflow-y-auto overflow-x-hidden [-webkit-overflow-scrolling:touch] px-3 pb-4">
<ul className="space-y-1">
{sessionGroups.map((group) => (
<li key={group.workDir} className="group/dir">
Expand Down Expand Up @@ -898,7 +898,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({
}
}}
onClick={(e) => e.stopPropagation()}
className="w-full text-sm font-medium text-foreground bg-background border border-input rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-ring"
className="w-full text-sm font-medium text-foreground border-b border-input focus:outline-none"
/>
) : (
<Tooltip delayDuration={500}>
Expand Down Expand Up @@ -1018,13 +1018,13 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({
}
}}
onClick={(e) => e.stopPropagation()}
className="w-full text-sm font-medium text-foreground bg-background border border-input rounded px-2 py-1 focus:outline-none focus:ring-1 focus:ring-ring"
className="w-full text-sm font-medium text-foreground focus:outline-none h-6 border-b border-input"
/>
) : (
<div className="flex items-center gap-2">
<Tooltip delayDuration={500}>
<TooltipTrigger asChild>
<p className="text-sm font-medium text-foreground truncate flex-1">
<p className="text-sm font-medium text-foreground truncate flex-1 leading-6">
{normalizeTitle(session.title)}
</p>
</TooltipTrigger>
Expand Down Expand Up @@ -1074,7 +1074,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({

{/* Archived Sessions Section */}
{(onArchiveSession || onUnarchiveSession) && (
<div className="mx-2 mb-2 shrink-0 rounded-lg border border-border bg-muted/30">
<div className="mx-3 mb-2 shrink-0 rounded-md border border-border bg-muted/30">
<Collapsible open={isArchivedExpanded} onOpenChange={setIsArchivedExpanded}>
<CollapsibleTrigger className="flex w-full items-center gap-2 px-3 py-2 text-xs text-muted-foreground hover:text-foreground rounded-lg hover:bg-muted/50 group">
<ChevronDown className="size-3 transition-transform group-data-[state=closed]:-rotate-90" />
Expand All @@ -1092,7 +1092,7 @@ export const SessionsSidebar = memo(function SessionsSidebarComponent({
) : archivedSessions.length === 0 ? (
<p className="px-3 py-3 text-xs text-muted-foreground">No archived sessions</p>
) : (
<div className="space-y-1 px-1 pb-2 max-h-[50vh] overflow-y-auto">
<div className="space-y-1 px-1 pb-1 max-h-[50vh] overflow-y-auto">
<ul className="space-y-1">
{archivedSessions.map((session) => {
const isActive = session.id === selectedSessionId;
Expand Down
Loading