From 3aaea709883fbc2167c1c423fc2a7c85e4fbdc7f Mon Sep 17 00:00:00 2001 From: anthony lio Date: Thu, 1 Oct 2026 20:34:03 +0300 Subject: [PATCH] feat(kb): add featured guides carousel and bookshelf variants --- apps/kb/public/textures/book-cover.jpg | Bin 0 -> 90187 bytes apps/kb/src/components/FeaturedBookshelf.tsx | 200 +++++++++++++ apps/kb/src/components/FeaturedGuides.tsx | 215 ++++++++++++++ apps/kb/src/layouts/Layout.astro | 2 +- apps/kb/src/lib/ascii/cover-shapes.ts | 280 +++++++++++++++++++ apps/kb/src/lib/iso-shapes.ts | 177 ++++++++++++ apps/kb/src/lib/reveal.ts | 26 ++ apps/kb/src/styles/globals.css | 8 + 8 files changed, 907 insertions(+), 1 deletion(-) create mode 100644 apps/kb/public/textures/book-cover.jpg create mode 100644 apps/kb/src/components/FeaturedBookshelf.tsx create mode 100644 apps/kb/src/components/FeaturedGuides.tsx create mode 100644 apps/kb/src/lib/ascii/cover-shapes.ts create mode 100644 apps/kb/src/lib/iso-shapes.ts create mode 100644 apps/kb/src/lib/reveal.ts diff --git a/apps/kb/public/textures/book-cover.jpg b/apps/kb/public/textures/book-cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51884de98242adee9ad9461bbccc6a3ca68fb1ab GIT binary patch literal 90187 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 Z!H1lY+y7Vg|4-tpS2zc|yL-L}{};C31l9lm literal 0 HcmV?d00001 diff --git a/apps/kb/src/components/FeaturedBookshelf.tsx b/apps/kb/src/components/FeaturedBookshelf.tsx new file mode 100644 index 00000000000..517c75642eb --- /dev/null +++ b/apps/kb/src/components/FeaturedBookshelf.tsx @@ -0,0 +1,200 @@ +import { cn } from 'ui' + +import { pickCoverTopic } from '../lib/ascii/cover-shapes' +import type { FeaturedGuide } from '../lib/guides' +import { + compositionBounds, + FALLBACK_COMPOSITION, + ISO_COMPOSITIONS, + paintOrder, + projectBox, + type IsoBox, + type IsoPoint, +} from '../lib/iso-shapes' +import { bindRevealOnce, REVEAL_GROUP_CLASS, REVEAL_ITEM_CLASS, revealStyle } from '../lib/reveal' + +export interface FeaturedBookshelfProps { + guides: FeaturedGuide[] + className?: string +} + +interface BookCardProps { + guide: FeaturedGuide +} + +interface IsoDrawingProps { + boxes: IsoBox[] + className?: string +} + +const COVER_TEXTURE_STYLE = { + backgroundImage: `url(${import.meta.env.BASE_URL}/textures/book-cover.jpg)`, +} + +const GRAIN_FILTER_ID = 'kb-book-grain' +const GRAIN_THRESHOLD = 0.42 +const GRAIN_CONTRAST = 9 +const RED_TO_ALPHA = '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0' + +const toPoints = (points: IsoPoint[]) => points.map(([px, py]) => `${px},${py}`).join(' ') + +const segment = ([x1, y1]: IsoPoint, [x2, y2]: IsoPoint) => ({ x1, y1, x2, y2 }) + +export const FeaturedBookshelf = ({ guides, className }: FeaturedBookshelfProps) => ( +
+
+ +
+
    + {guides.map((guide, index) => ( +
  • + +
  • + ))} +
+ +
+) + +const BookCard = ({ guide }: BookCardProps) => { + const topic = pickCoverTopic(guide.topics) + const { titleAt, boxes } = topic ? ISO_COMPOSITIONS[topic] : FALLBACK_COMPOSITION + const isTitleAtBottom = titleAt === 'bottom' + + return ( + +
+
+ {topic && topic !== guide.title ? ( + + {topic} + + ) : null} + + {guide.title} + +
+ + +
+
+

+ {guide.title} +

+

{guide.description}

+
+
+ ) +} + +const IsoDrawing = ({ boxes, className }: IsoDrawingProps) => { + const projected = paintOrder(boxes).map(projectBox) + const { x, y, width, height } = compositionBounds(projected) + + return ( + + + {projected.flatMap((box) => + box.guides.map(([from, to]) => ( + + )) + )} + + {projected.map((box) => ( + + {box.faces.map((face) => ( + + ))} + + {box.hiddenEdges.map(([from, to]) => ( + + ))} + + + {box.faces.map((face) => ( + + ))} + {box.insets.map((inset) => ( + + ))} + + + ))} + + ) +} + +const GrainFilter = () => ( + + + + + + + + + + +) diff --git a/apps/kb/src/components/FeaturedGuides.tsx b/apps/kb/src/components/FeaturedGuides.tsx new file mode 100644 index 00000000000..977dffe1a49 --- /dev/null +++ b/apps/kb/src/components/FeaturedGuides.tsx @@ -0,0 +1,215 @@ +import { ArrowLeft, ArrowRight } from 'lucide-react' +import { useCallback, useRef, useState } from 'react' +import { Button, cn } from 'ui' + +import { coverField, pickCoverTopic } from '../lib/ascii/cover-shapes' +import { + CELL_HEIGHT, + CELL_WIDTH, + clamp, + fitEdges, + GLYPH_PITCH, + splitEdges, + uniformEdges, + type Lattice, +} from '../lib/ascii/field' +import type { FeaturedGuide } from '../lib/guides' +import { useQueryVariant } from '../lib/use-query-variant' +import { AsciiCanvas, type CanvasSize, type FieldParams } from './AsciiCanvas' +import { FeaturedBookshelf } from './FeaturedBookshelf' + +export interface FeaturedGuidesProps { + guides: FeaturedGuide[] + className?: string +} + +interface CoverSlideProps { + guide: FeaturedGuide + position: number + total: number + isActive: boolean +} + +interface CenteredScrollLeftParams { + track: HTMLElement + slide: HTMLElement +} + +const CENTER_LINE_MARGIN = '0px -50% 0px -50%' +const COVER_WAKE_RADIUS = 100 + +const FEATURED_VARIANTS = ['carousel', 'book'] as const + +const getCoverGrid = ({ width, height }: CanvasSize): Lattice => ({ + xs: fitEdges({ size: width, target: CELL_WIDTH }), + ys: uniformEdges({ size: height, step: CELL_HEIGHT }), +}) + +const getCoverLattice = (size: CanvasSize): Lattice => { + const grid = getCoverGrid(size) + return { xs: splitEdges({ edges: grid.xs, target: GLYPH_PITCH }), ys: grid.ys } +} + +const centeredScrollLeft = ({ track, slide }: CenteredScrollLeftParams) => + slide.offsetLeft - (track.clientWidth - slide.offsetWidth) / 2 + +export const FeaturedGuides = (props: FeaturedGuidesProps) => { + const variant = useQueryVariant({ + key: 'featured', + options: FEATURED_VARIANTS, + fallback: 'carousel', + }) + return variant === 'book' ? : +} + +const FeaturedCarousel = ({ guides, className }: FeaturedGuidesProps) => { + const middleIndex = Math.floor(guides.length / 2) + const [activeIndex, setActiveIndex] = useState(middleIndex) + const trackRef = useRef(null) + const targetIndexRef = useRef(middleIndex) + + const bindTrack = useCallback((track: HTMLDivElement | null) => { + trackRef.current = track + if (!track) return + const observer = new IntersectionObserver( + (entries) => { + for (const entry of entries) { + if (!entry.isIntersecting) continue + const index = Array.prototype.indexOf.call(track.children, entry.target) + targetIndexRef.current = index + setActiveIndex(index) + } + }, + { root: track, rootMargin: CENTER_LINE_MARGIN, threshold: 0 } + ) + const middle = track.children[Math.floor(track.children.length / 2)] + if (middle instanceof HTMLElement) + track.scrollLeft = centeredScrollLeft({ track, slide: middle }) + for (const slide of track.children) observer.observe(slide) + return () => observer.disconnect() + }, []) + + const scrollToSlide = (index: number) => { + const track = trackRef.current + const target = clamp(index, 0, guides.length - 1) + const slide = track?.children[target] + if (!track || !(slide instanceof HTMLElement)) return + targetIndexRef.current = target + const isReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches + track.scrollTo({ + left: centeredScrollLeft({ track, slide }), + behavior: isReducedMotion ? 'auto' : 'smooth', + }) + } + + const handlePreviousClick = () => scrollToSlide(targetIndexRef.current - 1) + const handleNextClick = () => scrollToSlide(targetIndexRef.current + 1) + + if (guides.length === 0) return null + + return ( +
+
+ +
+
+
+
+ {guides.map((guide, index) => ( + + ))} +
+
+ ) +} + +const CoverSlide = ({ guide, position, total, isActive }: CoverSlideProps) => { + const titleRef = useRef(null) + const descriptionRef = useRef(null) + const ctaRef = useRef(null) + const getField = (params: FieldParams) => + coverField({ ...params, topic: pickCoverTopic(guide.topics) }) + + return ( + + ) +} diff --git a/apps/kb/src/layouts/Layout.astro b/apps/kb/src/layouts/Layout.astro index 30b0d827ae6..50e5276beae 100644 --- a/apps/kb/src/layouts/Layout.astro +++ b/apps/kb/src/layouts/Layout.astro @@ -65,7 +65,7 @@ const { title, description } = Astro.props {title} | Supabase Knowledge Base diff --git a/apps/kb/src/lib/ascii/cover-shapes.ts b/apps/kb/src/lib/ascii/cover-shapes.ts new file mode 100644 index 00000000000..4687ba04579 --- /dev/null +++ b/apps/kb/src/lib/ascii/cover-shapes.ts @@ -0,0 +1,280 @@ +import type { Topic } from '../topics' +import { createRng, latticeSize, type Lattice } from './field' + +interface ShapeGrid { + cols: number + rows: number + put: (c: number, r: number, density: number) => void +} + +interface Stage extends ShapeGrid { + rand: () => number + cellWidth: number + cellHeight: number + at: (u: number, v: number) => [number, number] + line: (from: [number, number], to: [number, number], density: number) => void +} + +type Shape = (stage: Stage) => void + +interface CoverFieldParams { + lattice: Lattice + seed: number + mask: Uint8Array + topic: Topic | null +} + +const STAGE = { left: 0.06, right: 0.8, top: 0.04, bottom: 0.62 } +const DROPOUT = 0.08 +const SCATTER_CHANCE = 0.06 +const SCATTER_DENSITY = 0.12 + +const FORMAT_TOPICS: Topic[] = ['Migration', 'Comparison', 'Troubleshooting', 'Tutorial'] + +const ramp = (from: number, to: number, t: number) => from + (to - from) * t + +const firstBlockedRow = (mask: Uint8Array, cols: number, rows: number) => { + for (let r = 0; r < rows; r++) { + const blocked = mask.subarray(r * cols, (r + 1) * cols).reduce((sum, cell) => sum + cell, 0) + if (blocked > cols / 2) return r - 1 + } + return rows +} + +const policyWall: Shape = ({ at, line, put, rand }) => { + const [wallC, wallTop] = at(0.56, 0) + const [, wallBottom] = at(0, 1) + for (let r = wallTop; r <= wallBottom; r++) { + put(wallC, r, 1) + put(wallC + 1, r, 1) + } + const [startC] = at(0, 0) + const [endC] = at(1, 0) + for (let r = wallTop + 1, k = 0; r <= wallBottom; r += 2, k++) { + for (let c = startC; c < wallC; c++) + put(c, r, ramp(0.25, 0.75, (c - startC) / (wallC - startC))) + if (k % 3 === 1 || rand() < 0.15) line([wallC + 2, r], [endC - 1, r], 0.75) + if (k % 3 === 1) put(endC, r, 1) + } +} + +const bTree: Shape = ({ at, line, put }) => { + const block = ([c, r]: [number, number]) => { + put(c, r, 1) + put(c + 1, r, 1) + put(c, r + 1, 1) + put(c + 1, r + 1, 1) + } + const root = at(0.5, 0) + const mids = [at(0.2, 0.32), at(0.5, 0.32), at(0.8, 0.32)] + block(root) + for (const mid of mids) { + block(mid) + line([root[0], root[1] + 2], [mid[0], mid[1] - 1], 0.6) + } + const leafRow = at(0, 0.72)[1] + mids.forEach((mid, m) => { + for (const offset of [-0.1, 0, 0.1]) { + const [leafC] = at(0.2 + m * 0.3 + offset, 0) + line([mid[0], mid[1] + 2], [leafC, leafRow - 1], 0.45) + put(leafC, leafRow, 1) + put(leafC, leafRow + 1, 0.25) + } + }) + const [listStart, listRow] = at(0, 0.95) + const [listEnd] = at(1, 0) + line([listStart, listRow], [listEnd, listRow], 0.5) + put(listEnd + 1, listRow, 1) +} + +const rings: Shape = ({ at, put, cols, rows, rand, cellWidth, cellHeight }) => { + const [cx, cy] = at(0.5, 0.5) + const spacing = Math.max(cellWidth, cellHeight) * 1.2 + const thickness = Math.max(cellWidth, cellHeight) * 0.55 + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const distance = Math.hypot((c - cx) * cellWidth, (r - cy) * cellHeight) + for (let k = 0; k < 7; k++) { + if (Math.abs(distance - (k + 1) * spacing) < thickness) put(c, r, 1 - k * 0.12) + } + } + } + put(cx, cy, 1) + for (let i = 0; i < 4; i++) { + const angle = rand() * Math.PI * 2 + const radius = (2 + Math.floor(rand() * 5)) * spacing + put( + Math.round(cx + (radius * Math.cos(angle)) / cellWidth), + Math.round(cy + (radius * Math.sin(angle)) / cellHeight), + 1 + ) + } +} + +const tableToTable: Shape = ({ at, line, put }) => { + const grid = (u0: number, u1: number, density: number) => { + const [c0, r0] = at(u0, 0.1) + const [c1, r1] = at(u1, 0.9) + for (let r = r0; r <= r1; r += 2) for (let c = c0; c <= c1; c++) put(c, r, density) + } + grid(0, 0.24, 0.75) + grid(0.76, 1, 1) + for (const v of [0.1, 0.42, 0.74]) { + const [from, row] = at(0.27, v) + const [to] = at(0.72, v) + line([from, row], [to, row], 0.3) + put(to, row, 0.9) + } +} + +const stackedBuckets: Shape = ({ at, line }) => { + for (let i = 0; i < 3; i++) { + const [c0, r0] = at(0.1 + i * 0.16, 0.05 + i * 0.12) + const [c1, r1] = at(0.55 + i * 0.16, 0.6 + i * 0.12) + const density = ramp(0.4, 1, i / 2) + line([c0, r0], [c1, r0], density) + line([c0, r0], [c0, r1], density) + line([c1, r0], [c1, r1], density) + line([c0, r1], [c1, r1], density) + } +} + +const linkedNodes: Shape = ({ at, line, put, rand }) => { + const center = at(0.5, 0.5) + for (let i = 0; i < 9; i++) { + const angle = (i / 9) * Math.PI * 2 + rand() * 0.4 + const node = at(0.5 + Math.cos(angle) * 0.45, 0.5 + Math.sin(angle) * 0.45) + line(center, node, 0.3) + put(node[0], node[1], 1) + put(node[0] + 1, node[1], 0.8) + } + put(center[0], center[1], 1) + put(center[0] + 1, center[1], 1) +} + +const conveyor: Shape = ({ at, line, put }) => { + const [startC, row] = at(0, 0.5) + const [endC] = at(1, 0) + line([startC, row + 2], [endC, row + 2], 0.25) + for (let c = startC, k = 0; c < endC - 2; c += 4, k++) { + const density = ramp(1, 0.25, k / 10) + for (let dc = 0; dc < 2; dc++) for (let dr = 0; dr < 2; dr++) put(c + dc, row + dr - 1, density) + } + put(endC, row + 2, 1) +} + +const staircase: Shape = ({ at, put }) => { + for (let step = 0; step < 6; step++) { + const [c0, r0] = at(step / 6, 1 - (step + 1) / 6) + const [c1, r1] = at((step + 1) / 6, 1) + for (let c = c0; c < c1; c++) put(c, r0, 1) + for (let r = r0; r <= r1; r += 2) + for (let c = c0; c < c1; c += 2) put(c, r, ramp(0.25, 0.6, step / 5)) + } +} + +const brokenPath: Shape = ({ at, line, put }) => { + const points: [number, number][] = [ + [0, 0.8], + [0.2, 0.3], + [0.38, 0.7], + [0.5, 0.45], + ] + for (let i = 0; i < points.length - 1; i++) line(at(...points[i]), at(...points[i + 1]), 0.75) + line(at(0.62, 0.35), at(0.8, 0.75), 0.45) + line(at(0.8, 0.75), at(1, 0.15), 0.45) + const [mc, mr] = at(0.56, 0.42) + for (let d = -1; d <= 1; d++) { + put(mc + d, mr + d, 1) + put(mc + d, mr - d, 1) + } +} + +const pairedColumns: Shape = ({ at, put }) => { + const heights = [0.55, 0.8, 0.35, 0.95, 0.6, 0.75] + heights.forEach((height, i) => { + const [c] = at(0.04 + i * 0.17, 0) + const [, bottom] = at(0, 1) + const [, top] = at(0, 1 - height) + const [, pairTop] = at(0, 1 - height * 0.7) + for (let r = top; r <= bottom; r++) put(c, r, 1) + for (let r = pairTop; r <= bottom; r++) put(c + 2, r, 0.35) + }) +} + +const stackedLayers: Shape = ({ at, line }) => { + for (let i = 0; i < 4; i++) { + const v = 0.12 + i * 0.26 + const skew = 0.08 + const density = ramp(1, 0.35, i / 3) + line(at(skew, v - 0.12), at(1, v - 0.12), density) + line(at(0, v), at(1 - skew, v), density) + line(at(skew, v - 0.12), at(0, v), density) + line(at(1, v - 0.12), at(1 - skew, v), density) + } +} + +const hatch: Shape = ({ cols, rows, put }) => { + for (let r = 0; r < rows; r++) + for (let c = 0; c < cols; c++) if ((c + r) % 6 === 0) put(c, r, 0.4) +} + +export const pickCoverTopic = (topics: Topic[]): Topic | null => + topics.find((topic) => !FORMAT_TOPICS.includes(topic)) ?? topics[0] ?? null + +export const coverField = ({ lattice, seed, mask, topic }: CoverFieldParams): Float32Array => { + const { cols, rows } = latticeSize(lattice) + const field = new Float32Array(cols * rows) + if (cols === 0 || rows === 0) return field + + const rand = createRng(seed) + const put = (c: number, r: number, density: number) => { + const col = Math.round(c) + const row = Math.round(r) + if (col < 0 || row < 0 || col >= cols || row >= rows) return + field[row * cols + col] = Math.max(field[row * cols + col], density) + } + const stageLeft = STAGE.left * cols + const stageTop = STAGE.top * rows + const stageWidth = (STAGE.right - STAGE.left) * cols + const stageHeight = Math.max( + 1, + Math.min(STAGE.bottom * rows, firstBlockedRow(mask, cols, rows)) - stageTop + ) + const at = (u: number, v: number): [number, number] => [ + Math.round(stageLeft + u * stageWidth), + Math.round(stageTop + v * stageHeight), + ] + const line = ([c0, r0]: [number, number], [c1, r1]: [number, number], density: number) => { + const steps = Math.max(Math.abs(c1 - c0), Math.abs(r1 - r0), 1) + for (let i = 0; i <= steps; i++) put(ramp(c0, c1, i / steps), ramp(r0, r1, i / steps), density) + } + + const shape = topic ? COVER_SHAPES[topic] : FALLBACK_SHAPE + const cellWidth = (lattice.xs[cols] - lattice.xs[0]) / cols + const cellHeight = (lattice.ys[rows] - lattice.ys[0]) / rows + shape({ cols, rows, put, rand, at, line, cellWidth, cellHeight }) + + for (let i = 0; i < field.length; i++) { + if (mask[i]) field[i] = 0 + else if (field[i] > 0 && rand() < DROPOUT) field[i] = 0 + else if (field[i] === 0 && rand() < SCATTER_CHANCE) field[i] = SCATTER_DENSITY + } + return field +} + +export const COVER_SHAPES: Record = { + Migration: tableToTable, + Comparison: pairedColumns, + Troubleshooting: brokenPath, + Tutorial: staircase, + Storage: stackedBuckets, + Auth: policyWall, + Database: bTree, + 'Edge Functions': linkedNodes, + Queues: conveyor, + Realtime: rings, + 'Supabase Platform': stackedLayers, +} + +const FALLBACK_SHAPE = hatch diff --git a/apps/kb/src/lib/iso-shapes.ts b/apps/kb/src/lib/iso-shapes.ts new file mode 100644 index 00000000000..58331a4194d --- /dev/null +++ b/apps/kb/src/lib/iso-shapes.ts @@ -0,0 +1,177 @@ +import type { Topic } from './topics' + +export type IsoPoint = [number, number] + +export interface IsoBox { + x: number + y: number + z: number + w: number + d: number + h: number + inset?: 'front' | 'top' +} + +export interface IsoComposition { + boxes: IsoBox[] + titleAt: 'top' | 'bottom' +} + +export interface ProjectedBox { + key: string + faces: IsoPoint[][] + hiddenEdges: [IsoPoint, IsoPoint][] + insets: IsoPoint[][] + guides: [IsoPoint, IsoPoint][] +} + +const COS = Math.cos(Math.PI / 6) +const SIN = 0.5 +const GUIDE_REACH = 1.6 +const INSET_MARGIN = 0.18 +const INSET_DEPTH = 0.12 + +export const isoPoint = (x: number, y: number, z: number): IsoPoint => [ + (x - y) * COS, + (x + y) * SIN - z, +] + +const cube = (x: number, y: number, z: number, size: number): IsoBox => ({ + x, + y, + z, + w: size, + d: size, + h: size, +}) + +export const paintOrder = (boxes: IsoBox[]): IsoBox[] => + [...boxes].sort( + (a, b) => a.x + a.w / 2 + a.y + a.d / 2 + a.z - (b.x + b.w / 2 + b.y + b.d / 2 + b.z) + ) + +export const projectBox = (box: IsoBox): ProjectedBox => { + const { x, y, z, w, d, h, inset } = box + const p = (px: number, py: number, pz: number) => isoPoint(px, py, pz) + const right = [p(x + w, y, z), p(x + w, y + d, z), p(x + w, y + d, z + h), p(x + w, y, z + h)] + const left = [p(x, y + d, z), p(x + w, y + d, z), p(x + w, y + d, z + h), p(x, y + d, z + h)] + const top = [p(x, y, z + h), p(x + w, y, z + h), p(x + w, y + d, z + h), p(x, y + d, z + h)] + const back = p(x, y, z) + const mw = w * INSET_MARGIN + const md = d * INSET_MARGIN + const mh = h * INSET_MARGIN + + const frontInset = (depth: number) => [ + p(x + w - depth, y + md, z + mh), + p(x + w - depth, y + d - md, z + mh), + p(x + w - depth, y + d - md, z + h - mh), + p(x + w - depth, y + md, z + h - mh), + ] + const topInset = (depth: number) => [ + p(x + mw, y + md, z + h - depth), + p(x + w - mw, y + md, z + h - depth), + p(x + w - mw, y + d - md, z + h - depth), + p(x + mw, y + d - md, z + h - depth), + ] + const insetFace = inset === 'front' ? frontInset : inset === 'top' ? topInset : null + + return { + key: `${x}:${y}:${z}`, + faces: [right, left, top], + hiddenEdges: [ + [back, p(x + w, y, z)], + [back, p(x, y + d, z)], + [back, p(x, y, z + h)], + ], + insets: insetFace ? [insetFace(0), insetFace(w * INSET_DEPTH)] : [], + guides: [ + [p(x - GUIDE_REACH, y + d, z), p(x + w + GUIDE_REACH, y + d, z)], + [p(x + w, y - GUIDE_REACH, z), p(x + w, y + d + GUIDE_REACH, z)], + ], + } +} + +export const compositionBounds = (boxes: ProjectedBox[], padding = 0.25) => { + const points = boxes.flatMap((box) => box.faces.flat()) + const xs = points.map(([px]) => px) + const ys = points.map(([, py]) => py) + const minX = Math.min(...xs) + const minY = Math.min(...ys) + const width = Math.max(...xs) - minX + const height = Math.max(...ys) - minY + const pad = Math.max(width, height) * padding + return { x: minX - pad, y: minY - pad, width: width + pad * 2, height: height + pad * 2 } +} + +export const ISO_COMPOSITIONS: Record = { + Auth: { + titleAt: 'bottom', + boxes: [cube(0, 0, 0, 1), { ...cube(0, 0, 1, 1), inset: 'front' }, cube(0, 0, 2, 1)], + }, + Database: { + titleAt: 'top', + boxes: Array.from({ length: 5 }, (_, i) => ({ + x: i * 0.1, + y: -i * 0.12, + z: i * 0.24, + w: 2, + d: 1.3, + h: 0.16, + })), + }, + Realtime: { + titleAt: 'top', + boxes: [{ ...cube(0, 0, 0, 2), inset: 'front' }, cube(2.3, 1.2, 0, 0.7)], + }, + Storage: { + titleAt: 'top', + boxes: [0, 1, 2].map((i) => ({ ...cube(0, i * 1.35, 0, 1.1), h: 0.8, inset: 'top' })), + }, + 'Edge Functions': { + titleAt: 'top', + boxes: [ + cube(0, 0, 0, 1), + cube(1.9, 0.3, 0, 0.4), + cube(0.3, 1.9, 0, 0.4), + cube(-1.3, 0.3, 0, 0.4), + cube(0.3, -1.3, 0, 0.4), + ], + }, + Queues: { + titleAt: 'top', + boxes: [0, 1, 2, 3, 4].map((i) => cube(i * 0.95, 0, 0, 0.7)), + }, + Migration: { + titleAt: 'top', + boxes: [ + { ...cube(0, 0, 0, 1), h: 1.2 }, + cube(1.5, 0.3, 0.2, 0.4), + { ...cube(2.6, 0, 0, 1), h: 1.2, inset: 'top' }, + ], + }, + Comparison: { + titleAt: 'bottom', + boxes: [ + { ...cube(0, 0, 0, 0.9), h: 2.2 }, + { ...cube(1.4, 0, 0, 0.9), h: 1.4 }, + ], + }, + Troubleshooting: { + titleAt: 'bottom', + boxes: [ + { ...cube(0, 0, 0, 1), h: 0.8 }, + { ...cube(0.25, -0.15, 0.8, 1), h: 0.8 }, + { ...cube(-0.1, 0.1, 1.6, 1), h: 0.8 }, + ], + }, + Tutorial: { + titleAt: 'top', + boxes: [0, 1, 2, 3].map((i) => ({ x: i * 0.8, y: 0, z: 0, w: 0.8, d: 1.2, h: (i + 1) * 0.45 })), + }, + 'Supabase Platform': { + titleAt: 'top', + boxes: [0, 1, 2].map((i) => ({ x: 0, y: 0, z: i * 0.55, w: 2.2, d: 2.2, h: 0.18 })), + }, +} + +export const FALLBACK_COMPOSITION: IsoComposition = { titleAt: 'top', boxes: [cube(0, 0, 0, 1)] } diff --git a/apps/kb/src/lib/reveal.ts b/apps/kb/src/lib/reveal.ts new file mode 100644 index 00000000000..aa98f19a93d --- /dev/null +++ b/apps/kb/src/lib/reveal.ts @@ -0,0 +1,26 @@ +import type { CSSProperties } from 'react' + +type RevealStyle = CSSProperties & { '--reveal-index': number } + +export const REVEAL_GROUP_CLASS = 'group/reveal' + +export const REVEAL_ITEM_CLASS = [ + 'motion-safe:opacity-0 motion-safe:group-data-[revealed=true]/reveal:opacity-100', + 'motion-safe:group-data-[revealed=true]/reveal:animate-[reveal-up_500ms_cubic-bezier(0.23,1,0.32,1)_calc(min(var(--reveal-index),8)*60ms)_both]', +].join(' ') + +export const bindRevealOnce = (element: HTMLElement | null) => { + if (!element) return + const observer = new IntersectionObserver( + ([entry]) => { + if (!entry?.isIntersecting) return + element.dataset.revealed = 'true' + observer.disconnect() + }, + { rootMargin: '0px 0px -10% 0px' } + ) + observer.observe(element) + return () => observer.disconnect() +} + +export const revealStyle = (index: number): RevealStyle => ({ '--reveal-index': index }) diff --git a/apps/kb/src/styles/globals.css b/apps/kb/src/styles/globals.css index df11978a63c..0a3b4210792 100644 --- a/apps/kb/src/styles/globals.css +++ b/apps/kb/src/styles/globals.css @@ -21,6 +21,7 @@ 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; + --font-serif: 'Newsreader', Georgia, serif; } /* Same type scale as apps/docs/styles/globals.css — without this, utilities @@ -115,3 +116,10 @@ h6:not(.font-mono), .shadow-codeblock { box-shadow: var(--shadow-codeblock, none); } + +@keyframes reveal-up { + from { + opacity: 0; + translate: 0 12px; + } +}