diff --git a/package.json b/package.json
index 767710769..a6e07da09 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,8 @@
"build": "pnpm --stream -r --filter \"!@graph-explorer/docs\" run build",
"dev": "pnpm --stream -r --filter \"!@graph-explorer/docs\" run dev",
"docs:dev": "pnpm --filter @graph-explorer/docs run dev",
- "docs:build": "pnpm --filter @graph-explorer/docs run build"
+ "docs:build": "pnpm --filter @graph-explorer/docs run build",
+ "docs:preview": "pnpm --filter @graph-explorer/docs run preview"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "5.100.14",
diff --git a/packages/docs/astro.config.mjs b/packages/docs/astro.config.mjs
index 5098759ee..de9b76a27 100644
--- a/packages/docs/astro.config.mjs
+++ b/packages/docs/astro.config.mjs
@@ -11,16 +11,18 @@ export default defineConfig({
"@fontsource/inter/400.css",
"@fontsource/inter/500.css",
"@fontsource/inter/600.css",
+ "@fontsource/inter/700.css",
"@fontsource/inter/800.css",
+ "./src/styles/tokens.css",
"./src/styles/custom.css",
],
expressiveCode: {
frames: false,
},
components: {
- Head: "./src/components/starlight/Head.astro",
- Header: "./src/components/starlight/Header.astro",
- Hero: "./src/components/starlight/Hero.astro",
+ Head: "./src/components/Head.astro",
+ Header: "./src/components/Header.astro",
+ Hero: "./src/components/Hero.astro",
},
social: [
{
diff --git a/packages/docs/package.json b/packages/docs/package.json
index fbb72a8db..6d956d7a9 100644
--- a/packages/docs/package.json
+++ b/packages/docs/package.json
@@ -12,6 +12,7 @@
"dependencies": {
"@astrojs/starlight": "0.38.3",
"@fontsource/inter": "^5.2.8",
+ "@lucide/astro": "^1.17.0",
"astro": "6.2.2",
"sharp": "0.34.5"
},
diff --git a/packages/docs/public/images/data-explorer.png b/packages/docs/public/images/data-explorer.png
new file mode 100644
index 000000000..a4b99eee1
Binary files /dev/null and b/packages/docs/public/images/data-explorer.png differ
diff --git a/packages/docs/public/images/graph-explorer.png b/packages/docs/public/images/graph-explorer.png
new file mode 100644
index 000000000..8098051f7
Binary files /dev/null and b/packages/docs/public/images/graph-explorer.png differ
diff --git a/packages/docs/public/images/schema-explorer.png b/packages/docs/public/images/schema-explorer.png
new file mode 100644
index 000000000..17553d4fb
Binary files /dev/null and b/packages/docs/public/images/schema-explorer.png differ
diff --git a/packages/docs/src/components/FeatureCard.astro b/packages/docs/src/components/FeatureCard.astro
new file mode 100644
index 000000000..d41309fa4
--- /dev/null
+++ b/packages/docs/src/components/FeatureCard.astro
@@ -0,0 +1,59 @@
+---
+interface Props {
+ title: string;
+}
+
+const { title } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
diff --git a/packages/docs/src/components/starlight/GraphBackground.astro b/packages/docs/src/components/GraphBackground.astro
similarity index 99%
rename from packages/docs/src/components/starlight/GraphBackground.astro
rename to packages/docs/src/components/GraphBackground.astro
index aaa7810e7..1fef97b7b 100644
--- a/packages/docs/src/components/starlight/GraphBackground.astro
+++ b/packages/docs/src/components/GraphBackground.astro
@@ -164,7 +164,7 @@
+
+
diff --git a/packages/docs/src/content/docs/index.mdx b/packages/docs/src/content/docs/index.mdx
deleted file mode 100644
index 09cf0ae2c..000000000
--- a/packages/docs/src/content/docs/index.mdx
+++ /dev/null
@@ -1,45 +0,0 @@
----
-title: Docs
-description: Graph Explorer makes your graph database visual and interactive.
-template: splash
-hero:
- title: Every Connection Tells a Story
- tagline: Graph Explorer makes your graph database visual and interactive. Search, expand, filter, and style — all from your browser.
- actions:
- - text: Get Started
- link: ./getting-started/
- icon: right-arrow
- variant: primary
- - text: View on GitHub
- link: https://github.com/aws/graph-explorer
- icon: external
- variant: minimal
----
-
-import { Card, CardGrid, LinkButton } from "@astrojs/starlight/components";
-
-## Features
-
-
-
- Double-click nodes to expand neighbors, filter by type, and build up a
- visual understanding of your data. [Learn more →](./features/graph-view/)
-
-
- Execute raw Gremlin, openCypher, or SPARQL queries and add results directly
- to the graph canvas. [Learn more →](./features/graph-view/#search-panel)
-
-
- Visualize your graph's schema as an interactive diagram showing node types,
- edge types, and their relationships. [Learn more →](./features/schema-view/)
-
-
- Change colors, shapes, icons, and labels for each node and edge type to make
- the graph meaningful at a glance. [Learn more
- →](./features/graph-view/#node-styling-panel)
-
-
-
-
- Explore all features
-
diff --git a/packages/docs/src/pages/index.astro b/packages/docs/src/pages/index.astro
new file mode 100644
index 000000000..597be03a4
--- /dev/null
+++ b/packages/docs/src/pages/index.astro
@@ -0,0 +1,87 @@
+---
+import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
+import { CardGrid, LinkButton } from "@astrojs/starlight/components";
+import FeatureCard from "../components/FeatureCard.astro";
+import ScreenshotCarousel from "../components/ScreenshotCarousel.astro";
+import { Search, ChevronsLeftRight, NotebookTabs, SwatchBook } from "@lucide/astro";
+---
+
+
+
+
+
+ Features
+
+
+
+
+ Double-click nodes to expand neighbors, filter by type, and build up a
+ visual understanding of your data. Learn more →
+
+
+
+ Execute raw Gremlin, openCypher, or SPARQL queries and add results directly
+ to the graph canvas. Learn more →
+
+
+
+ Visualize your graph's schema as an interactive diagram showing node types,
+ edge types, and their relationships. Learn more →
+
+
+
+ Change colors, shapes, icons, and labels for each node and edge type to make
+ the graph meaningful at a glance. Learn more →
+
+
+
+
+ Explore all features
+
+
+
+
+
diff --git a/packages/docs/src/styles/custom.css b/packages/docs/src/styles/custom.css
index bafe35bf6..1ada741ea 100644
--- a/packages/docs/src/styles/custom.css
+++ b/packages/docs/src/styles/custom.css
@@ -1,92 +1,24 @@
-/* Dark mode — slate grays, violet accent */
-:root {
- --sl-font: "Inter", sans-serif;
- --sl-color-accent-low: oklch(28.3% 0.141 291.089);
- --sl-color-accent: oklch(70.2% 0.183 293.541);
- --sl-color-accent-high: oklch(81.1% 0.111 293.571);
- --sl-color-accent-hover: oklch(81.1% 0.111 293.571);
- --sl-color-white: oklch(98.4% 0.003 247.858);
- --sl-color-gray-1: oklch(96.8% 0.007 247.896);
- --sl-color-gray-2: oklch(86.9% 0.022 252.894);
- --sl-color-gray-3: oklch(70.4% 0.04 256.788);
- --sl-color-gray-4: oklch(55.4% 0.046 257.417);
- --sl-color-gray-5: oklch(37.2% 0.044 257.287);
- --sl-color-gray-6: oklch(27.9% 0.041 260.031);
- --sl-color-gray-7: oklch(20.8% 0.042 265.755);
- --sl-color-black: oklch(12.9% 0.042 264.695);
- --sl-color-bg-nav: var(--sl-color-bg);
- --sl-color-bg-sidebar: var(--sl-color-bg);
- --sl-line-height: 1.6;
-
- --sl-color-orange-high: oklch(47% 0.157 37.304);
- --sl-color-orange: oklch(75% 0.183 55.934);
- --sl-color-orange-low: oklch(95.4% 0.038 75.164);
- --sl-color-green-high: oklch(44.8% 0.119 151.328);
- --sl-color-green: oklch(72.3% 0.219 149.579);
- --sl-color-green-low: oklch(96.2% 0.044 156.743);
- --sl-color-blue-high: oklch(42.4% 0.199 265.638);
- --sl-color-blue: oklch(70.7% 0.165 254.624);
- --sl-color-blue-low: oklch(93.2% 0.032 255.585);
- --sl-color-purple-high: oklch(43.8% 0.218 303.724);
- --sl-color-purple: oklch(71.4% 0.203 305.504);
- --sl-color-purple-low: oklch(94.6% 0.033 307.174);
- --sl-color-red-high: oklch(45.5% 0.188 13.697);
- --sl-color-red: oklch(64.5% 0.246 16.439);
- --sl-color-red-low: oklch(94.1% 0.03 12.58);
-
- --ge-gradient: linear-gradient(
- 135deg,
- oklch(58.5% 0.233 277.117),
- oklch(60.6% 0.25 292.717)
- );
-}
-
-/* Light mode — slate grays, violet accent */
-:root[data-theme="light"] {
- --sl-color-accent-low: oklch(94.3% 0.029 294.588);
- --sl-color-accent: oklch(54.1% 0.281 293.009);
- --sl-color-accent-high: oklch(43.2% 0.232 292.759);
- --sl-color-accent-hover: oklch(60.6% 0.25 292.717);
- --sl-color-white: oklch(12.9% 0.042 264.695);
- --sl-color-gray-1: oklch(20.8% 0.042 265.755);
- --sl-color-gray-2: oklch(27.9% 0.041 260.031);
- --sl-color-gray-3: oklch(44.6% 0.043 257.281);
- --sl-color-gray-4: oklch(55.4% 0.046 257.417);
- --sl-color-gray-5: oklch(86.9% 0.022 252.894);
- --sl-color-gray-6: oklch(96.8% 0.007 247.896);
- --sl-color-gray-7: oklch(98.4% 0.003 247.858);
- --sl-color-black: oklch(98.4% 0.003 247.858);
- --sl-color-bg: oklch(96.8% 0.007 247.896);
- --sl-color-bg-nav: var(--sl-color-bg);
- --sl-color-bg-sidebar: var(--sl-color-bg);
-
- --sl-color-orange-high: oklch(95.4% 0.038 75.164);
- --sl-color-orange: oklch(64.6% 0.222 41.116);
- --sl-color-orange-low: oklch(47% 0.157 37.304);
- --sl-color-green-high: oklch(96.2% 0.044 156.743);
- --sl-color-green: oklch(62.7% 0.194 149.214);
- --sl-color-green-low: oklch(44.8% 0.119 151.328);
- --sl-color-blue-high: oklch(93.2% 0.032 255.585);
- --sl-color-blue: oklch(54.6% 0.245 262.881);
- --sl-color-blue-low: oklch(42.4% 0.199 265.638);
- --sl-color-purple-high: oklch(94.6% 0.033 307.174);
- --sl-color-purple: oklch(55.8% 0.288 302.321);
- --sl-color-purple-low: oklch(43.8% 0.218 303.724);
- --sl-color-red-high: oklch(94.1% 0.03 12.58);
- --sl-color-red: oklch(58.6% 0.253 17.585);
- --sl-color-red-low: oklch(45.5% 0.188 13.697);
-
- --ge-gradient: linear-gradient(
- 135deg,
- oklch(51.1% 0.262 276.966),
- oklch(54.1% 0.281 293.009)
- );
-}
+/* ==========================================================================
+ View Transitions
+ ========================================================================== */
::view-transition-group(*) {
animation-duration: 50ms;
}
+/* ==========================================================================
+ Global Typography
+ ========================================================================== */
+
+html {
+ -webkit-font-smoothing: antialiased;
+}
+
+p {
+ text-wrap: pretty;
+}
+
+/* Heading base */
h1,
h2,
h3,
@@ -94,20 +26,98 @@ h4,
h5,
h6 {
text-wrap: balance;
+ font-weight: 700;
+ line-height: var(--sl-line-height-headings);
+ letter-spacing: -0.02em;
+ margin-block: 1.5rem 0.5rem;
}
-p {
- text-wrap: pretty;
+/* Tiered heading weights */
+h1,
+h2,
+h3 {
+ font-weight: 800;
+ letter-spacing: -0.03em;
+}
+
+h4,
+h5,
+h6 {
+ letter-spacing: -0.015em;
+}
+
+/* h6 as label style */
+h6 {
+ text-transform: uppercase;
+ letter-spacing: 0.035em;
+}
+
+/* ==========================================================================
+ Content Links
+ ========================================================================== */
+
+.sl-markdown-content a {
+ font-weight: 500;
+ text-decoration: none;
+ color: var(--sl-color-accent);
+}
+
+.sl-markdown-content a:hover,
+.sl-markdown-content a:focus {
+ text-decoration: underline;
+ color: var(--sl-color-accent);
+}
+
+/* ==========================================================================
+ Pagination
+ ========================================================================== */
+
+.pagination-links {
+ font-size: var(--sl-text-sm);
+ font-weight: 400;
+ line-height: 1.5;
+}
+
+.pagination-links .link-title {
+ font-size: var(--sl-text-lg);
+ font-weight: 600;
+ line-height: 1.4;
+}
+
+.pagination-links a {
+ --sl-shadow-md: var(--sl-shadow-sm);
+ border: 1px solid var(--sl-color-gray-5);
+ background: var(--sl-color-gray-7);
+ border-radius: 0.75rem;
+ transition:
+ border-color 0.2s ease,
+ box-shadow 0.2s ease;
+}
+
+.pagination-links a:hover {
+ border-color: var(--sl-color-accent);
+ box-shadow: 0 0 12px oklch(60.6% 0.25 292.717 / 0.06);
+}
+
+:root[data-theme="light"] .pagination-links a:hover {
+ border-color: var(--sl-color-accent);
+ box-shadow: 0 2px 12px oklch(54.1% 0.281 293.009 / 0.06);
}
-/* Dark mode background noise texture */
+/* ==========================================================================
+ Background Texture
+ ========================================================================== */
+
:root:not([data-theme="light"]) body {
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.015'/%3E%3C/svg%3E");
background-repeat: repeat;
background-size: 256px;
}
-/* Cards with gradient hover border */
+/* ==========================================================================
+ Cards
+ ========================================================================== */
+
.card-grid {
gap: 1rem;
}
@@ -144,16 +154,55 @@ p {
}
.card .title {
- font-weight: 600;
flex-direction: column;
align-items: flex-start;
}
.card .body {
- color: var(--sl-color-gray-2);
+ line-height: 1.5;
+ color: var(--sl-color-gray-3);
+}
+
+/* ==========================================================================
+ Link Cards
+ ========================================================================== */
+
+.sl-link-card {
+ border: 1px solid var(--sl-color-gray-5);
+ background: var(--sl-color-gray-7);
+ border-radius: 0.75rem;
+ transition:
+ border-color 0.2s ease,
+ box-shadow 0.2s ease;
}
-/* Nav bar */
+.sl-link-card:hover {
+ border-color: var(--sl-color-accent);
+ box-shadow: 0 0 12px oklch(60.6% 0.25 292.717 / 0.06);
+}
+
+:root[data-theme="light"] .sl-link-card:hover {
+ border-color: var(--sl-color-accent);
+ box-shadow: 0 2px 12px oklch(54.1% 0.281 293.009 / 0.06);
+}
+
+.sl-link-card .title {
+ font-size: var(--sl-text-h5);
+}
+
+.sl-link-card .description {
+ font-size: var(--sl-text-sm);
+}
+
+.sl-link-card a:hover,
+.sl-link-card a:focus {
+ text-decoration: none;
+}
+
+/* ==========================================================================
+ Nav Bar
+ ========================================================================== */
+
header.header {
background: oklch(12.9% 0.042 264.695 / 0.8);
backdrop-filter: blur(12px);
@@ -166,7 +215,7 @@ header.header {
border-bottom: 1px solid oklch(86.9% 0.022 252.894 / 0.5);
}
-/* Site title with gradient on hover */
+/* Site title */
.site-title {
font-weight: 800;
color: var(--sl-color-white);
@@ -177,6 +226,7 @@ header.header {
color: var(--sl-color-accent);
}
+/* Social icons */
header .social-icons a {
color: var(--sl-color-gray-2);
}
@@ -185,57 +235,70 @@ header .social-icons a:hover {
color: var(--sl-color-accent);
}
-/* Pagination prev/next links */
-.pagination-links a {
- --sl-shadow-md: var(--sl-shadow-sm);
- border: 1px solid var(--sl-color-gray-5);
- background: var(--sl-color-gray-7);
- border-radius: 0.75rem;
- transition:
- border-color 0.2s ease,
- box-shadow 0.2s ease;
-}
+/* ==========================================================================
+ Sidebar
+ ========================================================================== */
-.pagination-links a:hover {
- border-color: var(--sl-color-accent);
- box-shadow: 0 0 12px oklch(60.6% 0.25 292.717 / 0.06);
+.sidebar-content summary {
+ padding: 0;
}
-:root[data-theme="light"] .pagination-links a:hover {
- border-color: var(--sl-color-accent);
- box-shadow: 0 2px 12px oklch(54.1% 0.281 293.009 / 0.06);
+/* Group labels */
+.sidebar-content .group-label {
+ font-size: var(--sl-text-xs);
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+ margin-block-start: 1.5rem;
+ margin-block-end: 0.5rem;
+ padding: 0 0.75rem;
}
-/* Link cards */
-.sl-link-card {
- border: 1px solid var(--sl-color-gray-5);
- background: var(--sl-color-gray-7);
- border-radius: 0.75rem;
- transition:
- border-color 0.2s ease,
- box-shadow 0.2s ease;
+.sidebar-content .group-label .large {
+ font-size: var(--sl-text-xs);
}
-.sl-link-card:hover {
- border-color: var(--sl-color-accent);
- box-shadow: 0 0 12px oklch(60.6% 0.25 292.717 / 0.06);
+/* Sidebar links */
+.sidebar-content a {
+ color: var(--sl-color-gray-3);
+ font-weight: 400;
+ border-radius: 0.375rem;
+ transition:
+ color 0.15s,
+ background-color 0.15s;
+ padding: 0.35rem 0.75rem;
}
-:root[data-theme="light"] .sl-link-card:hover {
- border-color: var(--sl-color-accent);
- box-shadow: 0 2px 12px oklch(54.1% 0.281 293.009 / 0.06);
+.sidebar-content a:hover {
+ color: var(--sl-color-white);
+ text-decoration: none;
}
-/* Subtle sidebar active item */
+/* Active sidebar link */
.sidebar-content a[aria-current="page"],
.sidebar-content a[aria-current="page"]:hover,
.sidebar-content a[aria-current="page"]:focus {
- background-color: transparent;
+ background-color: oklch(from var(--sl-color-accent) l c h / 0.1);
color: var(--sl-color-accent);
- font-weight: 600;
+ font-weight: 400;
}
-/* Primary button with gradient */
+/* Remove nested indentation */
+.sidebar-content ul ul li {
+ margin-inline-start: 0;
+ border-inline-start: none;
+ padding-inline-start: 0;
+}
+
+/* ==========================================================================
+ Buttons
+ ========================================================================== */
+
+.sl-link-button {
+ padding: 0.85rem 1.3rem;
+ border-radius: 0.5rem;
+}
+
+/* Primary — gradient with glow */
.sl-link-button.primary {
background: var(--ge-gradient);
border-color: transparent;
@@ -244,19 +307,23 @@ header .social-icons a:hover {
transition:
box-shadow 0.2s ease,
filter 0.2s ease;
- box-shadow: 0 2px 8px oklch(58.5% 0.233 277.117 / 0.15);
+ box-shadow: 0 2px 12px oklch(58.5% 0.233 277.117 / 0.2);
}
.sl-link-button.primary:hover {
- box-shadow: 0 2px 12px oklch(58.5% 0.233 277.117 / 0.25);
- filter: brightness(1.15);
+ box-shadow: 0 4px 20px oklch(58.5% 0.233 277.117 / 0.3);
+ filter: brightness(1.1);
background: var(--ge-gradient);
border-color: transparent;
color: oklch(98.4% 0.003 247.858);
}
-/* Secondary button */
+/* Secondary — outline */
.sl-link-button.secondary {
+ border-width: 1px;
+ font-weight: 500;
+ border-color: var(--sl-color-gray-3);
+ color: var(--sl-color-gray-3);
transition:
border-color 0.2s ease,
color 0.2s ease;
@@ -265,9 +332,10 @@ header .social-icons a:hover {
.sl-link-button.secondary:hover {
border-color: var(--sl-color-accent);
color: var(--sl-color-accent);
+ text-decoration: none;
}
-/* Minimal button (e.g. "View on GitHub") */
+/* Minimal — text only */
.sl-link-button.minimal {
transition: color 0.2s ease;
}
@@ -276,82 +344,68 @@ header .social-icons a:hover {
color: var(--sl-color-accent);
}
-/* Gradient divider for sections on splash page */
-[data-page-type="splash"] h2 {
- position: relative;
- padding-bottom: 0.75rem;
-}
+/* ==========================================================================
+ Asides
+ ========================================================================== */
-[data-page-type="splash"] h2::after {
- content: "";
- position: absolute;
- bottom: 0;
- left: 0;
- width: 3rem;
- height: 2px;
- background: var(--ge-gradient);
- border-radius: 1px;
-}
-
-/* Subtle asides — dark mode */
+/* Dark mode */
.starlight-aside--note {
background-color: var(--sl-color-gray-6);
--sl-color-asides-text-accent: var(--sl-color-blue-low);
}
+
.starlight-aside--tip {
background-color: var(--sl-color-gray-6);
--sl-color-asides-text-accent: var(--sl-color-purple-low);
}
+
.starlight-aside--caution {
background-color: var(--sl-color-gray-6);
--sl-color-asides-text-accent: var(--sl-color-orange-low);
}
+
.starlight-aside--danger {
background-color: var(--sl-color-gray-6);
--sl-color-asides-text-accent: var(--sl-color-red-low);
}
-/* Subtle asides — light mode */
+/* Light mode */
:root[data-theme="light"] .starlight-aside--note {
background-color: oklch(from var(--sl-color-blue-low) l c h / 15%);
--sl-color-asides-text-accent: var(--sl-color-blue-low);
}
+
:root[data-theme="light"] .starlight-aside--tip {
background-color: oklch(from var(--sl-color-purple-low) l c h / 15%);
--sl-color-asides-text-accent: var(--sl-color-purple-low);
}
+
:root[data-theme="light"] .starlight-aside--caution {
background-color: oklch(from var(--sl-color-orange-low) l c h / 15%);
--sl-color-asides-text-accent: var(--sl-color-orange-low);
}
+
:root[data-theme="light"] .starlight-aside--danger {
background-color: oklch(from var(--sl-color-red-low) l c h / 15%);
--sl-color-asides-text-accent: var(--sl-color-red-low);
}
-/* Subtle badges */
-:root {
- --sl-badge-default-bg: oklch(from var(--sl-color-accent-high) l c h / 15%);
- --sl-badge-default-border: var(--sl-color-accent-high);
- --sl-badge-default-text: var(--sl-color-accent-high);
-
- --sl-badge-note-bg: oklch(from var(--sl-color-blue-low) l c h / 15%);
- --sl-badge-note-border: var(--sl-color-blue-low);
- --sl-badge-note-text: var(--sl-color-blue-low);
+/* ==========================================================================
+ Tabs
+ ========================================================================== */
- --sl-badge-danger-bg: oklch(from var(--sl-color-red-low) l c h / 15%);
- --sl-badge-danger-border: var(--sl-color-red-low);
- --sl-badge-danger-text: var(--sl-color-red-low);
-
- --sl-badge-success-bg: oklch(from var(--sl-color-green-low) l c h / 15%);
- --sl-badge-success-border: var(--sl-color-green-low);
- --sl-badge-success-text: var(--sl-color-green-low);
+.tab a[role="tab"] {
+ color: var(--sl-color-gray-3);
+ text-decoration: none;
+ padding: 0.625rem 1.25rem;
+ font-weight: 500;
+}
- --sl-badge-caution-bg: oklch(from var(--sl-color-orange-low) l c h / 15%);
- --sl-badge-caution-border: var(--sl-color-orange-low);
- --sl-badge-caution-text: var(--sl-color-orange-low);
+.tab a[role="tab"]:hover {
+ color: var(--sl-color-white);
+ text-decoration: none;
+}
- --sl-badge-tip-bg: oklch(from var(--sl-color-purple-low) l c h / 15%);
- --sl-badge-tip-border: var(--sl-color-purple-low);
- --sl-badge-tip-text: var(--sl-color-purple-low);
+.tab a[role="tab"][aria-selected="true"] {
+ color: var(--sl-color-accent);
}
diff --git a/packages/docs/src/styles/tokens.css b/packages/docs/src/styles/tokens.css
new file mode 100644
index 000000000..5674b13ef
--- /dev/null
+++ b/packages/docs/src/styles/tokens.css
@@ -0,0 +1,125 @@
+/* ==========================================================================
+ Color Tokens — Dark Mode
+ ========================================================================== */
+
+:root {
+ --sl-color-accent-low: oklch(28.3% 0.141 291.089);
+ --sl-color-accent: oklch(70.2% 0.183 293.541);
+ --sl-color-accent-high: oklch(81.1% 0.111 293.571);
+ --sl-color-accent-hover: oklch(81.1% 0.111 293.571);
+ --sl-color-white: oklch(98.4% 0.003 247.858);
+ --sl-color-gray-1: oklch(96.8% 0.007 247.896);
+ --sl-color-gray-2: oklch(86.9% 0.022 252.894);
+ --sl-color-gray-3: oklch(70.4% 0.04 256.788);
+ --sl-color-gray-4: oklch(55.4% 0.046 257.417);
+ --sl-color-gray-5: oklch(37.2% 0.044 257.287);
+ --sl-color-gray-6: oklch(27.9% 0.041 260.031);
+ --sl-color-gray-7: oklch(20.8% 0.042 265.755);
+ --sl-color-black: oklch(12.9% 0.042 264.695);
+ --sl-color-bg-nav: var(--sl-color-bg);
+ --sl-color-bg-sidebar: var(--sl-color-bg);
+
+ /* Semantic colors */
+ --sl-color-orange-high: oklch(47% 0.157 37.304);
+ --sl-color-orange: oklch(75% 0.183 55.934);
+ --sl-color-orange-low: oklch(95.4% 0.038 75.164);
+ --sl-color-green-high: oklch(44.8% 0.119 151.328);
+ --sl-color-green: oklch(72.3% 0.219 149.579);
+ --sl-color-green-low: oklch(96.2% 0.044 156.743);
+ --sl-color-blue-high: oklch(42.4% 0.199 265.638);
+ --sl-color-blue: oklch(70.7% 0.165 254.624);
+ --sl-color-blue-low: oklch(93.2% 0.032 255.585);
+ --sl-color-purple-high: oklch(43.8% 0.218 303.724);
+ --sl-color-purple: oklch(71.4% 0.203 305.504);
+ --sl-color-purple-low: oklch(94.6% 0.033 307.174);
+ --sl-color-red-high: oklch(45.5% 0.188 13.697);
+ --sl-color-red: oklch(64.5% 0.246 16.439);
+ --sl-color-red-low: oklch(94.1% 0.03 12.58);
+
+ /* Typography — minor third scale (1.2) */
+ --sl-font: "Inter", sans-serif;
+ --sl-line-height: 1.6;
+ --sl-text-h1: calc(var(--sl-text-sm) * pow(1.2, 6 - 1));
+ --sl-text-h2: calc(var(--sl-text-sm) * pow(1.2, 6 - 2));
+ --sl-text-h3: calc(var(--sl-text-sm) * pow(1.2, 6 - 3));
+ --sl-text-h4: calc(var(--sl-text-sm) * pow(1.2, 6 - 4));
+ --sl-text-h5: calc(var(--sl-text-sm) * pow(1.2, 6 - 5));
+ --sl-text-h6: calc(var(--sl-text-sm) * pow(1.2, 6 - 6));
+
+ /* Brand gradient */
+ --ge-gradient: linear-gradient(
+ 135deg,
+ oklch(58.5% 0.233 277.117),
+ oklch(60.6% 0.25 292.717)
+ );
+
+ /* Badges */
+ --sl-badge-default-bg: oklch(from var(--sl-color-accent-high) l c h / 15%);
+ --sl-badge-default-border: var(--sl-color-accent-high);
+ --sl-badge-default-text: var(--sl-color-accent-high);
+
+ --sl-badge-note-bg: oklch(from var(--sl-color-blue-low) l c h / 15%);
+ --sl-badge-note-border: var(--sl-color-blue-low);
+ --sl-badge-note-text: var(--sl-color-blue-low);
+
+ --sl-badge-danger-bg: oklch(from var(--sl-color-red-low) l c h / 15%);
+ --sl-badge-danger-border: var(--sl-color-red-low);
+ --sl-badge-danger-text: var(--sl-color-red-low);
+
+ --sl-badge-success-bg: oklch(from var(--sl-color-green-low) l c h / 15%);
+ --sl-badge-success-border: var(--sl-color-green-low);
+ --sl-badge-success-text: var(--sl-color-green-low);
+
+ --sl-badge-caution-bg: oklch(from var(--sl-color-orange-low) l c h / 15%);
+ --sl-badge-caution-border: var(--sl-color-orange-low);
+ --sl-badge-caution-text: var(--sl-color-orange-low);
+
+ --sl-badge-tip-bg: oklch(from var(--sl-color-purple-low) l c h / 15%);
+ --sl-badge-tip-border: var(--sl-color-purple-low);
+ --sl-badge-tip-text: var(--sl-color-purple-low);
+}
+
+/* ==========================================================================
+ Color Tokens — Light Mode
+ ========================================================================== */
+
+:root[data-theme="light"] {
+ --sl-color-accent-low: oklch(94.3% 0.029 294.588);
+ --sl-color-accent: oklch(54.1% 0.281 293.009);
+ --sl-color-accent-high: oklch(43.2% 0.232 292.759);
+ --sl-color-accent-hover: oklch(60.6% 0.25 292.717);
+ --sl-color-white: oklch(12.9% 0.042 264.695);
+ --sl-color-gray-1: oklch(20.8% 0.042 265.755);
+ --sl-color-gray-2: oklch(27.9% 0.041 260.031);
+ --sl-color-gray-3: oklch(44.6% 0.043 257.281);
+ --sl-color-gray-4: oklch(55.4% 0.046 257.417);
+ --sl-color-gray-5: oklch(86.9% 0.022 252.894);
+ --sl-color-gray-6: oklch(96.8% 0.007 247.896);
+ --sl-color-gray-7: oklch(98.4% 0.003 247.858);
+ --sl-color-black: oklch(98.4% 0.003 247.858);
+ --sl-color-bg: oklch(96.8% 0.007 247.896);
+ --sl-color-bg-nav: var(--sl-color-bg);
+ --sl-color-bg-sidebar: var(--sl-color-bg);
+
+ --sl-color-orange-high: oklch(95.4% 0.038 75.164);
+ --sl-color-orange: oklch(64.6% 0.222 41.116);
+ --sl-color-orange-low: oklch(47% 0.157 37.304);
+ --sl-color-green-high: oklch(96.2% 0.044 156.743);
+ --sl-color-green: oklch(62.7% 0.194 149.214);
+ --sl-color-green-low: oklch(44.8% 0.119 151.328);
+ --sl-color-blue-high: oklch(93.2% 0.032 255.585);
+ --sl-color-blue: oklch(54.6% 0.245 262.881);
+ --sl-color-blue-low: oklch(42.4% 0.199 265.638);
+ --sl-color-purple-high: oklch(94.6% 0.033 307.174);
+ --sl-color-purple: oklch(55.8% 0.288 302.321);
+ --sl-color-purple-low: oklch(43.8% 0.218 303.724);
+ --sl-color-red-high: oklch(94.1% 0.03 12.58);
+ --sl-color-red: oklch(58.6% 0.253 17.585);
+ --sl-color-red-low: oklch(45.5% 0.188 13.697);
+
+ --ge-gradient: linear-gradient(
+ 135deg,
+ oklch(51.1% 0.262 276.966),
+ oklch(54.1% 0.281 293.009)
+ );
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 414800a8d..f18b853f8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -66,6 +66,9 @@ importers:
'@fontsource/inter':
specifier: ^5.2.8
version: 5.2.8
+ '@lucide/astro':
+ specifier: ^1.17.0
+ version: 1.17.0(astro@6.2.2(@types/node@25.6.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.3)(terser@5.42.0)(tsx@4.21.0)(yaml@2.8.3))
astro:
specifier: 6.2.2
version: 6.2.2(@types/node@25.6.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.3)(terser@5.42.0)(tsx@4.21.0)(yaml@2.8.3)
@@ -1760,6 +1763,11 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@lucide/astro@1.17.0':
+ resolution: {integrity: sha512-wF5wyjF8zThvI5JVUWG1WLoFdbTcMNXouxnholAyR0EEFfWNnGP1DGsvuu7cym/2mj2vUEjPbIPPDgWwjabFRQ==}
+ peerDependencies:
+ astro: ^4 || ^5 || ^6
+
'@mdx-js/mdx@3.1.1':
resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
@@ -8344,6 +8352,10 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@lucide/astro@1.17.0(astro@6.2.2(@types/node@25.6.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.3)(terser@5.42.0)(tsx@4.21.0)(yaml@2.8.3))':
+ dependencies:
+ astro: 6.2.2(@types/node@25.6.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.3)(terser@5.42.0)(tsx@4.21.0)(yaml@2.8.3)
+
'@mdx-js/mdx@3.1.1':
dependencies:
'@types/estree': 1.0.8
@@ -12510,7 +12522,7 @@ snapshots:
parse-json@5.2.0:
dependencies:
- '@babel/code-frame': 7.29.0
+ '@babel/code-frame': 7.29.7
error-ex: 1.3.4
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4