Skip to content

docs: enhance widget documentation with playground examples and JSON structures#474

Merged
divyanshub024 merged 6 commits intodevfrom
mn/docs-preview
Apr 28, 2026
Merged

docs: enhance widget documentation with playground examples and JSON structures#474
divyanshub024 merged 6 commits intodevfrom
mn/docs-preview

Conversation

@Potatomonsta
Copy link
Copy Markdown
Contributor

@Potatomonsta Potatomonsta commented Apr 17, 2026

Description

  • Added playground examples and JSON structures for various widgets including AlertDialog, Align, AppBar, AspectRatio, AutoComplete, BackdropFilter, Badge, BottomNavigationBar, Card, CarouselView, Center, CheckBox, Chip, CircleAvatar, CircularProgressIndicator, ClipOval, ClipRRect, and ColoredBox.
  • Updated documentation format to include tabs for Dart code, JSON representation, and live preview.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Code refactor
  • Build configuration change
  • Documentation
  • Chore

Summary by CodeRabbit

  • Documentation
    • Added live interactive Preview tabs across many widget docs so examples render inline.
    • Reorganized examples into tabbed views (Dart, JSON, Preview) for clearer navigation.
    • Exposed shared playground configuration and per-example preview payloads to power embeds.
    • Improved preview initialization with retry/interval handling for more reliable embedded demos.

…structures

- Added playground examples and JSON structures for various widgets including AlertDialog, Align, AppBar, AspectRatio, AutoComplete, BackdropFilter, Badge, BottomNavigationBar, Card, CarouselView, Center, CheckBox, Chip, CircleAvatar, CircularProgressIndicator, ClipOval, ClipRRect, and ColoredBox.
- Updated documentation format to include tabs for Dart code, JSON representation, and live preview.
@divyanshub024
Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dde50af7-af7a-4a2f-9a84-16d55b900a7a

📥 Commits

Reviewing files that changed from the base of the PR and between 35d741a and 2254742.

📒 Files selected for processing (2)
  • docs/widgets/align.mdx
  • docs/widgets/sliver_grid.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/widgets/sliver_grid.mdx

📝 Walkthrough

Walkthrough

Replaced many widget examples’ single CodeGroup with Tabs (Dart / JSON / Preview), added PLAYGROUND_BASE_URL, and for each widget exported {widget}PreviewJson and {widget}PreviewSrc. Preview tabs embed an iframe and, on load, repeatedly post stac-preview-json payloads to the playground origin (250ms interval, max 12 attempts).

Changes

Cohort / File(s) Summary
Playground base snippet
docs/snippets/playground_base.mdx
Added export const PLAYGROUND_BASE_URL = "https://playground.stac.dev/";.
Widget docs — bulk preview wiring
docs/widgets/.../*.mdx (e.g. alert_dialog.mdx, align.mdx, app_bar.mdx, aspect_ratio.mdx, auto_complete.mdx, backdrop_filter.mdx, badge.mdx, bottom_navigation_bar.mdx, card.mdx, carousel_view.mdx, center.mdx, check_box.mdx, chip.mdx, circle_avatar.mdx, circular_progress_indicator.mdx, clip_oval.mdx, clip_rrect.mdx, colored_box.mdx, column.mdx, conditional.mdx, container.mdx, custom_scroll_view.mdx, divider.mdx, drawer.mdx, dropdown_menu.mdx, dynamic_view.mdx, elevated_button.mdx, expanded.mdx, filled_button.mdx, fitted_box.mdx, flexible.mdx, floating_action_button.mdx, form.mdx, fractionally_sized_box.mdx, gesture_detector.mdx, grid_view.mdx, hero.mdx, icon.mdx, icon_button.mdx, image.mdx, ink_well.mdx, limited_box.mdx, linear_progress_indicator.mdx, list_tile.mdx, listview.mdx, network_widget.mdx, opacity.mdx, outlined_button.mdx, padding.mdx, page_view.mdx, placeholder.mdx, positioned.mdx, radio_group.mdx, refresh_indicator.mdx, row.mdx, safe_area.mdx, scaffold.mdx, selectable_text.mdx, set_value.mdx, single_child_scroll_view.mdx, sized_box.mdx, slider.mdx, sliver_app_bar.mdx, sliver_fill_remaining.mdx, sliver_grid.mdx, sliver_list.mdx, sliver_opacity.mdx, sliver_padding.mdx, sliver_safe_area.mdx, sliver_to_box_adapter.mdx, sliver_visibility.mdx, spacer.mdx, stack.mdx, switch.mdx, tab_bar.mdx, table.mdx, table_cell.mdx, table_row.mdx, text.mdx, text_button.mdx, text_field.mdx, text_form_field.mdx, tool_tip.mdx, vertical_divider.mdx, visibility.mdx, webview.mdx, wrap.mdx
For each widget: imported PLAYGROUND_BASE_URL where applicable, added exported {widget}PreviewJson and {widget}PreviewSrc, converted CodeGroup examples into Tabs (Dart / JSON / Preview), added a Preview tab embedding an iframe (src={...PreviewSrc}) and onLoad logic that posts { type: "stac-preview-json", payload: ... } to the playground origin with retry (250ms interval, max 12 attempts). Also normalized some JSON numeric literals and removed some trailing newlines.

Sequence Diagram(s)

sequenceDiagram
  participant Docs as Docs Page (MDX)
  participant Iframe as Playground Iframe
  participant Playground as Playground Origin
  rect rgba(160,220,255,0.5)
  Docs->>Iframe: render <iframe src="{PLAYGROUND_BASE_URL}/embed">
  Iframe-->>Docs: load event
  loop up to 12 attempts (250ms)
    Docs->>Iframe.contentWindow: postMessage({type:"stac-preview-json", payload: PREVIEW_JSON}, targetOrigin=PLAYGROUND_BASE_URL)
    Iframe->>Playground: receive postMessage → apply preview
  end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • divyanshub024

Poem

"I hopped through docs with twitchy feet,
Tabs for Dart and JSON, a preview so neat.
An iframe hums, messages take flight,
Twelve little pings through day and night.
Rabbit applauds — the playground’s alight! 🐇"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: enhancing widget documentation with playground examples and JSON structures, which is the primary focus of this large documentation update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mn/docs-preview

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
docs/widgets/switch.mdx (1)

50-120: ⚠️ Potential issue | 🟡 Minor

Inconsistent: only Example 1 was migrated to Tabs/Preview.

Example 1 (Cupertino) now uses <Tabs> + Preview, but Example 2 (Adaptive, line 105) and Example 3 (Material, line 124) still use the old <CodeGroup>. The page reads as half-migrated. Either:

  • Convert Examples 2 and 3 to the same Tabs layout (each will need its own *PreviewJson/*PreviewSrc exports or — better — a shared component that takes previewJson as a prop), or
  • Defer the migration so all three examples switch together.

Also worth noting: Example 2 and 3 don't really need their own iframe src constants — only the JSON differs — which is another argument for extracting a shared <PlaygroundPreview json={...} /> component before scaling this pattern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/switch.mdx` around lines 50 - 120, The page is half-migrated:
Example 1 uses <Tabs> with a Preview while Example 2 ("Adaptive") and Example 3
("Material") still use <CodeGroup>; unify them by replacing the CodeGroup blocks
for the adaptive and material examples with the same Tabs/Preview pattern (Tab
titles "Dart", "JSON", "Preview") and wire their iframe messaging the same way
as the first example (see switchPreviewSrc and switchPreviewJson usage around
the iframe id="stac"), or roll Example 1 back to CodeGroup if you prefer
deferring the migration. Preferably extract a small shared PlaygroundPreview
component (props: previewJson, previewSrc) that encapsulates the iframe, onLoad
postMessage loop and constants (attempts/maxAttempts) and reuse it in the three
examples to pass different JSON payloads (adaptive/material/cupertino) so only
the JSON differs between previews.
docs/widgets/image.mdx (1)

101-181: ⚠️ Potential issue | 🟡 Minor

Inconsistent: only the StacImage.asset section was converted to Tabs/Preview.

The remaining sections — StacImage.network (line 107), StacImage.file (line 135), and the default StacImage (line 161) — still use the old <CodeGroup>. This leaves the page with a mixed look-and-feel and means three of four constructors have no preview. Either convert the rest to the new Tabs layout (network is a particularly good candidate for an actually-working preview) or drop the partial migration to keep the page consistent for now.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/image.mdx` around lines 101 - 181, The page is inconsistent:
only StacImage.asset was migrated to the new Tabs/Preview pattern while
StacImage.network, StacImage.file, and the default StacImage still use
<CodeGroup>; either convert those three <CodeGroup> sections to the same Tabs +
Preview structure used by StacImage.asset (preserving the Dart and JSON examples
and adding a live preview for network using a stable URL) or revert the asset
section back to <CodeGroup> so all constructors match; update the
StacImage.network, StacImage.file, and StacImage (default) sections accordingly
and ensure the preview uses the same component names and props as in the asset
example.
docs/widgets/alert_dialog.mdx (1)

100-128: ⚠️ Potential issue | 🟡 Minor

Fix JSON key name for text alignment to match Dart property.

Line 147 uses "align": "center" but the StacText parser expects "textAlign" (matching the Dart property at line 111). Update the JSON to use "textAlign": "center" so the documented JSON example renders identically to the Dart example.

Incorrect JSON at line 147
"align": "center",

Should be:

"textAlign": "center",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/alert_dialog.mdx` around lines 100 - 128, The JSON example uses
the wrong key "align" for text alignment; update the JSON to use "textAlign" so
it matches the Dart property and the StacText parser expectations (ensure the
JSON example that corresponds to the StacText widget uses "textAlign": "center"
instead of "align": "center").
docs/widgets/spacer.mdx (1)

18-20: ⚠️ Potential issue | 🟡 Minor

Broken Properties table — stray chore token in the separator row.

The separator row contains |--chore-----|, which breaks the markdown table rendering for the Type column. This looks like a stray edit/merge artifact.

🛠️ Proposed fix
 | Property | Type  | Description                                             |
-|----------|--chore-----|---------------------------------------------------------|
+|----------|-------|---------------------------------------------------------|
 | flex     | `int` | The flex factor to use for the spacer. Defaults to `1`. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/spacer.mdx` around lines 18 - 20, The markdown table's separator
row contains a stray token `chore` which breaks rendering; locate the table with
header "Property | Type | Description" and the separator row containing
"`|--chore-----|`" and replace it with a proper Markdown separator (e.g.,
"`|---|---|---|`" or matching dashes for three columns) so the "flex" property
row (`flex | \`int\` | The flex factor...`) renders correctly.
docs/widgets/divider.mdx (1)

88-148: ⚠️ Potential issue | 🟡 Minor

Inconsistent: second example still uses the old <CodeGroup> with no Preview tab.

The top-level example was migrated to the new Tabs + Preview layout, but the "Divider in a List" section below still uses the legacy <CodeGroup> pattern and has no playground preview. Readers will see an inconsistent experience on the same page. Either migrate this section to the tabbed layout with its own dividerInListPreviewJson, or intentionally keep it as code-only and add a short note explaining why.

Same inconsistency exists in docs/widgets/limited_box.mdx for "Example 2".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/divider.mdx` around lines 88 - 148, The "Divider in a List"
section still uses the legacy <CodeGroup> and lacks a Preview tab, causing
inconsistency with other examples that use the new Tabs+Preview pattern; update
this section (the block showing StacColumn/StacListTile/StacDivider) to the
tabbed layout by replacing <CodeGroup> with the Tabs + Preview structure and add
a matching preview JSON entry (e.g., dividerInListPreviewJson) so the example
renders in the playground, or alternatively keep the CodeGroup but add a short
explanatory note; also apply the same migration or explanatory-note change to
the "Example 2" in docs/widgets/limited_box.mdx to keep both pages consistent.
docs/widgets/visibility.mdx (1)

97-124: ⚠️ Potential issue | 🟡 Minor

Example 2 was not converted — inconsistent with Example 1.

Example 1 ("Basic Visibility") was migrated to the new <Tabs> layout with a Preview tab, but Example 2 ("Hidden with Replacement") is still using the old <CodeGroup> block and has no Preview. Readers will see two examples with different UX in the same page, and the more interesting case (visible: false with a replacement) loses its live demo.

🔧 Suggested approach

Add a visibilityHiddenPreviewJson export alongside the existing one, then convert Example 2 to the same Tabs/Preview structure (re-using PLAYGROUND_BASE_URL already declared at the top):

 export const visibilityPreviewSrc = `${PLAYGROUND_BASE_URL}/embed?showTopBar=false&showEditor=false`;
+export const visibilityHiddenPreviewJson = {
+  "type": "visibility",
+  "child": { "type": "text", "data": "I am hidden!" },
+  "replacement": { "type": "container", "color": "#FF5733", "width": 50, "height": 50 },
+  "visible": false
+};

…then replace the <CodeGroup> at lines 99–124 with the same <Tabs>/<Tab title="Preview"> pattern used in Example 1, passing visibilityHiddenPreviewJson as the payload.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/visibility.mdx` around lines 97 - 124, Add a new export named
visibilityHiddenPreviewJson (next to the existing preview JSON export)
containing the Example 2 JSON payload, then replace the <CodeGroup> block for
"Hidden with Replacement" with the same <Tabs>/<Tab title="Preview"> pattern
used in Example 1 and wire the Preview to the playground using
PLAYGROUND_BASE_URL and visibilityHiddenPreviewJson as the payload; ensure the
StacVisibility example keeps the replacement (StacContainer) and visible:false
fields in the exported payload so the live demo shows the
hidden-with-replacement behavior.
docs/widgets/badge.mdx (1)

46-271: ⚠️ Potential issue | 🟡 Minor

Inconsistent: only the first Badge example gets a Preview tab; the other five still use <CodeGroup>.

Within the same page, "Basic Badge with Label" (lines 46–111) is now <Tabs> with a Preview tab, while the remaining five examples — "Badge with Count", "Badge with Count Exceeding MaxCount", "Small Badge (No Label)", "Badge on IconButton", and "Badge with Custom Styling" (lines 112–271) — still use <CodeGroup> and have no preview. This is jarring UX-wise and hides the visually most interesting variants (count overflow, custom styling, badge on icon button) from the live preview.

Either convert the remaining examples to the same Tabs/Preview structure (ideally via the shared component suggested on docs/widgets/padding.mdx), or — if intentional for this PR's scope — add a brief note here and a follow-up issue to cover the rest.

Want me to draft the converted markup for the remaining four examples, or open a follow-up issue?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/badge.mdx` around lines 46 - 271, The page is inconsistent:
"Basic Badge with Label" uses a Tabs/Preview setup while the other examples
("Badge with Count", "Badge with Count Exceeding MaxCount", "Small Badge (No
Label)", "Badge on IconButton", "Badge with Custom Styling") remain as
CodeGroup; update those examples to the same Tabs (Dart/JSON/Preview) pattern
used in the "Basic Badge with Label" example by replacing each <CodeGroup> block
with a <Tabs sync={false}> containing <Tab title="Dart"> (the Dart snippet),
<Tab title="JSON"> (the JSON snippet) and a <Tab title="Preview"> with the same
iframe + onLoad postMessage logic (using their respective preview JSON payloads
like badgeCountPreviewJson, badgeOverflowPreviewJson, smallBadgePreviewJson,
iconButtonBadgePreviewJson, customBadgePreviewJson) so each example shows a live
preview; alternatively factor this into the shared preview component used in
docs/widgets/padding.mdx and reuse it for each badge variant to avoid
duplicating the iframe/postMessage logic.
🟡 Minor comments (27)
docs/widgets/hero.mdx-10-13 (1)

10-13: ⚠️ Potential issue | 🟡 Minor

Preview will show a broken image (https://example.com/avatar.png is not a real asset).

example.com returns an HTML page, not an image, so the StacImage in the preview iframe will fail to load and users will see whatever broken-image state the playground renders. Point this at a real asset (e.g. a small image hosted on the Stac docs/assets CDN, or a known placeholder like https://picsum.photos/200 / https://placehold.co/200) so the preview actually demonstrates the hero.

The Dart/JSON sample blocks lower in the file can keep example.com since they're just illustrative code, but the live preview payload needs a resolvable URL.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/hero.mdx` around lines 10 - 13, The preview payload in
docs/widgets/hero.mdx uses a broken image URL ("child" object with "type":
"image" and "network" set to https://example.com/avatar.png) which causes
StacImage in the preview iframe to fail; update that "network" value to a real,
resolvable image (for example a small CDN asset on the Stac docs/assets CDN or a
placeholder like https://picsum.photos/200 or https://placehold.co/200) so the
live preview renders correctly, while leaving the illustrative Dart/JSON sample
blocks that use example.com unchanged.
docs/widgets/gesture_detector.mdx-95-120 (1)

95-120: ⚠️ Potential issue | 🟡 Minor

setInterval can leak / stack up on repeated onLoad.

The interval handle is local to this onLoad callback and only cleared after maxAttempts is reached. There are two realistic cases where it is never cleared (or stacks):

  1. The iframe is removed from the DOM (tab switch re-renders, route change, Fast Refresh) before 12 ticks have run — the interval keeps firing postMessage on a detached contentWindow forever.
  2. onLoad fires more than once on the same iframe (e.g. navigation inside the playground, BFCache restore, or a src change). Each invocation starts a new interval; the previous ones are still alive, so you now have N overlapping posters.

Since this pattern was replicated across ~85 docs files, the leak multiplies. Consider caching the handle on the element and clearing any prior one, and also stopping on unload:

🛠️ Suggested hardening
 onLoad={(event) => {
   const iframe = event.currentTarget;
+  // Clear any prior interval on re-load of the same iframe
+  if (iframe.__stacPreviewInterval) {
+    clearInterval(iframe.__stacPreviewInterval);
+  }
   const targetOrigin = PLAYGROUND_BASE_URL;
   const message = {
     type: "stac-preview-json",
     payload: gestureDetectorPreviewJson
   };

   let attempts = 0;
   const maxAttempts = 12;
-  const interval = setInterval(() => {
+  const interval = setInterval(() => {
+    if (!iframe.isConnected) {
+      clearInterval(interval);
+      return;
+    }
     iframe.contentWindow?.postMessage(message, targetOrigin);
     attempts += 1;

     if (attempts >= maxAttempts) {
       clearInterval(interval);
     }
   }, 250);
+  iframe.__stacPreviewInterval = interval;
 }}

A cleaner long-term fix is a ready-handshake: have the playground post { type: "stac-preview-ready" } on load, and only then send the JSON once (listener removed after use). That also eliminates the blind 12× 250 ms spam.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/gesture_detector.mdx` around lines 95 - 120, The onLoad callback
for the iframe (id "stac") creates a local setInterval (variables attempts,
maxAttempts, interval) that can leak or stack across removals and repeated
onLoad calls; change it to first clear any existing interval stored on the
iframe element (e.g., iframe._stacInterval or iframe.dataset.stacInterval)
before creating a new one, assign the new interval handle to that property, and
ensure you clear it both when attempts >= maxAttempts and on iframe
unload/removal (add a one-time "beforeunload"/"unload" or MutationObserver
cleanup to clear iframe._stacInterval); alternatively implement a
ready-handshake where the playground posts { type: "stac-preview-ready" } and
you send gestureDetectorPreviewJson once (then remove the message listener) to
avoid polling entirely (use PLAYGROUND_BASE_URL and gestureDetectorPreviewJson
in the handshake).
docs/widgets/text.mdx-7-14 (1)

7-14: ⚠️ Potential issue | 🟡 Minor

Preview text will likely be invisible (white on white).

color: "#FFFFFF" on the top-level text payload means the preview renders white text. If the playground's default background is white (or even a light neutral), readers will just see an empty iframe and assume the preview is broken. Use a dark color, or wrap the text in a contrasting container:

🛠️ Suggested fix
 export const textPreviewJson = {
-  "type": "text",
-  "data": "Hello, World!",
-  "style": {
-    "color": "#FFFFFF",
-    "fontSize": 24
-  }
+  "type": "container",
+  "padding": 16,
+  "color": "#FF1E88E5",
+  "child": {
+    "type": "text",
+    "data": "Hello, World!",
+    "style": {
+      "color": "#FFFFFFFF",
+      "fontSize": 24
+    }
+  }
 };

Note: the Dart/JSON tabs can keep the original snippet — this change only affects the live preview payload.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/text.mdx` around lines 7 - 14, The preview payload
textPreviewJson uses color: "#FFFFFF" which will render white-on-white and
appear invisible; update the payload so the preview is visible by either
changing textPreviewJson.data.style.color to a dark/contrasting value (e.g.,
"#000000" or a dark gray) or wrap the text node in a contrasting container (add
a container node with a dark background and place the text inside) so the live
preview is readable; modify the textPreviewJson object accordingly (adjust the
"style.color" or structure to include a container) used by the preview renderer.
docs/widgets/image.mdx-7-15 (1)

7-15: ⚠️ Potential issue | 🟡 Minor

Preview won't be able to load assets/logo.png from the playground.

imagePreviewJson references assets/logo.png with imageType: "asset", but the embedded playground at playground.stac.dev has no way to resolve assets bundled in a consumer's app. The preview tab will most likely render a broken/placeholder image, which is worse than no preview. Consider switching the preview payload to a network image with a stable public URL (you can keep the Dart/JSON snippets showing the asset usage as the documented example), so the playground can actually display something meaningful.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/image.mdx` around lines 7 - 15, The preview payload
imagePreviewJson currently points to a local asset ("assets/logo.png") with
imageType: "asset", which the embedded playground cannot resolve; update
imagePreviewJson so imageType is "network" and src is a stable public URL (e.g.,
a CDN-hosted PNG) so the playground can render the preview, while leaving the
Dart/JSON examples in the docs that show asset usage unchanged; ensure you
update the src and imageType fields in imagePreviewJson (and keep
imagePreviewSrc as-is).
docs/widgets/switch.mdx-102-103 (1)

102-103: ⚠️ Potential issue | 🟡 Minor

Missing blank line between the closing </Tabs> and the next H3.

Line 102's </Tabs> is immediately followed by ### Example 2: Adaptive Switch on line 103 with no blank line. In MDX this can occasionally cause the heading to be parsed as part of the preceding JSX block. Add a blank line to be safe:

Proposed fix
 </Tabs>
+
 ### Example 2: Adaptive Switch
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/switch.mdx` around lines 102 - 103, There is no blank line
between the closing JSX tag </Tabs> and the subsequent markdown heading "###
Example 2: Adaptive Switch", which can cause the heading to be parsed as part of
the JSX; add a single blank line immediately after the </Tabs> tag so the H3 is
separated from the JSX block (locate the closing </Tabs> and insert one empty
line before "### Example 2: Adaptive Switch").
docs/widgets/outlined_button.mdx-7-23 (1)

7-23: ⚠️ Potential issue | 🟡 Minor

Fix empty action objects — missing required actionType field.

The action handlers (onPressed, onLongPress, onHover, onFocusChange) are set to empty objects {}, which are invalid. The Stac framework requires an actionType field on all action objects (throws FormatException if missing). The Dart example uses StacNoneAction(); replace the empty objects with {"actionType": "none"} in both the exported outlinedButtonPreviewJson (lines 7–23) and the JSON tab example (lines 66–69).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/outlined_button.mdx` around lines 7 - 23, The action handler
objects in outlinedButtonPreviewJson (fields onPressed, onLongPress, onHover,
onFocusChange) are empty and must include an actionType; replace each `{}` with
`{"actionType": "none"}` (matching StacNoneAction) in the exported
outlinedButtonPreviewJson and also update the JSON tab example where those
handlers appear so every action object contains an actionType field.
docs/widgets/clip_rrect.mdx-87-88 (1)

87-88: ⚠️ Potential issue | 🟡 Minor

Missing blank line between </Tabs> and the next heading.

In MDX, a heading immediately following a JSX closing tag without a blank line can be parsed as part of the JSX block / inline content rather than a new markdown section. Add a blank line before ## Properties to keep the heading rendering reliable.

🛠️ Proposed fix
 </Tabs>
+
 ## Properties
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/clip_rrect.mdx` around lines 87 - 88, Add a blank line after the
JSX closing tag "</Tabs>" so the "## Properties" heading is separated from the
JSX block; ensure the file contains an empty line between the "</Tabs>" token
and the "## Properties" heading to prevent MDX from parsing the heading as part
of the JSX block.
docs/widgets/circle_avatar.mdx-11-11 (1)

11-11: ⚠️ Potential issue | 🟡 Minor

Preview image uses a mutable refs/heads/dev URL.

https://raw.githubusercontent.com/StacDev/stac/refs/heads/dev/assets/companies/bettrdo.jpg resolves against whatever dev points to at request time. If that asset is renamed, moved, or deleted, this documentation preview silently breaks (and cache-busting on raw.githubusercontent.com is inconsistent). Consider pinning to a stable ref — either a tagged release (e.g. refs/tags/v…) or a specific commit SHA — or hosting the image alongside the docs.

The same URL is used on line 47 in the Dart example.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/circle_avatar.mdx` at line 11, The preview image URL uses the
mutable ref "refs/heads/dev" (seen in the "backgroundImage" property) which can
break when dev moves; update the URL to a stable ref by replacing
"refs/heads/dev" with either a released tag (refs/tags/vX.Y.Z) or a specific
commit SHA, or alternatively host the image alongside the docs and point
"backgroundImage" to that stable path; make the same change to the Dart example
occurrence mentioned (line ~47) so both references are pinned to the stable ref.
docs/widgets/opacity.mdx-35-35 (1)

35-35: ⚠️ Potential issue | 🟡 Minor

Copy error: description references the wrong widget.

This is the Opacity documentation, but the sentence says "the Slider widget in Flutter". The link target is correct (Opacity-class.html), only the prose is wrong.

✏️ Proposed fix
-To know more about the Slider widget in Flutter, refer to the [official documentation](https://api.flutter.dev/flutter/widgets/Opacity-class.html).
+To know more about the Opacity widget in Flutter, refer to the [official documentation](https://api.flutter.dev/flutter/widgets/Opacity-class.html).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/opacity.mdx` at line 35, The sentence incorrectly references the
"Slider widget" in the Opacity docs; update the prose in the string "To know
more about the Slider widget in Flutter, refer to the [official
documentation](https://api.flutter.dev/flutter/widgets/Opacity-class.html)." to
mention the Opacity widget instead (e.g., "To know more about the Opacity widget
in Flutter, refer to the [official
documentation](https://api.flutter.dev/flutter/widgets/Opacity-class.html)."),
keeping the existing Opacity-class.html link intact.
docs/widgets/sized_box.mdx-7-11 (1)

7-11: ⚠️ Potential issue | 🟡 Minor

640 px preview frame for a 25 px SizedBox will render as empty space.

The iframe is fixed at h-[640px] (standardized across the PR), but this widget's payload is a 25 px tall spacer with no visible content. Readers will see a large empty Playground chrome and likely assume the preview is broken.

Options:

  • Use a more illustrative payload (e.g. a colored container separated by the sizedBox) so the preview demonstrates the spacing effect.
  • Make the frame height a prop on the shared preview component proposed on dynamic_view.mdx and pick a smaller value here.

Also applies to: 45-72

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sized_box.mdx` around lines 7 - 11, The preview uses
sizedBoxPreviewJson (type: "sizedBox", height: 25) which renders as an empty
25px spacer inside a 640px iframe (sizedBoxPreviewSrc), making the playground
look broken; update sizedBoxPreviewJson to a more illustrative payload—e.g.,
wrap the SizedBox between two colored containers or add a visible child so the
spacing effect is visible—or change the shared preview component (referenced in
dynamic_view.mdx) to accept a frameHeight prop and set a smaller height for this
preview; modify either sizedBoxPreviewJson or the shared preview usage
accordingly and keep the PLAYGROUND_BASE_URL embed URL unchanged.
docs/widgets/dynamic_view.mdx-88-107 (1)

88-107: ⚠️ Potential issue | 🟡 Minor

Retry loop has no cleanup and no success signal — replace with a handshake.

Two minor but real issues with the onLoad block that will be inherited by every widget doc using this pattern:

  1. No teardown on navigation. setInterval self-clears only after 12 attempts (~3s). If a reader navigates away, reloads the iframe, or the tab unmounts during that window, the interval keeps firing postMessage against a detached contentWindow. It recovers quickly, but it's avoidable noise and can surface as "postMessage after unload" warnings in DevTools.
  2. Blind retries. The page posts 12 times regardless of whether the iframe already rendered the payload. A one-line message-event handshake (iframe posts { type: "stac-preview-ready" } on mount; host stops retrying on receipt) is cheaper and more reliable, and makes the max-attempt fallback a real safety net rather than the primary mechanism.

Since this code is about to be duplicated across ~85 files, fixing it here (or, better, in the shared snippet suggested above) has outsized value.

♻️ Sketch of a handshake-based version
onLoad={(event) => {
  const iframe = event.currentTarget;
  const targetOrigin = PLAYGROUND_BASE_URL;
  const message = { type: "stac-preview-json", payload: dynamicViewPreviewJson };

  let attempts = 0;
  const maxAttempts = 12;

  const onReady = (e) => {
    if (e.origin !== targetOrigin) return;
    if (e.data?.type === "stac-preview-ready") {
      iframe.contentWindow?.postMessage(message, targetOrigin);
      cleanup();
    }
  };

  const interval = setInterval(() => {
    iframe.contentWindow?.postMessage(message, targetOrigin);
    if (++attempts >= maxAttempts) cleanup();
  }, 250);

  const cleanup = () => {
    clearInterval(interval);
    window.removeEventListener("message", onReady);
    iframe.removeEventListener("unload", cleanup);
  };

  window.addEventListener("message", onReady);
  iframe.addEventListener("unload", cleanup, { once: true });
}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/dynamic_view.mdx` around lines 88 - 107, The onLoad handler
currently blasts postMessage in an untracked interval (using PLAYGROUND_BASE_URL
and dynamicViewPreviewJson) without teardown or success detection; replace it
with a handshake: add a window "message" listener (e.g., onReady) that checks
e.origin === PLAYGROUND_BASE_URL and e.data.type === "stac-preview-ready", send
the {type: "stac-preview-json", payload: dynamicViewPreviewJson} once onReady
and then call cleanup; keep the existing interval/maxAttempts fallback but have
cleanup clearInterval(interval), removeEventListener("message", onReady) and
remove any iframe unload/unmount listener (attach
iframe.addEventListener("unload", cleanup, { once: true }) or equivalent) so
retries stop on success or when the iframe/navigation unmounts.
docs/widgets/conditional.mdx-92-94 (1)

92-94: ⚠️ Potential issue | 🟡 Minor

Add a blank line between </Tabs> and the next markdown heading.

Same issue as in set_value.mdx: the ## Conditional with Complex Widgets heading directly follows the closing </Tabs> tag with no blank line, which can cause MDX to swallow the heading into the JSX block.

📝 Proposed fix
 </Tabs>
+
 ## Conditional with Complex Widgets
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/conditional.mdx` around lines 92 - 94, Insert a blank line after
the closing JSX tag </Tabs> so the Markdown heading "## Conditional with Complex
Widgets" is separated from the JSX block; locate the sequence containing the
</Tabs> tag in the docs/widgets/conditional.mdx content and add one empty line
before the "## Conditional with Complex Widgets" heading to prevent MDX from
treating the heading as part of the JSX.
docs/widgets/set_value.mdx-107-109 (1)

107-109: ⚠️ Potential issue | 🟡 Minor

Add a blank line between </Tabs> and the next markdown heading.

Without a blank line separating the closing JSX tag from ## Initializing State on Screen Load, many MDX renderers will treat the ## line as a continuation of the JSX block and fail to render it as a heading.

📝 Proposed fix
 </Tabs>
+
 ## Initializing State on Screen Load
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/set_value.mdx` around lines 107 - 109, Add a single blank line
after the closing JSX tag </Tabs> so the following markdown heading "##
Initializing State on Screen Load" is separated; update the snippet around the
closing </Tabs> tag to insert one empty line before the "## Initializing State
on Screen Load" heading to ensure MDX renders the heading correctly.
docs/widgets/tab_bar.mdx-20-33 (1)

20-33: ⚠️ Potential issue | 🟡 Minor

All three tab labels are "Red" — likely a copy/paste typo.

Tabs 2 and 3 are also titled "Red", both in this tabBarPreviewJson and in the Dart/JSON example blocks (lines 141–143 and 178–187). This makes the preview confusing — tapping tabs appears to do nothing because the labels never change. Suggest distinct labels (e.g. "Tab 1", "Tab 2", "Tab 3", or names matching the container colors).

📝 Proposed fix (apply to all three duplicated locations)
-          { "type": "tab", "text": "Red" },
-          { "type": "tab", "text": "Red" },
-          { "type": "tab", "text": "Red" }
+          { "type": "tab", "text": "Tab 1" },
+          { "type": "tab", "text": "Tab 2" },
+          { "type": "tab", "text": "Tab 3" }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/tab_bar.mdx` around lines 20 - 33, The tab labels in the
tabBarPreviewJson "tabs" array are duplicated ("Red" x3); update the "text"
values in the JSON examples (the "tabs" array used in tabBarPreviewJson and the
Dart/JSON example blocks) so each tab has a distinct label (e.g., "Tab 1", "Tab
2", "Tab 3" or names matching their container colors). Locate the arrays named
or referenced as tabBarPreviewJson and the two example blocks and replace the
repeated "Red" strings with unique labels in all three duplicated locations.
docs/widgets/filled_button.mdx-7-23 (1)

7-23: ⚠️ Potential issue | 🟡 Minor

Empty {} action objects are invalid and inconsistent with the Dart example.

The JSON examples use "onPressed": {} (and three other empty handler objects), but this pattern lacks the actionType discriminator required by the schema. The tool_tip.mdx file demonstrates the correct pattern: { "actionType": "none" } for no-op actions. More importantly, the Dart sample in the same file shows StacNoneAction() for onPressed only—the other three handlers are omitted. The JSON should match this by removing all four empty handler keys.

📝 Suggested cleanup
 export const filledButtonPreviewJson = {
   "type": "filledButton",
-  "onPressed": {},
-  "onLongPress": {},
-  "onHover": {},
-  "onFocusChange": {},
   "style": {
     "backgroundColor": "#FFC107",
     "foregroundColor": "#000000"
   },

Apply the same change to the JSON code block at lines 64–80.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/filled_button.mdx` around lines 7 - 23, The JSON example object
filledButtonPreviewJson currently contains invalid empty handler objects
("onPressed", "onLongPress", "onHover", "onFocusChange"); remove those four keys
entirely from filledButtonPreviewJson so the JSON matches the Dart sample (which
only uses StacNoneAction for onPressed and omits the other handlers), and apply
the same removal to the other JSON example block in this file to replace the
empty {} handlers with neither keys nor empty objects.
docs/widgets/radio_group.mdx-222-247 (1)

222-247: ⚠️ Potential issue | 🟡 Minor

Duplicate iframe id="stac" across all preview blocks.

Every widget doc uses id="stac" on its iframe. HTML id must be unique per document. Mintlify pages tend to be self-contained, so this is fine today, but if any landing page or aggregated route ever inlines two preview iframes, document.getElementById("stac") and CSS rules will silently target only the first, and accessibility tooling will flag the duplicate. Either drop the id (the onLoad handler already captures event.currentTarget) or make it widget-specific.

🔧 Suggested change
       <iframe
-        id="stac"
         src={radioGroupPreviewSrc}

The same change should be applied to the iframes in sliver_list.mdx, carousel_view.mdx, circular_progress_indicator.mdx, grid_view.mdx, safe_area.mdx, visibility.mdx, center.mdx, and (per the AI summary) the other ~85 widget docs touched by this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/radio_group.mdx` around lines 222 - 247, The iframe uses a
hardcoded id="stac" which creates duplicate HTML ids across widget docs; remove
the id attribute (or generate a widget-specific id) and rely on the existing
onLoad handler's event.currentTarget (and iframe.contentWindow) to post the
preview message; update all affected preview iframes (the element with id="stac"
and its onLoad handler in each widget doc such as radio_group.mdx,
sliver_list.mdx, carousel_view.mdx, circular_progress_indicator.mdx,
grid_view.mdx, safe_area.mdx, visibility.mdx, center.mdx, etc.) to drop the id
or make it unique so CSS/document.getElementById and accessibility tooling no
longer encounter duplicate ids.
docs/widgets/sliver_grid.mdx-253-271 (1)

253-271: ⚠️ Potential issue | 🟡 Minor

Replace the blind 12×250ms postMessage polling with a ready handshake, and clear the interval on unmount.

Two concerns with the current preview handler (present in every file in this PR):

  1. The handler fires postMessage up to 12 times regardless of whether the iframe has already consumed it. A cleaner pattern is for the embedded playground to post a { type: "stac-preview-ready" } message back to window.opener/parent, and for the parent to send the payload exactly once in response. This removes the 3-second racy loop and works reliably regardless of iframe warm-up time.
  2. setInterval is only cleared after maxAttempts. If the user switches tabs or navigates away within ~3s, the interval keeps firing against a detached iframe. Since this is a React onLoad, you can't return a cleanup, but you can at least guard with if (!iframe.isConnected) { clearInterval(interval); return; } inside the tick, or attach a one-shot message listener for the ready event instead.

Since this same handler ships in ~85 files, fixing it inside the shared component suggested above will fix it everywhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_grid.mdx` around lines 253 - 271, The onLoad handler
currently spams postMessage up to 12 times via setInterval (variables attempts,
maxAttempts, interval) and never reliably stops when the iframe is detached;
replace this polling with a handshake: in the onLoad callback (where iframe,
targetOrigin and the message {type: "stac-preview-json", payload:
sliverGridPreviewJson} are defined) register a one-time
window.addEventListener('message') handler that listens for {type:
"stac-preview-ready"} from the iframe and, when seen, calls
iframe.contentWindow.postMessage(message, targetOrigin) exactly once and then
removes the listener; additionally, remove the setInterval code and/or if you
keep a fallback interval, add a guard inside its tick to clearInterval(interval)
and return if !iframe.isConnected, and ensure any event listener is cleaned up
after firing (use { once: true } or explicitly removeEventListener).
docs/widgets/custom_scroll_view.mdx-23-23 (1)

23-23: ⚠️ Potential issue | 🟡 Minor

Remove empty action objects or use explicit no-op action in documentation examples.

An empty object {} creates a valid StacAction instance but has no actionType and won't function if invoked. In documentation examples at lines 23, 62, and 90, use a no-op action (with appropriate actionType) or omit the field entirely to clarify the behavior. This prevents confusion when developers reference these examples.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/custom_scroll_view.mdx` at line 23, The examples in
docs/widgets/custom_scroll_view.mdx use empty action objects for the onPressed
field which yield invalid StacAction instances; replace each empty onPressed
object with an explicit no-op action that includes the required actionType (use
your project’s designated no-op actionType) or simply remove the onPressed field
from those examples so they don’t imply a callable action (update all
occurrences of onPressed that currently have {}).
docs/widgets/sliver_padding.mdx-9-9 (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Correct the Properties table type annotation for padding.

The Properties table documents padding as Map<String, dynamic>, but the actual type is StacEdgeInsets. The code already supports the scalar format shown in your JSON examples ("padding": 16) via StacEdgeInsets.fromJson(), which accepts numeric input and expands it uniformly to all edges. Update the Properties table to reflect the correct type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_padding.mdx` at line 9, The Properties table incorrectly
lists the type of the padding property as Map<String, dynamic>; change it to
StacEdgeInsets to match the actual implementation and behaviors (e.g.,
StacEdgeInsets.fromJson supports scalar inputs like "padding": 16). Update the
documentation entry for the padding field to use StacEdgeInsets and optionally
mention that StacEdgeInsets.fromJson accepts numeric/scalar formats which expand
uniformly to all edges.
docs/widgets/backdrop_filter.mdx-219-220 (1)

219-220: ⚠️ Potential issue | 🟡 Minor

Add a blank line between </Tabs> and the next heading.

Same issue as in tool_tip.mdx: the ### Example 2: Dilate Filter Effect heading directly follows </Tabs> with no blank line, which can confuse MDX parsers. Add a blank line before the heading.

📝 Proposed fix
 </Tabs>
+
 ### Example 2: Dilate Filter Effect
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/backdrop_filter.mdx` around lines 219 - 220, The MDX has no
blank line between the closing </Tabs> tag and the next heading "### Example 2:
Dilate Filter Effect", which can break MDX parsing; open the docs file and
insert a single blank line immediately after the </Tabs> token so the heading is
separated (same fix as applied in tool_tip.mdx), ensuring there's a newline
between </Tabs> and the "### Example 2: Dilate Filter Effect" heading.
docs/widgets/tool_tip.mdx-108-109 (1)

108-109: ⚠️ Potential issue | 🟡 Minor

Add a blank line between </Tabs> and the next markdown heading.

Mintlify MDX requires a blank line between closing JSX tags and markdown headings to prevent parsing errors. Every other section in this file follows this pattern (lines 22, 49, 154, 189, 228 all have blank lines before their headings), but #### Styled Tooltip at line 109 is missing this blank line.

📝 Proposed fix
 </Tabs>
+
 #### Styled Tooltip
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/tool_tip.mdx` around lines 108 - 109, Add a blank line between
the closing JSX tag "</Tabs>" and the markdown heading "#### Styled Tooltip" so
the file has an empty line separating the JSX block and the heading (i.e.,
ensure there's one newline after "</Tabs>" before "#### Styled Tooltip") to
match the other sections and satisfy Mintlify MDX parsing.
docs/widgets/tool_tip.mdx-78-108 (1)

78-108: ⚠️ Potential issue | 🟡 Minor

Tooltip preview won't display the tooltip — only the icon will be visible.

By default, StacTooltip requires a long-press gesture to reveal the message. In an embedded iframe, long-press events cannot be reliably triggered, so readers will see only the info icon with no indication a tooltip exists.

Two options:

  1. Configure the preview with triggerMode: "manual" (or "tap") and pair with JavaScript to programmatically trigger visibility, or set a very short waitDuration to simulate hover behavior.
  2. Remove the Preview tab for this widget and keep the Dart/JSON tabs only until the playground supports interactive tooltip triggering.

Also confirm that triggerMode defaults are appropriate in iframe contexts where pointer events may be unavailable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/tool_tip.mdx` around lines 78 - 108, The Preview iframe shows
only the icon because StacTooltip requires a long-press to open and iframe
embedding prevents reliable long-press; update the preview payload
(toolTipPreviewJson) or the preview configuration to set StacTooltip.triggerMode
to "manual" or "tap" and/or reduce waitDuration so the tooltip will become
visible in the iframe, then programmatically postMessage from the parent (the
existing onLoad handler) to trigger visibility; alternatively remove the Preview
Tab entirely if you prefer not to simulate interaction. Ensure you reference
StacTooltip, triggerMode, waitDuration, toolTipPreviewJson (or
toolTipPreviewSrc) when making the change and verify defaults are suitable for
iframe contexts.
docs/widgets/network_widget.mdx-7-16 (1)

7-16: ⚠️ Potential issue | 🟡 Minor

Preview will fail because api.example.com/data returns invalid widget payload.

The playground receives the preview JSON via postMessage and attempts to fetch from https://api.example.com/data. This endpoint returns a 404 or generic documentation page, not a valid widget definition—the preview tab will display an error or parse failure.

Consider using a real test API (e.g., dummyjson.com like form.mdx does) or a network-less widget variant to demonstrate functionality.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/network_widget.mdx` around lines 7 - 16, The preview JSON in
networkWidgetPreviewJson points to an invalid endpoint (request.url =
"https://api.example.com/data") which causes the playground fetch to fail;
update networkWidgetPreviewJson to use a real test API (e.g., a dummyjson.com
endpoint) or convert it to a network-less example by removing the request field
so the preview does not perform an external fetch—modify the request.url value
or the request object inside networkWidgetPreviewJson accordingly.
docs/widgets/expanded.mdx-7-14 (1)

7-14: ⚠️ Potential issue | 🟡 Minor

Wrap Expanded in a Row, Column, or Flex container.

Expanded is a ParentDataWidget requiring a Flex parent (Row, Column, or Flex). The current preview puts it at root level, which will throw Incorrect use of ParentDataWidget at render time. The framework does not auto-wrap root widgets.

🛠️ Suggested payload
 export const expandedPreviewJson = {
-  "type": "expanded",
-  "flex": 2,
-  "child": {
-    "type": "text",
-    "data": "Hello, World!"
-  }
+  "type": "row",
+  "children": [
+    {
+      "type": "expanded",
+      "flex": 2,
+      "child": { "type": "text", "data": "Hello, World!" }
+    }
+  ]
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/expanded.mdx` around lines 7 - 14, The preview JSON places an
Expanded widget at the root (expandedPreviewJson with "type":"expanded"), which
will throw an Incorrect use of ParentDataWidget error; fix by wrapping the
Expanded node in a Flex parent (e.g., change expandedPreviewJson so the
top-level "type" is "row" or "column" or "flex" and move the existing expanded
object into that parent's "children"/"child" property), ensuring the Expanded
remains a descendant of a Flex (Row/Column/Flex) rather than the root.
docs/widgets/auto_complete.mdx-14-17 (1)

14-17: ⚠️ Potential issue | 🟡 Minor

onSelected references a callback that the embedded playground likely can't resolve.

The preview payload sends {"type": "callback", "name": "onOptionSelected"}, but the embedded playground iframe is launched with showEditor=false and has no way for a doc reader to register onOptionSelected. Selecting an option in the preview will probably no-op or throw. For preview-only payloads, consider omitting onSelected (or pointing it at a built-in noop action if Stac has one) so the preview is self-contained. The Dart/JSON snippets above can keep the callback to demonstrate the API.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/auto_complete.mdx` around lines 14 - 17, The preview payload
includes an onSelected callback referencing "onOptionSelected" which the
embedded playground (launched with showEditor=false) cannot resolve; remove the
onSelected entry from the preview payload or replace its value with a built-in
no-op action (e.g., a Stac-provided noop) so the iframe preview remains
self-contained—update the JSON used for the live preview (the object containing
"onSelected": {"type":"callback","name":"onOptionSelected"}) to either omit
"onSelected" or point it to the noop action.
docs/widgets/icon_button.mdx-24-24 (1)

24-24: ⚠️ Potential issue | 🟡 Minor

"onPressed": {} is not a valid Stac action shape.

An empty object will fail action parsing. The source documentation for stac_icon_button.dart shows the expected pattern is {"action": "navigate", "route": "/next"}. Alternatively, the function action pattern {"type": "function", "name": "..."} is also valid (as used in scaffold.mdx).

🔧 Suggested change
-  "onPressed": {},
+  "onPressed": {
+    "action": "navigate",
+    "route": "/next"
+  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/icon_button.mdx` at line 24, Replace the invalid empty action
object for "onPressed" with a valid Stac action shape; update the example in
docs/widgets/icon_button.mdx so "onPressed" uses either the navigation pattern
(e.g., {"action":"navigate","route":"/next"}) or the function pattern used
elsewhere ({"type":"function","name":"..."}) to match the expected parser in
stac_icon_button.dart and the scaffold.mdx examples.
docs/widgets/sliver_visibility.mdx-104-122 (1)

104-122: ⚠️ Potential issue | 🟡 Minor

Add cleanup handler to prevent setInterval firing on detached iframe after tab navigation.

The interval will continue firing for up to 3 seconds if the user navigates away or closes the Preview tab before the 12 retry attempts complete. Once the iframe unmounts, postMessage calls fire on a detached contentWindow.

Two remedies:

  1. Listen for an ack message event from the playground and clearInterval immediately on first successful receipt, rather than relying on a timer.
  2. Wrap the iframe in a component that returns cleanup from a useEffect, capturing the interval reference.

Minor note: The targetOrigin = PLAYGROUND_BASE_URL is correct (not "*"); verify the playground validates event.origin to reject spoofed messages.

This pattern is duplicated across multiple widget docs; consolidating into a shared component would fix it everywhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_visibility.mdx` around lines 104 - 122, The onLoad inline
handler starts a setInterval that can continue posting to a detached iframe;
replace this pattern by moving the logic into a React component (e.g., a
SliverVisibilityPreview component) that in a useEffect creates the message,
starts the retry interval (using the existing variables
attempts/maxAttempts/interval), adds a window "message" listener that checks
event.origin === PLAYGROUND_BASE_URL and the expected ack payload and
immediately clears the interval on first valid ack, and returns a cleanup that
clears the interval and removes the message listener on unmount; keep using
PLAYGROUND_BASE_URL and the same message shape (type: "stac-preview-json",
payload: sliverVisibilityPreviewJson) so the playground can validate origin and
respond.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 868a9343-45f4-4222-bdeb-daacfddd1b52

📥 Commits

Reviewing files that changed from the base of the PR and between 40b1428 and 4c8a63b.

📒 Files selected for processing (87)
  • docs/widgets/alert_dialog.mdx
  • docs/widgets/align.mdx
  • docs/widgets/app_bar.mdx
  • docs/widgets/aspect_ratio.mdx
  • docs/widgets/auto_complete.mdx
  • docs/widgets/backdrop_filter.mdx
  • docs/widgets/badge.mdx
  • docs/widgets/bottom_navigation_bar.mdx
  • docs/widgets/card.mdx
  • docs/widgets/carousel_view.mdx
  • docs/widgets/center.mdx
  • docs/widgets/check_box.mdx
  • docs/widgets/chip.mdx
  • docs/widgets/circle_avatar.mdx
  • docs/widgets/circular_progress_indicator.mdx
  • docs/widgets/clip_oval.mdx
  • docs/widgets/clip_rrect.mdx
  • docs/widgets/colored_box.mdx
  • docs/widgets/column.mdx
  • docs/widgets/conditional.mdx
  • docs/widgets/container.mdx
  • docs/widgets/custom_scroll_view.mdx
  • docs/widgets/divider.mdx
  • docs/widgets/drawer.mdx
  • docs/widgets/dropdown_menu.mdx
  • docs/widgets/dynamic_view.mdx
  • docs/widgets/elevated_button.mdx
  • docs/widgets/expanded.mdx
  • docs/widgets/filled_button.mdx
  • docs/widgets/fitted_box.mdx
  • docs/widgets/flexible.mdx
  • docs/widgets/floating_action_button.mdx
  • docs/widgets/form.mdx
  • docs/widgets/fractionally_sized_box.mdx
  • docs/widgets/gesture_detector.mdx
  • docs/widgets/grid_view.mdx
  • docs/widgets/hero.mdx
  • docs/widgets/icon.mdx
  • docs/widgets/icon_button.mdx
  • docs/widgets/image.mdx
  • docs/widgets/ink_well.mdx
  • docs/widgets/limited_box.mdx
  • docs/widgets/linear_progress_indicator.mdx
  • docs/widgets/list_tile.mdx
  • docs/widgets/listview.mdx
  • docs/widgets/network_widget.mdx
  • docs/widgets/opacity.mdx
  • docs/widgets/outlined_button.mdx
  • docs/widgets/padding.mdx
  • docs/widgets/page_view.mdx
  • docs/widgets/placeholder.mdx
  • docs/widgets/positioned.mdx
  • docs/widgets/radio_group.mdx
  • docs/widgets/refresh_indicator.mdx
  • docs/widgets/row.mdx
  • docs/widgets/safe_area.mdx
  • docs/widgets/scaffold.mdx
  • docs/widgets/selectable_text.mdx
  • docs/widgets/set_value.mdx
  • docs/widgets/single_child_scroll_view.mdx
  • docs/widgets/sized_box.mdx
  • docs/widgets/slider.mdx
  • docs/widgets/sliver_app_bar.mdx
  • docs/widgets/sliver_fill_remaining.mdx
  • docs/widgets/sliver_grid.mdx
  • docs/widgets/sliver_list.mdx
  • docs/widgets/sliver_opacity.mdx
  • docs/widgets/sliver_padding.mdx
  • docs/widgets/sliver_safe_area.mdx
  • docs/widgets/sliver_to_box_adapter.mdx
  • docs/widgets/sliver_visibility.mdx
  • docs/widgets/spacer.mdx
  • docs/widgets/stack.mdx
  • docs/widgets/switch.mdx
  • docs/widgets/tab_bar.mdx
  • docs/widgets/table.mdx
  • docs/widgets/table_cell.mdx
  • docs/widgets/table_row.mdx
  • docs/widgets/text.mdx
  • docs/widgets/text_button.mdx
  • docs/widgets/text_field.mdx
  • docs/widgets/text_form_field.mdx
  • docs/widgets/tool_tip.mdx
  • docs/widgets/vertical_divider.mdx
  • docs/widgets/visibility.mdx
  • docs/widgets/webview.mdx
  • docs/widgets/wrap.mdx

Comment thread docs/widgets/dropdown_menu.mdx
Comment thread docs/widgets/dynamic_view.mdx Outdated
Comment thread docs/widgets/elevated_button.mdx
Comment thread docs/widgets/ink_well.mdx
Comment thread docs/widgets/positioned.mdx
Comment thread docs/widgets/refresh_indicator.mdx
Comment thread docs/widgets/sliver_app_bar.mdx
Comment thread docs/widgets/sliver_safe_area.mdx
Comment thread docs/widgets/sliver_visibility.mdx Outdated
Comment thread docs/widgets/sliver_visibility.mdx
- Refactored widget documentation to include structured JSON representations and playground examples for DropdownMenu, Positioned, RefreshIndicator, SliverAppBar, SliverFillRemaining, SliverGrid, SliverOpacity, SliverPadding, SliverSafeArea, and SliverVisibility.
- Enhanced clarity and usability of widget examples for better developer experience.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/widgets/sliver_safe_area.mdx (1)

60-72: ⚠️ Potential issue | 🟡 Minor

JSON tab still shows a bare root-level sliver, inconsistent with the Preview payload.

The Preview payload (lines 7–25) correctly wraps sliverSafeArea inside scaffold > customScrollView > slivers, but the JSON example here shows the sliver at the root. A user copy-pasting this JSON will hit the same render-time failure the Preview fix was addressing. Consider aligning this snippet with the preview payload (or at least noting the required CustomScrollView parent) for consistency across both tabs.

✍️ Proposed fix
 ```json
 {
-  "type": "sliverSafeArea",
-  "top": true,
-  "sliver": {
-    "type": "sliverToBoxAdapter",
-    "child": {
-      "type": "text",
-      "data": "Hello World"
+  "type": "scaffold",
+  "body": {
+    "type": "customScrollView",
+    "slivers": [
+      {
+        "type": "sliverSafeArea",
+        "top": true,
+        "sliver": {
+          "type": "sliverToBoxAdapter",
+          "child": {
+            "type": "text",
+            "data": "Hello World"
+          }
+        }
+      }
+    ]
   }
 }

</details>

The same discrepancy likely exists in the other sliver docs touched by this PR (`sliver_grid.mdx`, `sliver_opacity.mdx`, `sliver_padding.mdx`, `sliver_visibility.mdx`, `sliver_fill_remaining.mdx`, `sliver_app_bar.mdx`) — worth a sweep.

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/widgets/sliver_safe_area.mdx around lines 60 - 72, The JSON example
currently shows a root-level "sliverSafeArea" which is inconsistent with the
Preview payload; update the example to wrap the "sliverSafeArea" inside a
"scaffold" -> "body": { "type":"customScrollView", "slivers":[ ... ] } structure
(preserving the inner "sliverToBoxAdapter" and "text" child), or add a clear
note that "sliverSafeArea" requires a CustomScrollView parent; also sweep the
other sliver docs (sliver_grid.mdx, sliver_opacity.mdx, sliver_padding.mdx,
sliver_visibility.mdx, sliver_fill_remaining.mdx, sliver_app_bar.mdx) and make
the same fix so examples consistently include the "customScrollView" ->
"slivers" wrapper.


</details>

</blockquote></details>

</blockquote></details>
♻️ Duplicate comments (1)
docs/widgets/dropdown_menu.mdx (1)

165-183: ⚠️ Potential issue | 🟡 Minor

Overlapping intervals on repeated iframe onLoad.

onLoad can fire more than once for a single iframe (e.g., if the playground performs a client-side navigation or the tab is toggled and the iframe reloads). Each invocation starts a fresh setInterval without cancelling the previous one, so multiple 250ms timers run concurrently, each blasting up to 12 postMessage calls at the playground. Track the active interval and clear it before starting a new one.

🛠️ Proposed fix
         onLoad={(event) => {
           const iframe = event.currentTarget;
           const targetOrigin = PLAYGROUND_BASE_URL;
           const message = {
             type: "stac-preview-json",
             payload: dropdownMenuPreviewJson
           };

+          if (iframe.__stacPreviewInterval) {
+            clearInterval(iframe.__stacPreviewInterval);
+          }
           let attempts = 0;
           const maxAttempts = 12;
           const interval = setInterval(() => {
             iframe.contentWindow?.postMessage(message, targetOrigin);
             attempts += 1;

             if (attempts >= maxAttempts) {
               clearInterval(interval);
+              iframe.__stacPreviewInterval = null;
             }
           }, 250);
+          iframe.__stacPreviewInterval = interval;
         }}

A cleaner alternative is a one-shot handshake: have the playground postMessage({type:"stac-preview-ready"}) to its parent once mounted, and send the payload from a single window.addEventListener("message", …) handler. That also lets you drop the retry loop entirely.

Note: this pattern appears to be replicated across all the widget docs touched in this PR, so a fix should be applied consistently.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/dropdown_menu.mdx` around lines 165 - 183, The onLoad handler
for the iframe creates overlapping setInterval timers (variables attempts,
maxAttempts, interval) and should clear any prior interval before starting a new
one or, better, replace the retry loop with a one-shot handshake; update the
onLoad logic (the inline onLoad handler that posts message
{type:"stac-preview-json", payload: dropdownMenuPreviewJson} to
PLAYGROUND_BASE_URL) to either track and clear an existing interval variable
before calling setInterval or remove the interval entirely and implement a
single message listener pattern where the playground sends back
{type:"stac-preview-ready"} and the parent (using
window.addEventListener("message", …)) sends the payload once—apply the same
change consistently across all widget docs that use this pattern.
🧹 Nitpick comments (3)
docs/widgets/sliver_fill_remaining.mdx (1)

91-109: Consider handshake-based messaging instead of fixed-attempt polling.

The current approach blindly posts the payload 12 times at 250ms intervals regardless of whether the playground has already received it. A ready-signal handshake (playground posts stac-preview-ready back, parent responds once) would be more reliable and eliminate redundant messages. Also note the interval is not cleared if the component unmounts or the iframe reloads mid-retry — minor since it self-terminates within ~3s, but worth addressing if this pattern is extracted into a shared component (which would be worthwhile given it is duplicated across many widget docs in this PR).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_fill_remaining.mdx` around lines 91 - 109, Replace the
blind polling in the onLoad handler with a handshake: listen for window
"message" events from PLAYGROUND_BASE_URL and when you receive type
"stac-preview-ready" post the "stac-preview-json" payload once to
event.currentTarget.contentWindow and remove the listener and any retry
interval; if you keep a fallback polling retry (attempts/interval), ensure you
clear the interval and remove the message listener on success, on iframe reload,
and on component unmount to avoid leaks. Verify origin === PLAYGROUND_BASE_URL
before trusting messages, reference the existing onLoad handler, the posted
message type "stac-preview-json", the expected reply "stac-preview-ready", and
the interval/attempts logic when implementing the cleanup and handshake.
docs/widgets/sliver_safe_area.mdx (1)

83-101: Retry loop fires 12 postMessages unconditionally — consider stopping on ack.

The interval posts the payload 12 times regardless of whether the playground has already received/processed it, and there's no handshake (e.g., listening for a ready/ack message from the iframe) to short-circuit. For a single iframe this is harmless, but it's noisy in DevTools and wastes work. If/when the playground can emit a readiness message, wiring a message listener to clearInterval early would be cleaner. Non-blocking.

Also note this same block (plus PLAYGROUND_BASE_URL and the embed URL) is duplicated verbatim across every widget MDX added in this PR — a small shared MDX component/hook (e.g., <StacPreview json={...} />) would eliminate the copy-paste and make future tweaks (origin change, retry tuning) a one-line edit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_safe_area.mdx` around lines 83 - 101, The retry loop in
the onLoad handler posts "stac-preview-json" up to 12 times unconditionally
(iframe.contentWindow?.postMessage with PLAYGROUND_BASE_URL and
sliverSafeAreaPreviewJson); change it to stop early by adding a
window.addEventListener('message') handler that verifies event.origin ===
PLAYGROUND_BASE_URL and event.data.type === 'stac-preview-ack' (or 'ready') and
then clears the interval and removes the listener; also refactor this duplicated
logic into a shared MDX/React component or hook (e.g., <StacPreview json={...}>
or useStacPreview) so the PLAYGROUND_BASE_URL, retry tuning and handshake live
in one place for all widgets.
docs/widgets/dropdown_menu.mdx (1)

118-154: JSON block duplicates dropdownMenuPreviewJson — drift risk.

The JSON shown in the “JSON” tab (lines 119–153) is a hand-written copy of the dropdownMenuPreviewJson constant (lines 7–41). Any future edit that updates one but not the other will cause the documented JSON to disagree with what the live Preview actually renders — which is exactly the kind of discrepancy users will file bugs on. Consider rendering the JSON tab from the same constant (e.g., via a small JSON fenced-code helper or a shared MDX component) so there is a single source of truth, or at minimum add a short comment in both places noting they must stay in sync. Since this pattern is repeated across many widget docs in this PR, a shared helper would pay off quickly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/dropdown_menu.mdx` around lines 118 - 154, The JSON block in the
"JSON" tab is a duplicated, hand-edited copy of the dropdownMenuPreviewJson
constant which creates a drift risk; instead of a static fenced JSON snippet,
import or reference the existing dropdownMenuPreviewJson value and render it
(e.g., stringify and inject into the JSON code block via a small MDX helper or
shared component) so the preview and docs share one source of truth, or if a
shared renderer is not feasible immediately, add a clear inline comment next to
dropdownMenuPreviewJson and the JSON tab noting they must remain in sync and
link to the single canonical constant name (dropdownMenuPreviewJson) to reduce
future divergence.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@docs/widgets/sliver_safe_area.mdx`:
- Around line 60-72: The JSON example currently shows a root-level
"sliverSafeArea" which is inconsistent with the Preview payload; update the
example to wrap the "sliverSafeArea" inside a "scaffold" -> "body": {
"type":"customScrollView", "slivers":[ ... ] } structure (preserving the inner
"sliverToBoxAdapter" and "text" child), or add a clear note that
"sliverSafeArea" requires a CustomScrollView parent; also sweep the other sliver
docs (sliver_grid.mdx, sliver_opacity.mdx, sliver_padding.mdx,
sliver_visibility.mdx, sliver_fill_remaining.mdx, sliver_app_bar.mdx) and make
the same fix so examples consistently include the "customScrollView" ->
"slivers" wrapper.

---

Duplicate comments:
In `@docs/widgets/dropdown_menu.mdx`:
- Around line 165-183: The onLoad handler for the iframe creates overlapping
setInterval timers (variables attempts, maxAttempts, interval) and should clear
any prior interval before starting a new one or, better, replace the retry loop
with a one-shot handshake; update the onLoad logic (the inline onLoad handler
that posts message {type:"stac-preview-json", payload: dropdownMenuPreviewJson}
to PLAYGROUND_BASE_URL) to either track and clear an existing interval variable
before calling setInterval or remove the interval entirely and implement a
single message listener pattern where the playground sends back
{type:"stac-preview-ready"} and the parent (using
window.addEventListener("message", …)) sends the payload once—apply the same
change consistently across all widget docs that use this pattern.

---

Nitpick comments:
In `@docs/widgets/dropdown_menu.mdx`:
- Around line 118-154: The JSON block in the "JSON" tab is a duplicated,
hand-edited copy of the dropdownMenuPreviewJson constant which creates a drift
risk; instead of a static fenced JSON snippet, import or reference the existing
dropdownMenuPreviewJson value and render it (e.g., stringify and inject into the
JSON code block via a small MDX helper or shared component) so the preview and
docs share one source of truth, or if a shared renderer is not feasible
immediately, add a clear inline comment next to dropdownMenuPreviewJson and the
JSON tab noting they must remain in sync and link to the single canonical
constant name (dropdownMenuPreviewJson) to reduce future divergence.

In `@docs/widgets/sliver_fill_remaining.mdx`:
- Around line 91-109: Replace the blind polling in the onLoad handler with a
handshake: listen for window "message" events from PLAYGROUND_BASE_URL and when
you receive type "stac-preview-ready" post the "stac-preview-json" payload once
to event.currentTarget.contentWindow and remove the listener and any retry
interval; if you keep a fallback polling retry (attempts/interval), ensure you
clear the interval and remove the message listener on success, on iframe reload,
and on component unmount to avoid leaks. Verify origin === PLAYGROUND_BASE_URL
before trusting messages, reference the existing onLoad handler, the posted
message type "stac-preview-json", the expected reply "stac-preview-ready", and
the interval/attempts logic when implementing the cleanup and handshake.

In `@docs/widgets/sliver_safe_area.mdx`:
- Around line 83-101: The retry loop in the onLoad handler posts
"stac-preview-json" up to 12 times unconditionally
(iframe.contentWindow?.postMessage with PLAYGROUND_BASE_URL and
sliverSafeAreaPreviewJson); change it to stop early by adding a
window.addEventListener('message') handler that verifies event.origin ===
PLAYGROUND_BASE_URL and event.data.type === 'stac-preview-ack' (or 'ready') and
then clears the interval and removes the listener; also refactor this duplicated
logic into a shared MDX/React component or hook (e.g., <StacPreview json={...}>
or useStacPreview) so the PLAYGROUND_BASE_URL, retry tuning and handshake live
in one place for all widgets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5bf7382e-680a-4c5a-bdcf-0c0dd3db2fe1

📥 Commits

Reviewing files that changed from the base of the PR and between 4c8a63b and 88511a0.

📒 Files selected for processing (10)
  • docs/widgets/dropdown_menu.mdx
  • docs/widgets/positioned.mdx
  • docs/widgets/refresh_indicator.mdx
  • docs/widgets/sliver_app_bar.mdx
  • docs/widgets/sliver_fill_remaining.mdx
  • docs/widgets/sliver_grid.mdx
  • docs/widgets/sliver_opacity.mdx
  • docs/widgets/sliver_padding.mdx
  • docs/widgets/sliver_safe_area.mdx
  • docs/widgets/sliver_visibility.mdx
✅ Files skipped from review due to trivial changes (1)
  • docs/widgets/sliver_opacity.mdx
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/widgets/refresh_indicator.mdx
  • docs/widgets/sliver_visibility.mdx
  • docs/widgets/sliver_grid.mdx
  • docs/widgets/sliver_app_bar.mdx
  • docs/widgets/positioned.mdx
  • docs/widgets/sliver_padding.mdx

- Updated multiple widget documentation files to import the PLAYGROUND_BASE_URL from a centralized snippet for consistency.
- Simplified the preview source URL for each widget by removing unnecessary query parameters.
- Adjusted iframe styling to maintain a consistent height across all widget previews.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/widgets/sliver_app_bar.mdx (1)

110-141: ⚠️ Potential issue | 🟠 Major

JSON tab is out of sync with the Preview payload.

sliverAppBarPreviewJson (lines 8–43) correctly wraps the sliverAppBar inside scaffold → customScrollView → slivers so the preview renders. But the JSON tab here still shows a bare top-level sliverAppBar, which is exactly the payload that prompted the earlier "slivers need a sliver-aware parent" feedback. Users copying the JSON tab will not reproduce what they see in the Preview, and the shown payload will fail to render on its own.

Please align the JSON tab with the exported preview payload.

🛠️ Suggested fix
 ```json
 {
-  "type": "sliverAppBar",
-  "title": {
-    "type": "text",
-    "data": "SliverAppBar"
-  },
-  "leading": {
-    "type": "iconButton",
-    "icon": {
-      "type": "icon",
-      "iconType": "material",
-      "icon": "menu"
-    },
-    "onPressed": {}
-  },
-  "backgroundColor": "primary",
-  "actions": [
-    {
-      "type": "iconButton",
-      "icon": {
-        "type": "icon",
-        "iconType": "cupertino",
-        "icon": "heart_solid"
-      },
-      "onPressed": {}
-    }
-  ]
+  "type": "scaffold",
+  "body": {
+    "type": "customScrollView",
+    "slivers": [
+      {
+        "type": "sliverAppBar",
+        "title": { "type": "text", "data": "SliverAppBar" },
+        "leading": {
+          "type": "iconButton",
+          "icon": { "type": "icon", "iconType": "material", "icon": "menu" },
+          "onPressed": {}
+        },
+        "backgroundColor": "primary",
+        "actions": [
+          {
+            "type": "iconButton",
+            "icon": { "type": "icon", "iconType": "cupertino", "icon": "heart_solid" },
+            "onPressed": {}
+          }
+        ]
+      }
+    ]
+  }
 }

Consider applying the same wrapping to the Dart tab so all three tabs tell the same story.
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/widgets/sliver_app_bar.mdx around lines 110 - 141, The JSON tab shows a
top-level "sliverAppBar" that won't render standalone and is out of sync with
sliverAppBarPreviewJson; update the JSON payload to wrap the sliverAppBar inside
a scaffold -> customScrollView -> slivers array (matching
sliverAppBarPreviewJson) so users can copy a working payload; also mirror this
same scaffold/customScrollView/slivers wrapping in the Dart tab if present to
keep all tabs consistent.


</details>

</blockquote></details>
<details>
<summary>docs/widgets/limited_box.mdx (1)</summary><blockquote>

`97-126`: _⚠️ Potential issue_ | _🟡 Minor_

**Example 2 was left on the old `<CodeGroup>` pattern.**

Example 1 was migrated to `<Tabs>` with a Preview tab, but Example 2 still uses `<CodeGroup>` and unnormalized float literals (`200.0`, `300.0`). This leaves the page visually inconsistent and Example 2 without a live preview. Consider migrating it for parity (or drop Example 2 if a preview isn't planned).

<details>
<summary>♻️ Sketch of the migration</summary>

```diff
-<CodeGroup>
-```dart Dart
-StacLimitedBox(
-  maxHeight: 200.0,
-  maxWidth: 300.0,
-  child: StacText(
-    data: 'Hello, World! from Limited Box',
-    style: StacTextStyle(fontSize: 16, color: StacColors.black),
-  ),
-)
-```
-
-```json JSON
-{
-  "type": "limitedBox",
-  "maxHeight": 200.0,
-  "maxWidth": 300.0,
-  "child": {
-    "type": "text",
-    "data": "Hello, World! from Limited Box",
-    "style": {
-      "fontSize": 16,
-      "color": "#000000"
-    }
-  }
-}
-```
-</CodeGroup>
+<Tabs sync={false}>
+  <Tab title="Dart">
+    ```dart
+    StacLimitedBox(
+      maxHeight: 200.0,
+      maxWidth: 300.0,
+      child: StacText(
+        data: 'Hello, World! from Limited Box',
+        style: StacTextStyle(fontSize: 16, color: StacColors.black),
+      ),
+    )
+    ```
+  </Tab>
+  <Tab title="JSON">
+    ```json
+    {
+      "type": "limitedBox",
+      "maxHeight": 200,
+      "maxWidth": 300,
+      "child": {
+        "type": "text",
+        "data": "Hello, World! from Limited Box",
+        "style": { "fontSize": 16, "color": "#000000" }
+      }
+    }
+    ```
+  </Tab>
+  {/* Optionally add a Preview tab, following the Example 1 pattern. */}
+</Tabs>

