From 0ed60110bd0755c6421ca59ca57479cdf73f0c3f Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Tue, 13 Jan 2026 19:39:35 +0100 Subject: [PATCH 01/18] feat: lint, wording, WIP --- packages/ui/src/components/session-review.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/components/session-review.tsx b/packages/ui/src/components/session-review.tsx index be5181a985f..349dee891ca 100644 --- a/packages/ui/src/components/session-review.tsx +++ b/packages/ui/src/components/session-review.tsx @@ -72,17 +72,17 @@ export const SessionReview = (props: SessionReviewProps) => {
style} label={(style) => (style === "unified" ? "Unified" : "Split")} - onSelect={(style) => style && props.onDiffStyleChange?.(style)} + onSelect={(style) => style && props.onDiffStyleChange?.(style as SessionReviewDiffStyle)} /> {props.actions} From ae7e07dcb4e9dccfb0b77f85f3a5e1566679a990 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Tue, 13 Jan 2026 19:40:26 +0100 Subject: [PATCH 02/18] fix: search clear icon contrast --- packages/ui/src/components/list.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx index 1283b30232f..a92fdb0828c 100644 --- a/packages/ui/src/components/list.tsx +++ b/packages/ui/src/components/list.tsx @@ -165,7 +165,7 @@ export function List(props: ListProps & { ref?: (ref: ListRef) => void }) />
- setInternalFilter("")} /> + setInternalFilter("")} /> From 1d8f764114de5af3fbca2ee90fce500038893406 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Tue, 13 Jan 2026 19:40:56 +0100 Subject: [PATCH 03/18] feat: icon button weak color variant --- packages/ui/src/components/icon-button.css | 35 +++++++++++++++------- packages/ui/src/components/icon-button.tsx | 2 +- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/packages/ui/src/components/icon-button.css b/packages/ui/src/components/icon-button.css index f3f7e1e6450..fa6f860386f 100644 --- a/packages/ui/src/components/icon-button.css +++ b/packages/ui/src/components/icon-button.css @@ -71,7 +71,6 @@ &[data-variant="ghost"] { background-color: transparent; - /* color: var(--icon-base); */ [data-slot="icon-svg"] { color: var(--icon-base); @@ -79,25 +78,41 @@ &:hover:not(:disabled) { background-color: var(--surface-raised-base-hover); + } + &:focus:not(:disabled) { + background-color: var(--surface-focus); + } + &:active:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + &:selected:not(:disabled) { + background-color: var(--surface-raised-base-active); + } + } - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-hover); */ - /* } */ + &[data-variant="weak"] { + opacity: 0.8; + background-color: transparent; + + [data-slot="icon-svg"] { + color: var(--icon-base); + } + + &:hover:not(:disabled) { + opacity: 1; + background-color: var(--surface-raised-base-hover); } &:focus:not(:disabled) { + opacity: 1; background-color: var(--surface-focus); } &:active:not(:disabled) { + opacity: 1; background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-active); */ - /* } */ } &:selected:not(:disabled) { + opacity: 1; background-color: var(--surface-raised-base-active); - /* [data-slot="icon-svg"] { */ - /* color: var(--icon-selected); */ - /* } */ } } diff --git a/packages/ui/src/components/icon-button.tsx b/packages/ui/src/components/icon-button.tsx index f1832ce7ffd..40fdfe3d3af 100644 --- a/packages/ui/src/components/icon-button.tsx +++ b/packages/ui/src/components/icon-button.tsx @@ -6,7 +6,7 @@ export interface IconButtonProps extends ComponentProps { icon: IconProps["name"] size?: "normal" | "large" iconSize?: IconProps["size"] - variant?: "primary" | "secondary" | "ghost" + variant?: "primary" | "secondary" | "ghost" | "weak" } export function IconButton(props: ComponentProps<"button"> & IconButtonProps) { From 2610fec62bb8589bc159491a7c75304bdcf817d4 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Tue, 13 Jan 2026 19:41:29 +0100 Subject: [PATCH 04/18] fix: workspace icon fix, fallback, clean structure --- .../src/components/dialog-edit-project.tsx | 38 +++++----- packages/app/src/components/project-icon.tsx | 73 +++++++++++++++++++ packages/app/src/pages/layout.tsx | 12 +-- 3 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 packages/app/src/components/project-icon.tsx diff --git a/packages/app/src/components/dialog-edit-project.tsx b/packages/app/src/components/dialog-edit-project.tsx index 2f0f7db1f68..8d389cef7c8 100644 --- a/packages/app/src/components/dialog-edit-project.tsx +++ b/packages/app/src/components/dialog-edit-project.tsx @@ -3,15 +3,20 @@ import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" import { TextField } from "@opencode-ai/ui/text-field" import { Icon } from "@opencode-ai/ui/icon" +import { Avatar } from "@opencode-ai/ui/avatar" import { createMemo, createSignal, For, Show } from "solid-js" import { createStore } from "solid-js/store" import { useGlobalSDK } from "@/context/global-sdk" import { type LocalProject, getAvatarColors } from "@/context/layout" -import { getFilename } from "@opencode-ai/util/path" -import { Avatar } from "@opencode-ai/ui/avatar" +import { ProjectIcon, isValidImageFile } from "@/components/project-icon" const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const +function getFilename(input: string) { + const parts = input.split("/") + return parts[parts.length - 1] || input +} + export function DialogEditProject(props: { project: LocalProject }) { const dialog = useDialog() const globalSDK = useGlobalSDK() @@ -29,9 +34,11 @@ export function DialogEditProject(props: { project: LocalProject }) { const [dragOver, setDragOver] = createSignal(false) function handleFileSelect(file: File) { - if (!file.type.startsWith("image/")) return + if (!isValidImageFile(file)) return const reader = new FileReader() - reader.onload = (e) => setStore("iconUrl", e.target?.result as string) + reader.onload = (e) => { + setStore("iconUrl", e.target?.result as string) + } reader.readAsDataURL(file) } @@ -94,7 +101,7 @@ export function DialogEditProject(props: { project: LocalProject }) {
document.getElementById("icon-upload")?.click()} > - - -
- } - > - Project icon - +
From 5a6c23d48449b44721ba52fabbe8b84958117d89 Mon Sep 17 00:00:00 2001 From: Aaron Iker Date: Thu, 15 Jan 2026 22:57:10 +0100 Subject: [PATCH 07/18] feat: rename project-avatar --- .../src/components/dialog-edit-project.tsx | 4 +-- .../{project-icon.tsx => project-avatar.tsx} | 4 +-- packages/app/src/pages/layout.tsx | 35 +++++++++---------- 3 files changed, 20 insertions(+), 23 deletions(-) rename packages/app/src/components/{project-icon.tsx => project-avatar.tsx} (91%) diff --git a/packages/app/src/components/dialog-edit-project.tsx b/packages/app/src/components/dialog-edit-project.tsx index 8d389cef7c8..5fa1f2ceeb7 100644 --- a/packages/app/src/components/dialog-edit-project.tsx +++ b/packages/app/src/components/dialog-edit-project.tsx @@ -8,7 +8,7 @@ import { createMemo, createSignal, For, Show } from "solid-js" import { createStore } from "solid-js/store" import { useGlobalSDK } from "@/context/global-sdk" import { type LocalProject, getAvatarColors } from "@/context/layout" -import { ProjectIcon, isValidImageFile } from "@/components/project-icon" +import { ProjectAvatar, isValidImageFile } from "@/components/project-avatar" const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const @@ -111,7 +111,7 @@ export function DialogEditProject(props: { project: LocalProject }) { onDragLeave={handleDragLeave} onClick={() => document.getElementById("icon-upload")?.click()} > - , "children"> { +export interface ProjectAvatarProps extends Omit, "children"> { name: string iconUrl?: string iconColor?: string @@ -36,7 +36,7 @@ export const isValidImageFile = (file: File): boolean => { return true } -export const ProjectIcon = (props: ProjectIconProps) => { +export const ProjectAvatar = (props: ProjectAvatarProps) => { const [local, rest] = splitProps(props, [ "name", "iconUrl", diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 67eed26d109..3282fa614db 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -53,7 +53,7 @@ import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme" import { DialogSelectProvider } from "@/components/dialog-select-provider" import { DialogSelectServer } from "@/components/dialog-select-server" import { useCommand, type CommandOption } from "@/context/command" -import { ProjectIcon } from "@/components/project-icon" +import { ProjectAvatar } from "@/components/project-avatar" import { ConstrainDragXAxis } from "@/utils/solid-dnd" import { navStart } from "@/utils/perf" import { DialogSelectDirectory } from "@/components/dialog-select-directory" @@ -813,27 +813,24 @@ export default function Layout(props: ParentProps) { const hasError = createMemo(() => notifications().some((n) => n.type === "error")) const name = createMemo(() => props.project.name || getFilename(props.project.worktree)) const mask = "radial-gradient(circle 6px at calc(100% - 3px) 3px, transparent 6px, black 6.5px)" - const opencode = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" return ( -
- 0 && props.notify ? { "-webkit-mask-image": mask, "mask-image": mask } : undefined - } - /> - -