mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-18 21:21:11 +02:00
style(x): side-pane chat sizing, bg-tasks stop chip, Brain contrast
- Chat empty state: smaller type scale in the side-pane copilot, compact prop on connections card - Background tasks: stop button sized to match the Updating pill, wraps under it in narrow panes, aligned with the state toggle - Sidebar: Code above Meetings - Brain: page + graph background matches other tabs, darker light-mode borders for Base rows and Files containers, bolder section labels
This commit is contained in:
parent
834b8b0390
commit
565a5032ec
7 changed files with 47 additions and 29 deletions
|
|
@ -1240,10 +1240,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-view {
|
.graph-view {
|
||||||
background-color: var(--background);
|
background-color: #f8f8f9;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark .graph-view {
|
||||||
|
background-color: #0b0b0d;
|
||||||
|
}
|
||||||
|
|
||||||
.graph-view::before {
|
.graph-view::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -884,7 +884,7 @@ function NoteRow({
|
||||||
|
|
||||||
const row = (
|
const row = (
|
||||||
<tr
|
<tr
|
||||||
className="border-b border-border/50 hover:bg-accent/50 cursor-pointer transition-colors"
|
className="border-b border-black/10 dark:border-border/50 hover:bg-accent/50 cursor-pointer transition-colors"
|
||||||
onClick={() => onSelectNote(note.path)}
|
onClick={() => onSelectNote(note.path)}
|
||||||
>
|
>
|
||||||
{visibleColumns.map((col) => (
|
{visibleColumns.map((col) => (
|
||||||
|
|
|
||||||
|
|
@ -1843,16 +1843,17 @@ export function BgTasksView({ onCreateWithCopilot, onEditWithCopilot, initialSlu
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-3">
|
<td className="px-4 py-3">
|
||||||
{isRunning ? (
|
{isRunning ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2 pl-7">
|
||||||
<span className="inline-flex items-center gap-1.5 rounded-md bg-primary/10 px-2 py-0.5 text-xs font-medium text-foreground animate-pulse">
|
<span className="inline-flex items-center gap-1.5 rounded-md bg-primary/10 px-2 py-0.5 text-xs font-medium text-foreground animate-pulse">
|
||||||
<Loader2 className="size-3 animate-spin" />
|
<Loader2 className="size-3 animate-spin" />
|
||||||
Updating…
|
Updating
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => handleStop(task.slug)}
|
onClick={() => handleStop(task.slug)}
|
||||||
disabled={isStopping}
|
disabled={isStopping}
|
||||||
|
className="h-auto gap-1.5 rounded-md px-2 py-0.5 text-xs font-medium"
|
||||||
>
|
>
|
||||||
{isStopping ? <Loader2 className="size-3 animate-spin" /> : <Square className="size-3" />}
|
{isStopping ? <Loader2 className="size-3 animate-spin" /> : <Square className="size-3" />}
|
||||||
Stop
|
Stop
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ const SUGGESTED_ACTIONS: { icon: typeof Mail; title: string; sub: string; prompt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty-state body for the chat surface: greeting and starter action cards.
|
* Empty-state body for the chat surface: greeting and starter action cards.
|
||||||
* Shown in both the side-pane copilot and full-screen chat.
|
* Shown in both the side-pane copilot and full-screen chat; the side pane
|
||||||
|
* (`wide` unset) uses slightly smaller type to fit the narrow column.
|
||||||
*/
|
*/
|
||||||
export function ChatEmptyState({
|
export function ChatEmptyState({
|
||||||
onPickPrompt,
|
onPickPrompt,
|
||||||
|
|
@ -27,8 +28,12 @@ export function ChatEmptyState({
|
||||||
return (
|
return (
|
||||||
<div className={cn('mx-auto flex w-full flex-col gap-5 py-6', wide ? 'max-w-4xl px-4' : 'max-w-md px-2')}>
|
<div className={cn('mx-auto flex w-full flex-col gap-5 py-6', wide ? 'max-w-4xl px-4' : 'max-w-md px-2')}>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-2xl font-semibold tracking-tight">What are we working on?</div>
|
<div className={cn('font-semibold tracking-tight', wide ? 'text-2xl' : 'text-lg')}>
|
||||||
<div className="mt-1 text-[15px] text-muted-foreground">Ask anything, or start with a suggestion.</div>
|
What are we working on?
|
||||||
|
</div>
|
||||||
|
<div className={cn('mt-1 text-muted-foreground', wide ? 'text-[15px]' : 'text-[13px]')}>
|
||||||
|
Ask anything, or start with a suggestion.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-hidden rounded-xl border border-border">
|
<div className="overflow-hidden rounded-xl border border-border">
|
||||||
|
|
@ -38,19 +43,24 @@ export function ChatEmptyState({
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => onPickPrompt(action.prompt)}
|
onClick={() => onPickPrompt(action.prompt)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'group flex w-full items-center gap-1.5 px-3.5 py-3 text-left transition-colors hover:bg-accent/50',
|
'group flex w-full items-center gap-1.5 text-left transition-colors hover:bg-accent/50',
|
||||||
|
wide ? 'px-3.5 py-3' : 'px-3 py-2.5',
|
||||||
i > 0 && 'border-t border-border/60',
|
i > 0 && 'border-t border-border/60',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<action.icon className="mr-2 size-4 shrink-0 text-foreground/80" strokeWidth={1.75} />
|
<action.icon className={cn('mr-2 shrink-0 text-foreground/80', wide ? 'size-4' : 'size-3.5')} strokeWidth={1.75} />
|
||||||
<span className="shrink-0 text-sm font-medium text-foreground">{action.title}</span>
|
<span className={cn('shrink-0 font-medium text-foreground', wide ? 'text-sm' : 'text-[13px]')}>
|
||||||
<span className="truncate text-[13px] text-muted-foreground">{action.sub}</span>
|
{action.title}
|
||||||
<ArrowRight className="ml-auto size-3.5 shrink-0 text-muted-foreground/50 transition-colors group-hover:text-foreground" />
|
</span>
|
||||||
|
<span className={cn('truncate text-muted-foreground', wide ? 'text-[13px]' : 'text-[12px]')}>
|
||||||
|
{action.sub}
|
||||||
|
</span>
|
||||||
|
<ArrowRight className={cn('ml-auto shrink-0 text-muted-foreground/50 transition-colors group-hover:text-foreground', wide ? 'size-3.5' : 'size-3')} />
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ToolConnectionsCard />
|
<ToolConnectionsCard compact={!wide} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ export function KnowledgeView({
|
||||||
const currentFolder = folderPath ? findNode(tree, folderPath) : null
|
const currentFolder = folderPath ? findNode(tree, folderPath) : null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-col overflow-hidden">
|
<div className="flex h-full flex-col overflow-hidden bg-[#f8f8f9] dark:bg-[#0b0b0d]">
|
||||||
<div className="mx-auto w-full max-w-[1120px] shrink-0 flex items-start justify-between gap-4 px-[30px] pt-[34px] pb-5">
|
<div className="mx-auto w-full max-w-[1120px] shrink-0 flex items-start justify-between gap-4 px-[30px] pt-[34px] pb-5">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<h1 className="text-[24px] font-[650] tracking-[-0.02em] text-[#0d0e11] dark:text-[#f4f5f7]">Brain</h1>
|
<h1 className="text-[24px] font-[650] tracking-[-0.02em] text-[#0d0e11] dark:text-[#f4f5f7]">Brain</h1>
|
||||||
|
|
@ -250,7 +250,7 @@ export function KnowledgeView({
|
||||||
{folders.length === 0 ? (
|
{folders.length === 0 ? (
|
||||||
<EmptyState text="No folders yet." />
|
<EmptyState text="No folders yet." />
|
||||||
) : (
|
) : (
|
||||||
<div className="overflow-hidden rounded-xl border border-border">
|
<div className="overflow-hidden rounded-xl border border-black/15 dark:border-border">
|
||||||
{folders.map((node, i) => (
|
{folders.map((node, i) => (
|
||||||
<div key={node.path} className={cn(i > 0 && 'border-t border-border/60')}>
|
<div key={node.path} className={cn(i > 0 && 'border-t border-border/60')}>
|
||||||
<FolderCard
|
<FolderCard
|
||||||
|
|
@ -270,7 +270,7 @@ export function KnowledgeView({
|
||||||
{looseNotes.length > 0 && (
|
{looseNotes.length > 0 && (
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<SectionHeader label={`Loose notes · ${looseNotes.length}`} />
|
<SectionHeader label={`Loose notes · ${looseNotes.length}`} />
|
||||||
<div className="overflow-hidden rounded-xl border border-border">
|
<div className="overflow-hidden rounded-xl border border-black/15 dark:border-border">
|
||||||
{looseNotes.map((node, i) => (
|
{looseNotes.map((node, i) => (
|
||||||
<div key={node.path} className={cn(i > 0 && 'border-t border-border/60')}>
|
<div key={node.path} className={cn(i > 0 && 'border-t border-border/60')}>
|
||||||
<ItemRow
|
<ItemRow
|
||||||
|
|
@ -394,7 +394,7 @@ function QuickAction({
|
||||||
function SectionHeader({ label, aside }: { label: string; aside?: string }) {
|
function SectionHeader({ label, aside }: { label: string; aside?: string }) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-2.5 flex items-center justify-between">
|
<div className="mb-2.5 flex items-center justify-between">
|
||||||
<span className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
<span className="text-xs font-bold uppercase tracking-wider text-muted-foreground">
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
{aside && <span className="text-xs text-muted-foreground">{aside}</span>}
|
{aside && <span className="text-xs text-muted-foreground">{aside}</span>}
|
||||||
|
|
@ -568,7 +568,7 @@ function FolderDetail({
|
||||||
{items.length === 0 ? (
|
{items.length === 0 ? (
|
||||||
<EmptyState text="This folder is empty." />
|
<EmptyState text="This folder is empty." />
|
||||||
) : (
|
) : (
|
||||||
<div className="overflow-hidden rounded-xl border border-border">
|
<div className="overflow-hidden rounded-xl border border-black/15 dark:border-border">
|
||||||
{items.map((node, i) => (
|
{items.map((node, i) => (
|
||||||
<div key={node.path} className={cn(i > 0 && 'border-t border-border/60')}>
|
<div key={node.path} className={cn(i > 0 && 'border-t border-border/60')}>
|
||||||
<ItemRow
|
<ItemRow
|
||||||
|
|
|
||||||
|
|
@ -789,6 +789,14 @@ export function SidebarContentPanel({
|
||||||
)}
|
)}
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
|
{codeModeEnabled && (
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton data-tour-id="nav-code" isActive={activeNav === 'code'} onClick={onOpenCode}>
|
||||||
|
<Code2 className="size-4 shrink-0" />
|
||||||
|
<span className="flex-1 truncate">Code</span>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
)}
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
data-tour-id="nav-meetings"
|
data-tour-id="nav-meetings"
|
||||||
|
|
@ -868,14 +876,6 @@ export function SidebarContentPanel({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
{codeModeEnabled && (
|
|
||||||
<SidebarMenuItem>
|
|
||||||
<SidebarMenuButton data-tour-id="nav-code" isActive={activeNav === 'code'} onClick={onOpenCode}>
|
|
||||||
<Code2 className="size-4 shrink-0" />
|
|
||||||
<span className="flex-1 truncate">Code</span>
|
|
||||||
</SidebarMenuButton>
|
|
||||||
</SidebarMenuItem>
|
|
||||||
)}
|
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
data-tour-id="nav-knowledge"
|
data-tour-id="nav-knowledge"
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ function ToolkitPreviewIcon({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolConnectionsCard({ className }: { className?: string }) {
|
export function ToolConnectionsCard({ className, compact = false }: { className?: string; compact?: boolean }) {
|
||||||
const [toolkitPreviews, setToolkitPreviews] = useState<ToolkitPreview[]>(cachedToolkitPreviews ?? [])
|
const [toolkitPreviews, setToolkitPreviews] = useState<ToolkitPreview[]>(cachedToolkitPreviews ?? [])
|
||||||
const [toolkitLogosLoaded, setToolkitLogosLoaded] = useState(cachedToolkitLogosLoaded)
|
const [toolkitLogosLoaded, setToolkitLogosLoaded] = useState(cachedToolkitLogosLoaded)
|
||||||
const [connectionsSettingsOpen, setConnectionsSettingsOpen] = useState(false)
|
const [connectionsSettingsOpen, setConnectionsSettingsOpen] = useState(false)
|
||||||
|
|
@ -102,7 +102,7 @@ export function ToolConnectionsCard({ className }: { className?: string }) {
|
||||||
<div className={cn('rounded-xl border border-border bg-card p-4', className)}>
|
<div className={cn('rounded-xl border border-border bg-card p-4', className)}>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="text-[13.5px] leading-snug">
|
<div className={cn('leading-snug', compact ? 'text-[12.5px]' : 'text-[13.5px]')}>
|
||||||
<span className="text-muted-foreground">Bring context from and take action in the apps you already use.</span>
|
<span className="text-muted-foreground">Bring context from and take action in the apps you already use.</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3 flex min-h-5 flex-wrap items-center gap-1.5">
|
<div className="mt-3 flex min-h-5 flex-wrap items-center gap-1.5">
|
||||||
|
|
@ -116,7 +116,10 @@ export function ToolConnectionsCard({ className }: { className?: string }) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setConnectionsSettingsOpen(true)}
|
onClick={() => setConnectionsSettingsOpen(true)}
|
||||||
className="ml-1 flex h-5 shrink-0 items-center gap-1 rounded-md px-1 text-[12px] font-medium text-primary hover:underline"
|
className={cn(
|
||||||
|
'ml-1 flex h-5 shrink-0 items-center gap-1 rounded-md px-1 font-medium text-primary hover:underline',
|
||||||
|
compact ? 'text-[11.5px]' : 'text-[12px]',
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
Connections
|
Connections
|
||||||
<ArrowRight className="size-3" />
|
<ArrowRight className="size-3" />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue