theme-aware prose palette for markdown in dark mode (#9971)

* fix(frontend): theme-aware prose palette for markdown in dark mode

* chore(frontend): add markdown example to kitchen_sink showcase
This commit is contained in:
Guilhem
2026-07-06 19:00:35 +00:00
committed by GitHub
parent 97d14d979f
commit f3da86512a
2 changed files with 67 additions and 6 deletions
@@ -4,9 +4,37 @@
import TabContent from '$lib/components/common/tabs/TabContent.svelte'
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
import DarkModeToggle from '$lib/components/sidebar/DarkModeToggle.svelte'
import GfmMarkdown from '$lib/components/GfmMarkdown.svelte'
import { Globe } from 'lucide-svelte'
let tab = $state('button')
const sampleMarkdown = `# Heading 1
## Heading 2
Body text with **bold**, *italic*, a [link](https://windmill.dev), and \`inline code\` that must stay readable in both themes.
> A block quote should be legible too.
- First bullet
- Second bullet with \`code\`
1. Ordered one
2. Ordered two
\`\`\`ts
const block = 'code block'
console.log(block)
\`\`\`
| Column A | Column B |
| -------- | -------- |
| one | two |
| three | four |
---
`
let dropdownItems = [
{
label: 'Lorem ipsum',
@@ -19,6 +47,7 @@
<Tabs bind:selected={tab}>
<Tab value="button" label="Buttons" />
<Tab value="markdown" label="Markdown" />
{#snippet content()}
<TabContent value="button" class="p-4 flex gap-4 flex-col ">
@@ -72,5 +101,8 @@
<Button variant="default" {dropdownItems}>Lorem</Button>
</div>
</TabContent>
<TabContent value="markdown" class="p-4">
<GfmMarkdown md={sampleMarkdown} />
</TabContent>
{/snippet}
</Tabs>
+35 -6
View File
@@ -456,17 +456,46 @@ const config = {
]
},
extend: {
// Tailwind Typography hardcodes `pre` code blocks to a dark background
// (gray-800) in both light and dark mode, so they render dark-on-light in
// light mode. Point the pre/pre-code variables at theme-aware surface
// tokens (light and inverted) so code blocks track the active theme.
// Tailwind Typography hardcodes every `prose` color (body, headings,
// borders, code, ...) to fixed gray shades. Our `.prose` usages mostly
// render without `dark:prose-invert`, so in dark mode those light-mode
// grays stay put and text/borders/code render near-black on a dark
// surface. Point the whole palette at our theme tokens — which already
// flip with the active theme — for BOTH the default and inverted sets, so
// bare `.prose` and `dark:prose-invert` usages both track the theme.
typography: {
DEFAULT: {
css: {
'--tw-prose-pre-bg': 'rgb(var(--color-surface-secondary))',
'--tw-prose-body': 'rgb(var(--color-text-secondary))',
'--tw-prose-headings': 'rgb(var(--color-text-primary))',
'--tw-prose-lead': 'rgb(var(--color-text-secondary))',
'--tw-prose-bold': 'rgb(var(--color-text-primary))',
'--tw-prose-counters': 'rgb(var(--color-text-tertiary))',
'--tw-prose-bullets': 'rgb(var(--color-text-tertiary))',
'--tw-prose-hr': 'rgb(var(--color-border-light))',
'--tw-prose-quotes': 'rgb(var(--color-text-secondary))',
'--tw-prose-quote-borders': 'rgb(var(--color-border-light))',
'--tw-prose-captions': 'rgb(var(--color-text-tertiary))',
'--tw-prose-code': 'rgb(var(--color-text-primary))',
'--tw-prose-pre-code': 'rgb(var(--color-text-primary))',
'--tw-prose-pre-bg': 'rgb(var(--color-surface-secondary))',
'--tw-prose-th-borders': 'rgb(var(--color-border-light))',
'--tw-prose-td-borders': 'rgb(var(--color-border-light))',
'--tw-prose-invert-body': 'rgb(var(--color-text-secondary))',
'--tw-prose-invert-headings': 'rgb(var(--color-text-primary))',
'--tw-prose-invert-lead': 'rgb(var(--color-text-secondary))',
'--tw-prose-invert-bold': 'rgb(var(--color-text-primary))',
'--tw-prose-invert-counters': 'rgb(var(--color-text-tertiary))',
'--tw-prose-invert-bullets': 'rgb(var(--color-text-tertiary))',
'--tw-prose-invert-hr': 'rgb(var(--color-border-light))',
'--tw-prose-invert-quotes': 'rgb(var(--color-text-secondary))',
'--tw-prose-invert-quote-borders': 'rgb(var(--color-border-light))',
'--tw-prose-invert-captions': 'rgb(var(--color-text-tertiary))',
'--tw-prose-invert-code': 'rgb(var(--color-text-primary))',
'--tw-prose-invert-pre-code': 'rgb(var(--color-text-primary))',
'--tw-prose-invert-pre-bg': 'rgb(var(--color-surface-secondary))',
'--tw-prose-invert-pre-code': 'rgb(var(--color-text-primary))'
'--tw-prose-invert-th-borders': 'rgb(var(--color-border-light))',
'--tw-prose-invert-td-borders': 'rgb(var(--color-border-light))'
}
}
},