diff --git a/CHANGELOG.md b/CHANGELOG.md index f33b752ce..af9320a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,23 +4,17 @@ ### Minor Changes -- d2c5395: migration from querySelector to refs for rovingfoucs, tree and slider +- d2c5395: migration from querySelector to refs for roving focus, tree and slider ### Patch Changes - 4db8aa7: ui revamp for multiple comps -## 0.2.2 - -### Patch Changes - -- 83cf51c: Update GitHub Actions workflows to Node 24 and newer GitHub action versions for release, test, lint, coverage, and Chromatic jobs. - ## 0.2.1 ### Patch Changes -- 9a28add: Align AlertDialog styling with theme tokens, and clean up Storybook examples and local dev startup behavior. +- 9a28add: Align AlertDialog styling with theme tokens. ## 0.2.0 @@ -36,7 +30,6 @@ - 38503b6: mergeRefs added - b968b4a: export types for all comps - a42620d: Fix select and combobox popup behavior by improving portal rendering, restoring macOS-style reopen anchoring for `Select`, and tightening related UI polish in the sandbox and shared component styles. -- 3e892dd: Refactored internal data attribute utilities from hook-style factories to plain functions and updated shared component usage. ## 0.1.10 @@ -57,27 +50,13 @@ - d22ef40: resize, size and varaint api support added for textarea -## 0.1.7 - -### Patch Changes - -- 75152f8: Fix GitHub workflows to use correct build script instead of silent failure - ## 0.1.6 ### Patch Changes - 4363ff3: Added Separator for dropdown , context and menubar menus - 336fe3f: MenuPrimitive root now supports rtl, loop, avoidCollision,placement and the item supports disabled, asChild , onSelect. Tests for the same have been added too. -- bcad222: ## Fix: Missing Components in NPM Bundle - - **Versions 0.1.0 - 0.1.5** had incomplete component bundles due to build failures. - - **Root Cause**: Due to updates we've made to build processes to build components for npm, we might have broken the process due to list on package.json not being in sync, we totally missed testing a couple of versions. - - **Fix**: Increased Node.js heap size to 8GB and added export validation to prevent silent build failures. - - **New Features**: Added `--check` flag for export validation, ESM/CommonJS support, and root export support. +- bcad222: Fix incomplete npm bundles for some 0.1.x releases; raise Node heap for builds, add export validation and a `--check` flag, with ESM/CJS and root export support. ## 0.1.5 @@ -85,94 +64,20 @@ - f77dc1b: Sub-components, now throw subtle warnings instead of console logs -## 0.1.4 - -### Patch Changes - -- 6b514f8: fix formatting of announcement - test workflow -- 6b514f8: Patch workflow indentation issue - -## 0.1.3 - -### Patch Changes - -- cb1205d: Patch workflow indentation issue -- 2d19c42: Testing Discord Release Workflow - -## 0.1.2 - -### Patch Changes - -- e394a8d: testing changeset workflow automation - part 2 - -## 0.1.1 - -### Patch Changes - -- 759dcc6: Test patch to check workflows - ## 0.1.0 ### Minor Changes -- b471ddb: This release adds tests around the codebase, improves API support across multiple components, introduces new features like Steps + Minimap and roving focus in CheckboxGroups, while cleaning up builds, docs, and accessibility. - - ### ✨ Features - - - Added **roving focus support for CheckboxGroup**. - - Improved **RadioGroup behavior and accessibility**. - - Enhanced **Select component behavior**. - - Introduced **Steps + Minimap basic implementation**. - - Refactored multiple components to support **`forwardRef`**: - - Avatar, Badge, BlockQuote, Card, Code, Collapsible, ContextMenu, DataList, RadioGroup, Splitter, Table, Tabs, ToggleGroup, VisuallyHidden. - - ### 🧪 Tests & Accessibility - - - Expanded **a11y test coverage**: axe-core, Accordion, Slider, RadioGroup, AlertDialog, Dialog, Primitive `asChild`, and SSR hydration scenarios. - - Added **portal test utilities** for Dialog/AlertDialog. - - Stabilized and silenced noisy test warnings. - - Enforced **global test coverage thresholds**. - - Parallelized Jest test runs with **sharding** for faster feedback. - - ### 🛠 Fixes & Refactors - - - Fixed `SelectPrimitiveItemProps` export typing. - - Refined **NavigationMenu typing**. - - Increased **Rollup build memory limit** and excluded Storybook files from builds. - - Silenced “Primitive `asChild`” warnings in tests. - - ### 📚 Docs & Chores - - - Added **CodeRabbit sponsor hero** to docs. - - Added **Changeset workflow** for release management. - - Improved **WCAG tree navigation support**. - - Minor styling fixes and dark mode improvements. - - Updated Toggle API: `onChange` → `onPressedChange`. - - ## BREAKING CHANGES - - ### Toggle Component API Rename - - The Toggle component's `onChange` prop has been renamed to `onPressedChange` to better reflect its semantic meaning and align with accessibility standards. - - **Migration Required:** - - ```tsx - // Before - { /* handle toggle */ }} /> - - // After - { /* handle toggle */ }} /> - ``` +- b471ddb: Tests, API improvements across components, Steps + Minimap, roving focus for CheckboxGroup, RadioGroup and Select updates, `forwardRef` on many primitives, a11y and build fixes. - **TypeScript Updates:** +### BREAKING CHANGES - - Update any TypeScript interfaces or type definitions that reference `onChange` to use `onPressedChange` - - The prop signature remains the same: `(pressed: boolean) => void` - - Update any custom Toggle wrapper components or higher-order components that pass through the `onChange` prop +**Toggle:** `onChange` was renamed to `onPressedChange`. - **Impact:** +```tsx +// Before + { /* handle toggle */ }} /> - - This change affects all consumers using the Toggle component - - Update your codebase to use the new `onPressedChange` prop name - - No functional changes to the component behavior - only the prop name has changed +// After + { /* handle toggle */ }} /> +``` diff --git a/agents/documentation/building-ui.md b/agents/documentation/building-ui.md new file mode 100644 index 000000000..e69de29bb diff --git a/agents/security/fix-vulnerabilities.md b/agents/security/fix-vulnerabilities.md new file mode 100644 index 000000000..45412baf2 --- /dev/null +++ b/agents/security/fix-vulnerabilities.md @@ -0,0 +1,25 @@ +You are working in this repo’s local clone. Goal: one integration branch that brings all dependency and security-related updates together so we can merge confidently. + +Scope + +Link to all open PRs - + +Treat open PRs from Dependabot, Snyk, Renovate, and similar automated dependency/security bots as the source of truth for what to bump (versions, packages, and which workspaces: root vs subfolders with their own package.json). +Apply equivalent changes on a single new branch off the appropriate base (usually main), instead of merging many small PRs one by one—unless I say otherwise. +Requirements + +Inventory: Summarize which packages/workspaces those bot PRs target and the version bumps they propose (group by root vs subproject). + +Implement: Update package.json (and lockfiles) consistently so dependency trees are up to date and aligned with those bumps; resolve conflicts and avoid partial upgrades that leave inconsistent peers. + +Verify: Run the project’s install, build, lint, and test commands (whatever this repo documents in package.json scripts / CI) until they pass for all relevant workspaces. + +Safety: Run npm audit / pnpm audit / yarn npm audit (whichever the repo uses) and address high/critical issues where reasonable; note anything that needs a breaking major or cannot be fixed without product decisions. +Deliverable: Short summary of what changed, remaining risks, and suggested PR title/description. Do not change unrelated code or docs unless required for the upgrade. +Constraints + +Prefer minimal, focused diffs; no drive-by refactors. +If gh or network access to GitHub fails, infer from package.json + lockfiles + audit and still produce a coherent upgrade plan. +Start only when I say “go” (or equivalent). + +Once all the relevant changes are done, provide a summary telling the user which PRs can be closed, which are pending, and which were not addressed, including relevant details and any blockers. diff --git a/docs/app/docs/docsNavigationSections.tsx b/docs/app/docs/docsNavigationSections.tsx index f49f4791f..a306dfe8a 100644 --- a/docs/app/docs/docsNavigationSections.tsx +++ b/docs/app/docs/docsNavigationSections.tsx @@ -14,6 +14,10 @@ export const docsNavigationSections = [ { title:"Usage", path:"/docs/first-steps/usage" + }, + { + title:"Changelog", + path:"/docs/first-steps/changelog" } ] }, diff --git a/docs/app/docs/first-steps/changelog/ChangelogMarkdown.tsx b/docs/app/docs/first-steps/changelog/ChangelogMarkdown.tsx new file mode 100644 index 000000000..b13da06c9 --- /dev/null +++ b/docs/app/docs/first-steps/changelog/ChangelogMarkdown.tsx @@ -0,0 +1,191 @@ +import { + cloneElement, + isValidElement, + type ReactElement, + type ReactNode, +} from "react"; +import clsx from "clsx"; +import ReactMarkdown from "react-markdown"; +import remarkGfm from "remark-gfm"; + +import { highlightChangelogCode } from "./highlightChangelogCode"; + +type ChangelogMarkdownProps = { + markdown: string; +}; + +const COMMIT_PREFIX = /^([a-f0-9]{7}):\s*/i; + +function headingPlainText(children: ReactNode): string { + if (children == null) return ""; + if (typeof children === "string" || typeof children === "number") { + return String(children); + } + if (Array.isArray(children)) { + return children.map(headingPlainText).join(""); + } + if (isValidElement(children)) { + const el = children as ReactElement<{ children?: ReactNode }>; + return headingPlainText(el.props.children); + } + return ""; +} + +function sectionHeadingStyles(label: string): string { + const l = label.toLowerCase(); + /** Tinted bar + near-black text for contrast on pale backgrounds */ + if (l.includes("breaking")) { + return "border-red-600 bg-red-100/90 text-gray-950"; + } + if (l.includes("minor")) { + return "border-red-500 bg-red-100/90 text-gray-950"; + } + if (l.includes("patch")) { + return "border-blue-600 bg-blue-100/90 text-gray-950"; + } + return "border-gray-400 bg-gray-100 text-gray-950"; +} + +/** + * Turns the leading `abc1234: ` on a list line into a monospace pill; works when + * remark splits inline marks (e.g. `hash: **Bold**:`) across several nodes. + */ +function peelLeadingCommitHash(node: ReactNode): ReactNode { + if (typeof node === "string") { + const m = node.match(COMMIT_PREFIX); + if (m) { + const rest = node.slice(m[0].length); + return ( + <> + + {m[1]} + + {rest} + + ); + } + return node; + } + if (Array.isArray(node)) { + if (node.length === 0) return node; + const [first, ...rest] = node; + return ( + <> + {peelLeadingCommitHash(first)} + {rest} + + ); + } + if (isValidElement(node)) { + const el = node as ReactElement<{ children?: ReactNode }>; + if (el.props.children != null) { + return cloneElement(el, { + ...el.props, + children: peelLeadingCommitHash(el.props.children), + }); + } + } + return node; +} + +/** + * Renders a single release section from CHANGELOG.md (GFM: lists, nested headings, fenced code). + */ +export function ChangelogMarkdown({ markdown }: ChangelogMarkdownProps) { + return ( + ( +

