This commit is contained in:
Frank
2025-10-10 19:39:01 -04:00
parent 48008f91ac
commit f14cd4a3db
4 changed files with 125 additions and 28 deletions

View File

@@ -0,0 +1,66 @@
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
[data-component="modal"][data-slot="overlay"] {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.5);
animation: fadeIn 0.2s ease;
@media (prefers-color-scheme: dark) {
background-color: rgba(0, 0, 0, 0.7);
}
[data-slot="content"] {
background-color: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-md);
padding: var(--space-6);
min-width: 400px;
max-width: 90vw;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
animation: slideUp 0.2s ease;
@media (max-width: 30rem) {
min-width: 300px;
padding: var(--space-4);
}
@media (prefers-color-scheme: dark) {
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
}
[data-slot="title"] {
margin: 0 0 var(--space-4) 0;
font-size: var(--font-size-lg);
font-weight: 600;
color: var(--color-text);
}
}

View File

@@ -0,0 +1,24 @@
import { JSX, Show } from "solid-js"
import "./modal.css"
interface ModalProps {
open: boolean
onClose: () => void
title?: string
children: JSX.Element
}
export function Modal(props: ModalProps) {
return (
<Show when={props.open}>
<div data-component="modal" data-slot="overlay" onClick={props.onClose}>
<div data-slot="content" onClick={(e) => e.stopPropagation()}>
<Show when={props.title}>
<h2 data-slot="title">{props.title}</h2>
</Show>
{props.children}
</div>
</div>
</Show>
)
}

View File

@@ -1,15 +1,15 @@
[data-component="workspace-picker"] {
position: relative;
/* Override blue accent colors with neutral colors */
--color-accent: var(--color-border);
--color-accent-hover: var(--color-border);
--color-accent-active: var(--color-border);
--color-primary: var(--color-border);
--color-primary-hover: var(--color-border);
--color-primary-active: var(--color-border);
--color-primary-alpha-20: transparent;
[data-slot="trigger"] {
/* Override blue accent colors with neutral colors for dropdown trigger */
--color-accent: var(--color-border);
--color-accent-hover: var(--color-border);
--color-accent-active: var(--color-border);
--color-primary: var(--color-border);
--color-primary-hover: var(--color-border);
--color-primary-active: var(--color-border);
--color-primary-alpha-20: transparent;
display: flex;
align-items: center;
justify-content: space-between;
@@ -73,22 +73,19 @@
}
[data-slot="create-form"] {
margin-top: var(--space-4);
padding: var(--space-4);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-sm);
background-color: var(--color-surface);
width: 100%;
}
[data-slot="create-input-group"] {
display: flex;
gap: var(--space-2);
align-items: center;
flex-direction: column;
gap: var(--space-3);
}
@media (max-width: 30rem) {
flex-direction: column;
align-items: stretch;
}
[data-slot="button-group"] {
display: flex;
gap: var(--space-2);
justify-content: flex-end;
}
[data-slot="create-input"] {

View File

@@ -8,6 +8,7 @@ import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.j
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
import { Workspace } from "@opencode-ai/console-core/workspace.js"
import { IconChevron } from "~/component/icon"
import { Modal } from "~/component/modal"
import "./workspace-picker.css"
const getWorkspaces = query(async () => {
@@ -46,6 +47,7 @@ export function WorkspacePicker() {
showDropdown: false,
})
let dropdownRef: HTMLDivElement | undefined
let inputRef: HTMLInputElement | undefined
const currentWorkspace = () => {
const ws = workspaces()?.find((w) => w.id === params.id)
@@ -56,6 +58,12 @@ export function WorkspacePicker() {
setStore({ showForm: true, showDropdown: false })
}
createEffect(() => {
if (store.showForm && inputRef) {
setTimeout(() => inputRef?.focus(), 0)
}
})
const handleSelectWorkspace = (workspaceID: string) => {
if (workspaceID === params.id) {
setStore("showDropdown", false)
@@ -112,26 +120,28 @@ export function WorkspacePicker() {
</Show>
</div>
<Show when={store.showForm}>
<Modal open={store.showForm} onClose={() => setStore("showForm", false)} title="Create New Workspace">
<form data-slot="create-form" action={createWorkspace} method="post">
<div data-slot="create-input-group">
<input
ref={inputRef}
data-slot="create-input"
type="text"
name="workspaceName"
placeholder="Enter workspace name"
required
autofocus
/>
<button type="submit" data-color="primary">
Create
</button>
<button type="button" onClick={() => setStore("showForm", false)}>
Cancel
</button>
<div data-slot="button-group">
<button type="button" data-color="ghost" onClick={() => setStore("showForm", false)}>
Cancel
</button>
<button type="submit" data-color="primary">
Create
</button>
</div>
</div>
</form>
</Show>
</Modal>
</div>
)
}