Conversation
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ariana Hlavaty <ariana.hlavaty@quantinuum.com> Co-authored-by: Vanya Eccles <89389514+vanyae-cqc@users.noreply.github.com> Co-authored-by: Aidan <104831665+aidanCQ@users.noreply.github.com>
Provide cookie version statically at build-time.
semantic-release has dropped support for Node 20
Also fix path to favicon
There was a problem hiding this comment.
Pull request overview
Ports GDPR/cookie-consent UI + services from Nexus into documentation-ui and integrates them into the Sphinx docs navbar injection, alongside build/tooling updates (Vitest, ESLint, TS/Node version alignment).
Changes:
- Replace
tsupwithtsdownfor Sphinx UI script builds and inject cookie-consent + conditional GA loading intoinjectNav. - Add GDPR cookie-consent components/services (banner, settings dialog/button, provider, cookie utils) to
documentation-uiand wire up Vitest + test setup. - Update build/lint/tooling: Node 22 in workflows, TS config adjustments, Rollup terser plugin swap, ESLint/Biome configs, and refreshed generated CSS/assets.
Reviewed changes
Copilot reviewed 63 out of 69 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| sphinx-ui/react/tsup.config.ts | Removes old tsup build configuration. |
| sphinx-ui/react/tsdown.config.ts | Adds tsdown build config and defines __NEXT_PUBLIC_GA_ID__ for IIFE bundles. |
| sphinx-ui/react/tailwind.config.ts | Minor formatting adjustment. |
| sphinx-ui/react/src/syncTheme.ts | Switches theme sync helpers import to @quantinuum/documentation-ui. |
| sphinx-ui/react/src/injectNav.tsx | Wraps navbar in cookie-consent provider/manager and conditionally injects Google Analytics. |
| sphinx-ui/react/src/globals.d.ts | Declares __NEXT_PUBLIC_GA_ID__ global constant. |
| sphinx-ui/react/package.json | Switches build script to tsdown and updates deps (incl. @next/third-parties). |
| sphinx-ui/quantinuum_sphinx/static/syncTheme.iife.js | Adds new built IIFE theme sync artifact. |
| sphinx-ui/quantinuum_sphinx/static/syncTheme.global.js | Removes old built theme sync artifact. |
| sphinx-ui/quantinuum_sphinx/static/styles/quantinuum-ui-tokens.css | Updates design tokens to match updated UI package output. |
| sphinx-ui/quantinuum_sphinx/static/styles/quantinuum-ui-tailwind.css | Updates generated Tailwind CSS output for Sphinx UI. |
| sphinx-ui/quantinuum_sphinx/page.html | Updates favicon path to _static/assets/. |
| sphinx-ui/quantinuum_sphinx/init.py | Loads injectNav.iife.js / syncTheme.iife.js instead of *.global.js. |
| sphinx-ui/build-dist.sh | Copies new *.iife.js build outputs into Sphinx theme static folder. |
| sphinx-ui/build-demo.sh | Adds demo build helper script to regenerate assets + build Sphinx demo HTML. |
| documentation-ui/vitest.config.mjs | Adds Vitest configuration for jsdom-based component/unit tests. |
| documentation-ui/tsconfig.json | Updates TS settings for Vitest globals, bundler resolution, and path aliases. |
| documentation-ui/stories/custom/theme-selector.stories.tsx | Updates story imports after extracting useTheme. |
| documentation-ui/src/utils/darkMode.ts | Simplifies Mode typing. |
| documentation-ui/src/index.ts | Re-exports new useTheme hook. |
| documentation-ui/src/custom/use-theme.ts | Adds standalone useTheme hook. |
| documentation-ui/src/custom/theme-selector.tsx | Refactors ThemeSelector to consume extracted useTheme type. |
| documentation-ui/src/custom/docs/scripts/nav/index.tsx | Removes unused React import. |
| documentation-ui/src/custom/docs/index.ts | Exposes GDPR exports via docs package entrypoint. |
| documentation-ui/src/custom/docs/components/triplecard/index.tsx | Removes Next/Zod coupling; introduces framework-agnostic typing for image/link components. |
| documentation-ui/src/custom/docs/components/triplecard/Card.tsx | Fixes incorrect prop typing (HTMLAttributes vs InputHTMLAttributes). |
| documentation-ui/src/custom/docs/components/page/index.tsx | Fixes incorrect prop typing for DocsPageLayout. |
| documentation-ui/src/custom/docs/components/navmenu/NavigationMenu.tsx | Removes unused helper function. |
| documentation-ui/src/custom/docs/components/logos/SystemsLogo.tsx | Spreads incoming SVG props onto <svg>. |
| documentation-ui/src/custom/docs/components/header/index.tsx | Fixes incorrect prop typing across header components. |
| documentation-ui/src/custom/docs/components/gdpr/utils/cookies.ts | Adds cookie serialization/deserialization utilities. |
| documentation-ui/src/custom/docs/components/gdpr/utils/cookies.test.ts | Adds unit tests for cookie utilities. |
| documentation-ui/src/custom/docs/components/gdpr/types.ts | Adds GDPR/cookie-consent types/enums. |
| documentation-ui/src/custom/docs/components/gdpr/service/cookie-consent-service.ts | Adds cookie-consent persistence + validation logic (Zod). |
| documentation-ui/src/custom/docs/components/gdpr/service/cookie-consent-service.test.ts | Adds tests for cookie-consent service behavior. |
| documentation-ui/src/custom/docs/components/gdpr/README.md | Adds GDPR component documentation and usage notes. |
| documentation-ui/src/custom/docs/components/gdpr/index.ts | Exposes GDPR components/contexts/types from module entrypoint. |
| documentation-ui/src/custom/docs/components/gdpr/cookies-consent.config.ts | Adds consent cookie configuration and category definitions. |
| documentation-ui/src/custom/docs/components/gdpr/contexts/useCookieConsent.ts | Adds hook for consuming consent context. |
| documentation-ui/src/custom/docs/components/gdpr/contexts/index.ts | Exports GDPR context utilities. |
| documentation-ui/src/custom/docs/components/gdpr/contexts/CookieConsentShared.ts | Defines consent context shape and creates context. |
| documentation-ui/src/custom/docs/components/gdpr/contexts/CookieConsentContext.tsx | Implements provider with reducer-backed state and cookie persistence integration. |
| documentation-ui/src/custom/docs/components/gdpr/contexts/CookieConsentContext.test.tsx | Adds hook/provider tests for consent context behavior. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsDialog/CookieSettingsDialog.tsx | Adds settings dialog UI (react-hook-form + Quantinuum UI components). |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsDialog/CookieSettingsDialog.test.tsx | Adds snapshot test for settings dialog. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsDialog/snapshots/CookieSettingsDialog.test.tsx.snap | Adds stored snapshot for settings dialog. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsDialog/snapshots/CookiePreferencesDialog.test.tsx.snap | Adds an additional snapshot file (appears unrelated to any test file). |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsButton/CookieSettingsButton.tsx | Adds persistent “Cookie Settings” floating button component. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsButton/CookieSettingsButton.test.tsx | Adds snapshot + click behavior tests for settings button. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieSettingsButton/snapshots/CookieSettingsButton.test.tsx.snap | Adds stored snapshot for settings button. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieConsentManager/index.ts | Adds export barrel for consent manager. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieConsentManager/CookieConsentManager.tsx | Adds runtime manager that switches between banner/dialog/button based on consent state. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieConsentManager/CookieConsentManager.test.tsx | Adds tests for consent manager view switching. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieConditional/index.ts | Adds export barrel for conditional wrapper. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieConditional/CookieConditional.tsx | Adds wrapper to conditionally render children based on category consent. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieBanner/CookieBanner.tsx | Adds cookie banner UI. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieBanner/CookieBanner.test.tsx | Adds snapshot tests for cookie banner. |
| documentation-ui/src/custom/docs/components/gdpr/_components/CookieBanner/snapshots/CookieBanner.test.tsx.snap | Adds stored snapshot for cookie banner. |
| documentation-ui/setupTest.ts | Adds Vitest global test setup (PointerEvent/ResizeObserver/matchMedia mocks + fake timers). |
| documentation-ui/rollup.config.js | Switches terser plugin and deduplicates “use client” warning suppression. |
| documentation-ui/package.json | Adds eslint/biome/vitest scripts + deps; updates Rollup ecosystem and UI dependency versions. |
| documentation-ui/eslint.config.js | Adds ESLint flat config for TS/React hooks/refresh. |
| documentation-ui/biome.json | Adds Biome formatter configuration. |
| .github/workflows/release.yml | Updates Node version to 22 and sets GA env during Sphinx asset generation. |
| .github/workflows/pre-release.yml | Updates Node version to 22 and renames job key. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 64 out of 70 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import dynamic from 'next/dynamic' | ||
| import { CookieSettingsButton } from 'src/custom/docs/components/gdpr/_components/CookieSettingsButton/CookieSettingsButton' | ||
| import { CookieSettingsDialog } from 'src/custom/docs/components/gdpr/_components/CookieSettingsDialog/CookieSettingsDialog' | ||
| import { useCookieConsent } from 'src/custom/docs/components/gdpr/contexts/useCookieConsent' | ||
|
|
||
| type CookieBannerProps = { | ||
| isOpen: boolean | ||
| onAccept(): void | ||
| onReject(): void | ||
| onSettings(): void | ||
| } | ||
|
|
||
| const CookieBanner = dynamic<CookieBannerProps>( | ||
| () => | ||
| import('src/custom/docs/components/gdpr/_components/CookieBanner/CookieBanner').then((module) => module.CookieBanner), | ||
| { ssr: false } | ||
| ) |
There was a problem hiding this comment.
CookieConsentManager imports next/dynamic, which makes this component (and any consumer importing it) require next at runtime. This breaks the Sphinx injectNav bundle (which consumes CookieConsentManager) because sphinx-ui/react does not depend on next, and tsdown will try to resolve it during bundling. Consider removing the Next-specific dynamic() usage here (use a normal import or React.lazy), or ensure next is installed wherever this component is bundled.
| "dependencies": { | ||
| "@quantinuum/documentation-ui": "file:../..", | ||
| "@next/third-parties": "^16.2.2", | ||
| "@quantinuum/documentation-ui": "file:../../documentation-ui", | ||
| "@quantinuum/quantinuum-ui": "^3.6.1", | ||
| "baseline-browser-mapping": "^2.10.13", | ||
| "caniuse-lite": "^1.0.30001784", | ||
| "react": "^18.3.1" | ||
| } |
There was a problem hiding this comment.
This package bundles code from @quantinuum/documentation-ui, and injectNav.tsx imports CookieConsentManager which currently depends on next/dynamic. Since next is not listed in this package's dependencies, the tsdown build is likely to fail with a missing next/* module. Either add next here (so bundling succeeds) or refactor CookieConsentManager to avoid next so this bundle can remain framework-agnostic.
| vi.mock('app/(dashboard)/_root_layout/Features', () => ({ | ||
| useFeaturesQuery: vi.fn(() => ({ | ||
| data: { | ||
| cookies_consent_manager: { | ||
| enabled: true, | ||
| version: 1, | ||
| }, | ||
| }, | ||
| })), | ||
| })) | ||
|
|
There was a problem hiding this comment.
This test mocks app/(dashboard)/_root_layout/Features, but that module path does not exist anywhere in this repository. In Vitest, mocking a non-existent module can fail unless it is marked as a virtual module. Either remove this unused mock, or add the appropriate virtual: true option so the test suite doesn't depend on external/absent app code.
| vi.mock('app/(dashboard)/_root_layout/Features', () => ({ | |
| useFeaturesQuery: vi.fn(() => ({ | |
| data: { | |
| cookies_consent_manager: { | |
| enabled: true, | |
| version: 1, | |
| }, | |
| }, | |
| })), | |
| })) |
| > | ||
| <article> | ||
| <header className="px-1 mb-5"> | ||
| <h2 className="text-lg font-semibold mb-1.5">Manage Cookies Settings</h2> |
There was a problem hiding this comment.
DialogContent sets aria-labelledby="cookies-settings", but there is no element in the dialog with id="cookies-settings" (the <h2> has no id). This leaves the dialog with a broken accessible name reference. Either add the matching id to the heading (and rely on aria-labelledby), or remove aria-labelledby and keep only aria-label.
| <h2 className="text-lg font-semibold mb-1.5">Manage Cookies Settings</h2> | |
| <h2 id="cookies-settings" className="text-lg font-semibold mb-1.5"> | |
| Manage Cookies Settings | |
| </h2> |
| export function Layout({ children }) { | ||
| return ( | ||
| <CookieConsentProvider> | ||
| <AppComponents /> | ||
| {children} | ||
| </CookieConsentProvider> | ||
| ) |
There was a problem hiding this comment.
The usage example shows <CookieConsentProvider> without the required version prop, but CookieConsentProvider is typed to require { version: number }. Update the example so it compiles and reflects the intended integration (e.g., pass the configured consent version).
| import { type useTheme } from './use-theme' | ||
|
|
||
| export const useTheme = () => { | ||
| const [theme, _setLocalTheme] = React.useState(typeof window !== "undefined" ? getTheme() : {mode: 'dark' as const, isDark: true}); | ||
|
|
||
| React.useEffect(() => { | ||
| subscribeToTheme((theme) => _setLocalTheme(theme)) | ||
| }, []) | ||
| return { theme, setMode: (_mode: typeof theme['mode']) => setTheme(_mode) } | ||
| } | ||
|
|
||
| export const ThemeSelector = React.forwardRef<HTMLButtonElement, ReturnType<typeof useTheme>>(({theme, setMode}, ref) => { | ||
| export const ThemeSelector = React.forwardRef<HTMLButtonElement, ReturnType<typeof useTheme>>(({ theme, setMode }, ref) => { | ||
|
|
There was a problem hiding this comment.
useTheme is imported with import { type useTheme } ..., but the component then uses it in ReturnType<typeof useTheme>. The typeof type query requires a value import; with a type-only import this will fail TypeScript compilation. Import useTheme as a value (or export a dedicated props/type from use-theme and reference that instead).
Also: