@chassis-ui/docs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +98 -0
  2. package/index.ts +7 -0
  3. package/package.json +66 -0
  4. package/src/components/DocsSidebar.astro +89 -0
  5. package/src/components/NavDocsMenu.astro +26 -0
  6. package/src/components/NavLink.astro +24 -0
  7. package/src/components/ResponsiveImage.astro +31 -0
  8. package/src/components/TableOfContents.astro +31 -0
  9. package/src/components/ThemeToggler.astro +70 -0
  10. package/src/components/shortcodes/AddedIn.astro +13 -0
  11. package/src/components/shortcodes/Callout.astro +37 -0
  12. package/src/components/shortcodes/CxTable.astro +16 -0
  13. package/src/js/color-modes.js +82 -0
  14. package/src/js/icon-loader.js +220 -0
  15. package/src/js/search.js +58 -0
  16. package/src/js/sidebar.js +30 -0
  17. package/src/js/theme-color.js +126 -0
  18. package/src/layouts/BaseLayout.astro +94 -0
  19. package/src/layouts/DocsLayout.astro +147 -0
  20. package/src/layouts/IconsLayout.astro +19 -0
  21. package/src/layouts/RedirectLayout.astro +23 -0
  22. package/src/layouts/SingleLayout.astro +33 -0
  23. package/src/layouts/footer/Footer.astro +56 -0
  24. package/src/layouts/footer/Scripts.astro +22 -0
  25. package/src/layouts/head/Analytics.astro +22 -0
  26. package/src/layouts/head/Favicons.astro +11 -0
  27. package/src/layouts/head/Head.astro +54 -0
  28. package/src/layouts/head/Scss.astro +9 -0
  29. package/src/layouts/head/Social.astro +38 -0
  30. package/src/layouts/head/Stylesheet.astro +15 -0
  31. package/src/layouts/header/Header.astro +19 -0
  32. package/src/layouts/header/Navigation.astro +121 -0
  33. package/src/layouts/header/Skippy.astro +22 -0
  34. package/src/libs/image.ts +13 -0
  35. package/src/libs/layout.ts +7 -0
  36. package/src/libs/rehype.ts +38 -0
  37. package/src/libs/remark.ts +205 -0
  38. package/src/libs/toc.ts +44 -0
  39. package/src/libs/utils.ts +122 -0
  40. package/src/scss/_anchor.scss +21 -0
  41. package/src/scss/_brand.scss +59 -0
  42. package/src/scss/_buttons.scss +36 -0
  43. package/src/scss/_callouts.scss +40 -0
  44. package/src/scss/_clipboard-js.scss +63 -0
  45. package/src/scss/_code.scss +116 -0
  46. package/src/scss/_colors.scss +140 -0
  47. package/src/scss/_content.scss +141 -0
  48. package/src/scss/_docsearch.scss +174 -0
  49. package/src/scss/_footer.scss +29 -0
  50. package/src/scss/_layout.scss +72 -0
  51. package/src/scss/_masthead.scss +124 -0
  52. package/src/scss/_navbar.scss +138 -0
  53. package/src/scss/_placeholder-img.scss +15 -0
  54. package/src/scss/_scrolling.scss +16 -0
  55. package/src/scss/_settings.scss +37 -0
  56. package/src/scss/_sidebar.scss +161 -0
  57. package/src/scss/_skippy.scss +7 -0
  58. package/src/scss/_syntax.scss +158 -0
  59. package/src/scss/_toc.scss +117 -0
  60. package/src/scss/_variables.scss +78 -0
  61. package/src/scss/fonts.scss +1 -0
  62. package/src/scss/main.scss +90 -0
  63. package/src/scss/search.scss +26 -0
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # @chassis-ui/docs
2
+
3
+ Shared Astro components and layouts for Chassis documentation sites.
4
+
5
+ ## Overview
6
+
7
+ This package provides reusable Astro components, layouts, and utilities specifically designed for building documentation websites within the Chassis UI ecosystem. It includes common documentation patterns, styling helpers, and content processing utilities.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @chassis-ui/docs
13
+ ```
14
+
15
+ or with pnpm:
16
+
17
+ ```bash
18
+ pnpm add @chassis-ui/docs
19
+ ```
20
+
21
+ ## Peer Dependencies
22
+
23
+ This package requires the following peer dependencies:
24
+
25
+ - `@chassis-ui/css`: Chassis CSS framework
26
+ - `@chassis-ui/icons`: Chassis icon library
27
+ - `@chassis-ui/tokens`: Chassis design tokens
28
+ - `astro`: ^4.0.0 || ^5.0.0
29
+
30
+ ## Usage
31
+
32
+ ### Importing Components
33
+
34
+ ```typescript
35
+ // Import layouts
36
+ import Layout from '@chassis-ui/docs/layouts/Layout.astro'
37
+ import DocsLayout from '@chassis-ui/docs/layouts/DocsLayout.astro'
38
+
39
+ // Import components
40
+ import CodeBlock from '@chassis-ui/docs/components/CodeBlock.astro'
41
+ import Callout from '@chassis-ui/docs/components/Callout.astro'
42
+
43
+ // Import utilities
44
+ import { generateTOC } from '@chassis-ui/docs'
45
+ import { processImage } from '@chassis-ui/docs'
46
+ ```
47
+
48
+ ### Available Exports
49
+
50
+ This package exports:
51
+
52
+ - **Layouts**: Pre-built Astro layouts for documentation pages
53
+ - **Components**: Reusable documentation components (code blocks, callouts, navigation, etc.)
54
+ - **Shortcodes**: MDX-compatible shortcode components
55
+ - **Libraries**: Utility functions for content processing, TOC generation, and more
56
+ - **Styles**: SCSS utilities and mixins
57
+ - **Scripts**: Client-side JavaScript utilities
58
+
59
+ ### Directory Structure
60
+
61
+ ```
62
+ src/
63
+ ├── components/ # Astro components
64
+ │ └── shortcodes/ # MDX shortcode components
65
+ ├── layouts/ # Page layouts
66
+ ├── libs/ # Utility libraries
67
+ ├── js/ # Client-side scripts
68
+ └── scss/ # Styling utilities
69
+ ```
70
+
71
+ ## Features
72
+
73
+ - **Content Processing**: Utilities for processing markdown and MDX content
74
+ - **Table of Contents**: Automatic TOC generation from headings
75
+ - **Image Optimization**: Helper functions for responsive images
76
+ - **Syntax Highlighting**: Code block components with syntax highlighting
77
+ - **Navigation**: Responsive documentation navigation components
78
+ - **Search Integration**: Ready-to-use search components
79
+ - **Accessibility**: WCAG-compliant components with proper ARIA attributes
80
+
81
+ ## Development
82
+
83
+ This package is part of the Chassis UI monorepo. For development instructions, see the main repository documentation.
84
+
85
+ ## License
86
+
87
+ MIT © [Chassis UI](https://github.com/chassis-ui)
88
+
89
+ ## Contributing
90
+
91
+ Contributions are welcome! Please read the contributing guidelines in the main repository.
92
+
93
+ ## Links
94
+
95
+ - [Documentation](https://chassis-ui.com/docs)
96
+ - [GitHub Repository](https://github.com/chassis-ui/website)
97
+ - [Issue Tracker](https://github.com/chassis-ui/website/issues)
98
+ - [Chassis UI Website](https://chassis-ui.com)
package/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ // Shared libraries for documentation sites
2
+ export * from './src/libs/image'
3
+ export * from './src/libs/layout'
4
+ export * from './src/libs/rehype'
5
+ export * from './src/libs/remark'
6
+ export * from './src/libs/toc'
7
+ export * from './src/libs/utils'
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@chassis-ui/docs",
3
+ "description": "Shared Astro components and layouts for Chassis documentation sites.",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/chassis-ui/website.git",
9
+ "directory": "packages/docs"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/chassis-ui/website/issues"
13
+ },
14
+ "homepage": "https://chassis-ui.com",
15
+ "author": "Ozgur Gunes <o.gunes@gmail.com>",
16
+ "license": "MIT",
17
+ "keywords": [
18
+ "astro",
19
+ "chassis",
20
+ "documentation",
21
+ "components",
22
+ "layouts",
23
+ "design-system"
24
+ ],
25
+ "files": [
26
+ "src",
27
+ "index.ts",
28
+ "README.md"
29
+ ],
30
+ "main": "index.ts",
31
+ "exports": {
32
+ ".": "./index.ts",
33
+ "./components/*": "./src/components/*",
34
+ "./shortcodes/*": "./src/components/shortcodes/*",
35
+ "./layouts/*": "./src/layouts/*",
36
+ "./libs/*": "./src/libs/*",
37
+ "./js/*": "./src/js/*",
38
+ "./scss/*": "./src/scss/*"
39
+ },
40
+ "peerDependencies": {
41
+ "@chassis-ui/css": "*",
42
+ "@chassis-ui/icons": "*",
43
+ "@chassis-ui/tokens": "*",
44
+ "astro": "^4.0.0 || ^5.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@chassis-ui/css": "github:chassis-ui/css#app/docs",
48
+ "@chassis-ui/icons": "github:chassis-ui/icons#app/docs",
49
+ "@chassis-ui/tokens": "github:chassis-ui/tokens#app/docs",
50
+ "@docsearch/css": "^3.9.0",
51
+ "@docsearch/js": "^3.9.0",
52
+ "@types/hast": "^3.0.4",
53
+ "@types/mdast": "^4.0.4",
54
+ "astro": "^5.13.9",
55
+ "github-slugger": "^2.0.0",
56
+ "image-size": "^2.0.2",
57
+ "mdast-util-from-markdown": "^2.0.2",
58
+ "mdast-util-mdx-jsx": "^3.2.0",
59
+ "mdast-util-to-string": "^4.0.0",
60
+ "remark": "^15.0.1",
61
+ "remark-html": "^16.0.1",
62
+ "unified": "^11.0.5",
63
+ "unist-util-visit": "^5.0.0",
64
+ "zod": "^4.1.11"
65
+ }
66
+ }
@@ -0,0 +1,89 @@
1
+ ---
2
+ import { getData } from '@libs/data'
3
+ import { getConfig } from '@libs/config'
4
+ import { docsPages } from '@libs/content'
5
+ import { getSlug } from '../libs/utils'
6
+
7
+ const sidebar = getData('sidebar')
8
+ ---
9
+
10
+ <nav class="cxd-links w-100" id="cxd-docs-nav" aria-label="Docs navigation">
11
+ <ul class="cxd-links-nav bulletless">
12
+ {
13
+ sidebar.map((group) => {
14
+ const groupSlug = getSlug(group.title)
15
+
16
+ if (group.pages) {
17
+ return (
18
+ <li
19
+ class:list={[
20
+ 'cxd-links-group',
21
+ groupSlug === Astro.params.slug?.split('/')[0] ? 'active' : undefined
22
+ ]}
23
+ >
24
+ <strong class="cxd-links-heading">
25
+ {group.icon && (
26
+ <svg
27
+ class="icon"
28
+ style={group.icon_color && `color: var(--cx-${group.icon_color});`}
29
+ aria-hidden="true"
30
+ >
31
+ <use xlink:href={`#${group.icon}`} />
32
+ </svg>
33
+ )}
34
+ {group.title}
35
+ </strong>
36
+ <ul>
37
+ {group.pages?.map((page) => {
38
+ const docSlug = getSlug(page.title)
39
+ const unversionedPageSlug = `${groupSlug}/${docSlug}`
40
+
41
+ const url = `${getConfig().docsPath}/${unversionedPageSlug}`
42
+ const active = Astro.params.slug === unversionedPageSlug
43
+
44
+ const generatedPage = docsPages.find((page) => page.id === unversionedPageSlug)
45
+
46
+ // This test should not be necessary, see comments for `getSlug()` in `src/libs/utils.ts`.
47
+ if (!generatedPage) {
48
+ throw new Error(
49
+ `The page '${page.title}' referenced in 'packages/websitedata/sidebar.yml' does not exist at '${url}'.`
50
+ )
51
+ }
52
+
53
+ return (
54
+ <li>
55
+ <a
56
+ href={url}
57
+ class:list={['cxd-links-link', { active }]}
58
+ aria-current={active ? 'page' : undefined}
59
+ >
60
+ {page.title}
61
+ </a>
62
+ </li>
63
+ )
64
+ })}
65
+ </ul>
66
+ </li>
67
+ )
68
+ } else {
69
+ const active = Astro.params.slug === groupSlug
70
+
71
+ return (
72
+ <>
73
+ <li class="cxd-links-span-all mt-2xsmall mb-medium mx-large border-top" />
74
+ <li class="cxd-links-span-all">
75
+ <a
76
+ href={`${getConfig().docsPath}/${groupSlug}/`}
77
+ class:list={['cxd-links-link', { active }]}
78
+ aria-current={active ? 'page' : undefined}
79
+ >
80
+ {group.title}
81
+ </a>
82
+ </li>
83
+ </>
84
+ )
85
+ }
86
+ })
87
+ }
88
+ </ul>
89
+ </nav>
@@ -0,0 +1,26 @@
1
+ ---
2
+ import type { Layout } from '../libs/layout'
3
+
4
+ interface Props {
5
+ layout: Layout
6
+ }
7
+
8
+ const { layout } = Astro.props
9
+ ---
10
+
11
+ <a
12
+ class="nav-link dropdown-toggle"
13
+ href="/docs"
14
+ role="button"
15
+ data-cx-toggle="dropdown"
16
+ aria-expanded="false">Docs</a
17
+ >
18
+ <ul class="dropdown-menu">
19
+ <li><a class="dropdown-item" href="/css">CSS</a></li>
20
+ <li><a class="dropdown-item" href="/tokens">Tokens</a></li>
21
+ <li><a class="dropdown-item" href="/icons">Icons</a></li>
22
+ <li><a class="dropdown-item" href="/figma">Figma</a></li>
23
+ <li><a class="dropdown-item" href="/assets">Assets</a></li>
24
+ <li><hr class="dropdown-separator" /></li>
25
+ <li><a class="dropdown-item" href="/docs">Docs Index</a></li>
26
+ </ul>
@@ -0,0 +1,24 @@
1
+ ---
2
+ interface Props {
3
+ active?: boolean
4
+ class?: string
5
+ href: string
6
+ rel?: HTMLAnchorElement['rel']
7
+ target?: HTMLAnchorElement['target']
8
+ track?: boolean
9
+ }
10
+
11
+ const { active, class: className, track, ...props } = Astro.props
12
+
13
+ const content = await Astro.slots.render('default')
14
+ ---
15
+
16
+ <li class="nav-item col-6 col-large-auto">
17
+ <a
18
+ aria-current={active ? true : undefined}
19
+ class:list={['nav-link', className, { active }]}
20
+ {...props}
21
+ >
22
+ <slot />
23
+ </a>
24
+ </li>
@@ -0,0 +1,31 @@
1
+ ---
2
+ interface Props {
3
+ imgPath: string
4
+ alt: string
5
+ classes?: string
6
+ lazyload?: boolean
7
+ width?: number
8
+ height?: number
9
+ }
10
+
11
+ const { imgPath, alt, classes = '', lazyload = true, width, height } = Astro.props
12
+
13
+ const classNames = ['image', classes].filter(Boolean).join(' ')
14
+
15
+ const basePath = imgPath.split('/').slice(0, -1).join('/')
16
+ const basename = imgPath.split('/').pop()?.split('.')[0] || ''
17
+ const ext = imgPath.includes('.') ? `.${imgPath.split('.').pop()}` : ''
18
+
19
+ const imgPath1x = `${basePath}/${basename}${ext}`
20
+ const imgPath2x = `${basePath}/${basename}@2x${ext}`
21
+ ---
22
+
23
+ <img
24
+ class={classNames}
25
+ srcset={`${imgPath1x}, ${imgPath2x} 2x`}
26
+ src={imgPath1x}
27
+ alt={alt}
28
+ loading={lazyload ? 'lazy' : undefined}
29
+ width={width}
30
+ height={height}
31
+ />
@@ -0,0 +1,31 @@
1
+ ---
2
+ import type { MarkdownHeading } from 'astro'
3
+ import { generateToc, type TocEntry } from '../libs/toc'
4
+
5
+ interface Props {
6
+ headings?: MarkdownHeading[]
7
+ entries?: TocEntry[]
8
+ level?: number
9
+ config?: any
10
+ }
11
+
12
+ const { entries, headings, level, config } = Astro.props
13
+
14
+ const toc = entries ? entries : generateToc(headings ?? [], config)
15
+ let entryLevel = level ? level + 1 : 1
16
+ ---
17
+
18
+ <ul>
19
+ {
20
+ toc.map(({ children, slug, text }) => {
21
+ return (
22
+ <li>
23
+ <a href={`#${slug}`} class={`level-${entryLevel}`}>
24
+ {text}
25
+ </a>
26
+ {children.length > 0 && <Astro.self entries={children} level={entryLevel} />}
27
+ </li>
28
+ )
29
+ })
30
+ }
31
+ </ul>
@@ -0,0 +1,70 @@
1
+ ---
2
+ import type { Layout } from '../libs/layout'
3
+
4
+ interface Props {
5
+ layout: Layout
6
+ }
7
+
8
+ const { layout } = Astro.props
9
+ ---
10
+
11
+ <button
12
+ class=`nav-link dropdown-toggle`
13
+ id="cxd-theme"
14
+ type="button"
15
+ aria-expanded="false"
16
+ data-cx-toggle="dropdown"
17
+ {...layout !== 'examples' ? { 'data-cx-display': 'static' } : {}}
18
+ aria-label="Toggle theme (auto)"
19
+ >
20
+ <svg class="icon theme-icon-active" aria-hidden="true"><use href="#circle-half-solid"></use></svg>
21
+ <span
22
+ class=`${layout === 'examples' ? 'visually-hidden' : 'd-large-none ms-xsmall'}`
23
+ id="cxd-theme-text">Toggle theme</span
24
+ >
25
+ </button>
26
+ <ul
27
+ class=`dropdown-menu dropdown-menu-end${layout === 'examples' ? ' shadow' : ''}`
28
+ aria-labelledby="cxd-theme-text"
29
+ >
30
+ <li>
31
+ <button
32
+ type="button"
33
+ class="dropdown-item d-flex align-items-center"
34
+ data-cx-theme-value="light"
35
+ aria-pressed="false"
36
+ >
37
+ <svg class="icon icon-reset me-xsmall" aria-hidden="true"><use href="#sun-solid"></use></svg>
38
+ Light
39
+ <svg class="icon ms-auto d-none" aria-hidden="true"><use href="#check-solid"></use></svg>
40
+ </button>
41
+ </li>
42
+ <li>
43
+ <button
44
+ type="button"
45
+ class="dropdown-item d-flex align-items-center"
46
+ data-cx-theme-value="dark"
47
+ aria-pressed="false"
48
+ >
49
+ <svg class="icon icon-reset me-xsmall" aria-hidden="true"
50
+ ><use href="#moon-stars-solid"></use></svg
51
+ >
52
+ Dark
53
+ <svg class="icon ms-auto d-none" aria-hidden="true"><use href="#check-solid"></use></svg>
54
+ </button>
55
+ </li>
56
+ <li>
57
+ <button
58
+ type="button"
59
+ class="dropdown-item d-flex align-items-center active"
60
+ data-cx-theme-value="auto"
61
+ aria-pressed="true"
62
+ >
63
+ <svg class="icon icon-reset me-xsmall" aria-hidden="true"
64
+ ><use href="#circle-half-solid"></use></svg
65
+ >
66
+ Auto
67
+ <svg class="icon ms-auto d-none" aria-hidden="true"><use href="#check-solid"></use></svg>
68
+ </button>
69
+ </li>
70
+ </ul>
@@ -0,0 +1,13 @@
1
+ ---
2
+ /*
3
+ * Outputs badge to identify the first version something was added
4
+ */
5
+
6
+ interface Props {
7
+ version: string
8
+ }
9
+
10
+ const { version } = Astro.props
11
+ ---
12
+
13
+ <span class="badge large success smooth mb-medium rounded-medium">Added in v{version}</span>
@@ -0,0 +1,37 @@
1
+ ---
2
+ import { getCalloutByName, type CalloutName } from '@libs/content'
3
+ import { render } from 'astro:content'
4
+ import type { MarkdownInstance } from 'astro'
5
+
6
+ interface Props {
7
+ /**
8
+ * The name of an existing callout to display located in `src/content/callouts`.
9
+ * This will override any content passed in via the default slot.
10
+ */
11
+ name?: CalloutName
12
+ /**
13
+ * The type of callout to display. One of `info`, `danger`, or `warning`.
14
+ * @default 'info'
15
+ */
16
+ type?: 'danger' | 'info' | 'warning'
17
+ }
18
+
19
+ const { name, type = 'info' } = Astro.props
20
+
21
+ let Content: MarkdownInstance<{}>['Content'] | undefined
22
+
23
+ if (name) {
24
+ const callout = await getCalloutByName(name)
25
+
26
+ if (!callout) {
27
+ throw new Error(`Could not find callout with name '${name}'.`)
28
+ }
29
+
30
+ const namedCallout = await render(callout)
31
+ Content = namedCallout.Content
32
+ }
33
+ ---
34
+
35
+ <div class={`cxd-callout cxd-callout-${type} context ${type}`}>
36
+ {Content ? <Content /> : <slot />}
37
+ </div>
@@ -0,0 +1,16 @@
1
+ ---
2
+ interface Props {
3
+ /**
4
+ * The CSS class to apply to the table.
5
+ * Note that the prop is not used in this component, but in a rehype plugin applying the classes to the table element
6
+ * directly on the HTML AST (HAST) generated by Astro.
7
+ * @default "table"
8
+ * @see src/libs/rehype.ts
9
+ */
10
+ class?: string
11
+ }
12
+ ---
13
+
14
+ <div class="table-responsive">
15
+ <slot />
16
+ </div>
@@ -0,0 +1,82 @@
1
+ /*!
2
+ * Color mode toggler for Chassis's docs (https://chassis-ui.com/)
3
+ * Copyright 2011-2025 The Chassis Authors
4
+ * Licensed under the Creative Commons Attribution 3.0 Unported License.
5
+ */
6
+
7
+ ;(() => {
8
+ 'use strict'
9
+
10
+ const getStoredTheme = () => localStorage.getItem('theme')
11
+ const setStoredTheme = (theme) => localStorage.setItem('theme', theme)
12
+
13
+ const getPreferredTheme = () => {
14
+ const storedTheme = getStoredTheme()
15
+ if (storedTheme) {
16
+ return storedTheme
17
+ }
18
+
19
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
20
+ }
21
+
22
+ const setTheme = (theme) => {
23
+ if (theme === 'auto') {
24
+ document.documentElement.setAttribute(
25
+ 'data-cx-theme',
26
+ window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
27
+ )
28
+ } else {
29
+ document.documentElement.setAttribute('data-cx-theme', theme)
30
+ }
31
+ }
32
+
33
+ setTheme(getPreferredTheme())
34
+
35
+ const showActiveTheme = (theme, focus = false) => {
36
+ const themeSwitcher = document.querySelector('#cxd-theme')
37
+
38
+ if (!themeSwitcher) {
39
+ return
40
+ }
41
+
42
+ const themeSwitcherText = document.querySelector('#cxd-theme-text')
43
+ const activeThemeIcon = document.querySelector('.theme-icon-active use')
44
+ const buttonToActive = document.querySelector(`[data-cx-theme-value="${theme}"]`)
45
+ const svgOfActiveButton = buttonToActive.querySelector('svg use').getAttribute('href')
46
+
47
+ document.querySelectorAll('[data-cx-theme-value]').forEach((element) => {
48
+ element.classList.remove('active')
49
+ element.setAttribute('aria-pressed', 'false')
50
+ })
51
+
52
+ buttonToActive.classList.add('active')
53
+ buttonToActive.setAttribute('aria-pressed', 'true')
54
+ activeThemeIcon.setAttribute('href', svgOfActiveButton)
55
+ const themeSwitcherLabel = `${themeSwitcherText.textContent} (${buttonToActive.dataset.cxThemeValue})`
56
+ themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
57
+
58
+ if (focus) {
59
+ themeSwitcher.focus()
60
+ }
61
+ }
62
+
63
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
64
+ const storedTheme = getStoredTheme()
65
+ if (storedTheme !== 'light' && storedTheme !== 'dark') {
66
+ setTheme(getPreferredTheme())
67
+ }
68
+ })
69
+
70
+ window.addEventListener('DOMContentLoaded', () => {
71
+ showActiveTheme(getPreferredTheme())
72
+
73
+ document.querySelectorAll('[data-cx-theme-value]').forEach((toggle) => {
74
+ toggle.addEventListener('click', () => {
75
+ const theme = toggle.getAttribute('data-cx-theme-value')
76
+ setStoredTheme(theme)
77
+ setTheme(theme)
78
+ showActiveTheme(theme, true)
79
+ })
80
+ })
81
+ })
82
+ })()