fix: align client portal shell and chat styles

This commit is contained in:
Arthur Belleville 2026-04-15 23:00:12 +02:00
parent 8f3927b68d
commit 84d94c49e9
No known key found for this signature in database
4 changed files with 105 additions and 54 deletions

View file

@ -0,0 +1,23 @@
import { describe, expect, it } from "vitest";
import { renderWithProviders } from "../test/testHelpers";
import { ClientLayout } from "./ClientLayout";
describe("ClientLayout", () => {
it("uses the main app style header shell and centered content container", () => {
const { container } = renderWithProviders(<ClientLayout />);
const header = container.querySelector("header");
expect(header).toHaveClass("h-[75px]");
expect(header).toHaveClass("bg-navbar-background");
const headerInner = header?.firstElementChild;
expect(headerInner).toHaveClass("w-full");
expect(headerInner).toHaveClass("max-w-7xl");
expect(headerInner).toHaveClass("mx-auto");
const main = container.querySelector("main");
expect(main).toHaveClass("w-full");
expect(main).toHaveClass("max-w-7xl");
expect(main).toHaveClass("mx-auto");
});
});

View file

@ -36,14 +36,10 @@ export function ClientLayout() {
};
return (
<div className="min-h-screen bg-background">
{/* Top bar */}
<header className="border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="flex h-14 items-center justify-between px-4 max-w-7xl mx-auto">
{/* Brand */}
<span className="text-lg font-bold text-foreground">Xtablo</span>
{/* User info + logout */}
<div className="flex min-h-screen flex-col bg-background">
<header className="h-[75px] shrink-0 border-b border-[#EAECF0] bg-navbar-background dark:border-gray-700">
<div className="mx-auto flex h-full w-full max-w-7xl items-center justify-between gap-4 px-4 sm:px-6">
<span className="text-lg font-semibold text-foreground">Xtablo</span>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<Avatar className="h-8 w-8">
@ -58,8 +54,7 @@ export function ClientLayout() {
</div>
</header>
{/* Page content */}
<main className="max-w-7xl mx-auto px-4 py-6">
<main className="mx-auto w-full max-w-7xl flex-1 px-4 py-6 sm:px-6">
<Outlet />
</main>
</div>

View file

@ -1,6 +1,8 @@
@import "tailwindcss";
@import "tw-animate-css";
@source "../../../packages/chat-ui/src/**/*.{ts,tsx}";
@custom-variant dark (&:is(.dark *));
:root {
@ -37,41 +39,45 @@
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
--navbar-background: rgb(249, 250, 251);
--navbar-darker: #e5e7eb;
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.145 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.145 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--background: oklch(0.17 0.012 290);
--foreground: oklch(0.985 0.005 290);
--card: oklch(0.16 0.014 290);
--card-foreground: oklch(0.985 0.005 290);
--popover: oklch(0.16 0.014 290);
--popover-foreground: oklch(0.985 0.005 290);
--primary: oklch(0.985 0.005 290);
--primary-foreground: oklch(0.2 0.012 290);
--secondary: oklch(0.22 0.018 290);
--secondary-foreground: oklch(0.985 0.005 290);
--muted: oklch(0.22 0.018 290);
--muted-foreground: oklch(0.65 0.02 290);
--accent: oklch(0.22 0.018 290);
--accent-foreground: oklch(0.985 0.005 290);
--destructive: oklch(0.396 0.141 25.723);
--destructive-foreground: oklch(0.637 0.237 25.331);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--border: oklch(0.26 0.02 290);
--input: oklch(0.26 0.02 290);
--ring: oklch(0.45 0.03 290);
--chart-1: oklch(0.55 0.2 290);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
--sidebar: oklch(0.18 0.016 290);
--sidebar-foreground: oklch(0.985 0.005 290);
--sidebar-primary: oklch(0.55 0.2 290);
--sidebar-primary-foreground: oklch(0.985 0.005 290);
--sidebar-accent: oklch(0.24 0.02 290);
--sidebar-accent-foreground: oklch(0.985 0.005 290);
--sidebar-border: oklch(0.26 0.02 290);
--sidebar-ring: oklch(0.45 0.03 290);
--navbar-background: #1e1b2e;
--navbar-darker: #141121;
}
@theme inline {
@ -111,8 +117,8 @@
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--color-navbar-background: #292e39;
--color-navbar-darker: #171920;
--color-navbar-background: var(--navbar-background);
--color-navbar-darker: var(--navbar-darker);
}
@layer base {
@ -122,31 +128,43 @@
body {
@apply bg-background text-foreground;
}
@media (display-mode: standalone) {
body {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
}
}
.str-chat {
--str-chat__primary-color: #8b7396;
--str-chat__active-primary-color: #6e5c7d;
--str-chat__primary-color: #804eec;
--str-chat__active-primary-color: #6f3fd4;
--str-chat__surface-color: #f5f3f7;
--str-chat__secondary-surface-color: #e8e4ec;
--str-chat__primary-surface-color: #ebe7f0;
--str-chat__primary-surface-color-low-emphasis: #f2f0f5;
--str-chat__primary-surface-color: #f4f3ff;
--str-chat__primary-surface-color-low-emphasis: #f8f7ff;
--str-chat__border-radius-circle: 6px;
--str-chat__own-message-bubble-color: #804eec;
--str-chat__own-message-text-color: #ffffff;
}
.dark .str-chat {
--str-chat__primary-color: #a68bb5;
--str-chat__active-primary-color: #8b7396;
--str-chat__surface-color: rgba(120, 107, 130, 0.25);
--str-chat__secondary-surface-color: rgba(140, 130, 150, 0.18);
--str-chat__primary-surface-color: rgba(166, 139, 181, 0.12);
--str-chat__primary-surface-color-low-emphasis: rgba(166, 139, 181, 0.06);
--str-chat__background-color: rgba(110, 100, 120, 0.2);
--str-chat__secondary-background-color: rgba(80, 72, 88, 0.35);
--str-chat__border-color: rgba(120, 107, 130, 0.28);
--str-chat__text-color: #f5f3f7;
--str-chat__text-low-emphasis-color: #b8b0c0;
--str-chat__disabled-color: rgba(155, 143, 165, 0.35);
--str-chat__primary-color: #9b6ff0;
--str-chat__active-primary-color: #804eec;
--str-chat__surface-color: rgba(128, 78, 236, 0.12);
--str-chat__secondary-surface-color: rgba(128, 78, 236, 0.08);
--str-chat__primary-surface-color: rgba(128, 78, 236, 0.1);
--str-chat__primary-surface-color-low-emphasis: rgba(128, 78, 236, 0.05);
--str-chat__background-color: rgba(30, 27, 46, 0.6);
--str-chat__secondary-background-color: rgba(20, 17, 33, 0.5);
--str-chat__border-color: rgba(128, 78, 236, 0.15);
--str-chat__text-color: #eeeaf5;
--str-chat__text-low-emphasis-color: #a8a0b8;
--str-chat__disabled-color: rgba(128, 78, 236, 0.2);
--str-chat__own-message-bubble-color: #804eec;
--str-chat__own-message-text-color: #ffffff;
}
@keyframes gradient-x {

View file

@ -0,0 +1,15 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
const mainCss = readFileSync(resolve(process.cwd(), "src/main.css"), "utf8");
describe("clients main.css", () => {
it("keeps the chat source and theme tokens aligned with the main app", () => {
expect(mainCss).toContain('@source "../../../packages/chat-ui/src/**/*.{ts,tsx}";');
expect(mainCss).toContain("--navbar-background: rgb(249, 250, 251);");
expect(mainCss).toContain("--color-navbar-background: var(--navbar-background);");
expect(mainCss).toContain("--str-chat__own-message-bubble-color: #804eec;");
expect(mainCss).toContain("--str-chat__own-message-text-color: #ffffff;");
});
});