Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/static/appkit-ui/styles.gen.css
Original file line number Diff line number Diff line change
Expand Up @@ -3967,6 +3967,11 @@
flex-direction: row;
}
}
.sm\:items-center {
@media (width >= 40rem) {
align-items: center;
}
}
.sm\:justify-end {
@media (width >= 40rem) {
justify-content: flex-end;
Expand All @@ -3977,6 +3982,11 @@
gap: calc(var(--spacing) * 2.5);
}
}
.sm\:gap-6 {
@media (width >= 40rem) {
gap: calc(var(--spacing) * 6);
}
}
.sm\:pr-2\.5 {
@media (width >= 40rem) {
padding-right: calc(var(--spacing) * 2.5);
Expand Down
1 change: 1 addition & 0 deletions packages/appkit-ui/src/react/charts/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ export function buildCartesianOption(
right: "10%",
top: ctx.title ? "15%" : "10%",
bottom: ctx.showLegend && hasMultipleSeries ? "20%" : "15%",
containLabel: true,
},
xAxis: {
type: isScatter ? "value" : isTimeSeries ? "time" : "category",
Expand Down
1 change: 1 addition & 0 deletions packages/appkit-ui/src/react/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export {
type UseChartDataResult,
useChartData,
} from "./use-chart-data";
export { useIsMobile } from "./use-mobile";
export { usePluginClientConfig } from "./use-plugin-config";
export {
type UseServingInvokeOptions,
Expand Down
5 changes: 3 additions & 2 deletions packages/appkit-ui/src/react/table/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ export function DataTable(props: DataTableProps) {
</Table>
</div>
</div>
<div className="flex items-center justify-between py-4">
<div className="flex items-center gap-6">
{/* On mobile, flex-col-reverse places pagination buttons above the info row for easier thumb access */}
<div className="flex flex-col-reverse sm:flex-row items-start sm:items-center justify-between gap-3 py-4">
<div className="flex flex-wrap items-center gap-3 sm:gap-6">
<div className="text-foreground text-sm">
{totalRows > 0
? finalLabels.showing
Expand Down
115 changes: 81 additions & 34 deletions template/client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { createBrowserRouter, RouterProvider, NavLink, Outlet } from 'react-router';
import { useState, useEffect } from 'react';
import {
Button,
Card,
CardContent,
CardHeader,
CardTitle,
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
useIsMobile,
} from '@databricks/appkit-ui/react';
import { Menu } from 'lucide-react';
{{- if .plugins.agents}}
import { AgentChat } from './pages/agents/AgentChat';
{{- end}}
Expand Down Expand Up @@ -37,59 +45,98 @@ const navLinkClass = ({ isActive }: { isActive: boolean }) =>
: 'text-muted-foreground hover:bg-muted hover:text-foreground'
}`;

function Layout() {
const mobileNavLinkClass = ({ isActive }: { isActive: boolean }) =>
`block px-3 py-2 rounded-md text-sm font-medium transition-colors ${
isActive
? 'bg-primary text-primary-foreground'
: 'text-muted-foreground hover:bg-muted hover:text-foreground'
}`;

type NavLinkClassFn = (props: { isActive: boolean }) => string;

function NavLinks({ className, linkClass, onClick }: { className?: string; linkClass: NavLinkClassFn; onClick?: () => void }) {
return (
<div className="min-h-screen bg-background flex flex-col">
<header className="border-b px-6 py-3 flex items-center gap-4">
<h1 className="text-lg font-semibold text-foreground">{{.projectName}}</h1>
<nav className="flex gap-1">
<NavLink to="/" end className={navLinkClass}>
Home
</NavLink>
<nav className={className}>
<NavLink to="/" end className={linkClass} onClick={onClick}>
Home
</NavLink>
{{- if .plugins.agents}}
<NavLink to="/agents" className={navLinkClass}>
Agents
</NavLink>
<NavLink to="/agents" className={linkClass} onClick={onClick}>
Agents
</NavLink>
{{- end}}
{{- if .plugins.analytics}}
<NavLink to="/analytics" className={navLinkClass}>
Analytics
</NavLink>
<NavLink to="/analytics" className={linkClass} onClick={onClick}>
Analytics
</NavLink>
{{- end}}
{{- if .plugins.lakebase}}
<NavLink to="/lakebase" className={navLinkClass}>
Lakebase
</NavLink>
<NavLink to="/lakebase" className={linkClass} onClick={onClick}>
Lakebase
</NavLink>
{{- end}}
{{- if .plugins.genie}}
<NavLink to="/genie" className={navLinkClass}>
Genie
</NavLink>
<NavLink to="/genie" className={linkClass} onClick={onClick}>
Genie
</NavLink>
{{- end}}
{{- if .plugins.files}}
<NavLink to="/files" className={navLinkClass}>
Files
</NavLink>
<NavLink to="/files" className={linkClass} onClick={onClick}>
Files
</NavLink>
{{- end}}
{{- if .plugins.serving}}
<NavLink to="/serving" className={navLinkClass}>
Serving
</NavLink>
<NavLink to="/serving" className={linkClass} onClick={onClick}>
Serving
</NavLink>
{{- end}}
{{- if .plugins.vectorSearch}}
<NavLink to="/vector-search" className={navLinkClass}>
Vector Search
</NavLink>
<NavLink to="/vector-search" className={linkClass} onClick={onClick}>
Vector Search
</NavLink>
{{- end}}
{{- if .plugins.jobs}}
<NavLink to="/jobs" className={navLinkClass}>
Jobs
</NavLink>
<NavLink to="/jobs" className={linkClass} onClick={onClick}>
Jobs
</NavLink>
{{- end}}
</nav>
</nav>
);
}

function Layout() {
const isMobile = useIsMobile();
const [mobileNavOpen, setMobileNavOpen] = useState(false);

// Close mobile nav when viewport crosses to desktop
useEffect(() => {
if (!isMobile) setMobileNavOpen(false);
}, [isMobile]);

return (
<div className="min-h-screen bg-background flex flex-col">
<header className="border-b px-4 md:px-6 py-3 flex items-center gap-4">
<h1 className="text-lg font-semibold text-foreground">{{.projectName}}</h1>
{/* Desktop nav — hidden below md breakpoint */}
<NavLinks className="hidden md:flex gap-1" linkClass={navLinkClass} />
{/* Mobile nav — visible below md breakpoint */}
<div className="ml-auto md:hidden">
<Sheet open={mobileNavOpen} onOpenChange={setMobileNavOpen}>
<Button variant="ghost" size="icon" onClick={() => setMobileNavOpen(true)}>
<Menu className="h-5 w-5" />
<span className="sr-only">Open navigation</span>
</Button>
<SheetContent side="left">
<SheetHeader>
<SheetTitle>Navigation</SheetTitle>
</SheetHeader>
<NavLinks className="flex flex-col gap-1" linkClass={mobileNavLinkClass} onClick={() => setMobileNavOpen(false)} />
</SheetContent>
</Sheet>
</div>
</header>

<main className="flex-1 p-6">
<main className="flex-1 p-4 md:p-6">
<Outlet />
</main>
</div>
Expand Down
2 changes: 1 addition & 1 deletion template/client/src/pages/agents/AgentChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export function AgentChat() {
</p>
</div>

<Card className="h-[600px] flex flex-col">
<Card className="h-[min(600px,70vh)] flex flex-col">
<CardContent
className="flex-1 overflow-y-auto p-4 space-y-3"
ref={scrollRef}
Expand Down
4 changes: 2 additions & 2 deletions template/client/src/pages/files/FilesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export function FilesPage() {
</p>
</div>

<div className="flex items-center justify-between">
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
<div className="flex items-center gap-3">
{volumes.length > 1 && (
<select
Expand Down Expand Up @@ -351,7 +351,7 @@ export function FilesPage() {
</div>
</div>

<div className="flex gap-6">
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
<DirectoryList
className="flex-2 min-w-0"
entries={entries}
Expand Down
2 changes: 1 addition & 1 deletion template/client/src/pages/genie/GeniePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function GeniePage() {
Ask questions about your data using Databricks AI/BI Genie.
</p>
</div>
<div className="h-[600px] border rounded-lg overflow-hidden">
<div className="h-[min(600px,70vh)] border rounded-lg overflow-hidden">
<GenieChat alias="default" />
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions template/client/src/pages/jobs/JobsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export function JobsPage() {
</p>
</div>

<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center gap-3">
<label
htmlFor={inputId}
className="text-sm font-medium text-foreground"
Expand All @@ -166,7 +166,7 @@ export function JobsPage() {
type="text"
value={jobKey}
onChange={(e) => setJobKey(e.target.value)}
className="rounded-md border border-input bg-background px-3 py-1.5 text-sm w-48"
className="rounded-md border border-input bg-background px-3 py-1.5 text-sm w-full sm:w-48"
/>
<Button
onClick={fetchStatus}
Expand Down
2 changes: 1 addition & 1 deletion template/client/src/pages/serving/ServingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function ServingPage() {
</p>
</div>

<div className="border rounded-lg flex flex-col h-[600px]">
<div className="border rounded-lg flex flex-col h-[min(600px,70vh)]">
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((msg) => (
<div
Expand Down
2 changes: 2 additions & 0 deletions tools/generate-app-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const APP_TEMPLATES: AppTemplate[] = [
"analytics.sql-warehouse.id": "placeholder",
"files.files.path": "placeholder",
"genie.genie-space.id": "placeholder",
"genie.genie-space.name": "placeholder",
"lakebase.postgres.branch": "placeholder",
"lakebase.postgres.database": "placeholder",
"serving.serving-endpoint.name": "placeholder",
Expand All @@ -86,6 +87,7 @@ const APP_TEMPLATES: AppTemplate[] = [
features: ["genie"],
set: {
"genie.genie-space.id": "placeholder",
"genie.genie-space.name": "placeholder",
},
description:
"Node.js app with AI/BI Genie for natural language data queries",
Expand Down
Loading