+ {children} +

+ ), + h2: ({ children }) => ( +

+ {children} +

+ ), + h3: ({ children }) => { + const label = headingPlainText(children); + const bar = sectionHeadingStyles(label); + return ( +
+ {children} +
+ ); + }, + p: ({ children }) => ( +

{children}

+ ), + ul: ({ children }) => ( +
    + {children} +
+ ), + ol: ({ children }) => ( +
    + {children} +
+ ), + li: ({ children }) => ( +
  • + {peelLeadingCommitHash(children)} +
  • + ), + pre: ({ children }) => ( +
    +                        {children}
    +                    
    + ), + code: ({ className, children, ...props }) => { + const isBlock = Boolean(className?.includes("language-")); + if (isBlock) { + const lang = + className?.match(/language-([\w-]+)/)?.[1] ?? "tsx"; + const source = String(children ?? ""); + return ( + + {highlightChangelogCode(source, lang)} + + ); + } + return ( + + {children} + + ); + }, + a: ({ href, children }) => ( + + {children} + + ), + strong: ({ children }) => ( + {children} + ), + }} + > + {markdown} +
    + ); +} diff --git a/docs/app/docs/first-steps/changelog/highlightChangelogCode.tsx b/docs/app/docs/first-steps/changelog/highlightChangelogCode.tsx new file mode 100644 index 000000000..774f19b7a --- /dev/null +++ b/docs/app/docs/first-steps/changelog/highlightChangelogCode.tsx @@ -0,0 +1,65 @@ +import React, { type ReactNode } from "react"; +import { refractor } from "refractor"; +import bash from "refractor/lang/bash"; +import js from "refractor/lang/javascript"; +import jsx from "refractor/lang/jsx"; +import ts from "refractor/lang/typescript"; +import tsx from "refractor/lang/tsx"; + +let registered = false; + +function ensureLanguagesRegistered() { + if (registered) return; + refractor.register(js); + refractor.register(jsx); + refractor.register(ts); + refractor.register(tsx); + refractor.register(bash); + registered = true; +} + +type HastElement = { + type: "element"; + tagName: string; + properties: { className?: string[] }; + children: HastChild[]; +}; + +type HastText = { type: "text"; value: string }; + +type HastChild = HastElement | HastText; + +function renderHastNode(element: HastChild, index: number): ReactNode { + if (element.type === "element") { + const { tagName, properties, children } = element; + const className = (properties.className ?? []).join(" "); + return React.createElement( + tagName, + { className, key: index }, + children.map((child, childIndex) => renderHastNode(child, childIndex)), + ); + } + if (element.type === "text") { + return element.value; + } + return null; +} + +/** + * Syntax-highlight markdown fenced code using the same Refractor + token CSS as docs CodeBlock. + */ +export function highlightChangelogCode( + source: string, + language: string, +): ReactNode { + ensureLanguagesRegistered(); + const trimmed = source.replace(/\n$/, ""); + try { + const tree = refractor.highlight(trimmed, language); + return tree.children.map((child, i) => + renderHastNode(child as HastChild, i), + ); + } catch { + return trimmed; + } +} diff --git a/docs/app/docs/first-steps/changelog/page.tsx b/docs/app/docs/first-steps/changelog/page.tsx new file mode 100644 index 000000000..84aaf1ad0 --- /dev/null +++ b/docs/app/docs/first-steps/changelog/page.tsx @@ -0,0 +1,226 @@ +import Link from "next/link"; +import { ExternalLink } from "lucide-react"; +import Button from "@radui/ui/Button"; + +import { ChangelogMarkdown } from "./ChangelogMarkdown"; +import { getSourceCodeFromPath } from "@/utils/parseSourceCode"; +import { + CHANGELOG_PAGE_SIZE, + parseChangelogMarkdown, +} from "@/utils/changelog/parseChangelog"; +import generateSeoMetadata from "@/utils/seo/generateSeoMetadata"; + +const SITE_URL = process.env.SITE_URL ?? "https://www.rad-ui.com"; +const CHANGELOG_PATH = "/docs/first-steps/changelog"; + +/** https://www.npmjs.com/package/@radui/ui */ +const NPM_PACKAGE_URL = "https://www.npmjs.com/package/@radui/ui"; + +function npmPackageVersionUrl(version: string) { + return `${NPM_PACKAGE_URL}/v/${encodeURIComponent(version)}`; +} + +/** Alias for older call sites / tooling that still references this name. */ +const NPM_VERSION = npmPackageVersionUrl; + +const baseMetadata = generateSeoMetadata({ + title: "Changelog", + description: + "Release history for @radui/ui: minor and patch changes shipped in each published version.", + keywords: ["changelog", "release notes", "@radui/ui", "npm", "versions"], + canonicalUrl: `${SITE_URL}${CHANGELOG_PATH}`, +}); + +export async function generateMetadata({ + searchParams, +}: { + searchParams: Promise<{ page?: string }>; +}) { + const sp = await searchParams; + const pageNum = parseChangelogPage(sp.page); + const titleSuffix = pageNum > 1 ? ` (page ${pageNum})` : ""; + const canonical = + pageNum > 1 + ? `${SITE_URL}${CHANGELOG_PATH}?page=${pageNum}` + : `${SITE_URL}${CHANGELOG_PATH}`; + + return { + ...baseMetadata, + title: `Changelog${titleSuffix} | Rad UI`, + alternates: { + ...baseMetadata.alternates, + canonical, + }, + openGraph: { + ...baseMetadata.openGraph, + title: `Changelog${titleSuffix}`, + url: canonical, + }, + twitter: { + ...baseMetadata.twitter, + title: `Changelog${titleSuffix}`, + }, + }; +} + +function parseChangelogPage(raw: string | undefined): number { + const n = parseInt(raw ?? "1", 10); + if (Number.isNaN(n) || n < 1) return 1; + return n; +} + +export default async function ChangelogPage({ + searchParams, +}: { + searchParams: Promise<{ page?: string }>; +}) { + const sp = await searchParams; + const pageNum = parseChangelogPage(sp.page); + const raw = await getSourceCodeFromPath("CHANGELOG.md"); + const releases = parseChangelogMarkdown(raw); + const totalPages = Math.max(1, Math.ceil(releases.length / CHANGELOG_PAGE_SIZE)); + const safePage = Math.min(pageNum, totalPages); + const offset = (safePage - 1) * CHANGELOG_PAGE_SIZE; + const pageReleases = releases.slice(offset, offset + CHANGELOG_PAGE_SIZE); + + return ( +
    +
    +

    + Changelog +

    +

    + Published versions of{" "} + + @radui/ui + + . Minor and patch sections follow{" "} + + SemVer + + . Source:{" "} + + CHANGELOG.md + {" "} + in the repository. +

    +
    + + {releases.length === 0 ? ( +

    + No releases found in CHANGELOG.md. +

    + ) : null} + +
    + {pageReleases.map((release) => ( +
    +
    +
    +

    + Release +

    +

    + v{release.version} +

    +
    + + npm + + +
    + +
    + ))} +
    + + {totalPages > 1 ? ( + + ) : null} +
    + ); +} diff --git a/docs/app/docs/layout.tsx b/docs/app/docs/layout.tsx index 17d08ee60..0e6abc429 100644 --- a/docs/app/docs/layout.tsx +++ b/docs/app/docs/layout.tsx @@ -6,11 +6,6 @@ import EditPageOnGithub from "@/components/docsHelpers/EditPageOnGithub"; import DocsTableOfContents from "@/components/layout/Documentation/DocsTableOfContents"; import ScrollArea from "@radui/ui/ScrollArea" -import Callout from "@radui/ui/Callout" -import Heading from "@radui/ui/Heading" -import Link from "@radui/ui/Link"; -import { Wrench } from "lucide-react"; - type Doc = { children: React.ReactNode; }; @@ -32,7 +27,6 @@ const Layout = ({ children }: Doc) => {
    -
    {children}
    @@ -52,10 +46,6 @@ const Layout = ({ children }: Doc) => { ) } -const DocsLayoutChunks = ({ children }: { children: React.ReactNode }) => { - return null; -} - const DocsLayoutGridRoot = ({ children }: { children: React.ReactNode }) => { return
    @@ -68,35 +58,4 @@ const DocsLayoutGridRoot = ({ children }: { children: React.ReactNode }) => {
    } -const DocsLayoutJoinDiscordCallout = () => { - return
    - - - - -
    - - Under Construction - - - We're actively working on new components and features. Stay tuned! Head over to our GitHub to see what's coming next. - - - Let’s build together on our{" "} - - Discord - - . - -
    -
    - -
    -} - - -// DocsLayoutChunks.Root = DocsLayoutGridRoot; -// DocsLayoutChunks.displayName = "DocsLayoutChunks"; - - export default Layout; diff --git a/docs/app/globals.scss b/docs/app/globals.scss index 72f3804b5..447578082 100644 --- a/docs/app/globals.scss +++ b/docs/app/globals.scss @@ -23,7 +23,6 @@ samp { } .docs-code-block { - color: var(--rad-ui-text-primary); font-size: 0.84rem; line-height: 1.72; } @@ -37,63 +36,240 @@ samp { box-shadow: none; } -pre code { - padding: 0; +/* Fenced code / CodeBlock: panel + tokens follow Theme ([data-rad-ui-theme]) */ +pre.docs-syntax-pre code.docs-code-block { border: 0; border-radius: 0; background: transparent; display: block; + padding: 0.875rem 1rem; font-size: 12px; line-height: 1.7; } -code .string { - color: var(--rad-ui-color-green-900); +[data-rad-ui-theme="light"] .docs-syntax-pre { + background-color: var(--rad-ui-surface-panel); + border-color: var(--rad-ui-border-soft); + color: var(--rad-ui-text-primary); + box-shadow: 0 16px 40px color-mix(in oklab, var(--rad-ui-color-gray-1000) 12%, transparent); } -code .punctuation { - color: var(--rad-ui-text-muted); +[data-rad-ui-theme="light"] .docs-syntax-pre .docs-code-block { + color: var(--rad-ui-text-primary); } -code .keyword { - color: var(--rad-ui-color-amber-900); +[data-rad-ui-theme="light"] .docs-syntax-pre code .keyword { + color: var(--rad-ui-color-red-900); } -code .function, -.function-variable { - color: var(--rad-ui-color-blue-900); +[data-rad-ui-theme="light"] .docs-syntax-pre code .string, +[data-rad-ui-theme="light"] .docs-syntax-pre code .attr-value, +[data-rad-ui-theme="light"] .docs-syntax-pre code .template-string, +[data-rad-ui-theme="light"] .docs-syntax-pre code .inserted { + color: var(--rad-ui-color-green-900); } -code .class-name { - color: var(--rad-ui-color-blue-900); +[data-rad-ui-theme="light"] .docs-syntax-pre code .number, +[data-rad-ui-theme="light"] .docs-syntax-pre code .boolean { + color: var(--rad-ui-color-green-900); } -code .tag { +[data-rad-ui-theme="light"] .docs-syntax-pre code .function, +[data-rad-ui-theme="light"] .docs-syntax-pre code .function-variable, +[data-rad-ui-theme="light"] .docs-syntax-pre code .class-name, +[data-rad-ui-theme="light"] .docs-syntax-pre code .tag, +[data-rad-ui-theme="light"] .docs-syntax-pre code .selector, +[data-rad-ui-theme="light"] .docs-syntax-pre code .property, +[data-rad-ui-theme="light"] .docs-syntax-pre code .maybe-class-name, +[data-rad-ui-theme="light"] .docs-syntax-pre code .builtin, +[data-rad-ui-theme="light"] .docs-syntax-pre code .constant { color: var(--rad-ui-color-blue-900); } -code .attr-name { +[data-rad-ui-theme="light"] .docs-syntax-pre code .attr-name { color: var(--rad-ui-color-red-900); } -code .attr-value { - color: var(--rad-ui-color-green-900); +[data-rad-ui-theme="light"] .docs-syntax-pre code .punctuation { + color: var(--rad-ui-text-muted); } -code .operator { +[data-rad-ui-theme="light"] .docs-syntax-pre code .operator { color: var(--rad-ui-color-purple-900); } -code .comment { +[data-rad-ui-theme="light"] .docs-syntax-pre code .comment, +[data-rad-ui-theme="light"] .docs-syntax-pre code .prolog, +[data-rad-ui-theme="light"] .docs-syntax-pre code .doctype, +[data-rad-ui-theme="light"] .docs-syntax-pre code .cdata { color: var(--rad-ui-color-gray-800); } -code .property { - color: var(--rad-ui-color-pink-900); +[data-rad-ui-theme="light"] .docs-syntax-pre code .regex, +[data-rad-ui-theme="light"] .docs-syntax-pre code .important, +[data-rad-ui-theme="light"] .docs-syntax-pre code .variable { + color: var(--rad-ui-color-blue-900); } -code .selector { - color: var(--rad-ui-color-blue-900); +[data-rad-ui-theme="light"] .docs-syntax-pre code .char { + color: var(--rad-ui-color-green-900); +} + +/* Dark: high-contrast editor palette on black panel */ +[data-rad-ui-theme="dark"] .docs-syntax-pre { + background-color: #000; + border-color: #27272a; + color: #fafafa; + box-shadow: 0 16px 48px rgb(0, 0, 0, 0.55); +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre .docs-code-block { + color: #fafafa; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .keyword { + color: #f472b6; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .string, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .attr-value, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .template-string, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .inserted { + color: #4ade80; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .number, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .boolean { + color: #2dd4bf; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .function, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .function-variable, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .class-name, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .tag, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .selector, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .property, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .maybe-class-name, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .builtin, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .constant { + color: #93c5fd; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .attr-name { + color: #f0abfc; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .punctuation, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .operator { + color: #fafafa; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .comment, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .prolog, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .doctype, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .cdata { + color: #737373; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .regex, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .important, +[data-rad-ui-theme="dark"] .docs-syntax-pre code .variable { + color: #93c5fd; +} + +[data-rad-ui-theme="dark"] .docs-syntax-pre code .char { + color: #4ade80; +} + +.docs-syntax-toolbar { + border-bottom: 1px solid var(--rad-ui-border-soft); + background: linear-gradient( + 180deg, + color-mix(in oklab, var(--rad-ui-text-primary) 3%, transparent), + transparent + ); +} + +[data-rad-ui-theme="dark"] .docs-syntax-toolbar { + border-color: #27272a; + background: #09090b; +} + +.docs-syntax-toolbar-label { + font-size: 0.68rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.14em; + color: var(--rad-ui-text-muted); +} + +[data-rad-ui-theme="dark"] .docs-syntax-toolbar-label { + color: #a1a1aa; +} + +.docs-syntax-scroll-area { + background-color: var(--rad-ui-surface-panel); +} + +[data-rad-ui-theme="dark"] .docs-syntax-scroll-area { + background-color: #000; +} + +.docs-syntax-footer { + border-top: 1px solid var(--rad-ui-border-soft); + background: color-mix(in oklab, var(--rad-ui-surface-subtle) 55%, transparent); +} + +[data-rad-ui-theme="dark"] .docs-syntax-footer { + border-color: #27272a; + background: rgb(9, 9, 11, 0.9); +} + +.docs-syntax-copy { + border-style: solid; + border-width: 1px; + border-color: var(--rad-ui-border-soft); + background: var(--rad-ui-surface-subtle); + color: var(--rad-ui-text-muted); +} + +.docs-syntax-copy:hover { + background: var(--rad-ui-surface-hover); + color: var(--rad-ui-text-primary); +} + +[data-rad-ui-theme="dark"] .docs-syntax-copy { + border-color: #3f3f46; + background: #18181b; + color: #a1a1aa; +} + +[data-rad-ui-theme="dark"] .docs-syntax-copy:hover { + background: #27272a; + color: #fafafa; +} + +.docs-syntax-expand { + border-style: solid; + border-color: var(--rad-ui-border-soft); + background: var(--rad-ui-surface-subtle); + color: var(--rad-ui-text-muted); +} + +.docs-syntax-expand:hover { + background: var(--rad-ui-surface-hover); + color: var(--rad-ui-text-primary); +} + +[data-rad-ui-theme="dark"] .docs-syntax-expand { + border-color: #3f3f46; + background: #18181b; + color: #a1a1aa; +} + +[data-rad-ui-theme="dark"] .docs-syntax-expand:hover { + background: #27272a; + color: #fafafa; } .code-block-blur { @@ -107,11 +283,22 @@ code .selector { height: 100px; width: 100%; bottom: 0; - background: linear-gradient(180deg, transparent, var(--rad-ui-surface-panel) 72%); - opacity: 0.9; + opacity: 0.95; } } +[data-rad-ui-theme="light"] .code-block-blur::before { + background: linear-gradient( + 180deg, + transparent, + var(--rad-ui-surface-panel) 72% + ); +} + +[data-rad-ui-theme="dark"] .code-block-blur::before { + background: linear-gradient(180deg, transparent, #000 72%); +} + .top-layout-line { position: relative; height: 1px; diff --git a/docs/app/layout.js b/docs/app/layout.js index 450a9ed84..e9556a53b 100644 --- a/docs/app/layout.js +++ b/docs/app/layout.js @@ -109,7 +109,7 @@ export default async function RootLayout({ children, ...props }) { const darkModeSsrValue = cookieStore.get('darkMode')?.value || false return ( - + @@ -147,7 +147,7 @@ export default async function RootLayout({ children, ...props }) { }} /> - +
    {children} diff --git a/docs/components/docsHelpers/EditPageOnGithub.tsx b/docs/components/docsHelpers/EditPageOnGithub.tsx index 20291f1eb..0a8dc40b0 100644 --- a/docs/components/docsHelpers/EditPageOnGithub.tsx +++ b/docs/components/docsHelpers/EditPageOnGithub.tsx @@ -3,19 +3,35 @@ import { usePathname } from "next/navigation"; import Link from "@radui/ui/Link"; -const EditPageOnGithub = () => { +const GITHUB_REPO_EDIT_BASE = "https://github.com/rad-ui/ui/edit/main"; + +const CHANGELOG_EDIT_HREF = `${GITHUB_REPO_EDIT_BASE}/CHANGELOG.md`; +const EditPageOnGithub = () => { const pathname = usePathname(); const page = pathname.split("/").slice(2).join("/"); + if (page === "first-steps/changelog") { + return ( +
    + + Edit changelog on GitHub + +
    + ); + } const currentDocsPath = "docs/app/docs/" + page; - return ( -
    - Edit this page on GitHub -
    - ); + return ( +
    + + Edit this page on GitHub + +
    + ); }; export default EditPageOnGithub; \ No newline at end of file diff --git a/docs/components/layout/Documentation/DocsTableOfContents.tsx b/docs/components/layout/Documentation/DocsTableOfContents.tsx index c23742987..6541b2ba4 100644 --- a/docs/components/layout/Documentation/DocsTableOfContents.tsx +++ b/docs/components/layout/Documentation/DocsTableOfContents.tsx @@ -103,7 +103,7 @@ const DocsTableOfContents = () => { return (