Skip to content
Open
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
62 changes: 58 additions & 4 deletions catalog-ui/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ const activeDomainData = activeDomain ? domains.find(d => d.id === activeDomain)
? <link rel="icon" href={SITE_CONFIG.logo_image} />
: <link rel="icon" type="image/svg+xml" href={`data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='8' fill='%230f172a'/><text x='50%25' y='56%25' dominant-baseline='middle' text-anchor='middle' font-size='16' font-weight='bold' fill='white' font-family='Inter'>${SITE_CONFIG.logo_text}</text></svg>`} />
}
<!-- FOUC prevention: apply saved theme before paint -->
<script is:inline>
(function() {
var saved = localStorage.getItem('theme');
if (!saved) saved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', saved);
})();
</script>
</head>
<body>
<div class="app-shell">
Expand Down Expand Up @@ -60,10 +68,16 @@ const activeDomainData = activeDomain ? domains.find(d => d.id === activeDomain)
</a>
</div>

<!-- Bottom: Meta Model -->
<a href="#" class="icon-bar-item" title="Meta Model" style="margin-top: auto; margin-bottom: 8px;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
</a>
<!-- Bottom: Theme toggle + Meta Model -->
<div style="margin-top: auto; display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px;">
<button class="icon-bar-item" title="Toggle dark mode" onclick="window.__toggleTheme()" id="theme-toggle-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="theme-icon-moon"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="theme-icon-sun" style="display:none;"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
</button>
<a href="#" class="icon-bar-item" title="Meta Model">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
</a>
</div>
</nav>

<!-- ═══ Nested Sidebar ═══ -->
Expand Down Expand Up @@ -147,6 +161,46 @@ const activeDomainData = activeDomain ? domains.find(d => d.id === activeDomain)

<!-- Sidebar auto-collapse for groups with > 6 items -->
<script>
// ── Theme toggle ──
function setTheme(theme: string) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
updateToggleIcon(theme);
}

function toggleTheme() {
const current = document.documentElement.getAttribute('data-theme');
// Enable smooth transition only on user-initiated toggle
document.documentElement.classList.add('theme-transition');
setTheme(current === 'dark' ? 'light' : 'dark');
// Remove transition class after animation completes
setTimeout(() => document.documentElement.classList.remove('theme-transition'), 350);
}

function updateToggleIcon(theme: string) {
const moon = document.querySelector('.theme-icon-moon') as HTMLElement;
const sun = document.querySelector('.theme-icon-sun') as HTMLElement;
if (moon && sun) {
moon.style.display = theme === 'dark' ? 'none' : 'block';
sun.style.display = theme === 'dark' ? 'block' : 'none';
}
}

// Restore saved theme on load, fall back to system preference
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const savedTheme = localStorage.getItem('theme') || (systemPrefersDark ? 'dark' : 'light');
setTheme(savedTheme);

// Listen for system preference changes (when no explicit choice saved)
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
setTheme(e.matches ? 'dark' : 'light');
}
});

// Expose globally for the toggle button
(window as any).__toggleTheme = toggleTheme;

const MAX_VISIBLE = 6;

function initSidebarCollapse() {
Expand Down
118 changes: 118 additions & 0 deletions catalog-ui/src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,105 @@
--ec-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}

/* ── Dark Mode ── */
[data-theme="dark"] {
--ec-page-bg: 15 23 42;
--ec-page-text: 226 232 240;
--ec-page-text-muted: 148 163 184;
--ec-page-border: 51 65 85;

--ec-header-bg: 15 23 42;
--ec-header-text: 226 232 240;
--ec-header-border: 51 65 85;

--ec-accent: 192 132 252;
--ec-accent-hover: 168 85 247;
--ec-accent-subtle: 30 20 50;
--ec-accent-text: 192 132 252;

--ec-button-bg: 226 232 240;
--ec-button-bg-hover: 203 213 225;
--ec-button-text: 15 23 42;

--ec-icon-color: 148 163 184;
--ec-icon-hover: 226 232 240;

--ec-sidebar-bg: 15 23 42;
--ec-sidebar-border: 51 65 85;
--ec-sidebar-text: 148 163 184;
--ec-sidebar-active-bg: 226 232 240;
--ec-sidebar-active-text: 15 23 42;
--ec-sidebar-hover-bg: 30 41 59;

--ec-content-bg: 15 23 42;
--ec-content-text: 226 232 240;
--ec-content-text-muted: 148 163 184;
--ec-content-text-secondary: 148 163 184;
--ec-content-border: 51 65 85;
--ec-content-hover: 30 41 59;
--ec-content-active: 30 20 50;

--ec-input-bg: 30 41 59;
--ec-input-border: 51 65 85;
--ec-input-text: 226 232 240;
--ec-input-placeholder: 100 116 139;

--ec-group-icon-bg: 30 41 59;
--ec-group-icon-text: 148 163 184;

--ec-card-bg: 30 41 59;

--ec-badge-domain-bg: 66 52 14;
--ec-badge-domain-text: 253 224 71;
--ec-badge-service-bg: 76 20 52;
--ec-badge-service-text: 249 168 212;
--ec-badge-event-bg: 69 46 8;
--ec-badge-event-text: 251 191 36;
--ec-badge-command-bg: 76 20 52;
--ec-badge-command-text: 249 168 212;
--ec-badge-query-bg: 46 26 80;
--ec-badge-query-text: 196 181 253;
--ec-badge-default-bg: 51 65 85;
--ec-badge-default-text: 203 213 225;

--ec-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3);
--ec-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.4), 0 1px 2px -1px rgb(0 0 0 / 0.3);
--ec-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3);
}

