diff options
| author | Aaron Iker <[email protected]> | 2025-12-22 12:41:38 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-22 05:41:38 -0600 |
| commit | 5fd873a35a19de2f9e89c420158d5697746d2983 (patch) | |
| tree | 583ef90753cbe5ddba07bc6a23112dc326fcc0e7 /packages/desktop/src/components | |
| parent | a9fbd786b3262a659620298b8071671452b497f1 (diff) | |
| download | opencode-5fd873a35a19de2f9e89c420158d5697746d2983.tar.gz opencode-5fd873a35a19de2f9e89c420158d5697746d2983.zip | |
feat: polish dialog & list styles for the desktop app, add fixed logos from models.dev (#5925)
Diffstat (limited to 'packages/desktop/src/components')
6 files changed, 52 insertions, 64 deletions
diff --git a/packages/desktop/src/components/dialog-connect-provider.tsx b/packages/desktop/src/components/dialog-connect-provider.tsx index 0d6737815..789a5d3b7 100644 --- a/packages/desktop/src/components/dialog-connect-provider.tsx +++ b/packages/desktop/src/components/dialog-connect-provider.tsx @@ -1,24 +1,24 @@ -import { createMemo, Match, onCleanup, onMount, Switch } from "solid-js" -import { createStore, produce } from "solid-js/store" +import type { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2/client" +import { Button } from "@opencode-ai/ui/button" import { useDialog } from "@opencode-ai/ui/context/dialog" -import { useGlobalSync } from "@/context/global-sync" -import { useGlobalSDK } from "@/context/global-sdk" -import { usePlatform } from "@/context/platform" -import { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2/client" import { Dialog } from "@opencode-ai/ui/dialog" -import { List, ListRef } from "@opencode-ai/ui/list" -import { Button } from "@opencode-ai/ui/button" +import { Icon } from "@opencode-ai/ui/icon" import { IconButton } from "@opencode-ai/ui/icon-button" -import { TextField } from "@opencode-ai/ui/text-field" +import type { IconName } from "@opencode-ai/ui/icons/provider" +import { List, type ListRef } from "@opencode-ai/ui/list" +import { ProviderIcon } from "@opencode-ai/ui/provider-icon" import { Spinner } from "@opencode-ai/ui/spinner" -import { Icon } from "@opencode-ai/ui/icon" +import { TextField } from "@opencode-ai/ui/text-field" import { showToast } from "@opencode-ai/ui/toast" -import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { IconName } from "@opencode-ai/ui/icons/provider" import { iife } from "@opencode-ai/util/iife" +import { createMemo, Match, onCleanup, onMount, Switch } from "solid-js" +import { createStore, produce } from "solid-js/store" import { Link } from "@/components/link" -import { DialogSelectProvider } from "./dialog-select-provider" +import { useGlobalSDK } from "@/context/global-sdk" +import { useGlobalSync } from "@/context/global-sync" +import { usePlatform } from "@/context/platform" import { DialogSelectModel } from "./dialog-select-model" +import { DialogSelectProvider } from "./dialog-select-provider" export function DialogConnectProvider(props: { provider: string }) { const dialog = useDialog() @@ -154,7 +154,9 @@ export function DialogConnectProvider(props: { provider: string }) { <div class="text-14-regular text-text-base">Select login method for {provider().name}.</div> <div class=""> <List - ref={(ref) => (listRef = ref)} + ref={(ref) => { + listRef = ref + }} items={methods} key={(m) => m?.label} onSelect={async (method, index) => { @@ -163,7 +165,7 @@ export function DialogConnectProvider(props: { provider: string }) { }} > {(i) => ( - <div class="w-full flex items-center gap-x-4"> + <div class="w-full flex items-center gap-x-2"> <div class="w-4 h-2 rounded-[1px] bg-input-base shadow-xs-border-base flex items-center justify-center"> <div class="w-2.5 h-0.5 bg-icon-strong-base hidden" data-slot="list-item-extra-icon" /> </div> @@ -175,7 +177,7 @@ export function DialogConnectProvider(props: { provider: string }) { </Match> <Match when={store.state === "pending"}> <div class="text-14-regular text-text-base"> - <div class="flex items-center gap-x-4"> + <div class="flex items-center gap-x-2"> <Spinner /> <span>Authorization in progress...</span> </div> @@ -183,7 +185,7 @@ export function DialogConnectProvider(props: { provider: string }) { </Match> <Match when={store.state === "error"}> <div class="text-14-regular text-text-base"> - <div class="flex items-center gap-x-4"> + <div class="flex items-center gap-x-2"> <Icon name="circle-ban-sign" class="text-icon-critical-base" /> <span>Authorization failed: {store.error}</span> </div> diff --git a/packages/desktop/src/components/dialog-manage-models.tsx b/packages/desktop/src/components/dialog-manage-models.tsx index 5765a8e1a..66d125288 100644 --- a/packages/desktop/src/components/dialog-manage-models.tsx +++ b/packages/desktop/src/components/dialog-manage-models.tsx @@ -1,16 +1,15 @@ -import { Component } from "solid-js" -import { useLocal } from "@/context/local" -import { popularProviders } from "@/hooks/use-providers" import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" import { Switch } from "@opencode-ai/ui/switch" +import type { Component } from "solid-js" +import { useLocal } from "@/context/local" +import { popularProviders } from "@/hooks/use-providers" export const DialogManageModels: Component = () => { const local = useLocal() return ( <Dialog title="Manage models" description="Customize which models appear in the model selector."> <List - class="px-2.5" search={{ placeholder: "Search models", autofocus: true }} emptyMessage="No model results" key={(x) => `${x?.provider?.id}:${x?.id}`} @@ -27,16 +26,24 @@ export const DialogManageModels: Component = () => { }} onSelect={(x) => { if (!x) return - const visible = local.model.visible({ modelID: x.id, providerID: x.provider.id }) + const visible = local.model.visible({ + modelID: x.id, + providerID: x.provider.id, + }) local.model.setVisibility({ modelID: x.id, providerID: x.provider.id }, !visible) }} > {(i) => ( - <div class="w-full flex items-center justify-between gap-x-2.5"> + <div class="w-full flex items-center justify-between gap-x-3"> <span>{i.name}</span> <div onClick={(e) => e.stopPropagation()}> <Switch - checked={!!local.model.visible({ modelID: i.id, providerID: i.provider.id })} + checked={ + !!local.model.visible({ + modelID: i.id, + providerID: i.provider.id, + }) + } onChange={(checked) => { local.model.setVisibility({ modelID: i.id, providerID: i.provider.id }, checked) }} diff --git a/packages/desktop/src/components/dialog-select-file.tsx b/packages/desktop/src/components/dialog-select-file.tsx index 61c518719..b27afdc8b 100644 --- a/packages/desktop/src/components/dialog-select-file.tsx +++ b/packages/desktop/src/components/dialog-select-file.tsx @@ -1,12 +1,12 @@ -import { useLocal } from "@/context/local" +import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" -import { List } from "@opencode-ai/ui/list" import { FileIcon } from "@opencode-ai/ui/file-icon" +import { List } from "@opencode-ai/ui/list" import { getDirectory, getFilename } from "@opencode-ai/util/path" -import { useLayout } from "@/context/layout" -import { useDialog } from "@opencode-ai/ui/context/dialog" import { useParams } from "@solidjs/router" import { createMemo } from "solid-js" +import { useLayout } from "@/context/layout" +import { useLocal } from "@/context/local" export function DialogSelectFile() { const layout = useLayout() @@ -18,7 +18,6 @@ export function DialogSelectFile() { return ( <Dialog title="Select file"> <List - class="px-2.5" search={{ placeholder: "Search files", autofocus: true }} emptyMessage="No files found" items={local.file.searchFiles} @@ -32,7 +31,7 @@ export function DialogSelectFile() { > {(i) => ( <div class="w-full flex items-center justify-between rounded-md"> - <div class="flex items-center gap-x-2 grow min-w-0"> + <div class="flex items-center gap-x-3 grow min-w-0"> <FileIcon node={{ path: i, type: "file" }} class="shrink-0 size-4" /> <div class="flex items-center text-14-regular"> <span class="text-text-weak whitespace-nowrap overflow-hidden overflow-ellipsis truncate min-w-0"> diff --git a/packages/desktop/src/components/dialog-select-model-unpaid.tsx b/packages/desktop/src/components/dialog-select-model-unpaid.tsx index 77e493d3c..24ec8092d 100644 --- a/packages/desktop/src/components/dialog-select-model-unpaid.tsx +++ b/packages/desktop/src/components/dialog-select-model-unpaid.tsx @@ -1,15 +1,15 @@ -import { Component, onCleanup, onMount, Show } from "solid-js" -import { useLocal } from "@/context/local" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { popularProviders, useProviders } from "@/hooks/use-providers" import { Button } from "@opencode-ai/ui/button" -import { Tag } from "@opencode-ai/ui/tag" +import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" -import { List, ListRef } from "@opencode-ai/ui/list" +import type { IconName } from "@opencode-ai/ui/icons/provider" +import { List, type ListRef } from "@opencode-ai/ui/list" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { IconName } from "@opencode-ai/ui/icons/provider" -import { DialogSelectProvider } from "./dialog-select-provider" +import { Tag } from "@opencode-ai/ui/tag" +import { type Component, onCleanup, onMount, Show } from "solid-js" +import { useLocal } from "@/context/local" +import { popularProviders, useProviders } from "@/hooks/use-providers" import { DialogConnectProvider } from "./dialog-connect-provider" +import { DialogSelectProvider } from "./dialog-select-provider" export const DialogSelectModelUnpaid: Component = () => { const local = useLocal() @@ -64,7 +64,7 @@ export const DialogSelectModelUnpaid: Component = () => { <div class="px-2 text-14-medium text-text-base">Add more models from popular providers</div> <div class="w-full"> <List - class="w-full" + class="w-full px-0" key={(x) => x?.id} items={providers.popular} activeIcon="plus-small" @@ -79,17 +79,8 @@ export const DialogSelectModelUnpaid: Component = () => { }} > {(i) => ( - <div class="w-full flex items-center gap-x-4"> - <ProviderIcon - data-slot="list-item-extra-icon" - id={i.id as IconName} - // TODO: clean this up after we update icon in models.dev - classList={{ - "text-icon-weak-base": true, - "size-4 mx-0.5": i.id === "opencode", - "size-5": i.id !== "opencode", - }} - /> + <div class="w-full flex items-center gap-x-3"> + <ProviderIcon data-slot="list-item-extra-icon" id={i.id as IconName} /> <span>{i.name}</span> <Show when={i.id === "opencode"}> <Tag>Recommended</Tag> diff --git a/packages/desktop/src/components/dialog-select-model.tsx b/packages/desktop/src/components/dialog-select-model.tsx index 622ab15fb..54783386a 100644 --- a/packages/desktop/src/components/dialog-select-model.tsx +++ b/packages/desktop/src/components/dialog-select-model.tsx @@ -35,7 +35,6 @@ export const DialogSelectModel: Component<{ provider?: string }> = (props) => { } > <List - class="px-2.5" search={{ placeholder: "Search models", autofocus: true }} emptyMessage="No model results" key={(x) => `${x.provider.id}:${x.id}`} @@ -61,7 +60,7 @@ export const DialogSelectModel: Component<{ provider?: string }> = (props) => { }} > {(i) => ( - <div class="w-full flex items-center gap-x-2.5"> + <div class="w-full flex items-center gap-x-3"> <span>{i.name}</span> <Show when={i.provider.id === "opencode" && (!i.cost || i.cost?.input === 0)}> <Tag>Free</Tag> diff --git a/packages/desktop/src/components/dialog-select-provider.tsx b/packages/desktop/src/components/dialog-select-provider.tsx index 52fac7073..5bbde5d41 100644 --- a/packages/desktop/src/components/dialog-select-provider.tsx +++ b/packages/desktop/src/components/dialog-select-provider.tsx @@ -15,7 +15,6 @@ export const DialogSelectProvider: Component = () => { return ( <Dialog title="Connect provider"> <List - class="px-2.5" search={{ placeholder: "Search providers", autofocus: true }} activeIcon="plus-small" key={(x) => x?.id} @@ -38,17 +37,8 @@ export const DialogSelectProvider: Component = () => { }} > {(i) => ( - <div class="px-1.25 w-full flex items-center gap-x-4"> - <ProviderIcon - data-slot="list-item-extra-icon" - id={i.id as IconName} - // TODO: clean this up after we update icon in models.dev - classList={{ - "text-icon-weak-base": true, - "size-4 mx-0.5": i.id === "opencode", - "size-5": i.id !== "opencode", - }} - /> + <div class="px-1.25 w-full flex items-center gap-x-3"> + <ProviderIcon data-slot="list-item-extra-icon" id={i.id as IconName} /> <span>{i.name}</span> <Show when={i.id === "opencode"}> <Tag>Recommended</Tag> |
