Skip to content

feat: extend code blocks with collapsible and flags#239

Open
david-on-github wants to merge 11 commits into
masterfrom
david/collapse-code-blocks
Open

feat: extend code blocks with collapsible and flags#239
david-on-github wants to merge 11 commits into
masterfrom
david/collapse-code-blocks

Conversation

@david-on-github

@david-on-github david-on-github commented Jul 17, 2026

Copy link
Copy Markdown
Member

Extends code blocks with metadata display options , configured with bare-word flags
on the md fence line, fixes #232 :

Flag Effect
result Marks query/mutation output; auto-collapses when ≥ 12 lines, adds a stable codeblock-result class
collapse Force the collapse UI on
noCollapse Force it off
expanded Collapsible, but starts open
valid / invalid Green/red border + tinted title bar for correct/incorrect examples

Example: ```json title="Result" result expanded

Collapsed blocks clip to ~8 lines with a fade and a centered "Expand (N lines)"
button; clicking anywhere on the block expands it. Blocks with no flags are
completely unaffected.

This replaces the old DOM-manipulation client module (src/plugins/code-blocks.js,
deleted) — the previous approach ran on a post-load timeout, targeted hashed
theme class names, and couldn't render blocks collapsed on first paint.

Docs

  • Tagged all # valid / # invalid examples with the matching flag and
    removed the now-redundant magic comments (filter, order, mutation-create,
    collections)
  • Tagged all ~85 title="Result" fences with result

Misc

  • Fix search button background color and other small css fixes

- Update CSS for code blocks to improve styling and consistency.
- Introduce validity styles for code blocks, allowing differentiation between valid and invalid states.
- Remove unused collapse context and integrate flags context for better state management.
- Adjust code block component to utilize new flags for collapsibility and validity.
- Enhance code block title bar styling for better visual feedback.
@david-on-github
david-on-github requested a review from ribiza July 17, 2026 15:52
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@david-on-github, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 19 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b897e2ef-58b6-43aa-ac46-11f5d922c203

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5e62d and b835d5a.

📒 Files selected for processing (19)
  • docs/defradb/dql/aggregating-functions.md
  • docs/defradb/dql/aliases.md
  • docs/defradb/dql/filter.md
  • docs/defradb/dql/group.md
  • docs/defradb/dql/limit-paginate.md
  • docs/defradb/dql/mutation-create.md
  • docs/defradb/dql/mutation-delete.md
  • docs/defradb/dql/mutation-query.md
  • docs/defradb/dql/mutation-update.md
  • docs/defradb/dql/order.md
  • docs/defradb/dql/variables.md
  • docs/defradb/quickstart.md
  • docs/defradb/schema/collections.md
  • docs/defradb/security/document-access-control.md
  • docs/defradb/security/node-access-control.md
  • docs/defradb/transactions.md
  • src/css/custom.scss
  • src/css/infima-variables.scss
  • src/theme/CodeBlock/styles.module.css
📝 Walkthrough

Walkthrough

The PR adds metadata-driven Docusaurus code-block rendering with result, validity, and collapsible states. Documentation examples receive corresponding fence annotations, while configuration, React wrappers, context, CSS modules, and theme variables are updated.

Changes

Code-block rendering

Layer / File(s) Summary
Fence metadata and Docusaurus wiring
docs/defradb/**/*.md, docusaurus.config.js
Result and validity annotations are added across documentation examples; obsolete client-module and magic-comment configuration is removed.
Fence parsing and collapsible content
src/theme/CodeBlock/index.tsx, src/theme/CodeBlock/flagsContext.ts, src/theme/CodeBlock/Content/*
Fence flags are parsed into context, and result blocks can collapse based on line count with accessible expand/collapse controls.
Code-block and theme styling
src/theme/CodeBlock/**/*.css, src/css/custom.scss, src/css/infima-variables.scss
Validity states, result spacing, collapsed content, title borders, scrollbars, navigation, search controls, and theme variables are styled.
Configuration cleanup
docusaurus.config.js
Markdown, sitemap, LLM, documentation plugin, and sidebar configuration formatting is normalized while preserving the documented plugin behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DocsFence
  participant CodeBlockWrapper
  participant ContentWrapper
  participant User
  DocsFence->>CodeBlockWrapper: Provide metastring flags
  CodeBlockWrapper->>ContentWrapper: Provide parsed result and collapse state
  ContentWrapper->>ContentWrapper: Calculate line count and collapse eligibility
  User->>ContentWrapper: Activate expand or collapse control
  ContentWrapper->>ContentWrapper: Update expanded state
Loading

Possibly related PRs

Suggested reviewers: ribiza, blackstoneengineering


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/css/infima-variables.scss (1)

31-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Quote font names with spaces and remove duplicates.

Font family names containing spaces should be enclosed in quotes to ensure they are parsed correctly by all browsers and minifiers. Additionally, Segoe UI and sans-serif are listed twice.

♻️ Proposed refactor
   // Fonts
   --ifm-font-family-base:
-    "Inter", system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell,
-    Noto Sans, sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
-    sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+    "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell,
+    "Noto Sans", BlinkMacSystemFont, Helvetica, Arial,
+    sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
   --ifm-font-size-base: 1rem;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/css/infima-variables.scss` around lines 31 - 34, Update the
