Skip to content

feat: port GDPR/Cookie components from Nexus to be used on Docs page#4

Open
sburton84 wants to merge 25 commits intomainfrom
gdpr
Open

feat: port GDPR/Cookie components from Nexus to be used on Docs page#4
sburton84 wants to merge 25 commits intomainfrom
gdpr

Conversation

@sburton84
Copy link
Copy Markdown
Collaborator

@sburton84 sburton84 commented Mar 30, 2026

Also:

  • set up vitest so the corresponding tests can be executed
  • update TypeScript to v5 consistent with Nexus and other docs sites
  • update Node to 22 consistent with Nexus (also because semantic-release has dropped support for Node 20)
  • add ESLint linting and fix various linter errors

stavros-tomas and others added 10 commits November 12, 2025 15:21
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.
@sburton84 sburton84 marked this pull request as ready for review April 1, 2026 13:02
@sburton84 sburton84 requested a review from irfankhan10 April 1, 2026 13:02
@sburton84 sburton84 changed the title Port GDPR/Cookie components from Nexus to be used on Docs page feat: port GDPR/Cookie components from Nexus to be used on Docs page Apr 1, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 tsup with tsdown for Sphinx UI script builds and inject cookie-consent + conditional GA loading into injectNav.
  • Add GDPR cookie-consent components/services (banner, settings dialog/button, provider, cookie utils) to documentation-ui and 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.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

Comment on lines +1 to +17
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 }
)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines 36 to 43
"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"
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +22
vi.mock('app/(dashboard)/_root_layout/Features', () => ({
useFeaturesQuery: vi.fn(() => ({
data: {
cookies_consent_manager: {
enabled: true,
version: 1,
},
},
})),
}))

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
vi.mock('app/(dashboard)/_root_layout/Features', () => ({
useFeaturesQuery: vi.fn(() => ({
data: {
cookies_consent_manager: {
enabled: true,
version: 1,
},
},
})),
}))

Copilot uses AI. Check for mistakes.
>
<article>
<header className="px-1 mb-5">
<h2 className="text-lg font-semibold mb-1.5">Manage Cookies Settings</h2>
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
<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>

Copilot uses AI. Check for mistakes.
Comment thread documentation-ui/src/custom/docs/components/gdpr/README.md
Comment on lines +54 to +60
export function Layout({ children }) {
return (
<CookieConsentProvider>
<AppComponents />
{children}
</CookieConsentProvider>
)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

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).

Copilot uses AI. Check for mistakes.
Comment on lines +5 to 8
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) => {

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

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).

Copilot uses AI. Check for mistakes.
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.

5 participants