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
5 changes: 5 additions & 0 deletions examples/chat/angular/src/app/shell/demo-shell.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@
/>
</chat-debug-section>
<chat-debug-section label="Appearance">
<chat-debug-segmented
[options]="colorSchemeOptions"
[value]="colorScheme()"
(valueChange)="onColorSchemeChange($event)"
/>
<chat-debug-select
label="Theme"
[options]="themeOptions()"
Expand Down
42 changes: 42 additions & 0 deletions examples/chat/angular/src/app/shell/demo-shell.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,28 @@ export class DemoShell {
this.document.documentElement.setAttribute('data-theme', this.theme());
});

// App-wide color scheme: drives the demo page bg/text via
// `data-color-scheme` and the chat-lib internals via
// `data-ngaf-chat-theme`. The pre-bootstrap script in index.html
// applies the initial value before stylesheets load; this effect
// keeps both attrs synced after Angular takes over and also
// auto-syncs the A2UI theme dropdown when it sits on a default
// preset — material picks are left alone since the user opted in.
effect(() => {
const scheme = this.colorScheme();
const html = this.document.documentElement;
html.setAttribute('data-color-scheme', scheme);
html.setAttribute('data-ngaf-chat-theme', scheme);
const currentTheme = this.theme();
if (currentTheme === 'default-dark' || currentTheme === 'default-light') {
const next = scheme === 'light' ? 'default-light' : 'default-dark';
if (currentTheme !== next) {
this.theme.set(next);
this.persistence.write('theme', next);
}
}
});

// Refresh threads list whenever the active thread changes (e.g. after
// create or switch) so the panel stays up to date. The effect also
// covers the initial load (fires synchronously on first reactive read).
Expand Down Expand Up @@ -152,6 +174,15 @@ export class DemoShell {
*/
readonly theme = signal<string>(this.persistence.read('theme') ?? 'default-dark');

/**
* App-wide color scheme. Single source of truth for the demo page bg,
* the chat lib's internal `data-ngaf-chat-theme`, and (when the A2UI
* theme is on a default preset) the base A2UI theme. Persisted.
*/
readonly colorScheme = signal<'light' | 'dark'>(
(this.persistence.read('colorScheme') as 'light' | 'dark' | null) ?? 'dark',
);

/** Whether the threads drawer is open. Persisted across reloads. */
protected readonly drawerOpen = signal<boolean>(this.persistence.read('drawerOpen') ?? false);

Expand Down Expand Up @@ -228,6 +259,11 @@ export class DemoShell {
{ value: 'json-render', label: 'json-render' },
]);

protected readonly colorSchemeOptions = [
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' },
] as const;

protected readonly themeOptions = signal<readonly { value: string; label: string }[]>([
{ value: 'default-dark', label: 'Default dark' },
{ value: 'default-light', label: 'Default light' },
Expand Down Expand Up @@ -347,6 +383,12 @@ export class DemoShell {
this.persistence.write('theme', next);
}

protected onColorSchemeChange(next: 'light' | 'dark' | string): void {
if (next !== 'light' && next !== 'dark') return;
this.colorScheme.set(next);
this.persistence.write('colorScheme', next);
}

protected onSidenavOpenChange(next: boolean): void {
this.drawerOpen.set(next);
this.persistence.write('drawerOpen', next);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface PaletteState {
drawerOpen?: boolean | null;
sidenavMode?: 'expanded' | 'collapsed' | null;
selectedProjectId?: string | null;
colorScheme?: 'light' | 'dark' | null;
}

type PaletteKey = keyof PaletteState;
Expand Down
23 changes: 22 additions & 1 deletion examples/chat/angular/src/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
<!doctype html>
<html lang="en" data-ngaf-chat-theme="dark">
<html lang="en">
<head>
<meta charset="utf-8" />
<title>NGAF chat — canonical demo</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
// Pre-bootstrap color-scheme apply: read persisted palette and set
// both `data-color-scheme` (drives the demo page bg/text) and
// `data-ngaf-chat-theme` (drives the chat lib's internal theming)
// BEFORE stylesheets load to avoid FOUC. The DemoShell effect
// takes over at runtime once Angular bootstraps.
(function () {
try {
var raw = localStorage.getItem('ngaf-chat-demo:palette');
var scheme = 'dark';
if (raw) {
var p = JSON.parse(raw);
if (p && (p.colorScheme === 'light' || p.colorScheme === 'dark')) {
scheme = p.colorScheme;
}
}
document.documentElement.setAttribute('data-color-scheme', scheme);
document.documentElement.setAttribute('data-ngaf-chat-theme', scheme);
} catch (e) { /* localStorage blocked — defaults apply */ }
})();
</script>
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
Expand Down
20 changes: 18 additions & 2 deletions examples/chat/angular/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,24 @@ html, body {
padding: 0;
height: 100%;
font-family: system-ui, -apple-system, sans-serif;
background: #0f1116;
color: #e6e9ef;
background: var(--demo-page-bg);
color: var(--demo-page-text);
}

/*
* Demo page color scheme — driven by `data-color-scheme` on <html>.
* The pre-bootstrap inline script in index.html sets the attribute
* from persisted state before any stylesheet applies; the runtime
* effect in DemoShell keeps it in sync afterwards. Default (no
* attribute) is dark to match prior behavior.
*/
html {
--demo-page-bg: #0f1116;
--demo-page-text: #e6e9ef;
}
html[data-color-scheme="light"] {
--demo-page-bg: #ffffff;
--demo-page-text: #1c1c1c;
}

/*
Expand Down
Loading