diff --git a/app/app.config.ts b/app/app.config.ts index b5c2f34bb..5f64020cb 100644 --- a/app/app.config.ts +++ b/app/app.config.ts @@ -7,21 +7,63 @@ export default defineAppConfig({ colors: { primary: 'purple', secondary: 'pink', - neutral: 'slate', + neutral: 'neutral', }, + button: { + slots: { + base: 'rounded-l-full rounded-r-full', + }, + }, + + container: { + base: '@max-[40rem]/docs-pane:px-4! @min-[40rem]/docs-pane:px-6! @min-[64rem]/docs-pane:px-8!', + }, + header: { + slots: { + left: '@max-[40rem]/docs-pane:flex-none! @min-[40rem]/docs-pane:flex-1!', + center: '@max-[40rem]/docs-pane:hidden! @min-[40rem]/docs-pane:flex!', + right: '@max-[40rem]/docs-pane:flex-none! @min-[40rem]/docs-pane:flex-1!', + toggle: '@max-[40rem]/docs-pane:flex! @min-[40rem]/docs-pane:hidden!', + content: '@max-[40rem]/docs-pane:block! @min-[40rem]/docs-pane:hidden!', + overlay: '@max-[40rem]/docs-pane:block! @min-[40rem]/docs-pane:hidden!', + }, + }, + contentToc: { + slots: { + bottom: '@max-[64rem]/docs-pane:hidden! @min-[64rem]/docs-pane:flex!', + }, + }, content: { callout: { // Fix background color of pre > code blocks wrapper: '[&_pre>code]:!bg-transparent', }, }, - page: { + contentSurround: { + slots: { + root: 'flex flex-col-reverse sm:grid sm:grid-cols-2 gap-8', + }, + }, + pageHeader: { slots: { - root: 'lg:gap-8', + wrapper: '@max-[40rem]/docs-pane:flex-col! @max-[40rem]/docs-pane:items-stretch! @max-[40rem]/docs-pane:justify-start! @min-[40rem]/docs-pane:flex-row! @min-[40rem]/docs-pane:items-center! @min-[40rem]/docs-pane:justify-between!', + title: 'text-3xl sm:text-4xl text-pretty font-display font-medium text-highlighted', }, }, prose: { + h1: { + base: 'font-display font-medium', + }, + h2: { + base: 'font-display font-medium', + }, + h3: { + base: 'font-display font-medium', + }, + h4: { + base: 'font-display font-medium', + }, pre: { slots: { base: 'text-xs/4', @@ -92,7 +134,7 @@ export default defineAppConfig({ { label: 'Security', to: '/guides/security/best-practices', - icon: 'i-ph-shield-check', + icon: 'material-symbols:verified-user-outline', }, { label: 'AI', @@ -112,17 +154,17 @@ export default defineAppConfig({ { label: 'Cloud', to: '/cloud/getting-started/introduction', - icon: 'i-ph-cloud', + icon: 'material-symbols:cloud-outline', }, { label: 'Self-Hosting', to: '/self-hosting/overview', - icon: 'i-ph-hard-drives', + icon: 'material-symbols:dns-outline', }, { label: 'Configuration', to: '/configuration/intro', - icon: 'i-ph-gear', + icon: 'material-symbols:settings-outline', }, ], }, @@ -132,22 +174,22 @@ export default defineAppConfig({ { label: 'Frameworks', to: '/frameworks', - icon: 'i-ph-brackets-curly', + icon: 'material-symbols:data-object', }, { label: 'Tutorials', to: '/tutorials', - icon: 'i-ph-article', + icon: 'material-symbols:article-outline', }, { label: 'Community', to: '/community/overview/welcome', - icon: 'i-ph-hand-heart', + icon: 'material-symbols:volunteer-activism-outline', }, { label: 'Releases', to: '/releases', - icon: 'i-ph-notebook', + icon: 'material-symbols:menu-book-outline', }, ], }, diff --git a/app/app.vue b/app/app.vue index 84522c811..9d027fe12 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,27 +1,67 @@ diff --git a/app/assets/css/main.css b/app/assets/css/main.css index 33c2e95f0..44f43b13b 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -2,10 +2,12 @@ @import "@nuxt/ui"; @source "../../../content/**/*"; +@source "../../../modules/**/*.{vue,ts}"; @theme static { --font-sans: "Inter", sans-serif; - --font-display: "Poppins", sans-serif; + --font-display: "Source Serif 4", serif; + --font-mono: "IBM Plex Mono", monospace; --color-purple-50: #f3f2ff; --color-purple-100: #e9e8ff; @@ -35,6 +37,14 @@ --diff-green: rgba(16, 185, 129, 0.2); } +.dark { + --ui-bg: #090909; +} + +::selection { + background: color-mix(in srgb, var(--color-primary) 50%, var(--ui-bg) 50%); +} + /* The default border color has changed to `currentcolor` in Tailwind CSS v4, so we've added these compatibility styles to make sure everything still @@ -66,6 +76,12 @@ html { scroll-behavior: smooth; } +.sp-divider, +.sp-divider *, +.sp-divider > :first-child::after { + cursor: col-resize !important; +} + pre { > code { & .line.diff.remove { @@ -78,3 +94,56 @@ pre { } } } + +html .shiki span { + color: var(--shiki-default); + background: var(--shiki-default-bg); + font-style: var(--shiki-default-font-style); + font-weight: var(--shiki-default-font-weight); + text-decoration: var(--shiki-default-text-decoration); +} + +html.light .shiki span, +html .light .shiki span { + color: var(--shiki-light); + background: var(--shiki-light-bg); + font-style: var(--shiki-light-font-style); + font-weight: var(--shiki-light-font-weight); + text-decoration: var(--shiki-light-text-decoration); +} + +html.dark .shiki span, +html .dark .shiki span { + color: var(--shiki-dark); + background: var(--shiki-dark-bg); + font-style: var(--shiki-dark-font-style); + font-weight: var(--shiki-dark-font-weight); + text-decoration: var(--shiki-dark-text-decoration); +} + +.scrollbar-thin { + scrollbar-width: thin; + scrollbar-color: var(--ui-border-accented) var(--ui-bg-muted); +} + +.scrollbar-thin::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.scrollbar-thin::-webkit-scrollbar-track { + background: var(--ui-bg-muted); + border-radius: 999px; +} + +.scrollbar-thin::-webkit-scrollbar-thumb { + background-color: var(--ui-border-accented); + border-radius: 999px; + border: 2px solid transparent; + background-clip: content-box; +} + +.scrollbar-thin::-webkit-scrollbar-thumb:hover { + background-color: var(--ui-text-dimmed); + background-clip: content-box; +} diff --git a/app/assets/shiki/directus-dark.json b/app/assets/shiki/directus-dark.json new file mode 100644 index 000000000..df6047e07 --- /dev/null +++ b/app/assets/shiki/directus-dark.json @@ -0,0 +1,318 @@ +{ + "name": "directus-dark", + "semanticHighlighting": true, + "tokenColors": [ + { + "settings": { + "foreground": "#94a3b8", + "background": "transparent" + } + }, + { + "scope": ["comment", "punctuation.definition.comment", "string.comment"], + "settings": { + "foreground": "#94a3b8" + } + }, + { + "scope": [ + "constant", + "entity.name.constant", + "variable.other.constant", + "variable.other.enummember", + "variable.language" + ], + "settings": { + "foreground": "#9B8BFF" + } + }, + { + "scope": ["entity", "entity.name"], + "settings": { + "foreground": "#9B8BFF" + } + }, + { + "scope": "variable.parameter.function", + "settings": { + "foreground": "#0e1c2f" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#22863a" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#FF97DC" + } + }, + { + "scope": ["storage", "storage.type"], + "settings": { + "foreground": "#FF97DC" + } + }, + { + "scope": ["storage.modifier.package", "storage.modifier.import", "storage.type.java"], + "settings": { + "foreground": "#e2e8f0" + } + }, + { + "scope": ["string", "punctuation.definition.string", "string punctuation.section.embedded source"], + "settings": { + "foreground": "#f8fafc" + } + }, + { + "scope": "support", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": "meta.property-name", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": "variable", + "settings": { + "foreground": "#FF97DC" + } + }, + { + "scope": "variable.other", + "settings": { + "foreground": "#e2e8f0" + } + }, + { + "scope": "invalid.broken", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "invalid.deprecated", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "invalid.illegal", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "invalid.unimplemented", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "carriage-return", + "settings": { + "fontStyle": "italic underline", + "background": "#FF97DC", + "foreground": "#fafbfc", + "content": "^M" + } + }, + { + "scope": "message.error", + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": "string variable", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": ["source.regexp", "string.regexp"], + "settings": { + "foreground": "#f8fafc" + } + }, + { + "scope": [ + "string.regexp.character-class", + "string.regexp constant.character.escape", + "string.regexp source.ruby.embedded", + "string.regexp string.regexp.arbitrary-repitition" + ], + "settings": { + "foreground": "#f8fafc" + } + }, + { + "scope": "string.regexp constant.character.escape", + "settings": { + "fontStyle": "bold", + "foreground": "#22863a" + } + }, + { + "scope": "support.constant", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": "support.variable", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": "meta.module-reference", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": "punctuation.definition.list.begin.markdown", + "settings": { + "foreground": "#FF97DC" + } + }, + { + "scope": ["markup.heading", "markup.heading entity.name"], + "settings": { + "fontStyle": "bold", + "foreground": "#6644FF" + } + }, + { + "scope": "markup.quote", + "settings": { + "foreground": "#22863a" + } + }, + { + "scope": "markup.italic", + "settings": { + "fontStyle": "italic", + "foreground": "#e2e8f0" + } + }, + { + "scope": "markup.bold", + "settings": { + "fontStyle": "bold", + "foreground": "#e2e8f0" + } + }, + { + "scope": ["markup.underline"], + "settings": { + "fontStyle": "underline" + } + }, + { + "scope": ["markup.strikethrough"], + "settings": { + "fontStyle": "strikethrough" + } + }, + { + "scope": "markup.inline.raw", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": ["markup.deleted", "meta.diff.header.from-file", "punctuation.definition.deleted"], + "settings": { + "background": "#ffeef0", + "foreground": "#b31d28" + } + }, + { + "scope": ["markup.inserted", "meta.diff.header.to-file", "punctuation.definition.inserted"], + "settings": { + "background": "#f0fff4", + "foreground": "#22863a" + } + }, + { + "scope": ["markup.changed", "punctuation.definition.changed"], + "settings": { + "background": "#ffebda", + "foreground": "#FF97DC" + } + }, + { + "scope": ["markup.ignored", "markup.untracked"], + "settings": { + "foreground": "#f6f8fa", + "background": "#6644FF" + } + }, + { + "scope": "meta.diff.range", + "settings": { + "foreground": "#9B8BFF", + "fontStyle": "bold" + } + }, + { + "scope": "meta.diff.header", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": "meta.separator", + "settings": { + "fontStyle": "bold", + "foreground": "#6644FF" + } + }, + { + "scope": "meta.output", + "settings": { + "foreground": "#6644FF" + } + }, + { + "scope": [ + "brackethighlighter.tag", + "brackethighlighter.curly", + "brackethighlighter.round", + "brackethighlighter.square", + "brackethighlighter.angle", + "brackethighlighter.quote" + ], + "settings": { + "foreground": "#586069" + } + }, + { + "scope": "brackethighlighter.unmatched", + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": ["constant.other.reference.link", "string.other.link"], + "settings": { + "foreground": "#f8fafc", + "fontStyle": "underline" + } + } + ] +} diff --git a/app/assets/shiki/directus-light.json b/app/assets/shiki/directus-light.json new file mode 100644 index 000000000..9457c59a4 --- /dev/null +++ b/app/assets/shiki/directus-light.json @@ -0,0 +1,318 @@ +{ + "name": "directus-light", + "semanticHighlighting": true, + "tokenColors": [ + { + "settings": { + "foreground": "#1f2937", + "background": "transparent" + } + }, + { + "scope": ["comment", "punctuation.definition.comment", "string.comment"], + "settings": { + "foreground": "#64748b" + } + }, + { + "scope": [ + "constant", + "entity.name.constant", + "variable.other.constant", + "variable.other.enummember", + "variable.language" + ], + "settings": { + "foreground": "#531ee3" + } + }, + { + "scope": ["entity", "entity.name"], + "settings": { + "foreground": "#531ee3" + } + }, + { + "scope": "variable.parameter.function", + "settings": { + "foreground": "#0e1c2f" + } + }, + { + "scope": "entity.name.tag", + "settings": { + "foreground": "#22863a" + } + }, + { + "scope": "keyword", + "settings": { + "foreground": "#ca0c72" + } + }, + { + "scope": ["storage", "storage.type"], + "settings": { + "foreground": "#ca0c72" + } + }, + { + "scope": ["storage.modifier.package", "storage.modifier.import", "storage.type.java"], + "settings": { + "foreground": "#24292e" + } + }, + { + "scope": ["string", "punctuation.definition.string", "string punctuation.section.embedded source"], + "settings": { + "foreground": "#032f62" + } + }, + { + "scope": "support", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": "meta.property-name", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": "variable", + "settings": { + "foreground": "#ca0c72" + } + }, + { + "scope": "variable.other", + "settings": { + "foreground": "#24292e" + } + }, + { + "scope": "invalid.broken", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "invalid.deprecated", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "invalid.illegal", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "invalid.unimplemented", + "settings": { + "fontStyle": "italic", + "foreground": "#b31d28" + } + }, + { + "scope": "carriage-return", + "settings": { + "fontStyle": "italic underline", + "background": "#FF97DC", + "foreground": "#fafbfc", + "content": "^M" + } + }, + { + "scope": "message.error", + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": "string variable", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": ["source.regexp", "string.regexp"], + "settings": { + "foreground": "#032f62" + } + }, + { + "scope": [ + "string.regexp.character-class", + "string.regexp constant.character.escape", + "string.regexp source.ruby.embedded", + "string.regexp string.regexp.arbitrary-repitition" + ], + "settings": { + "foreground": "#032f62" + } + }, + { + "scope": "string.regexp constant.character.escape", + "settings": { + "fontStyle": "bold", + "foreground": "#22863a" + } + }, + { + "scope": "support.constant", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": "support.variable", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": "meta.module-reference", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": "punctuation.definition.list.begin.markdown", + "settings": { + "foreground": "#ca0c72" + } + }, + { + "scope": ["markup.heading", "markup.heading entity.name"], + "settings": { + "fontStyle": "bold", + "foreground": "#4418bf" + } + }, + { + "scope": "markup.quote", + "settings": { + "foreground": "#22863a" + } + }, + { + "scope": "markup.italic", + "settings": { + "fontStyle": "italic", + "foreground": "#24292e" + } + }, + { + "scope": "markup.bold", + "settings": { + "fontStyle": "bold", + "foreground": "#24292e" + } + }, + { + "scope": ["markup.underline"], + "settings": { + "fontStyle": "underline" + } + }, + { + "scope": ["markup.strikethrough"], + "settings": { + "fontStyle": "strikethrough" + } + }, + { + "scope": "markup.inline.raw", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": ["markup.deleted", "meta.diff.header.from-file", "punctuation.definition.deleted"], + "settings": { + "background": "#ffeef0", + "foreground": "#b31d28" + } + }, + { + "scope": ["markup.inserted", "meta.diff.header.to-file", "punctuation.definition.inserted"], + "settings": { + "background": "#f0fff4", + "foreground": "#22863a" + } + }, + { + "scope": ["markup.changed", "punctuation.definition.changed"], + "settings": { + "background": "#ffebda", + "foreground": "#ca0c72" + } + }, + { + "scope": ["markup.ignored", "markup.untracked"], + "settings": { + "foreground": "#f6f8fa", + "background": "#6644FF" + } + }, + { + "scope": "meta.diff.range", + "settings": { + "foreground": "#531ee3", + "fontStyle": "bold" + } + }, + { + "scope": "meta.diff.header", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": "meta.separator", + "settings": { + "fontStyle": "bold", + "foreground": "#4418bf" + } + }, + { + "scope": "meta.output", + "settings": { + "foreground": "#4418bf" + } + }, + { + "scope": [ + "brackethighlighter.tag", + "brackethighlighter.curly", + "brackethighlighter.round", + "brackethighlighter.square", + "brackethighlighter.angle", + "brackethighlighter.quote" + ], + "settings": { + "foreground": "#586069" + } + }, + { + "scope": "brackethighlighter.unmatched", + "settings": { + "foreground": "#b31d28" + } + }, + { + "scope": ["constant.other.reference.link", "string.other.link"], + "settings": { + "foreground": "#032f62", + "fontStyle": "underline" + } + } + ] +} diff --git a/app/components/DocsAside.vue b/app/components/DocsAside.vue new file mode 100644 index 000000000..84b07ddcf --- /dev/null +++ b/app/components/DocsAside.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/app/components/DocsBanner.vue b/app/components/DocsBanner.vue index d1ba2ca68..853103778 100644 --- a/app/components/DocsBanner.vue +++ b/app/components/DocsBanner.vue @@ -6,27 +6,19 @@ const dismissedBanners = useCookie('directus-dismissed-banners', { }); const bannerVisible = computed(() => { - const bannerValue = unref(banner); - if (!bannerValue) return false; - if (Object.keys(bannerValue).length === 0) return false; - - if (!('id' in bannerValue) || !('content' in bannerValue)) return false; - return unref(dismissedBanners).includes(bannerValue.id) === false; + const value = banner.value; + if (!value || Object.keys(value).length === 0) return false; + if (!('id' in value) || !('content' in value)) return false; + return !dismissedBanners.value.includes(value.id); }); const dismiss = (id: string) => { - dismissedBanners.value = [...unref(dismissedBanners), id]; + dismissedBanners.value = [...dismissedBanners.value, id]; }; -const iconName = computed(() => { - const bannerValue = unref(banner); - if ( - !bannerValue - || (typeof bannerValue === 'object' && Object.keys(bannerValue).length === 0) - ) - return null; - return getIconName(bannerValue.icon); -}); +useHead(computed(() => ({ + style: [{ innerHTML: `:root { --ui-banner-height: ${bannerVisible.value ? '32px' : '0px'}; }` }], +})));