Files
ThothII/frontend/src/shell/NewSessionDialog.tsx
T
marcopanandClaude Fable 5 4cd1cbc493 style(frontend): look&feel v2 — layered shadows, sharper radii, mono data register
Colors (GSD palette) untouched. New visual vocabulary across the whole GUI:
- warm-tinted layered shadow tokens (--shadow-xs/sm/md) replacing flat rings;
  cards/dialogs framed with hairline border + real elevation
- strict radii scale: xl cards / lg inputs / md controls / 2xl dialogs;
  buttons move from pills to rounded-md
- third type register: --font-mono + tabular-nums on SQL, timers, dates, ids;
  standardized .thot-label micro-label tier
- prose: framed tables with uppercase headers, elevated code blocks
- SqlViewer badges moved from hardcoded Tailwind greens/reds to success/
  destructive token tints; ResultsPanel inline styles replaced with classes
- artifact gate: first option rendered as filled primary action

Verified offline via Playwright against a mock backend replaying a real psd
session (no VPN needed). tsc clean, 115/115 vitest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:04:46 +02:00

95 lines
2.8 KiB
TypeScript

// frontend/src/shell/NewSessionDialog.tsx
import { useState } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "../components/ui/dialog";
import { Button } from "../components/ui/button";
import { createSession } from "../api/sessions";
interface Props {
onCreated: (id: string) => void;
}
export function NewSessionDialog({ onCreated }: Props) {
const [open, setOpen] = useState(false);
const [question, setQuestion] = useState("");
const [error, setError] = useState<string | null>(null);
const [busy, setBusy] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setError(null);
if (!question.trim()) {
setError("The question cannot be empty.");
return;
}
setBusy(true);
try {
const { id } = await createSession({ question: question.trim() });
setOpen(false);
setQuestion("");
onCreated(id);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to create the session.");
} finally {
setBusy(false);
}
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<Button
variant="default"
size="sm"
className="w-full"
onClick={() => setOpen(true)}
>
New session
</Button>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>New session</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
<div>
<label className="mb-1.5 block text-xs font-medium text-muted-foreground" htmlFor="nsd-question">
Question
</label>
<textarea
id="nsd-question"
value={question}
onChange={(e) => setQuestion(e.target.value)}
rows={3}
className="w-full resize-none rounded-lg border border-input bg-card px-3 py-2 text-sm shadow-xs outline-none transition-[border-color,box-shadow] placeholder:text-muted-foreground focus:border-primary/50 focus:ring-3 focus:ring-ring/15"
placeholder="Enter your question…"
/>
</div>
{error && (
<p className="text-xs text-destructive" role="alert">
{error}
</p>
)}
<div className="flex justify-end gap-2 pt-1">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setOpen(false)}
>
Cancel
</Button>
<Button type="submit" size="sm" disabled={busy}>
{busy ? "Creating…" : "Create"}
</Button>
</div>
</form>
</DialogContent>
</Dialog>
);
}