Also worth adding the trailing newline back at EOF for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/limited_box.mdx` around lines 97 - 126, Example 2 in
docs/widgets/limited_box.mdx still uses the old <CodeGroup> pattern and
unnormalized float literals (e.g., 200.0, 300.0) causing visual inconsistency
and no live preview; replace the <CodeGroup> block for Example 2 with a <Tabs
sync={false}> containing <Tab title="Dart"> and <Tab title="JSON"> (optionally
add a Preview tab like Example 1), move the StacLimitedBox Dart snippet into the
Dart tab, convert JSON numeric fields ("maxHeight", "maxWidth") to integers
(200, 300) in the JSON tab, and ensure the file ends with a trailing newline;
refer to the existing Example 1 Tabs/Preview usage as the migration model.
♻️ Duplicate comments (1)
docs/widgets/positioned.mdx (1)

55-80: ⚠️ Potential issue | 🟡 Minor

Keep the code tabs aligned with the fixed preview payload.

The Preview tab now uses a stack, but the Dart/JSON tabs still show Positioned as a standalone root. Wrap the examples too so copied examples match the preview and remain valid as a complete widget tree.

Suggested update
-StacPositioned(
-  left: 10,
-  top: 20,
-  right: 30,
-  bottom: 40,
-  child: StacText(data: 'Hello, World!'),
+StacStack(
+  children: [
+    StacPositioned(
+      left: 10,
+      top: 20,
+      right: 30,
+      bottom: 40,
+      child: StacText(data: 'Hello, World!'),
+    ),
+  ],
 )
 {
-  "type": "positioned",
-  "left": 10,
-  "top": 20,
-  "right": 30,
-  "bottom": 40,
-  "child": {
-    "type": "text",
-    "data": "Hello, World!"
-  }
+  "type": "stack",
+  "children": [
+    {
+      "type": "positioned",
+      "left": 10,
+      "top": 20,
+      "right": 30,
+      "bottom": 40,
+      "child": {
+        "type": "text",
+        "data": "Hello, World!"
+      }
+    }
+  ]
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/positioned.mdx` around lines 55 - 80, The Dart and JSON examples
show StacPositioned as the root but the preview uses a stack; update both
examples so they are wrapped in a Stack/root "stack" node so copied snippets
form a complete widget tree: in the Dart tab wrap StacPositioned (and its
StacText child) inside the same Stack construct used by the preview (e.g., a
Stack containing StacPositioned), and in the JSON tab make the top-level object
type "stack" with a children array that contains the positioned object (keep
"type": "positioned", left/top/right/bottom and the nested text node intact).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/widgets/align.mdx`:
- Around line 11-28: The JSON preview payload for the Align example is missing
the clipBehavior property, causing it to differ from the Dart example; update
the alignPreviewJson payload in docs/widgets/align.mdx to include
"clipBehavior": "hardEdge" on the relevant align/container object so the Preview
tab renders the same documented payload as the Dart example and keeps JSON and
Preview consistent.

In `@docs/widgets/dynamic_view.mdx`:
- Around line 8-18: Update the dynamicView preview object dynamicViewPreviewJson
so it uses a reachable, deterministic endpoint and the correct template field:
change request.url to "https://dummyjson.com/users/1" and update template.data
to reference the returned user property by replacing "{{name}}" with
"{{firstName}}"; ensure the template.type ("text") and the
dynamicViewPreviewJson export remain unchanged.

In `@docs/widgets/sized_box.mdx`:
- Around line 8-12: sizedBoxPreviewJson currently specifies only
"type":"sizedBox" and "height":25 which renders blank; update
sizedBoxPreviewJson to include a simple child (e.g., a small container/box or
text element with a background color) so the Preview tab shows visible output,
and make the analogous change to the other sizedBox preview definitions
referenced (lines 30-41) so they also include a visible child; retain
sizedBoxPreviewSrc/PLAYGROUND_BASE_URL as-is.

In `@docs/widgets/sliver_to_box_adapter.mdx`:
- Around line 8-30: The preview JSON for sliverToBoxAdapter is not wrapped in a
CustomScrollView scaffold context; update sliverToBoxAdapterPreviewJson so its
root follows the same structure as other sliver docs by nesting the current
payload under the path scaffold > body > customScrollView > slivers (i.e., move
the existing sliverPadding/sliverToBoxAdapter object into a slivers array inside
a customScrollView body of a scaffold) so the sliver has the proper viewport
context for rendering.

---

Outside diff comments:
In `@docs/widgets/limited_box.mdx`:
- Around line 97-126: Example 2 in docs/widgets/limited_box.mdx still uses the
old <CodeGroup> pattern and unnormalized float literals (e.g., 200.0, 300.0)
causing visual inconsistency and no live preview; replace the <CodeGroup> block
for Example 2 with a <Tabs sync={false}> containing <Tab title="Dart"> and <Tab
title="JSON"> (optionally add a Preview tab like Example 1), move the
StacLimitedBox Dart snippet into the Dart tab, convert JSON numeric fields
("maxHeight", "maxWidth") to integers (200, 300) in the JSON tab, and ensure the
file ends with a trailing newline; refer to the existing Example 1 Tabs/Preview
usage as the migration model.

In `@docs/widgets/sliver_app_bar.mdx`:
- Around line 110-141: The JSON tab shows a top-level "sliverAppBar" that won't
render standalone and is out of sync with sliverAppBarPreviewJson; update the
JSON payload to wrap the sliverAppBar inside a scaffold -> customScrollView ->
slivers array (matching sliverAppBarPreviewJson) so users can copy a working
payload; also mirror this same scaffold/customScrollView/slivers wrapping in the
Dart tab if present to keep all tabs consistent.

---

Duplicate comments:
In `@docs/widgets/positioned.mdx`:
- Around line 55-80: The Dart and JSON examples show StacPositioned as the root
but the preview uses a stack; update both examples so they are wrapped in a
Stack/root "stack" node so copied snippets form a complete widget tree: in the
Dart tab wrap StacPositioned (and its StacText child) inside the same Stack
construct used by the preview (e.g., a Stack containing StacPositioned), and in
the JSON tab make the top-level object type "stack" with a children array that
contains the positioned object (keep "type": "positioned", left/top/right/bottom
and the nested text node intact).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc72eaf3-6577-47e7-b80d-0f203268c2a4

📥 Commits

Reviewing files that changed from the base of the PR and between 88511a0 and 847466d.

⛔ Files ignored due to path filters (4)
  • examples/counter_example/pubspec.lock is excluded by !**/*.lock
  • examples/movie_app/pubspec.lock is excluded by !**/*.lock
  • examples/stac_gallery/pubspec.lock is excluded by !**/*.lock
  • packages/stac_cli/pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (88)
  • docs/snippets/playground_base.mdx
  • docs/widgets/alert_dialog.mdx
  • docs/widgets/align.mdx
  • docs/widgets/app_bar.mdx
  • docs/widgets/aspect_ratio.mdx
  • docs/widgets/auto_complete.mdx
  • docs/widgets/backdrop_filter.mdx
  • docs/widgets/badge.mdx
  • docs/widgets/bottom_navigation_bar.mdx
  • docs/widgets/card.mdx
  • docs/widgets/carousel_view.mdx
  • docs/widgets/center.mdx
  • docs/widgets/check_box.mdx
  • docs/widgets/chip.mdx
  • docs/widgets/circle_avatar.mdx
  • docs/widgets/circular_progress_indicator.mdx
  • docs/widgets/clip_oval.mdx
  • docs/widgets/clip_rrect.mdx
  • docs/widgets/colored_box.mdx
  • docs/widgets/column.mdx
  • docs/widgets/conditional.mdx
  • docs/widgets/container.mdx
  • docs/widgets/custom_scroll_view.mdx
  • docs/widgets/divider.mdx
  • docs/widgets/drawer.mdx
  • docs/widgets/dropdown_menu.mdx
  • docs/widgets/dynamic_view.mdx
  • docs/widgets/elevated_button.mdx
  • docs/widgets/expanded.mdx
  • docs/widgets/filled_button.mdx
  • docs/widgets/fitted_box.mdx
  • docs/widgets/flexible.mdx
  • docs/widgets/floating_action_button.mdx
  • docs/widgets/form.mdx
  • docs/widgets/fractionally_sized_box.mdx
  • docs/widgets/gesture_detector.mdx
  • docs/widgets/grid_view.mdx
  • docs/widgets/hero.mdx
  • docs/widgets/icon.mdx
  • docs/widgets/icon_button.mdx
  • docs/widgets/image.mdx
  • docs/widgets/ink_well.mdx
  • docs/widgets/limited_box.mdx
  • docs/widgets/linear_progress_indicator.mdx
  • docs/widgets/list_tile.mdx
  • docs/widgets/listview.mdx
  • docs/widgets/network_widget.mdx
  • docs/widgets/opacity.mdx
  • docs/widgets/outlined_button.mdx
  • docs/widgets/padding.mdx
  • docs/widgets/page_view.mdx
  • docs/widgets/placeholder.mdx
  • docs/widgets/positioned.mdx
  • docs/widgets/radio_group.mdx
  • docs/widgets/refresh_indicator.mdx
  • docs/widgets/row.mdx
  • docs/widgets/safe_area.mdx
  • docs/widgets/scaffold.mdx
  • docs/widgets/selectable_text.mdx
  • docs/widgets/set_value.mdx
  • docs/widgets/single_child_scroll_view.mdx
  • docs/widgets/sized_box.mdx
  • docs/widgets/slider.mdx
  • docs/widgets/sliver_app_bar.mdx
  • docs/widgets/sliver_fill_remaining.mdx
  • docs/widgets/sliver_grid.mdx
  • docs/widgets/sliver_list.mdx
  • docs/widgets/sliver_opacity.mdx
  • docs/widgets/sliver_padding.mdx
  • docs/widgets/sliver_safe_area.mdx
  • docs/widgets/sliver_to_box_adapter.mdx
  • docs/widgets/sliver_visibility.mdx
  • docs/widgets/spacer.mdx
  • docs/widgets/stack.mdx
  • docs/widgets/switch.mdx
  • docs/widgets/tab_bar.mdx
  • docs/widgets/table.mdx
  • docs/widgets/table_cell.mdx
  • docs/widgets/table_row.mdx
  • docs/widgets/text.mdx
  • docs/widgets/text_button.mdx
  • docs/widgets/text_field.mdx
  • docs/widgets/text_form_field.mdx
  • docs/widgets/tool_tip.mdx
  • docs/widgets/vertical_divider.mdx
  • docs/widgets/visibility.mdx
  • docs/widgets/webview.mdx
  • docs/widgets/wrap.mdx
✅ Files skipped from review due to trivial changes (6)
  • docs/snippets/playground_base.mdx
  • docs/widgets/conditional.mdx
  • docs/widgets/text_field.mdx
  • docs/widgets/clip_rrect.mdx
  • docs/widgets/sliver_fill_remaining.mdx
  • docs/widgets/sliver_opacity.mdx
🚧 Files skipped from review as they are similar to previous changes (46)
  • docs/widgets/app_bar.mdx
  • docs/widgets/alert_dialog.mdx
  • docs/widgets/linear_progress_indicator.mdx
  • docs/widgets/safe_area.mdx
  • docs/widgets/container.mdx
  • docs/widgets/tool_tip.mdx
  • docs/widgets/badge.mdx
  • docs/widgets/form.mdx
  • docs/widgets/visibility.mdx
  • docs/widgets/webview.mdx
  • docs/widgets/flexible.mdx
  • docs/widgets/row.mdx
  • docs/widgets/column.mdx
  • docs/widgets/hero.mdx
  • docs/widgets/tab_bar.mdx
  • docs/widgets/network_widget.mdx
  • docs/widgets/floating_action_button.mdx
  • docs/widgets/vertical_divider.mdx
  • docs/widgets/divider.mdx
  • docs/widgets/center.mdx
  • docs/widgets/drawer.mdx
  • docs/widgets/carousel_view.mdx
  • docs/widgets/refresh_indicator.mdx
  • docs/widgets/fractionally_sized_box.mdx
  • docs/widgets/selectable_text.mdx
  • docs/widgets/scaffold.mdx
  • docs/widgets/listview.mdx
  • docs/widgets/circular_progress_indicator.mdx
  • docs/widgets/image.mdx
  • docs/widgets/expanded.mdx
  • docs/widgets/stack.mdx
  • docs/widgets/filled_button.mdx
  • docs/widgets/spacer.mdx
  • docs/widgets/table_cell.mdx
  • docs/widgets/fitted_box.mdx
  • docs/widgets/clip_oval.mdx
  • docs/widgets/custom_scroll_view.mdx
  • docs/widgets/sliver_safe_area.mdx
  • docs/widgets/table_row.mdx
  • docs/widgets/sliver_list.mdx
  • docs/widgets/switch.mdx
  • docs/widgets/slider.mdx
  • docs/widgets/icon_button.mdx
  • docs/widgets/elevated_button.mdx
  • docs/widgets/sliver_grid.mdx
  • docs/widgets/text.mdx

Comment thread docs/widgets/align.mdx Outdated
Comment on lines +8 to +18
export const dynamicViewPreviewJson = {
"type": "dynamicView",
"request": {
"url": "https://api.example.com/user/1",
"method": "get"
},
"template": {
"type": "text",
"data": "Hello, {{name}}!"
}
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Confirm whether the preview URL returns JSON compatible with the template.
# Expected: A 2xx JSON response containing the fields used by the template.
python - <<'PY'
import urllib.request

url = "https://api.example.com/user/1"
try:
    req = urllib.request.Request(url, headers={"Accept": "application/json"})
    with urllib.request.urlopen(req, timeout=5) as response:
        print("status:", response.status)
        print("content-type:", response.headers.get("content-type"))
        print("body-prefix:", response.read(200).decode("utf-8", errors="replace"))
except Exception as exc:
    print(type(exc).__name__ + ":", exc)
PY

Repository: StacDev/stac

Length of output: 118


🏁 Script executed:

# First, locate and read the file to confirm content
fd -t f "dynamic_view.mdx" --exec head -120 {}

Repository: StacDev/stac

Length of output: 4127


🏁 Script executed:

# Test the suggested endpoint to confirm it returns compatible JSON
python - <<'PY'
import urllib.request
import json

url = "https://dummyjson.com/users/1"
try:
    req = urllib.request.Request(url, headers={"Accept": "application/json"})
    with urllib.request.urlopen(req, timeout=5) as response:
        print("status:", response.status)
        print("content-type:", response.headers.get("content-type"))
        body = response.read().decode("utf-8")
        data = json.loads(body)
        print("response-keys:", list(data.keys()))
        # Check for the fields mentioned in review
        if "firstName" in data:
            print("firstName:", data["firstName"])
        if "name" in data:
            print("name:", data["name"])
except Exception as exc:
    print(type(exc).__name__ + ":", exc)
PY

Repository: StacDev/stac

Length of output: 193


🏁 Script executed:

# Try with curl and disable SSL verification (for sandbox testing)
curl -s "https://dummyjson.com/users/1" 2>/dev/null | python - <<'PY'
import sys
import json
data = json.load(sys.stdin)
print("Available fields:", list(data.keys()))
print("\nRelevant fields:")
if "firstName" in data:
    print(f"  firstName: {data['firstName']}")
if "lastName" in data:
    print(f"  lastName: {data['lastName']}")
if "name" in data:
    print(f"  name: {data['name']}")
PY

Repository: StacDev/stac

Length of output: 776


🌐 Web query:

dummyjson API users endpoint response structure firstName

💡 Result:

The DummyJSON API users endpoint (https://dummyjson.com/users) returns a JSON object with a "users" array containing user objects. Each user object includes a "firstName" field as a string property, such as "Emily" or "Terry". Example structure from official docs: { "users": [ { "id": 1, "firstName": "Emily", "lastName": "Johnson", ... }, ... ], "total": 208, "skip": 0, "limit": 30 }

Citations:


Make the DynamicView preview deterministic.

This live preview posts a network-backed dynamicView payload up to 12 times at 250ms intervals, and the URL is a placeholder endpoint that cannot be reached. If the playground applies each message, the preview repeatedly issues failing API requests instead of rendering a stable example.

Replace the placeholder endpoint with a real working endpoint and update the template field name accordingly. Use https://dummyjson.com/users/1 (which returns a user object with firstName), and update the template to use {{firstName}} instead of {{name}}.

🛠️ Corrected preview payload
 export const dynamicViewPreviewJson = {
   "type": "dynamicView",
   "request": {
-    "url": "https://api.example.com/user/1",
+    "url": "https://dummyjson.com/users/1",
     "method": "get"
   },
   "template": {
     "type": "text",
-    "data": "Hello, {{name}}!"
+    "data": "Hello, {{firstName}}!"
   }
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/dynamic_view.mdx` around lines 8 - 18, Update the dynamicView
preview object dynamicViewPreviewJson so it uses a reachable, deterministic
endpoint and the correct template field: change request.url to
"https://dummyjson.com/users/1" and update template.data to reference the
returned user property by replacing "{{name}}" with "{{firstName}}"; ensure the
template.type ("text") and the dynamicViewPreviewJson export remain unchanged.

