fix: align client portal shell and chat styles
This commit is contained in:
parent
8f3927b68d
commit
84d94c49e9
4 changed files with 105 additions and 54 deletions
23
apps/clients/src/components/ClientLayout.test.tsx
Normal file
23
apps/clients/src/components/ClientLayout.test.tsx
Normal 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");
|
||||
});
|
||||
});
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
15
apps/clients/src/mainCss.test.ts
Normal file
15
apps/clients/src/mainCss.test.ts
Normal 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;");
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue