mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-06 19:35:44 +02:00
Extend dark mode coverage and soften elements
This commit is contained in:
parent
82e4b66395
commit
22190d920d
12 changed files with 167 additions and 143 deletions
|
|
@ -1,3 +1,4 @@
|
|||
@import './styles/quill-mentions.css';
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
|
@ -76,7 +77,6 @@ html, body {
|
|||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
/* Add these new utility classes */
|
||||
.card-shadow {
|
||||
@apply shadow-sm dark:shadow-none dark:border-border;
|
||||
}
|
||||
|
|
@ -90,105 +90,11 @@ html, body {
|
|||
}
|
||||
}
|
||||
|
||||
/* Add this to disable color transitions */
|
||||
* {
|
||||
-webkit-transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out, opacity 0.2s ease-in-out !important;
|
||||
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out, opacity 0.2s ease-in-out !important;
|
||||
}
|
||||
|
||||
/* Ensure smooth transitions */
|
||||
* {
|
||||
@apply transition-colors duration-200;
|
||||
}
|
||||
|
||||
/* Add these styles alongside your other global styles */
|
||||
.ql-mention-list-container {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
background-color: white;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* Base dark mode styles */
|
||||
.dark .ql-mention-list-container {
|
||||
background-color: #1f2937;
|
||||
border-color: #374151;
|
||||
}
|
||||
|
||||
.dark .ql-mention-list-container * {
|
||||
background-color: #1f2937 !important;
|
||||
color: #f9fafb !important;
|
||||
}
|
||||
|
||||
/* Target individual items */
|
||||
.dark .ql-mention-list-item {
|
||||
color: #f9fafb !important;
|
||||
background-color: #1f2937 !important;
|
||||
}
|
||||
|
||||
/* Target hover and selected states for individual items */
|
||||
.dark .ql-mention-list-container .ql-mention-list-item.selected,
|
||||
.dark .ql-mention-list-container .ql-mention-list-item:hover {
|
||||
background-color: #6b7280 !important;
|
||||
}
|
||||
|
||||
/* Ensure the background color only applies to the item itself */
|
||||
.dark .ql-mention-list-item > * {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
/* Additional catch-all for any other possible class combinations */
|
||||
.dark [class*="mention"].selected,
|
||||
.dark [class*="mention"]:hover {
|
||||
background-color: #6b7280 !important;
|
||||
}
|
||||
|
||||
.ql-mention-list {
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
/* Styles for mentions in the editor */
|
||||
.ql-editor .mention {
|
||||
background-color: #e0f2fe; /* light blue bg */
|
||||
color: #1e40af; /* darker blue text */
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Style for the @ symbol */
|
||||
.ql-editor .mention .ql-mention-denotation-char {
|
||||
color: #1e40af; /* blue color for @ symbol */
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.ql-editor .mention .invalid {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Add custom scrollbar styling */
|
||||
.dark *::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.dark *::-webkit-scrollbar-track {
|
||||
background: #1f2937; /* dark gray background */
|
||||
}
|
||||
|
||||
.dark *::-webkit-scrollbar-thumb {
|
||||
background: #4b5563; /* medium gray thumb */
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dark *::-webkit-scrollbar-thumb:hover {
|
||||
background: #6b7280; /* lighter gray on hover */
|
||||
}
|
||||
|
||||
/* For Firefox */
|
||||
.dark * {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #4b5563 #1f2937;
|
||||
}
|
||||
57
apps/rowboat/app/lib/components/atmentions.ts
Normal file
57
apps/rowboat/app/lib/components/atmentions.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
interface AtMentionItem {
|
||||
id: string;
|
||||
value: string;
|
||||
[key: string]: string; // Add index signature to allow any string key
|
||||
}
|
||||
|
||||
interface CreateAtMentionsProps {
|
||||
agents: any[];
|
||||
prompts: any[];
|
||||
tools: any[];
|
||||
currentAgentName?: string;
|
||||
}
|
||||
|
||||
export function createAtMentions({ agents, prompts, tools, currentAgentName }: CreateAtMentionsProps): AtMentionItem[] {
|
||||
const atMentions: AtMentionItem[] = [];
|
||||
|
||||
// Add agents
|
||||
for (const a of agents) {
|
||||
if (a.disabled || a.name === currentAgentName) {
|
||||
continue;
|
||||
}
|
||||
const id = `agent:${a.name}`;
|
||||
atMentions.push({
|
||||
id,
|
||||
value: id,
|
||||
denotationChar: "@", // Add required properties for Match type
|
||||
link: id,
|
||||
target: "_self"
|
||||
});
|
||||
}
|
||||
|
||||
// Add prompts
|
||||
for (const prompt of prompts) {
|
||||
const id = `prompt:${prompt.name}`;
|
||||
atMentions.push({
|
||||
id,
|
||||
value: id,
|
||||
denotationChar: "@",
|
||||
link: id,
|
||||
target: "_self"
|
||||
});
|
||||
}
|
||||
|
||||
// Add tools
|
||||
for (const tool of tools) {
|
||||
const id = `tool:${tool.name}`;
|
||||
atMentions.push({
|
||||
id,
|
||||
value: id,
|
||||
denotationChar: "@",
|
||||
link: id,
|
||||
target: "_self"
|
||||
});
|
||||
}
|
||||
|
||||
return atMentions;
|
||||
}
|
||||
|
|
@ -24,8 +24,8 @@ export function Section({
|
|||
title: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return <div className="w-full flex flex-col gap-4 border border-gray-300 p-4 rounded-md">
|
||||
<h2 className="font-semibold pb-2 border-b border-gray-200">{title}</h2>
|
||||
return <div className="w-full flex flex-col gap-4 border border-border p-4 rounded-md">
|
||||
<h2 className="font-semibold pb-2 border-b border-border">{title}</h2>
|
||||
{children}
|
||||
</div>;
|
||||
}
|
||||
|
|
@ -235,8 +235,8 @@ export function ApiKeysSection({
|
|||
|
||||
<Divider />
|
||||
{loading && <Spinner size="sm" />}
|
||||
{!loading && <div className="border rounded-lg text-sm">
|
||||
<div className="flex items-center border-b p-4">
|
||||
{!loading && <div className="border border-border rounded-lg text-sm">
|
||||
<div className="flex items-center border-b border-border p-4">
|
||||
<div className="flex-[3] font-normal">API Key</div>
|
||||
<div className="flex-1 font-normal">Created</div>
|
||||
<div className="flex-1 font-normal">Last Used</div>
|
||||
|
|
@ -253,7 +253,7 @@ export function ApiKeysSection({
|
|||
</div>}
|
||||
<div className="flex flex-col">
|
||||
{keys.map((key) => (
|
||||
<div key={key._id} className="flex items-start border-b last:border-b-0 p-4">
|
||||
<div key={key._id} className="flex items-start border-b border-border last:border-b-0 p-4">
|
||||
<div className="flex-[3] p-2">
|
||||
<ApiKeyDisplay apiKey={key.key} />
|
||||
</div>
|
||||
|
|
@ -570,7 +570,7 @@ export default function App({
|
|||
projectId: string;
|
||||
}) {
|
||||
return <div className="flex flex-col h-full">
|
||||
<div className="shrink-0 flex justify-between items-center pb-4 border-b border-b-gray-100">
|
||||
<div className="shrink-0 flex justify-between items-center pb-4 border-b border-border">
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-lg">Project config</h1>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export function Nav({
|
|||
setCollapsed(!collapsed);
|
||||
}
|
||||
|
||||
return <div className={clsx("shrink-0 flex flex-col gap-2 border-r-1 border-gray-100 relative p-2", {
|
||||
return <div className={clsx("shrink-0 flex flex-col gap-2 border-r border-border relative p-2", {
|
||||
"w-40": !collapsed,
|
||||
"w-10": collapsed
|
||||
})}>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default async function Page({
|
|||
}
|
||||
|
||||
return <div className="flex flex-col h-full">
|
||||
<div className="shrink-0 flex justify-between items-center pb-4 border-b border-b-gray-100">
|
||||
<div className="shrink-0 flex justify-between items-center pb-4 border-b border-border">
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-lg">Add data source</h1>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export function SourcesList({
|
|||
}, [projectId]);
|
||||
|
||||
return <div className="flex flex-col h-full">
|
||||
<div className="shrink-0 flex justify-between items-center pb-4 border-b border-b-gray-100">
|
||||
<div className="shrink-0 flex justify-between items-center pb-4 border-b border-border">
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-lg">Data sources <sup>(beta)</sup></h1>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { PreviewModalProvider } from "./preview-modal";
|
|||
import { CopilotMessage } from "@/app/lib/types/copilot_types";
|
||||
import { getCopilotAgentInstructions } from "@/app/actions/copilot_actions";
|
||||
import { Dropdown as CustomDropdown } from "../../../lib/components/dropdown";
|
||||
import { createAtMentions } from "../../../lib/components/atmentions";
|
||||
|
||||
export function AgentConfig({
|
||||
projectId,
|
||||
|
|
@ -46,31 +47,12 @@ export function AgentConfig({
|
|||
}) {
|
||||
const [isAdvancedConfigOpen, setIsAdvancedConfigOpen] = useState(false);
|
||||
|
||||
const atMentions = [];
|
||||
for (const a of agents) {
|
||||
if (a.disabled || a.name === agent.name) {
|
||||
continue;
|
||||
}
|
||||
const id = `agent:${a.name}`;
|
||||
atMentions.push({
|
||||
id,
|
||||
value: id,
|
||||
});
|
||||
}
|
||||
for (const prompt of prompts) {
|
||||
const id = `prompt:${prompt.name}`;
|
||||
atMentions.push({
|
||||
id,
|
||||
value: id,
|
||||
});
|
||||
}
|
||||
for (const tool of tools) {
|
||||
const id = `tool:${tool.name}`;
|
||||
atMentions.push({
|
||||
id,
|
||||
value: id,
|
||||
});
|
||||
}
|
||||
const atMentions = createAtMentions({
|
||||
agents,
|
||||
prompts,
|
||||
tools,
|
||||
currentAgentName: agent.name
|
||||
});
|
||||
|
||||
const [showGenerateModal, setShowGenerateModal] = useState(false);
|
||||
const { showPreview } = usePreviewModal();
|
||||
|
|
@ -466,4 +448,4 @@ function GenerateInstructionsModal({
|
|||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -37,10 +37,10 @@ export default function App() {
|
|||
}, [router]);
|
||||
|
||||
return (
|
||||
<div className="h-full pt-4 px-4 overflow-auto">
|
||||
<div className="h-full pt-4 px-4 overflow-auto dark:bg-gray-900">
|
||||
<div className="max-w-[768px] mx-auto">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="text-lg">Select a project</div>
|
||||
<div className="text-lg dark:text-white">Select a project</div>
|
||||
<Button
|
||||
href="/projects/new"
|
||||
as={Link}
|
||||
|
|
@ -55,18 +55,18 @@ export default function App() {
|
|||
</div>
|
||||
|
||||
{isLoading && <Spinner size="sm" />}
|
||||
{!isLoading && projects.length == 0 && <p className="mt-4 text-center text-gray-600 text-sm">You do not have any projects.</p>}
|
||||
{!isLoading && projects.length == 0 && <p className="mt-4 text-center text-gray-600 dark:text-gray-400 text-sm">You do not have any projects.</p>}
|
||||
{!isLoading && projects.length > 0 && <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-4">
|
||||
{projects.map((project) => (
|
||||
<NextLink
|
||||
key={project._id}
|
||||
href={`/projects/${project._id}`}
|
||||
className="flex flex-col gap-2 border border-gray-300 hover:border-gray-500 rounded p-4 bg-white"
|
||||
className="flex flex-col gap-2 border border-gray-300 dark:border-gray-700 hover:border-gray-500 dark:hover:border-gray-500 rounded p-4 bg-white dark:bg-gray-800 dark:text-white"
|
||||
>
|
||||
<div className="text-lg">
|
||||
{project.name}
|
||||
</div>
|
||||
<div className="shrink-0 text-sm text-gray-500">
|
||||
<div className="shrink-0 text-sm text-gray-500 dark:text-gray-400">
|
||||
Created <RelativeTime date={new Date(project.createdAt)} />
|
||||
</div>
|
||||
</NextLink>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import logo from "@/public/rowboat-logo.png";
|
||||
import logoDark from "@/public/rowboat-logo-dark-mode.png";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { UserButton } from "../lib/components/user_button";
|
||||
|
|
@ -17,6 +18,13 @@ export default function Layout({
|
|||
src={logo}
|
||||
height={24}
|
||||
alt="RowBoat Labs Logo"
|
||||
className="block dark:hidden"
|
||||
/>
|
||||
<Image
|
||||
src={logoDark}
|
||||
height={24}
|
||||
alt="RowBoat Labs Logo"
|
||||
className="hidden dark:block"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,15 +21,21 @@ function TemplateCard({
|
|||
selected: boolean
|
||||
}) {
|
||||
return <button
|
||||
className={cn("relative flex flex-col gap-2 border border-gray-300 hover:border-gray-500 rounded p-4 pt-6 bg-white shadow-sm", selected && "border-gray-800 shadow-md")}
|
||||
className={cn(
|
||||
"relative flex flex-col gap-2 rounded p-4 pt-6 shadow-sm",
|
||||
"border border-gray-300 dark:border-gray-700",
|
||||
"hover:border-gray-500 dark:hover:border-gray-500",
|
||||
"bg-white dark:bg-gray-900",
|
||||
selected && "border-gray-800 dark:border-gray-300 shadow-md"
|
||||
)}
|
||||
type="button"
|
||||
onClick={() => onSelect(templateKey)}
|
||||
>
|
||||
{selected && <div className="absolute top-0 right-0 bg-gray-200 flex items-center justify-center rounded p-1">
|
||||
{selected && <div className="absolute top-0 right-0 bg-gray-200 dark:bg-gray-800 flex items-center justify-center rounded p-1">
|
||||
<CheckIcon size={16} />
|
||||
</div>}
|
||||
<div className="text-lg">{template.name}</div>
|
||||
<div className="shrink-0 text-sm text-gray-500 text-left">{template.description}</div>
|
||||
<div className="text-lg dark:text-gray-100">{template.name}</div>
|
||||
<div className="shrink-0 text-sm text-gray-500 dark:text-gray-400 text-left">{template.description}</div>
|
||||
</button>
|
||||
}
|
||||
|
||||
|
|
@ -57,9 +63,9 @@ export default function App() {
|
|||
setSelectedTemplate(templateKey);
|
||||
}
|
||||
|
||||
return <div className="h-full pt-4 px-4 overflow-auto">
|
||||
<div className="max-w-[768px] mx-auto p-4 bg-white rounded-lg">
|
||||
<div className="text-lg pb-2 border-b border-b-gray-100">Create a new project</div>
|
||||
return <div className="h-full pt-4 px-4 overflow-auto bg-gray-50 dark:bg-gray-950">
|
||||
<div className="max-w-[768px] mx-auto p-4 bg-white dark:bg-gray-900 rounded-lg">
|
||||
<div className="text-lg pb-2 border-b border-b-gray-100 dark:border-b-gray-800 dark:text-gray-100">Create a new project</div>
|
||||
<form className="mt-4 flex flex-col gap-4" action={createProject}>
|
||||
<Input
|
||||
required
|
||||
|
|
@ -70,7 +76,7 @@ export default function App() {
|
|||
labelPlacement="outside"
|
||||
/>
|
||||
<input type="hidden" name="template" value={selectedTemplate} />
|
||||
<div className="text-sm">Select a template</div>
|
||||
<div className="text-sm dark:text-gray-300">Select a template</div>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<TemplateCard
|
||||
key="default"
|
||||
|
|
|
|||
65
apps/rowboat/app/styles/quill-mentions.css
Normal file
65
apps/rowboat/app/styles/quill-mentions.css
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/* Quill mention styles */
|
||||
.ql-mention-list-container {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
background-color: white;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* Dark mode styles */
|
||||
.dark .ql-mention-list-container {
|
||||
background-color: #1f2937;
|
||||
border-color: #374151;
|
||||
}
|
||||
|
||||
.dark .ql-mention-list-container * {
|
||||
background-color: #1f2937 !important;
|
||||
color: #f9fafb !important;
|
||||
}
|
||||
|
||||
.dark .ql-mention-list-item {
|
||||
color: #f9fafb !important;
|
||||
background-color: #1f2937 !important;
|
||||
}
|
||||
|
||||
.dark .ql-mention-list-container .ql-mention-list-item.selected,
|
||||
.dark .ql-mention-list-container .ql-mention-list-item:hover {
|
||||
background-color: #6b7280 !important;
|
||||
}
|
||||
|
||||
.dark .ql-mention-list-item > * {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
/* Mention item styles with tags */
|
||||
.dark .ql-mention-list-item {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
padding: 4px 8px !important;
|
||||
}
|
||||
|
||||
.mention-type-tag {
|
||||
font-size: 0.7rem !important;
|
||||
padding: 2px 6px !important;
|
||||
border-radius: 4px !important;
|
||||
margin-left: 8px !important;
|
||||
font-weight: 500 !important;
|
||||
text-transform: uppercase !important;
|
||||
}
|
||||
|
||||
.mention-type-tag.agent {
|
||||
background-color: #3b82f6 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.mention-type-tag.prompt {
|
||||
background-color: #10b981 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.mention-type-tag.tool {
|
||||
background-color: #f59e0b !important;
|
||||
color: white !important;
|
||||
}
|
||||
BIN
apps/rowboat/public/rowboat-logo-dark-mode.png
Normal file
BIN
apps/rowboat/public/rowboat-logo-dark-mode.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Loading…
Add table
Add a link
Reference in a new issue