Comment on lines +8 to +12
export const sizedBoxPreviewJson = {
"type": "sizedBox",
"height": 25
};
export const sizedBoxPreviewSrc = `${PLAYGROUND_BASE_URL}/embed`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Make the SizedBox preview visibly render something.

A SizedBox with only height and no child/background produces a blank Preview tab, which can look broken. Add a small child so the live preview has visible output.

Suggested update
 export const sizedBoxPreviewJson = {
   "type": "sizedBox",
-  "height": 25
+  "width": 160,
+  "height": 40,
+  "child": {
+    "type": "center",
+    "child": {
+      "type": "text",
+      "data": "SizedBox"
+    }
+  }
 };
-StacSizedBox(height: 25)
+StacSizedBox(
+  width: 160,
+  height: 40,
+  child: StacCenter(
+    child: StacText(data: 'SizedBox'),
+  ),
+)
 {
   "type": "sizedBox",
-  "height": 25
+  "width": 160,
+  "height": 40,
+  "child": {
+    "type": "center",
+    "child": {
+      "type": "text",
+      "data": "SizedBox"
+    }
+  }
 }

Also applies to: 30-41

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sized_box.mdx` around lines 8 - 12, sizedBoxPreviewJson
currently specifies only "type":"sizedBox" and "height":25 which renders blank;
update sizedBoxPreviewJson to include a simple child (e.g., a small
container/box or text element with a background color) so the Preview tab shows
visible output, and make the analogous change to the other sizedBox preview
definitions referenced (lines 30-41) so they also include a visible child;
retain sizedBoxPreviewSrc/PLAYGROUND_BASE_URL as-is.

Comment on lines +8 to +30
export const sliverToBoxAdapterPreviewJson = {
"type": "sliverPadding",
"padding": 16,
"sliver": {
"type": "sliverToBoxAdapter",
"child": {
"type": "container",
"height": 150,
"color": "#4CAF50",
"child": {
"type": "center",
"child": {
"type": "text",
"data": "I am a Box inside a SliverToBoxAdapter!",
"style": {
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}
}
}
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check whether the preview renderer already wraps root sliver payloads in a viewport.
# Expected: If no automatic sliver-root wrapper exists, sliver preview payloads should be wrapped in the MDX preview JSON.
rg -n -C3 'stac-preview-json|CustomScrollView|customScrollView|sliverToBoxAdapter|SliverToBoxAdapter'

Repository: StacDev/stac

Length of output: 50371


🏁 Script executed:

#!/bin/bash
# Check other sliver widget docs to see if they wrap slivers
fd -e mdx docs/widgets/sliver | head -20

Repository: StacDev/stac

Length of output: 38


🏁 Script executed:

#!/bin/bash
# Look for playground renderer or iframe postMessage handler
rg -l 'postMessage|iframe|stac-preview-json' docs/ --type mdx | head -10

Repository: StacDev/stac

Length of output: 83


🏁 Script executed:

#!/bin/bash
# Check how sliver_visibility and sliver_padding docs handle preview JSON
for file in docs/widgets/sliver_*.mdx; do
  echo "=== $file ==="
  head -35 "$file" | grep -A 30 'export const'
done

Repository: StacDev/stac

Length of output: 7101


Wrap the preview payload in customScrollView to match other sliver widget docs.

All other sliver widget documentation (sliver_padding.mdx, sliver_opacity.mdx, sliver_safe_area.mdx, sliver_visibility.mdx, etc.) wrap their preview JSON in scaffold > body > customScrollView > slivers. The sliverToBoxAdapterPreviewJson should follow the same pattern since slivers require a viewport context to render.

🛠️ Proposed fix
 export const sliverToBoxAdapterPreviewJson = {
+  "type": "scaffold",
+  "body": {
+    "type": "customScrollView",
+    "slivers": [
+      {
-  "type": "sliverPadding",
-  "padding": 16,
-  "sliver": {
-    "type": "sliverToBoxAdapter",
+        "type": "sliverPadding",
+        "padding": 16,
+        "sliver": {
+          "type": "sliverToBoxAdapter",
-    "child": {
-      "type": "container",
-      "height": 150,
-      "color": "#4CAF50",
-      "child": {
-        "type": "center",
-        "child": {
-          "type": "text",
-          "data": "I am a Box inside a SliverToBoxAdapter!",
-          "style": {
-            "color": "#FFFFFF",
-            "fontWeight": "bold"
+          "child": {
+            "type": "container",
+            "height": 150,
+            "color": "#4CAF50",
+            "child": {
+              "type": "center",
+              "child": {
+                "type": "text",
+                "data": "I am a Box inside a SliverToBoxAdapter!",
+                "style": {
+                  "color": "#FFFFFF",
+                  "fontWeight": "bold"
+                }
+              }
+            }
           }
         }
       }
-    }
-  }
+      }
+    ]
+  }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const sliverToBoxAdapterPreviewJson = {
"type": "sliverPadding",
"padding": 16,
"sliver": {
"type": "sliverToBoxAdapter",
"child": {
"type": "container",
"height": 150,
"color": "#4CAF50",
"child": {
"type": "center",
"child": {
"type": "text",
"data": "I am a Box inside a SliverToBoxAdapter!",
"style": {
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}
}
}
};
export const sliverToBoxAdapterPreviewJson = {
"type": "scaffold",
"body": {
"type": "customScrollView",
"slivers": [
{
"type": "sliverPadding",
"padding": 16,
"sliver": {
"type": "sliverToBoxAdapter",
"child": {
"type": "container",
"height": 150,
"color": "#4CAF50",
"child": {
"type": "center",
"child": {
"type": "text",
"data": "I am a Box inside a SliverToBoxAdapter!",
"style": {
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}
}
}
}
]
}
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_to_box_adapter.mdx` around lines 8 - 30, The preview JSON
for sliverToBoxAdapter is not wrapped in a CustomScrollView scaffold context;
update sliverToBoxAdapterPreviewJson so its root follows the same structure as
other sliver docs by nesting the current payload under the path scaffold > body
> customScrollView > slivers (i.e., move the existing
sliverPadding/sliverToBoxAdapter object into a slivers array inside a
customScrollView body of a scaffold) so the sliver has the proper viewport
context for rendering.

