summaryrefslogtreecommitdiffhomepage
path: root/packages/ui
diff options
context:
space:
mode:
authorRonan Kearns <[email protected]>2026-01-21 05:44:17 -0500
committerGitHub <[email protected]>2026-01-21 04:44:17 -0600
commit996eeb1f6848b393d887791557e0d8cbe56255ec (patch)
tree8f061d2f333f2334b5cdabc3e9a98f2abbdd3fc1 /packages/ui
parent2e5fe6d5c88907aefe3dc19c3e95f761ba0efdea (diff)
downloadopencode-996eeb1f6848b393d887791557e0d8cbe56255ec.tar.gz
opencode-996eeb1f6848b393d887791557e0d8cbe56255ec.zip
feat(app): add manage models icon to selector (per Figma request) (#9722)
Diffstat (limited to 'packages/ui')
-rw-r--r--packages/ui/src/components/list.css38
-rw-r--r--packages/ui/src/components/list.tsx47
2 files changed, 61 insertions, 24 deletions
diff --git a/packages/ui/src/components/list.css b/packages/ui/src/components/list.css
index ee9be422c..95641bb20 100644
--- a/packages/ui/src/components/list.css
+++ b/packages/ui/src/components/list.css
@@ -23,14 +23,46 @@
overflow: hidden;
padding: 0 12px;
- [data-slot="list-search"] {
+ [data-slot="list-search-wrapper"] {
display: flex;
flex-shrink: 0;
- padding: 8px;
align-items: center;
- gap: 12px;
+ gap: 8px;
align-self: stretch;
margin-bottom: 4px;
+ padding-right: 4px;
+
+ > [data-component="icon-button"] {
+ width: 24px;
+ height: 24px;
+ flex-shrink: 0;
+ background-color: transparent;
+ opacity: 0.5;
+ transition: opacity 0.15s ease;
+
+ &:hover:not(:disabled),
+ &:focus:not(:disabled),
+ &:active:not(:disabled) {
+ background-color: transparent;
+ opacity: 0.7;
+ }
+
+ &:hover:not(:disabled) [data-slot="icon-svg"] {
+ color: var(--icon-hover);
+ }
+
+ &:active:not(:disabled) [data-slot="icon-svg"] {
+ color: var(--icon-active);
+ }
+ }
+ }
+
+ [data-slot="list-search"] {
+ display: flex;
+ flex: 1;
+ padding: 8px;
+ align-items: center;
+ gap: 12px;
border-radius: var(--radius-md);
background: var(--surface-base);
diff --git a/packages/ui/src/components/list.tsx b/packages/ui/src/components/list.tsx
index 066363502..fc9fa5405 100644
--- a/packages/ui/src/components/list.tsx
+++ b/packages/ui/src/components/list.tsx
@@ -11,6 +11,7 @@ export interface ListSearchProps {
autofocus?: boolean
hideIcon?: boolean
class?: string
+ action?: JSX.Element
}
export interface ListProps<T> extends FilteredListProps<T> {
@@ -60,6 +61,7 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
const { filter, grouped, flat, active, setActive, onKeyDown, onInput } = useFilteredList<T>(props)
const searchProps = () => (typeof props.search === "object" ? props.search : {})
+ const searchAction = () => searchProps().action
const moved = (event: MouseEvent) => event.movementX !== 0 || event.movementY !== 0
@@ -198,29 +200,32 @@ export function List<T>(props: ListProps<T> & { ref?: (ref: ListRef) => void })
return (
<div data-component="list" classList={{ [props.class ?? ""]: !!props.class }}>
<Show when={!!props.search}>
- <div data-slot="list-search" classList={{ [searchProps().class ?? ""]: !!searchProps().class }}>
- <div data-slot="list-search-container">
- <Show when={!searchProps().hideIcon}>
- <Icon name="magnifying-glass" />
+ <div data-slot="list-search-wrapper">
+ <div data-slot="list-search" classList={{ [searchProps().class ?? ""]: !!searchProps().class }}>
+ <div data-slot="list-search-container">
+ <Show when={!searchProps().hideIcon}>
+ <Icon name="magnifying-glass" />
+ </Show>
+ <TextField
+ autofocus={searchProps().autofocus}
+ variant="ghost"
+ data-slot="list-search-input"
+ type="text"
+ value={internalFilter()}
+ onChange={setInternalFilter}
+ onKeyDown={handleKey}
+ placeholder={searchProps().placeholder}
+ spellcheck={false}
+ autocorrect="off"
+ autocomplete="off"
+ autocapitalize="off"
+ />
+ </div>
+ <Show when={internalFilter()}>
+ <IconButton icon="circle-x" variant="ghost" onClick={() => setInternalFilter("")} />
</Show>
- <TextField
- autofocus={searchProps().autofocus}
- variant="ghost"
- data-slot="list-search-input"
- type="text"
- value={internalFilter()}
- onChange={setInternalFilter}
- onKeyDown={handleKey}
- placeholder={searchProps().placeholder}
- spellcheck={false}
- autocorrect="off"
- autocomplete="off"
- autocapitalize="off"
- />
</div>
- <Show when={internalFilter()}>
- <IconButton icon="circle-x" variant="ghost" onClick={() => setInternalFilter("")} />
- </Show>
+ {searchAction()}
</div>
</Show>
<div ref={setScrollRef} data-slot="list-scroll">