app: more new designs (#28603)

This commit is contained in:
Brendan Allan 2026-05-21 14:42:13 +08:00 committed by GitHub
parent 6de584f25c
commit b2661c4a03
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 46 additions and 48 deletions

View file

@ -174,25 +174,28 @@ function HomeDesign() {
}
return (
<div class="size-full overflow-y-auto bg-background-base rounded-[10px] shadow-[var(--v2-elevation-raised)] overflow-hidden">
<div class="mx-auto grid w-full max-w-[1080px] gap-8 px-6 pb-16 pt-12 lg:grid-cols-[280px_minmax(0,720px)]">
<HomeProjectColumn
projects={projects()}
selected={selectedProject()?.worktree}
selectProject={selectProject}
chooseProject={() => void chooseProject()}
openSettings={openSettings}
openHelp={() => platform.openLink("https://opencode.ai/desktop-feedback")}
language={language}
/>
<div class="mx-auto grid w-full h-full max-w-[1080px] gap-8 px-6 pb-16 lg:grid-cols-[280px_minmax(0,720px)]">
<HomeProjectColumn
projects={projects()}
selected={selectedProject()?.worktree}
selectProject={selectProject}
chooseProject={() => void chooseProject()}
openSettings={openSettings}
openHelp={() => platform.openLink("https://opencode.ai/desktop-feedback")}
language={language}
/>
<section class="min-w-0" aria-label={language.t("sidebar.project.recentSessions")}>
<HomeSessionSearch
value={state.search}
placeholder={language.t("home.sessions.search.placeholder")}
onInput={(value) => setState("search", value)}
/>
<div class="mt-6 flex flex-col gap-6">
<section
class="min-w-0 flex-1 flex flex-col overflow-y-hidden pt-12"
aria-label={language.t("sidebar.project.recentSessions")}
>
<HomeSessionSearch
value={state.search}
placeholder={language.t("home.sessions.search.placeholder")}
onInput={(value) => setState("search", value)}
/>
<div class="mt-3 overflow-auto flex-1">
<div class="pt-3 flex flex-col gap-6">
<Show when={!sessionLoad.isLoading} fallback={<HomeSessionSkeleton label={language.t("common.loading")} />}>
<Show
when={groups().length > 0}
@ -220,8 +223,8 @@ function HomeDesign() {
</Show>
</Show>
</div>
</section>
</div>
</div>
</section>
</div>
)
}
@ -319,7 +322,7 @@ function HomeProjectAvatar(props: { project: LocalProject }) {
function HomeSessionSearch(props: { value: string; placeholder: string; onInput: (value: string) => void }) {
return (
<label class="ml-4 flex h-9 w-[calc(100%_-_48px)] items-center gap-2 rounded-[6px] bg-v2-background-bg-deep px-3 py-1 text-v2-icon-icon-muted transition-[background-color,box-shadow] duration-[120ms] ease-in-out focus-within:bg-v2-background-bg-base focus-within:shadow-[0_0_0_0.5px_var(--v2-border-border-focus),var(--v2-elevation-raised)]">
<label class="ml-4 flex h-9 w-[calc(100%_-_48px)] sticky top-0 inset-x-0 items-center gap-2 rounded-[6px] bg-v2-background-bg-deep px-3 py-1 text-v2-icon-icon-muted transition-[background-color,box-shadow] duration-[120ms] ease-in-out focus-within:bg-v2-background-bg-base focus-within:shadow-[0_0_0_0.5px_var(--v2-border-border-focus),var(--v2-elevation-raised)]">
<IconV2 name="magnifying-glass" size="small" />
<input
class="min-w-0 flex-1 border-0 bg-transparent text-v2-text-text-base outline-0 [font-weight:440] placeholder:text-v2-text-text-faint"

View file

@ -2366,14 +2366,17 @@ export default function Layout(props: ParentProps) {
<div class="relative bg-v2-background-bg-deep flex-1 min-h-0 min-w-0 flex flex-col select-none [&_input]:select-text [&_textarea]:select-text [&_[contenteditable]]:select-text">
{autoselecting() ?? ""}
<Titlebar update={titlebarUpdate} />
<div class="flex-1 min-h-0 min-w-0 flex">
<main class="size-full overflow-x-hidden flex flex-col items-start contain-strict p-2 pt-0">
<Show when={!autoselecting.loading} fallback={<div class="size-full" />}>
{props.children}
</Show>
</main>
{import.meta.env.DEV && <DebugBar />}
</div>
<main
class="flex-1 min-h-0 min-w-0 overflow-x-hidden flex flex-col items-start contain-strict bg-v2-background-bg-base"
classList={{
"m-2 mt-0 rounded-[10px] shadow-[var(--v2-elevation-raised)] overflow-hidden": !!params.id || !params.dir,
}}
>
<Show when={!autoselecting.loading} fallback={<div class="size-full" />}>
{props.children}
</Show>
</main>
{import.meta.env.DEV && <DebugBar />}
<Toast.Region />
</div>
)

View file

@ -1703,15 +1703,8 @@ export default function Page() {
/>
)
const USE_NEW_LAYOUT = import.meta.env.VITE_OPENCODE_CHANNEL !== "prod"
return (
<div
class="relative bg-background-base size-full overflow-hidden flex flex-col"
classList={{
"p-2 pt-0 bg-v2-background-bg-deep": USE_NEW_LAYOUT,
}}
>
<div class="relative bg-background-base size-full overflow-hidden flex flex-col">
{sessionSync() ?? ""}
<SessionHeader />
<div class="flex-1 min-h-0 flex flex-col md:flex-row">
@ -1746,7 +1739,6 @@ export default function Page() {
"@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger flex-1 md:flex-none": true,
"transition-[width] duration-[240ms] ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[width] motion-reduce:transition-none":
!size.active() && !ui.reviewSnap,
"rounded-[10px] shadow-[var(--v2-elevation-raised)] overflow-hidden": USE_NEW_LAYOUT && !!params.id,
}}
style={{
width: sessionPanelWidth(),

View file

@ -1,4 +1,4 @@
[data-component="avatar"] {
[data-component="avatar-v2"] {
--avatar-bg: var(--v2-background-bg-layer-02);
--avatar-fg: var(--v2-text-text-muted);
--avatar-radius: 9999px;
@ -26,7 +26,7 @@
-webkit-user-select: none;
}
[data-component="avatar"]::before {
[data-component="avatar-v2"]::before {
content: "";
position: absolute;
inset: 0;
@ -34,30 +34,30 @@
pointer-events: none;
}
[data-component="avatar"][data-has-image]::before {
[data-component="avatar-v2"][data-has-image]::before {
display: none;
}
[data-component="avatar"][data-kind="org"] {
[data-component="avatar-v2"][data-kind="org"] {
--avatar-radius: 6px;
}
[data-component="avatar"][data-kind="org"][data-size="normal"],
[data-component="avatar"][data-kind="org"][data-size="small"] {
[data-component="avatar-v2"][data-kind="org"][data-size="normal"],
[data-component="avatar-v2"][data-kind="org"][data-size="small"] {
--avatar-radius: 4px;
}
[data-component="avatar"][data-size="normal"] {
[data-component="avatar-v2"][data-size="normal"] {
width: 20px;
height: 20px;
}
[data-component="avatar"][data-size="small"] {
[data-component="avatar-v2"][data-size="small"] {
width: 16px;
height: 16px;
}
[data-component="avatar"] [data-slot="avatar-image"] {
[data-component="avatar-v2"] [data-slot="avatar-image"] {
position: relative;
z-index: 1;
width: 100%;

View file

@ -37,7 +37,7 @@ export function Avatar(props: AvatarProps) {
return (
<div
{...rest}
data-component="avatar"
data-component="avatar-v2"
data-size={split.size || "large"}
data-kind={split.kind || "user"}
data-has-image={src ? "" : undefined}