- Refactored multiple widget documentation files to adopt a consistent scaffold structure for JSON representations.
- Updated examples for Align, Positioned, SliverAppBar, SliverFillRemaining, SliverGrid, SliverOpacity, SliverPadding, SliverSafeArea, and SliverVisibility to enhance clarity and usability.
- Adjusted the PLAYGROUND_BASE_URL for better accessibility in examples.
- Updated the JSON representation of the Align widget to include a Scaffold wrapper for better layout context.
- Adjusted the Dart code examples to reflect the new structure and improved alignment properties.
- Enhanced the documentation to clarify the usage of StacAlignmentDirectional for child alignment.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/widgets/sliver_grid.mdx (1)

119-176: ⚠️ Potential issue | 🟡 Minor

Wrap the Dart example in scroll-view context to match the documented constraint.

Line 110 says sliverGrid must be inside customScrollView, but the Dart snippet on Lines 120-175 shows StacSliverGrid standalone. This makes the copy/paste example inconsistent with the JSON/Preview payloads.

🛠️ Suggested documentation fix
-const StacSliverGrid(
-  crossAxisCount: 2,
-  mainAxisSpacing: 16,
-  crossAxisSpacing: 16,
-  childAspectRatio: 1,
-  children: [
-    ...
-  ],
-)
+StacScaffold(
+  body: StacCustomScrollView(
+    slivers: [
+      const StacSliverGrid(
+        crossAxisCount: 2,
+        mainAxisSpacing: 16,
+        crossAxisSpacing: 16,
+        childAspectRatio: 1,
+        children: [
+          ...
+        ],
+      ),
+    ],
+  ),
+)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/sliver_grid.mdx` around lines 119 - 176, The example shows
StacSliverGrid used standalone but must be nested inside a customScrollView per
the docs; update the snippet so StacSliverGrid is wrapped by the
customScrollView widget (e.g., place StacSliverGrid inside the children/slivers
of customScrollView) so the example matches the documented constraint and the
JSON/Preview payloads; keep the existing StacSliverGrid, children, and spacing
values unchanged—only add the surrounding customScrollView wrapper.
♻️ Duplicate comments (1)
docs/widgets/align.mdx (1)

8-33: ⚠️ Potential issue | 🟡 Minor

Keep alignPreviewJson synchronized with the Dart/JSON examples.

alignPreviewJson currently diverges from the examples: Line 12 adds outer "alignment": "topEnd" that the tabs don’t show, and the preview payload omits the appBar present on Lines 87-93. This makes the Preview tab demonstrate a different configuration.

🛠️ Suggested consistency patch
 export const alignPreviewJson = {
   "type": "scaffold",
+  "appBar": {
+    "type": "appBar",
+    "title": {
+      "type": "text",
+      "data": "Align"
+    }
+  },
   "body": {
     "type": "align",
-    "alignment": "topEnd",
     "child": {
       "type": "container",
       "color": "#FC5632",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/align.mdx` around lines 8 - 33, alignPreviewJson diverges from
