diff options
| author | Adam <[email protected]> | 2025-12-09 15:21:04 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-09 15:21:47 -0600 |
| commit | 1fbd7a7f9a611749768168ea9a30f87d7eda2c5b (patch) | |
| tree | f0ec9c556954d86948ebfea43486df71d0ba3f05 | |
| parent | d7563d16944316a537cf49a6dc7875addaf5dba9 (diff) | |
| download | opencode-1fbd7a7f9a611749768168ea9a30f87d7eda2c5b.tar.gz opencode-1fbd7a7f9a611749768168ea9a30f87d7eda2c5b.zip | |
wip(desktop): progress
| -rw-r--r-- | packages/desktop/src/pages/layout.tsx | 49 | ||||
| -rw-r--r-- | packages/ui/src/components/avatar.css | 5 | ||||
| -rw-r--r-- | packages/ui/src/components/avatar.tsx | 10 |
3 files changed, 39 insertions, 25 deletions
diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index c2755b9dc..c083fbdfe 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -140,8 +140,8 @@ export default function Layout(props: ParentProps) { return <></> } - const ProjectVisual = (props: { directory: string; class?: string }): JSX.Element => { - const name = createMemo(() => getFilename(props.directory)) + const ProjectVisual = (props: { project: Project & { expanded: boolean }; class?: string }): JSX.Element => { + const name = createMemo(() => getFilename(props.project.worktree)) return ( <Switch> <Match when={layout.sidebar.opened()}> @@ -153,7 +153,12 @@ export default function Layout(props: ParentProps) { > <div class="flex items-center gap-3 p-0 text-left min-w-0 grow"> <div class="size-6 shrink-0"> - <Avatar fallback={name()} background="var(--surface-info-base)" class="size-full" /> + <Avatar + fallback={name()} + src={props.project.icon?.url} + background={props.project.icon?.color ?? "var(--surface-info-base)"} + class="size-full" + /> </div> <span class="truncate text-14-medium text-text-strong">{name()}</span> </div> @@ -164,11 +169,16 @@ export default function Layout(props: ParentProps) { variant="ghost" size="large" class="flex items-center justify-center p-0 aspect-square border-none" - data-selected={props.directory === currentDirectory()} - onClick={() => navigateToProject(props.directory)} + data-selected={props.project.worktree === currentDirectory()} + onClick={() => navigateToProject(props.project.worktree)} > <div class="size-6 shrink-0"> - <Avatar fallback={name()} background="var(--surface-info-base)" class="size-full" /> + <Avatar + fallback={name()} + src={props.project.icon?.url} + background={props.project.icon?.color ?? "var(--surface-info-base)"} + class="size-full" + /> </div> </Button> </Match> @@ -194,18 +204,12 @@ export default function Layout(props: ParentProps) { > <Collapsible.Trigger class="group/trigger flex items-center gap-3 p-0 text-left min-w-0 grow border-none"> <div class="size-6 shrink-0"> - <Switch> - <Match when={props.project.icon?.url}> - {(url) => <img src={url()} class="size-full group-hover/session:hidden" />} - </Match> - <Match when={true}> - <Avatar - fallback={name()} - background={props.project.icon?.color ?? "var(--surface-info-base)"} - class="size-full group-hover/session:hidden" - /> - </Match> - </Switch> + <Avatar + fallback={name()} + src={props.project.icon?.url} + background={props.project.icon?.color ?? "var(--surface-info-base)"} + class="size-full group-hover/session:hidden" + /> <Icon name="chevron-right" size="large" @@ -282,7 +286,7 @@ export default function Layout(props: ParentProps) { </Match> <Match when={true}> <Tooltip placement="right" value={props.project.worktree}> - <ProjectVisual directory={props.project.worktree} /> + <ProjectVisual project={props.project} /> </Tooltip> </Match> </Switch> @@ -291,11 +295,12 @@ export default function Layout(props: ParentProps) { } const ProjectDragOverlay = (): JSX.Element => { + const project = createMemo(() => layout.projects.list().find((p) => p.worktree === store.activeDraggable)) return ( - <Show when={store.activeDraggable}> - {(directory) => ( + <Show when={project()}> + {(p) => ( <div class="bg-background-base rounded-md"> - <ProjectVisual directory={directory()} /> + <ProjectVisual project={p()} /> </div> )} </Show> diff --git a/packages/ui/src/components/avatar.css b/packages/ui/src/components/avatar.css index bc87f3bd8..4e42e6f99 100644 --- a/packages/ui/src/components/avatar.css +++ b/packages/ui/src/components/avatar.css @@ -13,6 +13,11 @@ color: oklch(from var(--avatar-bg) calc(l * 0.72) calc(c * 8) h); } +[data-component="avatar"][data-has-image] { + background-color: transparent; + border: none; +} + [data-component="avatar"][data-size="small"] { width: 1.25rem; height: 1.25rem; diff --git a/packages/ui/src/components/avatar.tsx b/packages/ui/src/components/avatar.tsx index 183a15b9b..1ff3008ee 100644 --- a/packages/ui/src/components/avatar.tsx +++ b/packages/ui/src/components/avatar.tsx @@ -2,27 +2,31 @@ import { type ComponentProps, splitProps, Show } from "solid-js" export interface AvatarProps extends ComponentProps<"div"> { fallback: string + src?: string background?: string size?: "small" | "normal" | "large" } export function Avatar(props: AvatarProps) { - const [split, rest] = splitProps(props, ["fallback", "background", "size", "class", "classList", "style"]) + const [split, rest] = splitProps(props, ["fallback", "src", "background", "size", "class", "classList", "style"]) return ( <div {...rest} data-component="avatar" data-size={split.size || "normal"} + data-has-image={split.src ? "" : undefined} classList={{ ...(split.classList ?? {}), [split.class ?? ""]: !!split.class, }} style={{ ...(typeof split.style === "object" ? split.style : {}), - ...(split.background ? { "--avatar-bg": split.background } : {}), + ...(!split.src && split.background ? { "--avatar-bg": split.background } : {}), }} > - <Show when={split.fallback}>{split.fallback[0]}</Show> + <Show when={split.src} fallback={split.fallback?.[0]}> + {(src) => <img src={src()} draggable={false} class="size-full object-cover" />} + </Show> </div> ) } |