/* ── Dark overrides for hardcoded badge classes ── */
[data-theme="dark"] .badge-capability { background: rgb(6 78 59); color: rgb(167 243 208); }
[data-theme="dark"] .badge-component { background: rgb(46 26 80); color: rgb(196 181 253); }
[data-theme="dark"] .badge-system { background: rgb(23 37 84); color: rgb(147 197 253); }
[data-theme="dark"] .badge-data { background: rgb(69 46 8); color: rgb(251 191 36); }
[data-theme="dark"] .badge-api { background: rgb(30 27 75); color: rgb(165 180 252); }
[data-theme="dark"] .badge-process { background: rgb(66 52 14); color: rgb(253 224 71); }

[data-theme="dark"] .badge-active { background: rgb(6 78 59); color: rgb(167 243 208); }
[data-theme="dark"] .badge-new { background: rgb(12 74 110); color: rgb(125 211 252); }
[data-theme="dark"] .badge-planned { background: rgb(12 74 110); color: rgb(125 211 252); }
[data-theme="dark"] .badge-deprecated { background: rgb(127 29 29); color: rgb(254 202 202); }
[data-theme="dark"] .badge-retired { background: rgb(51 65 85); color: rgb(148 163 184); }

[data-theme="dark"] .badge-in-house { background: rgb(23 37 84); color: rgb(147 197 253); }
[data-theme="dark"] .badge-vendor { background: rgb(69 46 8); color: rgb(251 191 36); }
[data-theme="dark"] .badge-hybrid { background: rgb(46 26 80); color: rgb(196 181 253); }

[data-theme="dark"] .badge-excellent { background: rgb(6 78 59); color: rgb(167 243 208); }
[data-theme="dark"] .badge-good { background: rgb(23 37 84); color: rgb(147 197 253); }
[data-theme="dark"] .badge-developing { background: rgb(69 46 8); color: rgb(251 191 36); }

/* ── Reset ── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

/* ── Theme transition (applied after initial paint to prevent FOUC) ── */
html.theme-transition,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
transition: background-color 0.3s ease, color 0.2s ease, border-color 0.3s ease, box-shadow 0.3s ease !important;
}

body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: rgb(var(--ec-page-text));
Expand Down Expand Up @@ -545,6 +641,11 @@ button { font-family: inherit; cursor: pointer; }
line-height: 1.6;
}

[data-theme="dark"] .detail-body pre {
background: #0f172a;
border: 1px solid rgb(51 65 85);
}

.detail-body pre code {
background: none;
padding: 0;
Expand Down Expand Up @@ -598,6 +699,10 @@ button { font-family: inherit; cursor: pointer; }
border-color: rgb(203 213 225);
}

[data-theme="dark"] .card:hover {
border-color: rgb(71 85 105);
}

.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
Expand Down Expand Up @@ -729,6 +834,16 @@ button { font-family: inherit; cursor: pointer; }
color: #8b5cf6;
}

[data-theme="dark"] .rel-group-outgoing {
background: rgba(96, 165, 250, 0.15);
color: #60a5fa;
}

[data-theme="dark"] .rel-group-incoming {
background: rgba(167, 139, 250, 0.15);
color: #a78bfa;
}

.rel-group-label {
flex: 1;
}
Expand Down Expand Up @@ -903,6 +1018,9 @@ button { font-family: inherit; cursor: pointer; }
.rel-col-out { background: #3b82f6; }
.rel-col-in { background: #8b5cf6; }

[data-theme="dark"] .rel-col-out { background: #60a5fa; }
[data-theme="dark"] .rel-col-in { background: #a78bfa; }

.rel-cell-pills {
display: inline;
}
Expand Down