diff --git a/docusaurus.config.ts b/docusaurus.config.ts index d30e368ae8..3953247c5d 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -200,7 +200,7 @@ const config: Config = { copyright: `Copyright © ${new Date().getFullYear()} RavenDB`, }, prism: { - theme: prismThemes.github, + theme: prismThemes.nightOwlLight, darkTheme: prismThemes.dracula, additionalLanguages: ["csharp", "java", "php"], }, diff --git a/src/components/ContentFrame.tsx b/src/components/ContentFrame.tsx new file mode 100644 index 0000000000..3a085203cc --- /dev/null +++ b/src/components/ContentFrame.tsx @@ -0,0 +1,20 @@ +import clsx from "clsx"; +import React from "react"; + +export type ContentFrameProps = { + children: React.ReactNode; + className?: string; + flush?: boolean; +}; + +export function ContentFrame(props: ContentFrameProps) { + const { children, className, flush } = props; + + return ( +
+ {children} +
+ ); +} + +export default ContentFrame; diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx index 6f3ff21d64..a02f96d41d 100644 --- a/src/components/LanguageSwitcher.tsx +++ b/src/components/LanguageSwitcher.tsx @@ -50,8 +50,8 @@ export default function LanguageSwitcher({ onClick={() => setLanguage(lang.value)} className={clsx( "px-3 py-1.5 rounded-md border text-sm transition-colors cursor-pointer", - "border-gray-300 text-gray-500 hover:bg-black/5 hover:border-gray-500 hover:text-gray-600", - "dark:text-gray-300 dark:border-gray-600 dark:hover:text-gray-200 dark:hover:border-gray-400 dark:hover:bg-white/5", + "border-black/10 text-gray-500 hover:bg-black/5 hover:border-black/15 hover:text-gray-600", + "dark:text-gray-300 dark:border-white/10 dark:hover:text-gray-200 dark:hover:border-white/15 dark:hover:bg-white/5", )} style={ isActive diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx new file mode 100644 index 0000000000..2b15b1ff3f --- /dev/null +++ b/src/components/Panel.tsx @@ -0,0 +1,27 @@ +import clsx from "clsx"; +import React from "react"; +import Heading from "@theme/Heading"; + +export type PanelProps = { + children: React.ReactNode; + className?: string; + flush?: boolean; + heading: string; + headingLevel?: 1 | 2 | 3 | 4 | 5 | 6; +}; + +export function Panel(props: PanelProps) { + const { children, className, flush, heading, headingLevel = 2 } = props; + const headingTag = (`h${headingLevel}` as any); + + return ( +
+ {heading} +
+ {children} +
+
+ ); +} + +export default Panel; diff --git a/src/css/custom.css b/src/css/custom.css index 864d89cbff..ab9a25dc37 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -31,6 +31,7 @@ --font-mono: "JetBrains Mono", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --ifm-pre-background: color-mix(in oklab, var(--ifm-background-surface-color) 72%, #FFF 28%); --anchor-icon: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyB2aWV3Qm94PSIwIDAgMjU2IDI1NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCBmaWxsPSJub25lIiBoZWlnaHQ9IjI1NiIgd2lkdGg9IjI1NiIvPjxwYXRoIGQ9Ik0yMTAsNDZhNTEuOCw1MS44LDAsMCwwLTczLjUsMEwxMTYuNyw2NS44QTgsOCwwLDAsMCwxMjgsNzcuMWwxOS44LTE5LjhhMzYuMSwzNi4xLDAsMCwxLDUwLjksMCwzNS45LDM1LjksMCwwLDEsMCw1MC45bC0yOC4zLDI4LjNhMzYuMSwzNi4xLDAsMCwxLTUwLjksMCw4LDgsMCwxLDAtMTEuMywxMS4zLDUyLDUyLDAsMCwwLDczLjUsMEwyMTAsMTE5LjVBNTEuOCw1MS44LDAsMCwwLDIxMCw0NloiLz48cGF0aCBkPSJNMTI4LDE3OC45bC0xOS44LDE5LjhhMzYsMzYsMCwwLDEtNTAuOS01MC45bDI4LjMtMjguM2EzNi4xLDM2LjEsMCwwLDEsNTAuOSwwLDgsOCwwLDAsMCwxMS4zLTExLjMsNTIsNTIsMCwwLDAtNzMuNSwwTDQ2LDEzNi41QTUyLDUyLDAsMSwwLDExOS41LDIxMGwxOS44LTE5LjhBOCw4LDAsMCwwLDEyOCwxNzguOVoiLz48L3N2Zz4="); --docsearch-searchbox-focus-background: var(--ifm-background-color) !important; --docsearch-hit-color: var(--ifm-color-primary-lightest) !important; @@ -47,9 +48,18 @@ --ifm-color-primary-lightest: #86baf2; --ifm-navbar-background-color: var(--ifm-background-color); --ifm-background-surface-color: #222225; + --ifm-pre-background: color-mix(in oklab, var(--ifm-background-surface-color) 72%, #000 28%); --anchor-icon: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2Ij4KIDxnPgogIDx0aXRsZT5iYWNrZ3JvdW5kPC90aXRsZT4KICA8cmVjdCBmaWxsPSJub25lIiBpZD0iY2FudmFzX2JhY2tncm91bmQiIGhlaWdodD0iNDAyIiB3aWR0aD0iNTgyIiB5PSItMSIgeD0iLTEiLz4KIDwvZz4KIDxnPgogIDx0aXRsZT5MYXllciAxPC90aXRsZT4KICA8cmVjdCBpZD0ic3ZnXzEiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZmlsbD0iI2ZmZmZmZiIgaWQ9InN2Z18yIiBkPSJtMjEwLDQ2YTUxLjgsNTEuOCAwIDAgMCAtNzMuNSwwbC0xOS44LDE5LjhhOCw4IDAgMCAwIDExLjMsMTEuM2wxOS44LC0xOS44YTM2LjEsMzYuMSAwIDAgMSA1MC45LDBhMzUuOSwzNS45IDAgMCAxIDAsNTAuOWwtMjguMywyOC4zYTM2LjEsMzYuMSAwIDAgMSAtNTAuOSwwYTgsOCAwIDEgMCAtMTEuMywxMS4zYTUyLDUyIDAgMCAwIDczLjUsMGwyOC4zLC0yOC4zYTUxLjgsNTEuOCAwIDAgMCAwLC03My41eiIvPgogIDxwYXRoIGZpbGw9IiNmZmZmZmYiIGlkPSJzdmdfMyIgZD0ibTEyOCwxNzguOWwtMTkuOCwxOS44YTM2LDM2IDAgMCAxIC01MC45LC01MC45bDI4LjMsLTI4LjNhMzYuMSwzNi4xIDAgMCAxIDUwLjksMGE4LDggMCAwIDAgMTEuMywtMTEuM2E1Miw1MiAwIDAgMCAtNzMuNSwwbC0yOC4zLDI4LjNhNTIsNTIgMCAxIDAgNzMuNSw3My41bDE5LjgsLTE5LjhhOCw4IDAgMCAwIC0xMS4zLC0xMS4zeiIvPgogPC9nPgo8L3N2Zz4= "); } +/* Ensure code blocks use the harmonized background even if theme overrides */ +.theme-code-block, +.codeBlockContainer, +pre[class*="language-"] { + --prism-background-color: var(--ifm-pre-background) !important; + background-color: var(--prism-background-color) !important; +} + /* Custom search variables */ [data-theme="light"] .DocSearch { --docsearch-primary-color: var(--ifm-color-primary); @@ -331,3 +341,71 @@ code { [class^="tabItem"]:has(+ *), .theme-admonition:has(+ *) { @apply mb-4; } + +/* Remove trailing margin from the last element inside the last div of an admonition */ +.theme-admonition > div:last-child > :last-child { + @apply mb-0; +} + +/* Frames for documentation content */ +.content-frame { + @apply rounded-md border border-black/10 dark:border-white/10 p-4; + background-color: color-mix(in oklab, var(--ifm-background-surface-color) 85%, transparent); +} + +.content-frame > :first-child { + @apply mt-0; +} + +.content-frame > :last-child { + @apply mb-0; +} + +.content-frame pre, +.content-frame .theme-code-block { + @apply my-0; +} + +.panel { + @apply rounded-lg border border-black/10 dark:border-white/10; +} + +.panel__body { + padding: 1.5rem; + background-color: color-mix(in oklab, var(--ifm-background-surface-color) 30%, transparent); +} + +.panel__body > :first-child { + @apply mt-0; +} + +.panel__body > :last-child { + @apply mb-0; +} + +.panel__body pre, +.panel__body .theme-code-block { + @apply my-0; +} + +.panel__heading { + @apply rounded-t-lg border-b border-black/10 dark:border-white/10 m-0; + padding: 0.875rem 1rem; +} + +.panel__heading { + background-color: var(--ifm-background-surface-color); +} + +.theme-code-block { + @apply border border-black/10 dark:border-white/10; +} + +/* Remove borders for code blocks when placed inside tabs container */ +.tabs-container .theme-code-block, +.tabs-container .codeBlockContainer, +.tabs-container pre[class*="language-"] { + @apply !border-0; + border: 0 !important; + box-shadow: none !important; +} \ No newline at end of file diff --git a/src/theme/Tabs/index.tsx b/src/theme/Tabs/index.tsx index 17fe48077a..2798fbd035 100644 --- a/src/theme/Tabs/index.tsx +++ b/src/theme/Tabs/index.tsx @@ -67,7 +67,7 @@ function TabList({ role="tablist" aria-orientation="horizontal" className={clsx( - "!my-0 !px-4 flex gap-2 bg-ifm-background-surface", + "!my-0 !px-4 flex gap-2 bg-black/6 dark:bg-white/3 border-b border-black/10 dark:border-white/10", { "tabs--block": block, }, @@ -128,7 +128,7 @@ function TabContent({ }); } return ( -
+
{childTabs.map((tabItem, i) => cloneElement(tabItem, { key: i, @@ -144,7 +144,7 @@ function TabsComponent(props: Props): ReactNode { return (
diff --git a/templates/frames.mdx b/templates/frames.mdx new file mode 100644 index 0000000000..75518a6f20 --- /dev/null +++ b/templates/frames.mdx @@ -0,0 +1,234 @@ +--- +title: "Frames: ContentFrame and Panel" +hide_table_of_contents: false +sidebar_label: Frames +--- + +import Admonition from '@theme/Admonition'; +import ContentFrame from '@site/src/components/ContentFrame'; +import Panel from '@site/src/components/Panel'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Frames overview + +This guide shows how to use content frames in MDX: lightweight `ContentFrame` for small/medium chunks and `Panel` for larger sections with a built‑in heading and body. + +## ContentFrame + +### Import +```mdx +import ContentFrame from '@site/src/components/ContentFrame'; +``` + +### Basic usage +````mdx + + Text, lists, images, and even code blocks. + + ```ts + console.log('Hello world!') + ``` + +```` + +#### Live example + + + Text, lists, images, and even code blocks. + + ```ts + console.log('Hello world!') + ``` + + +- Comes with consistent background, border and inner spacing. +- Has vertical margin by default. + +### Flush variant (removes the outer vertical margin) +```mdx + + Social card + +``` + +#### Live example + + + Social card + + +
+ Need spacing after a flush frame? See: [Tailwind margin documentation](https://tailwindcss.com/docs/margin). +
+ +### Custom classes +```mdx + + Custom font class. + +``` + +#### Live example + + + Custom font class. + + +## Panel + +### Import +```mdx +import Panel from '@site/src/components/Panel'; +``` + +### Basic usage with heading and body +```mdx + + Content of the section placed inside the panel. + +``` + +#### Live example + + + Content of the section placed inside the panel. + + +### Heading level + +Use `headingLevel` (1–6) to control the semantic level. Default is 2. +```mdx + + Content... + +``` + +#### Live example + + + Content... + + +The heading renders via `@theme/Heading`, so it automatically gets the anchor link. The id is generated from the `heading` text. + +### Flush variant (removes the outer vertical margin) +```mdx + + + +``` + +#### Live example + + + + + +
+Need spacing after a flush frame? See: [Tailwind margin documentation](https://tailwindcss.com/docs/margin). +
+ +### Custom classes +```mdx + + Content styled with a custom font. + +``` + +#### Live example + + + Content styled with a custom font. + + +### Nesting frames + +You can combine `Panel` and `ContentFrame`: +```mdx + + + Short piece of content inside the panel. + + +``` + +#### Live example + + + + Short piece of content inside the panel. + + + +### Panels with code and tabs + +````mdx +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + + ```csharp + // sample code + Console.WriteLine("Hello"); + ``` + + + ```csharp + await Console.Out.WriteLineAsync("Hello"); + ``` + + + +```` + +#### Live example + + + + + ```csharp + // sample code + Console.WriteLine("Hello"); + ``` + + + ```csharp + await Console.Out.WriteLineAsync("Hello"); + ``` + + + + +## Best practices + +- Use `ContentFrame` for short, self‑contained fragments: notes, option lists, compact code examples. +- Use `Panel` for larger sections: full blocks with headings and multi‑paragraph content. +- Prefer `flush` when the inner content controls its own spacing (images, embedded widgets). +- Avoid redundant wrappers — both components already provide consistent background and borders. + + +Keep the heading hierarchy consistent using `headingLevel` to preserve a correct document outline. + + +## Props + +### ContentFrame + +| Prop | Type | Default | Description | +| ---------- | ------------------- | ------- | ----------------------------------------------- | +| children | React.ReactNode | — | Frame content (markdown, code, images, etc.). | +| className | string | — | Additional classes for custom styling. | +| flush | boolean | false | Removes only the outer vertical margin. | + +### Panel + +| Prop | Type | Default | Description | +| ------------ | ------------------------- | ------- | ---------------------------------------------------------------------- | +| heading | string | — | Panel heading text. Used to generate the anchor id (slug). | +| headingLevel | 1 \| 2 \| 3 \| 4 \| 5 \| 6 | 2 | Semantic level of the heading (`h1`..`h6`). | +| children | React.ReactNode | — | Content placed inside the panel body. | +| className | string | — | Additional classes for custom styling. | +| flush | boolean | false | Removes only the outer vertical margin. | \ No newline at end of file