feat(web,cms): add quiz-button section component#443
feat(web,cms): add quiz-button section component#443Kneesal merged 16 commits intoJesusFilm:mainfrom
Conversation
Add quiz-button component with buttonText and iframeSrc attributes. Register it in the section content dynamic zone and update the GraphQL schema with the new type and union memberships. Made-with: Cursor
Create the QuizButton component with animated gradient button that opens a fullscreen modal with an embedded iframe. Wire the GraphQL fragment, register in section renderer, and add mesh gradient keyframe animation to globals.css. Made-with: Cursor
Seed the quiz button as the last block in the first section of the first experience on CMS bootstrap, with idempotency check. Made-with: Cursor
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
WalkthroughThis PR introduces a new quiz-button section component across the CMS and web platforms. It includes CMS schema definitions, a web React component with modal functionality, GraphQL type definitions, mesh-gradient styling, and integration into the section renderer and content query system. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
Remove standalone seed file and bootstrap hook. Add quiz button block to the first section in both seed-easter.cjs and seed-easter.mjs instead. Made-with: Cursor
Keep quiz-button seed only in the web seed script. Made-with: Cursor
Keep quiz-button seed only in apps/cms/scripts/seed-easter.cjs. Made-with: Cursor
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/cms/src/components/sections/quiz-button.json`:
- Around line 14-16: The iframeSrc schema currently allows any string; constrain
it at the CMS boundary by adding a pattern (and optionally format) validation to
the iframeSrc property in quiz-button.json so editors can only save approved
quiz origins—for example update the "iframeSrc" field (type "string", required
true) to include a "pattern" regex that matches your allowed origin(s) (e.g.,
the production quiz host and any subpaths) and/or "format": "uri" to enforce
valid URLs; ensure the pattern covers the exact hostname(s) and protocol you
trust so arbitrary remote embeds are rejected.
In `@apps/web/src/components/sections/QuizButton.tsx`:
- Around line 64-85: The modal is not keyboard accessible: remove the backdrop's
role="button" and tabIndex to stop it being focusable, ensure the dialog moves
focus into itself on open and returns focus to the triggering element on close
(capture the trigger via a ref), add a keydown handler on the dialog wrapper to
close on Escape (call onClose), and implement focus trapping while open (or
replace this implementation with the shared Dialog primitive used elsewhere).
Update the elements referenced in QuizButton.tsx (the backdrop div with
onClick/onKeyDown, the outer div with aria-modal, and the close button/onClose
handler) to enforce initial focus, focus return, Escape-to-close, and focus
trap.
- Around line 100-104: The iframe in the QuizButton component renders
third-party content via iframeSrc from quiz-button-section; tighten its
privileges by adding a restrictive sandbox attribute (e.g., empty sandbox or
minimal tokens only if needed such as "allow-scripts" if the embed requires
scripts) and set a strict referrerPolicy like "no-referrer" (or
"strict-origin-when-cross-origin") to avoid leaking referrer info; update the
<iframe> in QuizButton.tsx to include sandbox and referrerPolicy attributes
while keeping the existing title and className, and document any minimal sandbox
tokens chosen so future changes know why they were allowed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 33145d74-ebde-4c88-b9eb-60e0a3e97f56
📒 Files selected for processing (12)
apps/cms/schema.graphqlapps/cms/scripts/seed-easter.cjsapps/cms/src/components/sections/quiz-button.jsonapps/cms/src/components/sections/section.jsonapps/web/src/app/globals.cssapps/web/src/components/sections/QuizButton.tsxapps/web/src/components/sections/Section.tsxapps/web/src/lib/fragments/index.tsapps/web/src/lib/fragments/quiz-button-section.tsapps/web/src/lib/fragments/section.tspackages/graphql/src/graphql-env.d.tsscripts/seed-easter.mjs
Add null guard in determineDepth to prevent TypeError when traversing fragment spreads that resolve to undefined nodes in dynamic zone union queries. Made-with: Cursor
This reverts commit 3be3903.
graphql-depth-limit@1.1.0 crashes on fragment spreads within dynamic-zone unions. Disable depth limiting in the Strapi GraphQL plugin config until upstream is fixed. Made-with: Cursor
Add quizButtonSectionFragment to the GET_WATCH_EXPERIENCE query's fragment array so the definition is included in the document sent to Strapi. Set depthLimit to 100 to work around graphql-depth-limit crash on dynamic-zone fragment traversal. Made-with: Cursor
The separate QuizButtonSection fragment wasn't being composed into the final GraphQL document by gql.tada. Inline the fields directly in the section fragment, matching the pattern used by containerFragment. Made-with: Cursor
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/cms/config/plugins.ts`:
- Around line 56-59: Replace the workaround that sets depthLimit: 100 (which
neutralizes DoS protection) by upgrading `@strapi/plugin-graphql` to a version
that uses a maintained depth limiter; if the upgraded plugin still depends on
graphql-depth-limit, replace that dependency with `@graphile/depth-limit` and
update the GraphQL plugin configuration to use the new limiter; finally lower
the depthLimit value in the plugin config (the depthLimit setting) to a
reasonable value such as 10–15 and run tests/fragment/union queries to verify
fragment spreads no longer crash the traversal.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ac2be4a6-a488-4cc3-8129-3efe0e466af0
📒 Files selected for processing (2)
apps/cms/config/plugins.tsapps/web/src/lib/content.ts
Restore bg-blend-multiply, hover:bg-orange-500, cursor-pointer on inner div, plain transition on arrow span, and remove extra classes that weren't in the original. Made-with: Cursor
The modal was constrained to the section because a parent element's CSS transform created a new containing block for fixed positioning. Using createPortal to render at document.body bypasses this. Also adds Escape key handling and body scroll lock while open. Made-with: Cursor
The previous custom modal used position:fixed inside a section with backdrop-blur, which creates a containing block and traps the modal within the section. Switch to shadcn Dialog (renders via Portal at document root) with fullscreen styles matching the original component. Made-with: Cursor
Adds the quiz-button block as the last item in the first section's content array so it renders at the bottom of the section. Made-with: Cursor
- Constrain iframeSrc to approved nextstep.is origin via regex - Sandbox iframe with allow-forms/scripts/same-origin - Add strict-origin-when-cross-origin referrer policy Made-with: Cursor
Review feedback addressed (f43edb1)Fixed:
Not changed:
|
Summary
quiz-buttonCMS component schema withbuttonTextandiframeSrcattributes, registered in the section content dynamic zoneQuizButtonweb component with animated mesh gradient button that opens a fullscreen modal with embedded iframeContracts Changed
apps/cms/schema.graphql—ComponentSectionsQuizButtontype added toSectionContentDynamicZoneandGenericMorphunionsRegeneration Required
packages/graphql/src/graphql-env.d.tsregenerated viagql-tada generate outputValidation
Resolves #442
Made with Cursor
Summary by CodeRabbit