--ifm-font-family-base declaration to quote every font family containing spaces,
including Segoe UI and Noto Sans, and remove the duplicate Segoe UI and
sans-serif entries while preserving the existing fallback order.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/css/infima-variables.scss`:
- Around line 31-34: Update the --ifm-font-family-base declaration to quote
every font family containing spaces, including Segoe UI and Noto Sans, and
remove the duplicate Segoe UI and sans-serif entries while preserving the
existing fallback order.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4dfaa24d-447d-4456-b8a6-c7ec79c45cf3

📥 Commits

Reviewing files that changed from the base of the PR and between 16f276b and 7d5e62d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (25)
  • docs/defradb/dql/aggregating-functions.md
  • docs/defradb/dql/aliases.md
  • docs/defradb/dql/filter.md
  • docs/defradb/dql/group.md
  • docs/defradb/dql/limit-paginate.md
  • docs/defradb/dql/mutation-create.md
  • docs/defradb/dql/mutation-delete.md
  • docs/defradb/dql/mutation-query.md
  • docs/defradb/dql/mutation-update.md
  • docs/defradb/dql/order.md
  • docs/defradb/dql/variables.md
  • docs/defradb/quickstart.md
  • docs/defradb/schema/collections.md
  • docs/defradb/security/document-access-control.md
  • docs/defradb/security/node-access-control.md
  • docs/defradb/transactions.md
  • docusaurus.config.js
  • src/css/custom.scss
  • src/css/infima-variables.scss
  • src/plugins/code-blocks.js
  • src/theme/CodeBlock/Content/index.tsx
  • src/theme/CodeBlock/Content/styles.module.css
  • src/theme/CodeBlock/flagsContext.ts
  • src/theme/CodeBlock/index.tsx
  • src/theme/CodeBlock/styles.module.css
💤 Files with no reviewable changes (1)
  • src/plugins/code-blocks.js
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Cloudflare Pages
🧰 Additional context used
📓 Path-based instructions (3)
src/{theme,css,code-theme}/**/*.{js,jsx,ts,tsx,scss,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Custom theme components use Docusaurus swizzling with custom footer components, color mode toggle, SCSS styling in /src/css/custom.scss, and custom code theme in /src/code-theme/code-theme.js

Files:

  • src/theme/CodeBlock/flagsContext.ts
  • src/theme/CodeBlock/styles.module.css
  • src/theme/CodeBlock/index.tsx
  • src/theme/CodeBlock/Content/styles.module.css
  • src/theme/CodeBlock/Content/index.tsx
  • src/css/infima-variables.scss
  • src/css/custom.scss
**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

Documentation files support both .md (CommonMark) and .mdx (MDX) formats

Files:

  • docs/defradb/dql/limit-paginate.md
  • docs/defradb/dql/mutation-update.md
  • docs/defradb/dql/mutation-delete.md
  • docs/defradb/dql/aliases.md
  • docs/defradb/dql/variables.md
  • docs/defradb/transactions.md
  • docs/defradb/dql/order.md
  • docs/defradb/schema/collections.md
  • docs/defradb/dql/aggregating-functions.md
  • docs/defradb/dql/mutation-create.md
  • docs/defradb/dql/mutation-query.md
  • docs/defradb/quickstart.md
  • docs/defradb/security/node-access-control.md
  • docs/defradb/dql/group.md
  • docs/defradb/security/document-access-control.md
  • docs/defradb/dql/filter.md
docusaurus.config.js

📄 CodeRabbit inference engine (CLAUDE.md)

docusaurus.config.js: Changelog and release notes sidebar items should be automatically reversed (newest first) via the reverseSidebarChangelog() function in docusaurus.config.js
The site uses dark mode by default with respectPrefersColorScheme: false
GitHub edit links should be configured to point to the master branch
Algolia search is configured with app ID N3M9YBYYQY

Files:

  • docusaurus.config.js
🪛 Stylelint (17.14.0)
src/css/infima-variables.scss

[error] 32-32: Expected "Segoe" to be "segoe" (value-keyword-case)

(value-keyword-case)


[error] 32-32: Expected "UI" to be "ui" (value-keyword-case)

(value-keyword-case)


[error] 32-32: Expected "Roboto" to be "roboto" (value-keyword-case)

(value-keyword-case)


[error] 32-32: Expected "Ubuntu" to be "ubuntu" (value-keyword-case)

(value-keyword-case)


[error] 32-32: Expected "Cantarell" to be "cantarell" (value-keyword-case)

(value-keyword-case)


[error] 33-33: Expected "Noto" to be "noto" (value-keyword-case)

(value-keyword-case)


[error] 33-33: Expected "Sans" to be "sans" (value-keyword-case)

(value-keyword-case)


[error] 33-33: Expected "BlinkMacSystemFont" to be "blinkmacsystemfont" (value-keyword-case)

(value-keyword-case)


[error] 33-33: Expected "Helvetica" to be "helvetica" (value-keyword-case)

(value-keyword-case)


[error] 33-33: Expected "Arial" to be "arial" (value-keyword-case)

(value-keyword-case)

🔇 Additional comments (17)
docs/defradb/dql/aggregating-functions.md (1)

198-198: LGTM!

Also applies to: 267-267, 336-336, 417-417, 544-544, 559-559

docs/defradb/dql/aliases.md (1)

133-133: LGTM!

Also applies to: 176-176, 233-233

docs/defradb/dql/filter.md (1)

142-142: LGTM!

Also applies to: 168-168, 184-184, 193-193, 219-219, 267-267, 325-325, 365-365, 393-393, 429-429, 500-500, 551-551, 570-570, 588-588, 597-597, 620-620, 646-646, 682-682

docs/defradb/dql/group.md (1)

152-152: LGTM!

Also applies to: 245-245, 331-331, 438-438, 532-532, 569-569, 610-610, 667-667, 704-704

docs/defradb/dql/limit-paginate.md (1)

135-135: LGTM!

Also applies to: 173-173

docs/defradb/dql/mutation-create.md (1)

65-65: LGTM!

Also applies to: 116-116, 166-166, 233-233, 277-277, 312-312, 338-338, 350-350

docs/defradb/dql/mutation-delete.md (1)

149-149: LGTM!

Also applies to: 173-173, 196-196

docs/defradb/dql/mutation-query.md (1)

178-178: LGTM!

Also applies to: 229-229, 278-278, 338-338, 403-403, 487-487, 522-522

docs/defradb/dql/mutation-update.md (1)

152-152: LGTM!

Also applies to: 175-175, 201-201

docs/defradb/dql/order.md (1)

133-133: LGTM!

Also applies to: 175-175, 206-206, 219-219

docs/defradb/dql/variables.md (1)

149-149: LGTM!

Also applies to: 185-185, 222-222

docusaurus.config.js (1)

17-21: LGTM!

Also applies to: 41-41, 166-172, 181-183, 209-210, 228-265, 281-285, 313-313, 341-341, 369-374

src/theme/CodeBlock/flagsContext.ts (1)

1-13: LGTM!

src/theme/CodeBlock/index.tsx (1)

15-60: LGTM!

src/theme/CodeBlock/Content/styles.module.css (1)

1-40: LGTM!

src/theme/CodeBlock/styles.module.css (1)

1-23: LGTM!

src/theme/CodeBlock/Content/index.tsx (1)

28-32: 🩺 Stability & Availability

No change needed: metadata.code is the expected shape here. useCodeBlockContext() exposes metadata.code in Docusaurus 3.10.1, so this access is valid.

			> Likely an incorrect or invalid review comment.

@coderabbitai coderabbitai Bot mentioned this pull request Jul 17, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploying docs-source-network with  Cloudflare Pages  Cloudflare Pages

Latest commit: b835d5a
Status: ✅  Deploy successful!
Preview URL: https://d1c8c163.docs-source-network.pages.dev
Branch Preview URL: https://david-collapse-code-blocks.docs-source-network.pages.dev

View logs

@ribiza ribiza left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big thank you David for expanding and cleaning up the previous implementation. It looks tidier and well functioning :)

Can you include the table you put in the PR body in the readme too? It's valuable info to have for people interacting with this repo.

Comment thread src/css/custom.scss
:root {
// Source variables
--src-primary: #06b250;
--src-highlight: #39e265;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the (future?) intention for this? I don't think I see it used.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we start to define the 'brand' variables separate from the docusarus 'ifm' variables.
And reference the source brand variables inside the ifm vars. To keep it a bit more organized.

Comment thread src/css/custom.scss
// Code block variables
--codeblock-title-border: #323232;
--codeblock-valid-border: var(--src-primary);
--codeblock-invalid-border: var(--src-red);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are valid/invalid-border provided for clarity here? The values for dark mode are the same as in :root.

:root {
// Colors
--ifm-color-primary: #058041;
--ifm-color-primary: #06b250;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we at least define --ifm-color-primary in terms of --src-primary? They have the same value.

Also, I'm unsure about the reason of the split. From your work in this PR I infer that you wanted to keep --ifm-color-primary for docusaurus native use, and use --src-primary for our custom implementation. However, if we would change the brand identity and make --src-primary, say, bright pink, only a handful of places would change color, but the bulk of colors would stay the same, and it's unlikely what we want. So we'd need to change two variables.
If these two variables always go in tandem, then we can as well have just one.

Suggested change
--ifm-color-primary: #06b250;
--src-primary: #06b250;
--ifm-color-primary: var(--src-primary);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was exactly the intention, I just didn't do it 😅, nice catch.

return {
collapsible: pick(["noCollapse", false], ["collapse", true]),
collapsed: pick(["expanded", false]),
validity: pick<Validity>(["invalid", "invalid"], ["valid", "valid"]),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
validity: pick<Validity>(["invalid", "invalid"], ["valid", "valid"]),
validity: pick(["valid", true], ["invalid", false]),

Then,

  • value in pick could be of type bool instead of generic T
  • Validity could be removed entirely from flagsContext.ts

valid/invalid is after all not different from collapse/noCollapse, so mirroring its behavior makes sense.

I'm trying to think if there's future scenarios in which we could want fence flags to work with enums instead of forcing bools, but it takes a second to flip pick.value to T again, and we can export enums from flagsContext.ts when we'll need them.

// valid → frame the block as a valid example
// invalid → frame the block as a invalid example
// result → mark the block as a result
function parseFenceFlags(metastring = ""): CodeBlockFlags {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: is Fence a term you created for this context, or is it the standard md/docusaurus terminology? Asking because I've seen it referred as fence but also as metadata in this PR (and the argument is metastring).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't know. I see it referred to as both internally in docusaurus also.
Apparently these types of triple tick code blocks are called "Fenced code blocks".

But they call that leading line in a "fenced code block" a "metastring"
AI named them fenceFlags. Happy to go by one name.

Still call them "flags", but just avoid the use of fence? parseMetastringFlags?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still call them "flags", but just avoid the use of fence? parseMetastringFlags?

I think this is the best approach 👍

--codeblock-state-border: var(--codeblock-invalid-border);
--codeblock-state-text: var(--codeblock-invalid-text);
--codeblock-state-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m15 9-6 6'/%3E%3Cpath d='m9 9 6 6'/%3E%3C/svg%3E");
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: put the var definitions in these two last blocks at the top of the file. It's easier to follow.


.valid {
--codeblock-state-border: var(--codeblock-valid-border);
--codeblock-state-text: var(--codeblock-valid-text);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--codeblock-valid-text is undefined. Same for invalid.

background-color: var(
--codeblock-state-text,
var(--codeblock-state-border)
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is misdeclared

Suggested change
);
var(--codeblock-state-text), var(--codeblock-state-border)

export type CodeBlockFlags = {
collapsible?: boolean;
collapsed?: boolean;
validity?: Validity;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
validity?: Validity;
valid?: Validity;

suggestion: For consistence with the others

font-size: 0.875rem;
color: var(--ifm-color-primary);
background: transparent;
transition: all 0.3s ease;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has no effect (tried changing it to 3s, the expand is still instantaneous). I'd love if we could have a smooth opening/closing of the block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Collapsed code blocks break hash links

2 participants