Files
supabase/apps/docs/styles/globals.css
T
Anthony Lio 6d08a747f1 fix(docs): guide reference perf enhancements (#50239)
## What kind of change does this PR introduce?

follow-up to #50235 to reduce reference page payloads and cold rendering
overhead

## What is the current behavior?

reference pages ship a large rsc payload inside the html _ most of it is
duplication rather than content along with shiki that writes ~30
character css variable name for every syntax token making the page heavy
in some cases

## What is the new behavior?

- moves repeated styles into shared css and uses compact, namespaced
token classes
- renders details icons inside the client trigger
- follows shiki’s guidance to [reuse one
highlighter](https://shiki.style/guide/best-performance#cache-the-highlighter-instance)
and [load languages on
demand](https://shiki.style/guide/best-performance#use-shorthands)

`page size`
page | before | after | change
-- | -- | -- | --
javascript | 10.61 mb | 8.28 mb | -21.9%
dart | 4.59 mb | 4.13 mb | -10.1%
python | 4.38 mb | 3.73 mb | -14.9%
swift | 2.87 mb | 2.56 mb | -10.9%
server | 1.59 mb | 1.35 mb | -15.2%
kotlin | 3.42 mb | 3.17 mb | -7.2%

`cold initialization`
language | before | after | reduction
-- | -- | -- | --
bash | 2,180 ms | 23 ms | 98.95%
javascript | 2,245 ms | 38 ms | 98.29%

## Additional context

measured on a local production build which uses the checked in generated
content _ production has larger sdk data, so absolute sizes there will
be higher

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added reusable expand/collapse controls for API reference details,
with updated icons, labels, and styling.
* Improved code block rendering with class-based syntax highlighting,
wrapped-code support, responsive layouts, and lazy language loading.

* **Style**
* Added theme-aware syntax-token colors, line-number styling, and
configurable code-block shadows.
  * Consolidated expandable reference panel and item styling.

* **Tests**
* Added coverage for syntax highlighting, code block rendering, language
support, token stability, and reference details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 23:55:49 +03:00

410 lines
8.3 KiB
CSS

@import 'config/tailwind.config.css';
@import './../../../packages/ui/build/css/themes/faux-classic-dark.css';
@import './code-block.css';
@import './reference.css';
@source '../app/**/*.{ts,tsx,mdx}';
@source '../components/**/*.tsx';
@source '../content/**/*.{ts,tsx,mdx}';
@source '../docs/**/*.{tsx,mdx}';
@source '../features/**/*.{ts,tsx,mdx}';
@source '../layouts/**/*.tsx';
@source '../pages/**/*.{tsx,mdx}';
@source './../../../packages/ui/src/**/*.{tsx,ts,js}';
@source './../../../packages/ui-patterns/src/**/*.{tsx,ts,js}';
@theme inline {
--font-sans:
var(--font-inter), Inter, Helvetica Neue, Helvetica, ui-sans-serif, system-ui, sans-serif;
--font-heading: var(--font-manrope, var(--font-sans));
--font-mono: 'Source Code Pro', ui-monospace, Menlo, monospace;
}
@theme {
--text-sm: 0.8125rem;
--text-base: 0.9375rem;
--text-lg: 1rem;
--text-xl: 1.125rem;
--text-2xl: 1.375rem;
--text-3xl: 1.75rem;
--text-4xl: 2.125rem;
--text-5xl: 2.875rem;
--text-6xl: 3.625rem;
--text-7xl: 4.375rem;
--text-8xl: 5.875rem;
--text-9xl: 7.875rem;
--font-weight-normal: 450;
}
@layer utilities {
.prose--remove-p-margin p {
margin: 0;
}
}
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--border-default, currentColor);
}
code,
.code-content,
pre,
kbd,
samp,
.font-mono {
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
--text-5xl: 3rem;
--text-6xl: 3.75rem;
--text-7xl: 4.5rem;
--text-8xl: 6rem;
--text-9xl: 8rem;
--font-weight-normal: 400;
}
}
:root {
--sidebar-width: 300px;
--header-height: 50px;
}
html {
scroll-behavior: smooth;
font-weight: 500;
}
html[data-theme*='dark'] {
font-weight: 450;
}
body {
@apply bg-background text-foreground;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
::selection {
background-color: #6ee7b7 !important;
color: #333 !important;
}
h1:not(.font-mono),
h2:not(.font-mono),
h3:not(.font-mono),
h4:not(.font-mono),
h5:not(.font-mono),
h6:not(.font-mono),
.h1:not(.font-mono),
.h2:not(.font-mono),
.h3:not(.font-mono),
.h4:not(.font-mono),
.h5:not(.font-mono),
.h6:not(.font-mono) {
@apply font-heading font-semibold;
}
.thin-scrollbar {
scrollbar-width: thin;
}
.sidebar-width {
width: var(--sidebar-width);
}
.docs-width {
max-width: calc(100% - var(--sidebar-width));
@media screen and (max-width: 1024px) {
max-width: none;
}
}
.width-full {
width: 100% !important;
}
.p:not(.prose *):not(.overwrite) {
@apply text-foreground-light;
margin-bottom: 16px;
}
.small:not(.prose *):not(.overwrite) {
@apply text-foreground-muted text-xs;
}
.prose :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
white-space: pre-line;
}
.prose :where(p, a, code, pre):not(:where([class~='not-prose'], [class~='not-prose'] *)),
.prose :where(ol > li):not(:where([class~='not-prose'], [class~='not-prose'] *))::marker {
font-weight: inherit;
}
/* Body text inherits a heavier base weight, so override the shared `strong: 500`
* to keep bold text visually distinct. */
.prose :where(strong, b):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
font-weight: 700;
}
.prose :where(h1, h2, h3, h4, h5, h6):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@apply font-heading font-semibold;
}
/* Alert set its own type scale to prevent drift in docs */
.prose
:where(p, li, a, figcaption):not(:where([class~='not-prose'], [class~='not-prose'] *)):not(
:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) *
):not(:where([data-slot='alert'] *)) {
@apply text-base leading-7;
}
.prose :where([data-slot='alert'] ol > li)::before {
top: 0;
}
.prose :where(h1, .h1):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@apply text-4xl;
}
.prose :where(h2, .h2):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@apply text-2xl;
}
.prose :where(h3, .h3):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
@apply text-xl leading-7;
}
code[class*='language-'],
pre[class*='language-'] {
text-shadow: none !important;
}
/* Spec doc specifics ported from docusaurus */
/* @TODO these should be converted to Tailwind classes */
.method-list-item {
@apply border-t border-gray-400;
.method-list-item-label {
@apply flex items-center gap-1;
}
.method-list-item-label-name {
@apply font-mono font-bold text-sm py-2;
}
.method-list-item-label-badge {
@apply font-mono text-xs px-1;
overflow-wrap: anywhere;
}
.method-list-item-validation {
@apply flex flex-wrap gap-2 items-center;
}
.method-list-item-description {
@apply text-sm space-y-2;
}
}
.method-list-title-isChild {
font-family: var(--font-mono);
& h5 {
font-weight: 200;
}
}
.method-list-item-validation {
code {
@apply text-xs bg-control rounded-sm;
padding: 1px 6px;
}
}
.method-list-group {
@apply p-0 m-0 list-none border-b;
}
.method-list-group .method-list-group {
@apply border border-overlay rounded-md;
margin-bottom: 20px;
max-width: 600px;
}
.method-list-group .method-list-group li {
margin-top: 0;
padding: 12px;
border-bottom: none;
}
.method-list-title {
margin: 0;
padding: 6px 12px;
}
.method-list-group .method-list-group li div,
.method-list-group .method-list-group li h4,
.method-list-group .method-list-group li p {
padding: 0;
margin: 0;
}
.method-list-group .method-list-group li h4 {
margin-bottom: 4px;
}
/* These should move to their own components */
/* wasn't able to get an import path working */
.parent-menu-toggle.active {
svg {
transform: rotate(90deg);
}
}
/* ToC styles */
/* .toc__menu-item--active { */
/* color: hsl(var(--brand-default)) !important; */
/* } */
.video-container {
position: relative;
width: 100%;
padding-bottom: 56.25%;
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
}
/* format <code> inside <p> */
h2 code,
h3 code,
h4 code {
word-break: keep-all !important;
white-space: nowrap !important;
padding: 0.1rem 0.35rem !important;
&:before {
display: none;
}
&::after {
display: none;
}
}
article p strong {
color: inherit !important;
}
/* fix box shadow when <code> is inside <a> */
a:has(code) {
box-shadow: none !important;
}
/* fix code line wrapping */
/* need to set this to happen from medium onwards, otherwise the would cause horizontal scroll */
article p code {
&::before,
&::after {
display: none !important;
}
}
.short-inline-codeblock {
word-wrap: break-word;
@media screen and (min-width: 769px) {
white-space: pre !important;
}
}
/* fix firefox issue with li wrapping */
.doc-content-container ul li div.relative {
display: inline-block;
}
/* fix ToC links when they have <code> inside */
.toc-menu li a code {
background: none;
border: none;
}
/*
* sets the image in @Next/Image components to respect the height of the content
*/
.next-image--dynamic-fill {
width: 100%;
grid-column: 1 / -1;
}
.next-image--dynamic-fill > span {
position: relative !important;
}
.next-image--dynamic-fill img {
object-fit: contain;
width: 100% !important;
position: relative !important;
height: unset !important;
}
#docs-content-container #introduction {
@apply scroll-mt-60;
}
/* dat.GUI */
.dg.ac {
z-index: 9999 !important;
}
/* tables */
th code {
@apply text-nowrap;
}
/*
* First column (e.g. variable names): wrap at word boundaries, not mid-token.
*/
.prose :where(td:first-child) code {
@apply break-words whitespace-normal;
}
/*
* Other columns: prevents very long code lines (checksums, URLs, etc.) from
* breaking table widths.
*/
.prose :where(td:not(:first-child)) code {
@apply break-all;
}
.prose table td:first-child,
.prose table th:first-child {
min-width: 12rem;
width: 30%;
}
/* Zoomable image */
[data-rmiz-modal]:focus,
[data-rmiz-modal-overlay]:focus {
outline: none !important;
}
[data-rmiz-modal-overlay],
[data-rmiz-modal-img] {
transition-timing-function: cubic-bezier(0.24, 0.25, 0.05, 1) !important;
}
[data-rmiz-modal-overlay='visible'] {
background-color: var(--background-default) !important;
opacity: 0.8;
}
[data-rmiz-modal-img] {
image-rendering: high-quality;
}