Skip to content

Commit 5be0a9c

Browse files
committed
Responsiveness improvements
1 parent e77f62c commit 5be0a9c

6 files changed

Lines changed: 78 additions & 64 deletions

File tree

docs/app/(home)/page.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,19 @@ function DemoGallery() {
7474
return (
7575
<div className="mx-auto max-w-screen-2xl px-4">
7676
<div
77-
className="mx-auto mb-6 flex max-w-6xl flex-wrap justify-center gap-2"
77+
className="scrollbar-none mx-auto mb-6 flex max-w-6xl gap-2 overflow-x-auto px-4 pb-2 sm:flex-wrap sm:justify-center sm:overflow-visible sm:px-0 sm:pb-0"
7878
role="tablist"
7979
aria-label="Demo gallery"
80+
tabIndex={0}
8081
>
8182
{demos.map((demo) => (
8283
<button
8384
key={demo.id}
8485
role="tab"
8586
aria-selected={active === demo.id}
8687
aria-controls={`demo-panel-${demo.id}`}
87-
onMouseEnter={() => setActive(demo.id)}
8888
onClick={() => setActive(demo.id)}
89-
className={`shrink-0 rounded-lg border px-4 py-3 text-left transition-colors ${
89+
className={`shrink-0 cursor-pointer rounded-lg border px-4 py-3 text-left transition-colors ${
9090
active === demo.id
9191
? "border-fd-primary bg-fd-primary/10 text-fd-foreground"
9292
: "border-fd-border bg-fd-card text-fd-muted-foreground hover:border-fd-primary/50 hover:text-fd-foreground"
@@ -97,16 +97,16 @@ function DemoGallery() {
9797
</button>
9898
))}
9999
</div>
100-
<div className="relative overflow-hidden rounded-xl border border-fd-border shadow-lg">
100+
<div className="relative h-[500px] overflow-hidden rounded-xl border border-fd-border shadow-lg sm:h-[700px] lg:h-[950px]">
101101
{demos.map((demo) => (
102102
<div
103103
key={demo.id}
104104
id={`demo-panel-${demo.id}`}
105105
role="tabpanel"
106106
aria-label={demo.title}
107-
className={active === demo.id ? "" : "invisible absolute inset-0"}
107+
className={active === demo.id ? "h-full" : "invisible absolute inset-0"}
108108
>
109-
<StoryEmbed storyId={demo.storyId} height={950} />
109+
<StoryEmbed storyId={demo.storyId} height="100%" />
110110
</div>
111111
))}
112112
</div>

docs/components/quick-start-selector.tsx

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Check, Copy, Download, X } from "lucide-react";
55

66
type Method = "binary" | "docker" | "cargo";
77
type OS = "linux-x86_64" | "linux-arm64" | "macos-arm64" | "windows";
8-
type Profile = "full" | "standard" | "minimal" | "tiny";
8+
type Profile = "full" | "headless" | "standard" | "minimal" | "tiny";
99
type Libc = "gnu" | "musl";
1010

1111
const osLabels: Record<OS, string> = {
@@ -20,6 +20,14 @@ const libcLabels: Record<Libc, string> = {
2020
musl: "musl",
2121
};
2222

23+
const profileLabels: Record<Profile, string> = {
24+
full: "Full",
25+
headless: "Headless",
26+
standard: "Standard",
27+
minimal: "Minimal",
28+
tiny: "Tiny",
29+
};
30+
2331
function getTarget(os: OS, libc: Libc): string {
2432
switch (os) {
2533
case "linux-x86_64":
@@ -35,38 +43,42 @@ function getTarget(os: OS, libc: Libc): string {
3543

3644
const profileSummaries: Record<Profile, string> = {
3745
full: "Everything",
46+
headless: "Full features, no embedded assets (serve frontend separately)",
3847
standard: "Production deployment",
3948
minimal: "Development and embedded use",
4049
tiny: "Stateless proxy",
4150
};
4251

52+
const allProfiles: Profile[] = ["full", "headless", "standard", "minimal", "tiny"];
53+
const embeddedAssetProfiles: Profile[] = ["minimal", "standard", "full"];
54+
4355
const featureMatrix: { name: string; profiles: Profile[] }[] = [
44-
{ name: "OpenAI", profiles: ["tiny", "minimal", "standard", "full"] },
45-
{ name: "Anthropic", profiles: ["minimal", "standard", "full"] },
46-
{ name: "AWS Bedrock", profiles: ["minimal", "standard", "full"] },
47-
{ name: "Google Vertex AI", profiles: ["minimal", "standard", "full"] },
48-
{ name: "Azure OpenAI", profiles: ["minimal", "standard", "full"] },
49-
{ name: "SQLite", profiles: ["minimal", "standard", "full"] },
50-
{ name: "Embedded UI", profiles: ["minimal", "standard", "full"] },
51-
{ name: "Model catalog", profiles: ["minimal", "standard", "full"] },
52-
{ name: "Setup wizard", profiles: ["minimal", "standard", "full"] },
53-
{ name: "PostgreSQL", profiles: ["standard", "full"] },
54-
{ name: "Redis caching", profiles: ["standard", "full"] },
55-
{ name: "SSO (OIDC / OAuth)", profiles: ["standard", "full"] },
56-
{ name: "CEL RBAC", profiles: ["standard", "full"] },
57-
{ name: "S3 storage", profiles: ["standard", "full"] },
58-
{ name: "Secrets managers", profiles: ["standard", "full"] },
59-
{ name: "OTLP & Prometheus", profiles: ["standard", "full"] },
60-
{ name: "OpenAPI docs", profiles: ["standard", "full"] },
61-
{ name: "Embedded docs", profiles: ["standard", "full"] },
62-
{ name: "Doc extraction", profiles: ["standard", "full"] },
63-
{ name: "Cost forecasting", profiles: ["standard", "full"] },
64-
{ name: "CSV export", profiles: ["standard", "full"] },
65-
{ name: "Response validation", profiles: ["standard", "full"] },
66-
{ name: "JSON schema", profiles: ["standard", "full"] },
67-
{ name: "SAML SSO", profiles: ["full"] },
68-
{ name: "Kreuzberg OCR", profiles: ["full"] },
69-
{ name: "ClamAV scanning", profiles: ["full"] },
56+
{ name: "OpenAI", profiles: allProfiles },
57+
{ name: "Anthropic", profiles: ["minimal", "standard", "headless", "full"] },
58+
{ name: "AWS Bedrock", profiles: ["minimal", "standard", "headless", "full"] },
59+
{ name: "Google Vertex AI", profiles: ["minimal", "standard", "headless", "full"] },
60+
{ name: "Azure OpenAI", profiles: ["minimal", "standard", "headless", "full"] },
61+
{ name: "SQLite", profiles: ["minimal", "standard", "headless", "full"] },
62+
{ name: "Embedded UI", profiles: embeddedAssetProfiles },
63+
{ name: "Model catalog", profiles: embeddedAssetProfiles },
64+
{ name: "Setup wizard", profiles: embeddedAssetProfiles },
65+
{ name: "PostgreSQL", profiles: ["standard", "headless", "full"] },
66+
{ name: "Redis caching", profiles: ["standard", "headless", "full"] },
67+
{ name: "SSO (OIDC / OAuth)", profiles: ["standard", "headless", "full"] },
68+
{ name: "CEL RBAC", profiles: ["standard", "headless", "full"] },
69+
{ name: "S3 storage", profiles: ["standard", "headless", "full"] },
70+
{ name: "Secrets managers", profiles: ["standard", "headless", "full"] },
71+
{ name: "OTLP & Prometheus", profiles: ["standard", "headless", "full"] },
72+
{ name: "OpenAPI docs", profiles: ["standard", "headless", "full"] },
73+
{ name: "Embedded docs", profiles: embeddedAssetProfiles },
74+
{ name: "Doc extraction", profiles: ["standard", "headless", "full"] },
75+
{ name: "Cost forecasting", profiles: ["standard", "headless", "full"] },
76+
{ name: "CSV export", profiles: ["standard", "headless", "full"] },
77+
{ name: "Response validation", profiles: ["standard", "headless", "full"] },
78+
{ name: "JSON schema", profiles: ["standard", "headless", "full"] },
79+
{ name: "SAML SSO", profiles: ["headless", "full"] },
80+
{ name: "Kreuzberg OCR", profiles: ["headless", "full"] },
81+
{ name: "ClamAV scanning", profiles: ["headless", "full"] },
7082
];
7183

7284
function getInstallCommand(method: Method, os: OS, profile: Profile, libc: Libc): string {
@@ -135,7 +147,7 @@ function ToggleGroup<T extends string>({
135147
key={opt}
136148
onClick={() => onChange(opt)}
137149
disabled={isDisabled}
138-
className={`rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${
150+
className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors sm:px-3 sm:py-1.5 sm:text-sm ${
139151
isDisabled
140152
? "cursor-not-allowed bg-fd-muted text-fd-muted-foreground/40"
141153
: value === opt
@@ -152,9 +164,10 @@ function ToggleGroup<T extends string>({
152164
}
153165

154166
function getDisabledProfiles(os: OS, libc: Libc): Set<Profile> | undefined {
155-
if (os === "windows") return new Set(["full", "standard"]);
156-
if (os === "linux-arm64") return new Set(["full"]);
157-
if (os.startsWith("linux-") && libc === "musl") return new Set(["full"]);
167+
// headless and full only built for linux-x86_64-gnu and macos-arm64
168+
if (os === "windows") return new Set(["full", "headless"]);
169+
if (os === "linux-arm64") return new Set(["full", "headless"]);
170+
if (os.startsWith("linux-") && libc === "musl") return new Set(["full", "headless"]);
158171
return undefined;
159172
}
160173

@@ -184,7 +197,7 @@ export function QuickStartSelector() {
184197

185198
const handleLibcChange = (newLibc: Libc) => {
186199
setLibc(newLibc);
187-
if (newLibc === "musl" && profile === "full") {
200+
if (newLibc === "musl" && (profile === "full" || profile === "headless")) {
188201
setProfile("standard");
189202
}
190203
};
@@ -193,27 +206,18 @@ export function QuickStartSelector() {
193206
const downloadUrl = method === "binary" ? getDownloadUrl(os, profile, libc) : null;
194207

195208
const handleCopy = async () => {
196-
if (navigator.clipboard) {
197-
await navigator.clipboard.writeText(command);
198-
} else {
199-
const textarea = document.createElement("textarea");
200-
textarea.value = command;
201-
textarea.style.position = "fixed";
202-
textarea.style.opacity = "0";
203-
document.body.appendChild(textarea);
204-
textarea.select();
205-
document.execCommand("copy");
206-
document.body.removeChild(textarea);
207-
}
209+
await navigator.clipboard.writeText(command);
208210
setCopied(true);
209211
setTimeout(() => setCopied(false), 2000);
210212
};
211213

212214
return (
213215
<div className="not-prose overflow-hidden rounded-lg border border-fd-border bg-fd-card">
214216
<div className="space-y-3 border-b border-fd-border bg-fd-muted/50 p-4">
215-
<div className="flex flex-wrap items-center gap-3">
216-
<span className="w-16 shrink-0 text-sm font-medium text-fd-muted-foreground">Method</span>
217+
<div className="flex flex-col gap-1.5 sm:flex-row sm:items-center sm:gap-3">
218+
<span className="text-sm font-medium text-fd-muted-foreground sm:w-16 sm:shrink-0">
219+
Method
220+
</span>
217221
<ToggleGroup
218222
options={["binary", "docker", "cargo"] as Method[]}
219223
value={method}
@@ -223,8 +227,10 @@ export function QuickStartSelector() {
223227
</div>
224228
{method === "binary" && (
225229
<>
226-
<div className="flex flex-wrap items-center gap-3">
227-
<span className="w-16 shrink-0 text-sm font-medium text-fd-muted-foreground">OS</span>
230+
<div className="flex flex-col gap-1.5 sm:flex-row sm:items-center sm:gap-3">
231+
<span className="text-sm font-medium text-fd-muted-foreground sm:w-16 sm:shrink-0">
232+
OS
233+
</span>
228234
<ToggleGroup
229235
options={["linux-x86_64", "linux-arm64", "macos-arm64", "windows"] as OS[]}
230236
value={os}
@@ -233,8 +239,8 @@ export function QuickStartSelector() {
233239
/>
234240
</div>
235241
{isLinux && (
236-
<div className="flex flex-wrap items-center gap-3">
237-
<span className="w-16 shrink-0 text-sm font-medium text-fd-muted-foreground">
242+
<div className="flex flex-col gap-1.5 sm:flex-row sm:items-center sm:gap-3">
243+
<span className="text-sm font-medium text-fd-muted-foreground sm:w-16 sm:shrink-0">
238244
Libc
239245
</span>
240246
<ToggleGroup
@@ -246,14 +252,15 @@ export function QuickStartSelector() {
246252
/>
247253
</div>
248254
)}
249-
<div className="flex flex-wrap items-center gap-3">
250-
<span className="w-16 shrink-0 text-sm font-medium text-fd-muted-foreground">
255+
<div className="flex flex-col gap-1.5 sm:flex-row sm:items-center sm:gap-3">
256+
<span className="text-sm font-medium text-fd-muted-foreground sm:w-16 sm:shrink-0">
251257
Features
252258
</span>
253259
<ToggleGroup
254-
options={["full", "standard", "minimal", "tiny"] as Profile[]}
260+
options={allProfiles}
255261
value={profile}
256262
onChange={setProfile}
263+
labels={profileLabels}
257264
disabled={disabledProfiles}
258265
/>
259266
</div>

ui/src/components/Markdown/Markdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export function Markdown({ content, className }: MarkdownProps) {
4545
ref={containerRef}
4646
className={cn(
4747
"markdown-content prose prose-sm dark:prose-invert",
48-
"max-w-[calc(100vw-8rem)] sm:max-w-[500px] md:max-w-[600px] lg:max-w-[700px]",
48+
"max-w-none",
4949
"[&_pre]:overflow-x-auto",
5050
className
5151
)}

ui/src/components/ModelSelector/ModelSelector.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,15 @@ export function ModelSelector({
309309

310310
return (
311311
<div className="flex items-center gap-2 min-w-0">
312-
{/* Horizontally scrollable chip container */}
313-
<div className="flex flex-wrap items-center gap-2 min-w-0">
312+
{/* Model count badge - mobile only, shown when multiple models selected */}
313+
{selectedInstances.length > 1 && (
314+
<span className="sm:hidden shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground tabular-nums">
315+
{selectedInstances.length}
316+
</span>
317+
)}
318+
319+
{/* Chip container - horizontal scroll on mobile, wraps on desktop */}
320+
<div className="flex items-center gap-2 min-w-0 overflow-x-auto sm:overflow-x-visible sm:flex-wrap scrollbar-none">
314321
<TooltipProvider>
315322
<DndContext
316323
sensors={sensors}

ui/src/components/MultiModelResponse/MultiModelResponse.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ const ModelResponseCard = memo(function ModelResponseCard({
626626
"hover:shadow-md",
627627
"animate-slide-up-bounce",
628628
isSelectedBest && "ring-2 ring-success ring-offset-2 ring-offset-background",
629-
useHorizontalLayout ? "min-w-[500px] w-[500px] shrink-0" : "w-full"
629+
useHorizontalLayout ? "grow shrink-0 basis-[min(500px,85vw)]" : "w-full"
630630
)}
631631
style={{ animationDelay: `${index * 100}ms` }}
632632
>

ui/src/components/StreamingMarkdown/StreamingMarkdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ function StreamingMarkdownComponent({ content, isStreaming, className }: Streami
7575
<div
7676
className={cn(
7777
"markdown-content prose prose-sm dark:prose-invert",
78-
"max-w-[calc(100vw-8rem)] sm:max-w-[500px] md:max-w-[600px] lg:max-w-[700px]",
78+
"max-w-none",
7979
"[&_pre]:overflow-x-auto",
8080
className
8181
)}

0 commit comments

Comments
 (0)