@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
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Chassis Icons SVG Sprite Loader
3
+ *
4
+ * Efficiently loads and caches the chassis-icons.svg sprite using localStorage.
5
+ * This reduces page size by avoiding inline SVG and enables browser caching.
6
+ *
7
+ * Features:
8
+ * - localStorage caching with version control
9
+ * - Automatic fallback on cache miss or corruption
10
+ * - Network request deduplication
11
+ * - Small footprint and fast execution
12
+ */
13
+
14
+ ;(function () {
15
+ 'use strict'
16
+
17
+ // Configuration
18
+ const CACHE_KEY = 'chassis-icons-sprite'
19
+ const VERSION_KEY = 'chassis-icons-version'
20
+ const CURRENT_VERSION = '1.0.0' // Update when icons change
21
+ const SVG_URL = '/static/icons/chassis-icons.svg' // Icons SVG sprite path
22
+
23
+ // State management
24
+ let loadPromise = null
25
+
26
+ /**
27
+ * Get SVG sprite from localStorage cache
28
+ * @returns {string|null} Cached SVG content or null if not found/invalid
29
+ */
30
+ function getCachedSprite() {
31
+ try {
32
+ const cachedVersion = localStorage.getItem(VERSION_KEY)
33
+ const cachedSprite = localStorage.getItem(CACHE_KEY)
34
+
35
+ if (cachedVersion === CURRENT_VERSION && cachedSprite) {
36
+ return cachedSprite
37
+ }
38
+ } catch (error) {
39
+ console.warn('Failed to read icon cache:', error)
40
+ }
41
+
42
+ return null
43
+ }
44
+
45
+ /**
46
+ * Store SVG sprite in localStorage cache
47
+ * @param {string} spriteContent - SVG content to cache
48
+ */
49
+ function setCachedSprite(spriteContent) {
50
+ try {
51
+ localStorage.setItem(VERSION_KEY, CURRENT_VERSION)
52
+ localStorage.setItem(CACHE_KEY, spriteContent)
53
+ } catch (error) {
54
+ console.warn('Failed to cache icon sprite:', error)
55
+ // Handle localStorage quota exceeded or other errors
56
+ // Clear old cache and try again
57
+ try {
58
+ localStorage.removeItem(CACHE_KEY)
59
+ localStorage.removeItem(VERSION_KEY)
60
+ localStorage.setItem(VERSION_KEY, CURRENT_VERSION)
61
+ localStorage.setItem(CACHE_KEY, spriteContent)
62
+ } catch (retryError) {
63
+ console.warn('Failed to cache icon sprite after retry:', retryError)
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Fetch SVG sprite from network
70
+ * @returns {Promise<string>} Promise resolving to SVG content
71
+ */
72
+ async function fetchSprite() {
73
+ const response = await fetch(SVG_URL)
74
+
75
+ if (!response.ok) {
76
+ throw new Error(`Failed to fetch icon sprite: ${response.status} ${response.statusText}`)
77
+ }
78
+
79
+ const spriteContent = await response.text()
80
+
81
+ // Basic validation - ensure it's actually SVG content
82
+ if (!spriteContent.includes('<svg') || !spriteContent.includes('</svg>')) {
83
+ throw new Error('Invalid SVG content received')
84
+ }
85
+
86
+ return spriteContent
87
+ }
88
+
89
+ /**
90
+ * Inject SVG sprite into the DOM
91
+ * @param {string} spriteContent - SVG content to inject
92
+ */
93
+ function injectSprite(spriteContent) {
94
+ // Remove any existing sprite container
95
+ const existingContainer = document.getElementById('chassis-icons-sprite')
96
+ if (existingContainer) {
97
+ existingContainer.remove()
98
+ }
99
+
100
+ // Create hidden container for the sprite
101
+ const container = document.createElement('div')
102
+ container.id = 'chassis-icons-sprite'
103
+ container.style.display = 'none'
104
+ container.setAttribute('aria-hidden', 'true')
105
+ container.innerHTML = spriteContent
106
+
107
+ // Insert at the beginning of body
108
+ document.body.insertBefore(container, document.body.firstChild)
109
+ }
110
+
111
+ /**
112
+ * Load and inject the icon sprite
113
+ * @returns {Promise<void>} Promise that resolves when sprite is loaded
114
+ */
115
+ function loadIconSprite() {
116
+ // Return existing promise if already loading
117
+ if (loadPromise) {
118
+ return loadPromise
119
+ }
120
+
121
+ // Check cache first
122
+ const cachedSprite = getCachedSprite()
123
+ if (cachedSprite) {
124
+ injectSprite(cachedSprite)
125
+ return Promise.resolve()
126
+ }
127
+
128
+ // Fetch from network
129
+ loadPromise = fetchSprite()
130
+ .then((spriteContent) => {
131
+ // Cache the content
132
+ setCachedSprite(spriteContent)
133
+
134
+ // Inject into DOM
135
+ injectSprite(spriteContent)
136
+ })
137
+ .catch((error) => {
138
+ console.error('Failed to load icon sprite:', error)
139
+ // Don't throw - let the page continue to work without icons
140
+ })
141
+ .finally(() => {
142
+ loadPromise = null
143
+ })
144
+
145
+ return loadPromise
146
+ }
147
+
148
+ /**
149
+ * Initialize icon loading
150
+ * Runs immediately if DOM is ready, or waits for DOMContentLoaded
151
+ */
152
+ function init() {
153
+ if (document.readyState === 'loading') {
154
+ document.addEventListener('DOMContentLoaded', loadIconSprite)
155
+ } else {
156
+ loadIconSprite()
157
+ }
158
+ }
159
+
160
+ // Public API for manual cache management
161
+ window.ChassisIcons = {
162
+ /**
163
+ * Manually reload the icon sprite (bypasses cache)
164
+ * @returns {Promise<void>}
165
+ */
166
+ reload: async function () {
167
+ try {
168
+ // Clear cache
169
+ localStorage.removeItem(CACHE_KEY)
170
+ localStorage.removeItem(VERSION_KEY)
171
+
172
+ // Force reload
173
+ loadPromise = null
174
+ await loadIconSprite()
175
+ } catch (error) {
176
+ console.error('Failed to reload icon sprite:', error)
177
+ }
178
+ },
179
+
180
+ /**
181
+ * Clear the icon cache
182
+ */
183
+ clearCache: function () {
184
+ try {
185
+ localStorage.removeItem(CACHE_KEY)
186
+ localStorage.removeItem(VERSION_KEY)
187
+ } catch (error) {
188
+ console.warn('Failed to clear icon cache:', error)
189
+ }
190
+ },
191
+
192
+ /**
193
+ * Get cache information
194
+ * @returns {object} Cache status and size info
195
+ */
196
+ getCacheInfo: function () {
197
+ try {
198
+ const version = localStorage.getItem(VERSION_KEY)
199
+ const sprite = localStorage.getItem(CACHE_KEY)
200
+ return {
201
+ version: version,
202
+ cached: !!sprite,
203
+ size: sprite ? sprite.length : 0,
204
+ currentVersion: CURRENT_VERSION
205
+ }
206
+ } catch (error) {
207
+ return {
208
+ version: null,
209
+ cached: false,
210
+ size: 0,
211
+ currentVersion: CURRENT_VERSION,
212
+ error: error.message
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ // Initialize
219
+ init()
220
+ })()
@@ -0,0 +1,58 @@
1
+ // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
2
+ // IT'S ALL JUST JUNK FOR OUR DOCS!
3
+ // ++++++++++++++++++++++++++++++++++++++++++
4
+
5
+ /*!
6
+ * JavaScript for Chassis's docs (https://chassis-ui.com/)
7
+ * Copyright 2024-2025 The Chassis Authors
8
+ * Licensed under the Creative Commons Attribution 3.0 Unported License.
9
+ * For details, see https://creativecommons.org/licenses/by/3.0/.
10
+ */
11
+
12
+ import docsearch from '@docsearch/js'
13
+ ;(() => {
14
+ // These values will be replaced by Astro's Vite plugin
15
+ const CONFIG = {
16
+ apiKey: '__API_KEY__',
17
+ indexName: '__INDEX_NAME__',
18
+ appId: '__APP_ID__'
19
+ }
20
+
21
+ const searchElement = document.getElementById('docsearch')
22
+
23
+ if (!searchElement) {
24
+ return
25
+ }
26
+
27
+ const siteDocsVersion = searchElement.getAttribute('data-cxd-docs-version')
28
+
29
+ docsearch({
30
+ apiKey: CONFIG.apiKey,
31
+ indexName: CONFIG.indexName,
32
+ appId: CONFIG.appId,
33
+ container: searchElement,
34
+ searchParameters: {
35
+ facetFilters: [`version:${siteDocsVersion}`]
36
+ },
37
+ transformItems(items) {
38
+ return items.map((item) => {
39
+ const liveUrl = 'https://chassis-ui.com/'
40
+
41
+ item.url = window.location.origin.startsWith(liveUrl)
42
+ ? // On production, return the result as is
43
+ item.url
44
+ : // On development or Netlify, replace `item.url` with a trailing slash,
45
+ // so that the result link is relative to the server root
46
+ item.url.replace(liveUrl, '/')
47
+
48
+ // Prevent jumping to first header
49
+ if (item.anchor === 'content') {
50
+ item.url = item.url.replace(/#content$/, '')
51
+ item.anchor = null
52
+ }
53
+
54
+ return item
55
+ })
56
+ }
57
+ })
58
+ })()
@@ -0,0 +1,30 @@
1
+ // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
2
+ // IT'S ALL JUST JUNK FOR OUR DOCS!
3
+ // ++++++++++++++++++++++++++++++++++++++++++
4
+
5
+ /*
6
+ * JavaScript for Chassis's docs (https://chassis-ui.com/)
7
+ * Copyright 2011-2025 The Chassis Authors
8
+ * Licensed under the Creative Commons Attribution 3.0 Unported License.
9
+ * For details, see https://creativecommons.org/licenses/by/3.0/.
10
+ */
11
+
12
+ ;(() => {
13
+ // Scroll the active sidebar link into view
14
+ const sidenav = document.querySelector('.cxd-sidebar')
15
+ const sidenavActiveLink = document.querySelector('.cxd-links-nav .active')
16
+
17
+ if (!sidenav || !sidenavActiveLink) {
18
+ return
19
+ }
20
+
21
+ const sidenavHeight = sidenav.clientHeight
22
+ const sidenavActiveLinkTop = sidenavActiveLink.offsetTop
23
+ const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight
24
+ const viewportTop = sidenavActiveLinkTop
25
+ const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight
26
+
27
+ if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) {
28
+ sidenav.scrollTop = viewportTop - sidenavHeight / 2 + sidenavActiveLinkHeight / 2
29
+ }
30
+ })()
@@ -0,0 +1,126 @@
1
+ // Dynamic theme color based on scroll position
2
+ ;(() => {
3
+ 'use strict'
4
+
5
+ // Configuration
6
+ const CONFIG = {
7
+ scrollThreshold: 100,
8
+ defaultColor: '#00A4CC'
9
+ }
10
+
11
+ // DOM elements
12
+ const elements = {
13
+ themeColorMeta: document.querySelector('meta[name="theme-color"]'),
14
+ header: document.querySelector('header'),
15
+ footer: document.querySelector('.cxd-footer')
16
+ }
17
+
18
+ // Early return if required elements are missing
19
+ if (!elements.themeColorMeta || !elements.header || !elements.footer) {
20
+ return
21
+ }
22
+
23
+ /**
24
+ * Extracts RGB values from a CSS color string
25
+ * @param {string} color - CSS color string (rgb/rgba)
26
+ * @returns {Object|null} RGB object or null if invalid
27
+ */
28
+ function extractRGB(color) {
29
+ const match = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/)
30
+ return match
31
+ ? {
32
+ r: parseInt(match[1], 10),
33
+ g: parseInt(match[2], 10),
34
+ b: parseInt(match[3], 10)
35
+ }
36
+ : null
37
+ }
38
+
39
+ /**
40
+ * Converts RGB values to hex color string
41
+ * @param {number} r - Red value (0-255)
42
+ * @param {number} g - Green value (0-255)
43
+ * @param {number} b - Blue value (0-255)
44
+ * @returns {string} Hex color string
45
+ */
46
+ function rgbToHex(r, g, b) {
47
+ return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()
48
+ }
49
+
50
+ /**
51
+ * Gets the computed background color of an element as hex
52
+ * @param {HTMLElement} element - DOM element
53
+ * @returns {string} Hex color string or default color
54
+ */
55
+ function getElementBackgroundColor(element) {
56
+ const bgColor = getComputedStyle(element).backgroundColor
57
+ const rgb = extractRGB(bgColor)
58
+ return rgb ? rgbToHex(rgb.r, rgb.g, rgb.b) : CONFIG.defaultColor
59
+ }
60
+
61
+ /**
62
+ * Determines the current scroll position context
63
+ * @returns {string} 'top', 'bottom', or 'middle'
64
+ */
65
+ function getScrollContext() {
66
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop
67
+ const windowHeight = window.innerHeight
68
+ const documentHeight = document.documentElement.scrollHeight
69
+
70
+ if (scrollTop < CONFIG.scrollThreshold) {
71
+ return 'top'
72
+ }
73
+
74
+ if (scrollTop + windowHeight >= documentHeight - CONFIG.scrollThreshold) {
75
+ return 'bottom'
76
+ }
77
+
78
+ return 'middle'
79
+ }
80
+
81
+ /**
82
+ * Updates the theme color meta tag based on scroll position
83
+ */
84
+ function updateThemeColor() {
85
+ const context = getScrollContext()
86
+ let color = CONFIG.defaultColor
87
+
88
+ switch (context) {
89
+ case 'top':
90
+ color = getElementBackgroundColor(elements.header)
91
+ break
92
+ case 'bottom':
93
+ color = getElementBackgroundColor(elements.footer)
94
+ break
95
+ case 'middle':
96
+ default:
97
+ color = CONFIG.defaultColor
98
+ break
99
+ }
100
+
101
+ elements.themeColorMeta.setAttribute('content', color)
102
+ }
103
+
104
+ // Throttle function for performance optimization
105
+ function throttle(func, limit) {
106
+ let inThrottle
107
+ return function () {
108
+ const args = arguments
109
+ const context = this
110
+ if (!inThrottle) {
111
+ func.apply(context, args)
112
+ inThrottle = true
113
+ setTimeout(() => (inThrottle = false), limit)
114
+ }
115
+ }
116
+ }
117
+
118
+ // Event listeners with throttling for better performance
119
+ const throttledUpdate = throttle(updateThemeColor, 16) // ~60fps
120
+
121
+ window.addEventListener('scroll', throttledUpdate, { passive: true })
122
+ window.addEventListener('resize', throttledUpdate, { passive: true })
123
+
124
+ // Initial update
125
+ updateThemeColor()
126
+ })()
@@ -0,0 +1,94 @@
1
+ ---
2
+ import type { CollectionEntry } from 'astro:content'
3
+ import { getConfig } from '@libs/config'
4
+ import type { Layout, LayoutOverridesHTMLAttributes } from '../libs/layout'
5
+ import Head from './head/Head.astro'
6
+ import Header from './header/Header.astro'
7
+ import Scripts from './footer/Scripts.astro'
8
+ import Footer from './footer/Footer.astro'
9
+ import { stripMarkdown } from '../libs/utils'
10
+
11
+ // The following props can be directly passed to the base layout component from any page or layout extending it,
12
+ // e.g. <BaseLayout layout="docs" robots="noindex" />.
13
+ type Props = {
14
+ // A specific layout to use for the current page used to determine if some components should be rendered or not.
15
+ // Available layouts are defined in `src/libs/layout.ts`.
16
+ layout?: Layout
17
+ // An object containing HTML attributes that can be overridden for some HTML elements used in the base layout keyed by
18
+ // HTML element names.
19
+ overrides?: {
20
+ body?: LayoutOverridesHTMLAttributes<'body'>
21
+ // Note that main can also be overridden by the Astro slot named "main" and that the slot will take precedence over
22
+ // any override.
23
+ main?: LayoutOverridesHTMLAttributes<'main'>
24
+ }
25
+ // A string containing the robots meta tag content. If not set, the tag will not be rendered.
26
+ robots?: string
27
+ // An override for the page title. If not defined, the title will either be the content of the `title` frontmatter
28
+ // property when rendering a markdown page or default back to the one defined in the `config.yml` file.
29
+ title?: string
30
+ } & MarkdownProps
31
+
32
+ // The following props are automatically set by Astro (if defined) based on the markdown frontmatter when rendering a
33
+ // markdown page. They can be accessed through the `Astro.props.frontmatter` object but note that they won't be set when
34
+ // not rendering a markdown page.
35
+ type MarkdownProps = { frontmatter?: Partial<CollectionEntry<'docs' | 'blog'>['data']> }
36
+
37
+ const { frontmatter, layout, overrides, robots } = Astro.props
38
+
39
+ const title = Astro.props.title ?? frontmatter?.title ?? getConfig().title
40
+ const description = frontmatter?.description
41
+ ? stripMarkdown(frontmatter.description)
42
+ : getConfig().description
43
+ const thumbnail = frontmatter?.thumbnail
44
+ ? `img/${frontmatter.thumbnail}`
45
+ : 'logo/chassis-logo-default.svg'
46
+
47
+ const bodyProps = overrides?.body ?? {}
48
+ const mainProps = overrides?.main ?? {}
49
+ ---
50
+
51
+ <!doctype html>
52
+ <html lang="en" data-cx-theme="auto">
53
+ <head>
54
+ <Head
55
+ description={description}
56
+ layout={layout}
57
+ robots={robots}
58
+ thumbnail={thumbnail}
59
+ title={title}
60
+ />
61
+ </head>
62
+ <body {...bodyProps}>
63
+ <Header layout={layout} title={title} />
64
+
65
+ {
66
+ Astro.slots.has('main') ? (
67
+ <slot name="main" />
68
+ ) : (
69
+ <main {...mainProps}>
70
+ <slot />
71
+ </main>
72
+ )
73
+ }
74
+
75
+ <Footer />
76
+
77
+ <Scripts layout={layout}>
78
+ <slot name="scripts" slot="scripts" />
79
+ </Scripts>
80
+
81
+ {
82
+ frontmatter?.extra_js &&
83
+ frontmatter.extra_js.map((js) => <script is:inline async={js.async} src={js.src} />)
84
+ }
85
+
86
+ {
87
+ (layout === 'docs' || layout === 'icons') && (
88
+ <div class="position-fixed" aria-hidden="true">
89
+ <input type="text" tabindex="-1" />
90
+ </div>
91
+ )
92
+ }
93
+ </body>
94
+ </html>
@@ -0,0 +1,147 @@
1
+ ---
2
+ import type { MarkdownHeading } from 'astro'
3
+ import type { CollectionEntry } from 'astro:content'
4
+ import { getConfig } from '@libs/config'
5
+ import { getChassisDocsPath } from '@libs/path'
6
+ import type { LayoutOverridesHTMLAttributes } from '../libs/layout'
7
+ import { getSlug, processMarkdownToHtml } from '../libs/utils'
8
+ import BaseLayout from './BaseLayout.astro'
9
+ import DocsSidebar from '../components/DocsSidebar.astro'
10
+ import TableOfContents from '../components/TableOfContents.astro'
11
+
12
+ interface Props {
13
+ frontmatter: CollectionEntry<'docs'>['data']
14
+ headings?: MarkdownHeading[]
15
+ id: CollectionEntry<'docs'>['id']
16
+ }
17
+
18
+ const { frontmatter, headings, id } = Astro.props
19
+
20
+ // Extract the directory/section from the ID (format: "directory/filename.mdx")
21
+ const parentDirectory = id.includes('/') ? id.split('/')[0] : ''
22
+
23
+ const bodyProps: LayoutOverridesHTMLAttributes<'body'> = {}
24
+
25
+ if (frontmatter.toc) {
26
+ bodyProps['data-cx-spy'] = 'scroll'
27
+ bodyProps['data-cx-target'] = '#TableOfContents'
28
+ }
29
+ ---
30
+
31
+ <BaseLayout {...Astro.props} layout="docs" overrides={{ body: bodyProps }}>
32
+ <div slot="main" class="container-fluid cxd-gutter cxd-layout">
33
+ <aside class="cxd-sidebar">
34
+ <div
35
+ class="offcanvas-large offcanvas-start"
36
+ tabindex="-1"
37
+ id="cxdSidebar"
38
+ aria-labelledby="cxdSidebarOffcanvasLabel"
39
+ >
40
+ <div class="offcanvas-header border-bottom">
41
+ <h5 class="offcanvas-title" id="cxdSidebarOffcanvasLabel">Browse docs</h5>
42
+ <button
43
+ type="button"
44
+ class="close-button"
45
+ data-cx-dismiss="offcanvas"
46
+ aria-label="Close"
47
+ data-cx-target="#cxdSidebar"></button>
48
+ </div>
49
+
50
+ <div class="offcanvas-body">
51
+ <DocsSidebar />
52
+ </div>
53
+ </div>
54
+ </aside>
55
+
56
+ <main class="cxd-main">
57
+ <div class="cxd-intro">
58
+ <div
59
+ class="d-medium-flex flex-medium-row-reverse justify-content-between align-items-start"
60
+ >
61
+ <div class="mb-medium mb-medium-0 d-flex text-nowrap">
62
+ {
63
+ // This is needed because we want to show the badge if show_badge isn't present or is set to false
64
+ frontmatter.added &&
65
+ ((frontmatter.added.show_badge !== undefined &&
66
+ frontmatter.added.show_badge === true) ||
67
+ frontmatter.added.show_badge === undefined) && (
68
+ <span class="badge success smooth rounded-medium me-xsmall">
69
+ Added in v{frontmatter.added.version}
70
+ </span>
71
+ )
72
+ }
73
+ <a
74
+ class="button default small"
75
+ href={`${getConfig().repo}/blob/${id}.mdx`}
76
+ title="View and edit this file on GitHub"
77
+ target="_blank"
78
+ rel="noopener"
79
+ >
80
+ View on GitHub
81
+ </a>
82
+ </div>
83
+ <h1 class="cxd-title mb-0" id="content">{frontmatter.title}</h1>
84
+ </div>
85
+ <div class="cxd-subtitle">
86
+ {
87
+ frontmatter.description && (
88
+ <Fragment set:html={processMarkdownToHtml(frontmatter.description)} />
89
+ )
90
+ }
91
+ </div>
92
+ </div>
93
+
94
+ {
95
+ frontmatter.toc && headings && (
96
+ <div class="cxd-toc">
97
+ <button
98
+ class="button default mb-large text-decoration-none cxd-toc-toggle d-medium-none"
99
+ type="button"
100
+ data-cx-toggle="collapse"
101
+ data-cx-target="#tocContents"
102
+ aria-expanded="false"
103
+ aria-controls="tocContents"
104
+ >
105
+ On this page
106
+ <svg class="icon icon-small" aria-hidden="true">
107
+ <use xlink:href="#chevron-sort-solid" />
108
+ </svg>
109
+ </button>
110
+ <strong class="d-none d-medium-block h6 my-xsmall">On this page</strong>
111
+ <hr class="d-none d-medium-block my-xsmall" />
112
+ <div class="collapse cxd-toc-collapse" id="tocContents">
113
+ <nav id="TableOfContents">
114
+ <TableOfContents headings={headings} config={getConfig()} />
115
+ </nav>
116
+ </div>
117
+ </div>
118
+ )
119
+ }
120
+
121
+ <div class="cxd-content">
122
+ {
123
+ frontmatter.sections && (
124
+ <div class="row g-xlarge">
125
+ {frontmatter.sections.map((section) => (
126
+ <div class="col-medium-6">
127
+ <a
128
+ class="d-block text-decoration-none"
129
+ href={getChassisDocsPath(
130
+ `${parentDirectory ? parentDirectory + '/' : ''}${getSlug(section.title)}/`
131
+ )}
132
+ >
133
+ <strong class="d-block h5 mb-2xsmall">{section.title}</strong>
134
+ <span class="fg-subtle">{section.description}</span>
135
+ </a>
136
+ </div>
137
+ ))}
138
+ </div>
139
+ )
140
+ }
141
+
142
+ <slot />
143
+ </div>
144
+ </main>
145
+ </div>
146
+ <slot name="scripts" slot="scripts" />
147
+ </BaseLayout>
@@ -0,0 +1,19 @@
1
+ ---
2
+ import type { LayoutOverridesHTMLAttributes } from '../libs/layout'
3
+ import BaseLayout from './BaseLayout.astro'
4
+
5
+ const bodyProps: LayoutOverridesHTMLAttributes<'body'> = {}
6
+
7
+ bodyProps['id'] = 'icons-body'
8
+ bodyProps['data-cx-spy'] = 'scroll'
9
+ bodyProps['data-cx-target'] = '#icons-nav'
10
+ ---
11
+
12
+ <BaseLayout {...Astro.props} layout="icons" overrides={{ body: bodyProps }}>
13
+ <div
14
+ slot="main"
15
+ class="container-2xlarge px-medium px-medium-4xlarge cxd-gutter icon-docs icon-reset pt-medium-large pb-medium-large"
16
+ >
17
+ <slot />
18
+ </div>
19
+ </BaseLayout>