feat: comprehensive code block CSS
- Borderless container with subtle shadow - VS Code filename header with dot indicators - Line numbers via CSS counter - Copy button (hover-visible) - Highlighted line accent stripe - Highlighted chars background - Shiki dual theme token color switching - Light and dark mode overrides for all code elements
This commit is contained in:
125
app/globals.css
125
app/globals.css
@@ -123,6 +123,131 @@
|
||||
--shadow-card: 0 1px 4px oklch(1 0 0 / 0.06);
|
||||
}
|
||||
|
||||
/* === Code Blocks: Borderless, VS Code Style, Line Numbers === */
|
||||
[data-rehype-pretty-code-figure] {
|
||||
@apply relative overflow-hidden rounded-[var(--radius-code)];
|
||||
background-color: var(--color-code-block);
|
||||
border: none;
|
||||
box-shadow: 0 0 0 1px var(--color-border),
|
||||
0 2px 8px oklch(0 0 0 / 0.06);
|
||||
}
|
||||
.dark [data-rehype-pretty-code-figure] {
|
||||
box-shadow: 0 0 0 1px var(--color-border),
|
||||
0 2px 8px oklch(1 0 0 / 0.04);
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-title] {
|
||||
@apply relative flex items-center gap-2.5 px-4 py-2 text-xs;
|
||||
background-color: var(--color-code-title-bg);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-code) var(--radius-code) 0 0;
|
||||
}
|
||||
.dark [data-rehype-pretty-code-title] {
|
||||
background-color: var(--color-code-title-bg);
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-title] + pre {
|
||||
@apply m-0 rounded-b-[var(--radius-code)] rounded-t-none;
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-title] .vscode-dots {
|
||||
@apply inline-flex gap-[6px] mr-2;
|
||||
}
|
||||
[data-rehype-pretty-code-title] .vscode-dots span {
|
||||
@apply block h-2.5 w-2.5 rounded-full;
|
||||
}
|
||||
[data-rehype-pretty-code-title] .dot-red {
|
||||
background-color: var(--color-code-dot-red);
|
||||
box-shadow: inset 0 0 0 0.5px oklch(0 0 0 / 0.15);
|
||||
}
|
||||
[data-rehype-pretty-code-title] .dot-yellow {
|
||||
background-color: var(--color-code-dot-yellow);
|
||||
box-shadow: inset 0 0 0 0.5px oklch(0 0 0 / 0.15);
|
||||
}
|
||||
[data-rehype-pretty-code-title] .dot-green {
|
||||
background-color: var(--color-code-dot-green);
|
||||
box-shadow: inset 0 0 0 0.5px oklch(0 0 0 / 0.15);
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] pre {
|
||||
@apply relative overflow-auto p-4;
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] pre code {
|
||||
@apply !bg-transparent font-mono text-[13px] leading-[1.6];
|
||||
display: grid;
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] code[data-line-numbers] {
|
||||
counter-reset: line;
|
||||
}
|
||||
[data-rehype-pretty-code-figure] code[data-line-numbers] > [data-line]::before {
|
||||
counter-increment: line;
|
||||
content: counter(line);
|
||||
@apply mr-5 inline-block w-4 text-right select-none;
|
||||
color: var(--color-code-gutter);
|
||||
@apply text-[11px] font-mono;
|
||||
}
|
||||
.dark [data-rehype-pretty-code-figure] code[data-line-numbers] > [data-line]::before {
|
||||
color: var(--color-code-gutter);
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] [data-line] {
|
||||
@apply relative px-2;
|
||||
border-left: 2px solid transparent;
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] [data-highlighted-line] {
|
||||
@apply rounded-r-sm;
|
||||
background-color: var(--color-code-line-highlight);
|
||||
border-left-color: var(--color-code-line-highlight-border);
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] [data-highlighted-chars] {
|
||||
@apply rounded py-0.5 px-1;
|
||||
background-color: var(--color-code-mark-bg);
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] .rehype-pretty-copy {
|
||||
@apply absolute right-3 top-3 z-10 flex items-center gap-1 rounded-md border px-2 py-1 text-xs font-medium;
|
||||
background-color: oklch(0.97 0 0 / 0.85);
|
||||
color: var(--color-code-copy);
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
.dark [data-rehype-pretty-code-figure] .rehype-pretty-copy {
|
||||
background-color: oklch(0.10 0 0 / 0.85);
|
||||
color: var(--color-code-copy);
|
||||
}
|
||||
[data-rehype-pretty-code-figure]:hover .rehype-pretty-copy {
|
||||
opacity: 1;
|
||||
}
|
||||
[data-rehype-pretty-code-figure] .rehype-pretty-copy:hover {
|
||||
@apply border-current;
|
||||
background-color: oklch(0.95 0 0 / 0.95);
|
||||
color: var(--color-code-copy-hover);
|
||||
}
|
||||
.dark [data-rehype-pretty-code-figure] .rehype-pretty-copy:hover {
|
||||
background-color: oklch(0.15 0 0 / 0.95);
|
||||
}
|
||||
[data-rehype-pretty-code-figure] .rehype-pretty-copy.rehype-pretty-copied {
|
||||
@apply border-green-500/50;
|
||||
color: oklch(0.55 0.18 140);
|
||||
}
|
||||
.dark [data-rehype-pretty-code-figure] .rehype-pretty-copy.rehype-pretty-copied {
|
||||
color: oklch(0.70 0.15 140);
|
||||
}
|
||||
|
||||
/* Shiki dual theme token color switching */
|
||||
code[data-theme*=" "],
|
||||
code[data-theme*=" "] span {
|
||||
color: var(--shiki-light);
|
||||
}
|
||||
html.dark code[data-theme*=" "],
|
||||
html.dark code[data-theme*=" "] span {
|
||||
color: var(--shiki-dark);
|
||||
}
|
||||
|
||||
/* === Blog typography === */
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user