the Dart/JSON examples: remove the extra outer "alignment": "topEnd" from the
top-level body and add the same appBar object used in the examples to the
preview payload's body so the Preview tab matches the Dart/JSON tabs; update the
alignPreviewJson object (and keep alignPreviewSrc as-is) to mirror the examples'
structure exactly, referencing the alignPreviewJson symbol to locate the change.
🧹 Nitpick comments (1)
docs/widgets/ink_well.mdx (1)

146-163: Consider extracting the iframe postMessage retry block into a helper.

The retry/onLoad block is repeated across widget docs; a small shared helper (or local function) would reduce drift and simplify future updates.

♻️ Example local extraction (same file)
+const postPreviewJsonToIframe = (iframe, payload) => {
+  const targetOrigin = PLAYGROUND_BASE_URL;
+  const message = { type: "stac-preview-json", payload };
+  let attempts = 0;
+  const maxAttempts = 12;
+  const interval = setInterval(() => {
+    iframe.contentWindow?.postMessage(message, targetOrigin);
+    attempts += 1;
+    if (attempts >= maxAttempts) clearInterval(interval);
+  }, 250);
+};

 ...
-        onLoad={(event) => {
-          const iframe = event.currentTarget;
-          const targetOrigin = PLAYGROUND_BASE_URL;
-          const message = {
-            type: "stac-preview-json",
-            payload: inkWellPreviewJson
-          };
-
-          let attempts = 0;
-          const maxAttempts = 12;
-          const interval = setInterval(() => {
-            iframe.contentWindow?.postMessage(message, targetOrigin);
-            attempts += 1;
-
-            if (attempts >= maxAttempts) {
-              clearInterval(interval);
-            }
-          }, 250);
-        }}
+        onLoad={(event) => {
+          postPreviewJsonToIframe(event.currentTarget, inkWellPreviewJson);
+        }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/widgets/ink_well.mdx` around lines 146 - 163, Extract the repeated
postMessage retry logic into a reusable helper function (e.g.,
sendPostMessageWithRetries) that accepts the iframe element (or its
contentWindow), the message object, targetOrigin, maxAttempts (default 12) and
delayMs (default 250); implement the same behavior (postMessage, increment
attempts, clearInterval when reaching max) and replace the inline onLoad block
in ink_well.mdx by calling this helper from the onLoad handler so the file only
constructs message/targetOrigin and invokes sendPostMessageWithRetries(iframe,
message, targetOrigin).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@docs/widgets/sliver_grid.mdx`:
- Around line 119-176: The example shows StacSliverGrid used standalone but must
be nested inside a customScrollView per the docs; update the snippet so
StacSliverGrid is wrapped by the customScrollView widget (e.g., place
StacSliverGrid inside the children/slivers of customScrollView) so the example
matches the documented constraint and the JSON/Preview payloads; keep the
existing StacSliverGrid, children, and spacing values unchanged—only add the
surrounding customScrollView wrapper.

---

Duplicate comments:
In `@docs/widgets/align.mdx`:
- Around line 8-33: alignPreviewJson diverges from the Dart/JSON examples:
remove the extra outer "alignment": "topEnd" from the top-level body and add the
same appBar object used in the examples to the preview payload's body so the
Preview tab matches the Dart/JSON tabs; update the alignPreviewJson object (and
keep alignPreviewSrc as-is) to mirror the examples' structure exactly,
referencing the alignPreviewJson symbol to locate the change.

---

Nitpick comments:
In `@docs/widgets/ink_well.mdx`:
- Around line 146-163: Extract the repeated postMessage retry logic into a
reusable helper function (e.g., sendPostMessageWithRetries) that accepts the
iframe element (or its contentWindow), the message object, targetOrigin,
maxAttempts (default 12) and delayMs (default 250); implement the same behavior
(postMessage, increment attempts, clearInterval when reaching max) and replace
the inline onLoad block in ink_well.mdx by calling this helper from the onLoad
handler so the file only constructs message/targetOrigin and invokes
sendPostMessageWithRetries(iframe, message, targetOrigin).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e000bd22-4136-4d98-9521-1e7c2255d796

📥 Commits

Reviewing files that changed from the base of the PR and between 847466d and 35d741a.

📒 Files selected for processing (11)
  • docs/snippets/playground_base.mdx
  • docs/widgets/align.mdx
  • docs/widgets/ink_well.mdx
  • docs/widgets/positioned.mdx
  • docs/widgets/sliver_app_bar.mdx
  • docs/widgets/sliver_fill_remaining.mdx
  • docs/widgets/sliver_grid.mdx
  • docs/widgets/sliver_opacity.mdx
  • docs/widgets/sliver_padding.mdx
  • docs/widgets/sliver_safe_area.mdx
  • docs/widgets/sliver_visibility.mdx
🚧 Files skipped from review as they are similar to previous changes (7)
  • docs/snippets/playground_base.mdx
  • docs/widgets/positioned.mdx
  • docs/widgets/sliver_fill_remaining.mdx
  • docs/widgets/sliver_padding.mdx
  • docs/widgets/sliver_safe_area.mdx
  • docs/widgets/sliver_visibility.mdx
  • docs/widgets/sliver_opacity.mdx

- Updated the SliverGrid documentation to adopt a consistent structure, including a customScrollView wrapper.
- Simplified the JSON representation and Dart code examples for both SliverGrid and Align widgets.
- Enhanced clarity in the documentation to improve usability and understanding of widget properties.
@divyanshub024 divyanshub024 merged commit c806ed6 into dev Apr 28, 2026
6 checks passed
@divyanshub024 divyanshub024 deleted the mn/docs-preview branch April 28, 2026 16:52
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.

2 participants