@chassis-ui/docs 0.1.10 → 0.3.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 (79) hide show
  1. package/README.md +16 -16
  2. package/index.ts +6 -1
  3. package/package.json +20 -8
  4. package/src/components/DocsSidebar.astro +63 -23
  5. package/src/components/FeatureCard.astro +8 -8
  6. package/src/components/NavLink.astro +1 -1
  7. package/src/components/TableOfContents.astro +8 -7
  8. package/src/components/ThemeToggler.astro +16 -37
  9. package/src/components/shortcodes/Blockquote.astro +31 -0
  10. package/src/components/shortcodes/CSSOnly.astro +22 -0
  11. package/src/components/shortcodes/Callout.astro +6 -2
  12. package/src/components/shortcodes/Code.astro +289 -0
  13. package/src/components/shortcodes/DeprecatedIn.astro +18 -0
  14. package/src/components/shortcodes/Example.astro +132 -0
  15. package/src/components/shortcodes/Icon.astro +57 -0
  16. package/src/components/shortcodes/InFigma.astro +26 -0
  17. package/src/components/shortcodes/JsDocs.astro +64 -0
  18. package/src/components/shortcodes/Placeholder.astro +28 -0
  19. package/src/components/shortcodes/ResizableExample.astro +126 -0
  20. package/src/components/shortcodes/ScssDocs.astro +108 -0
  21. package/src/components/shortcodes/ScssDocsSimple.astro +66 -0
  22. package/src/js/color-modes.js +3 -3
  23. package/src/js/example-mode.js +75 -0
  24. package/src/js/search.js +501 -39
  25. package/src/js/theme-color.js +1 -1
  26. package/src/layouts/DocsLayout.astro +18 -21
  27. package/src/layouts/RedirectLayout.astro +1 -0
  28. package/src/layouts/SingleLayout.astro +3 -3
  29. package/src/layouts/footer/Footer.astro +5 -5
  30. package/src/layouts/footer/Scripts.astro +14 -7
  31. package/src/layouts/head/Analytics.astro +12 -6
  32. package/src/layouts/head/Favicons.astro +0 -2
  33. package/src/layouts/head/Head.astro +2 -7
  34. package/src/layouts/head/Stylesheet.astro +18 -11
  35. package/src/layouts/header/Header.astro +2 -5
  36. package/src/layouts/header/Navigation.astro +40 -42
  37. package/src/layouts/header/SearchDialog.astro +74 -0
  38. package/src/layouts/header/SearchTrigger.astro +41 -0
  39. package/src/layouts/header/Skippy.astro +1 -1
  40. package/src/libs/highlight.ts +91 -0
  41. package/src/libs/icon.ts +75 -0
  42. package/src/libs/image.ts +12 -1
  43. package/src/libs/layout.ts +18 -0
  44. package/src/libs/markdown.ts +128 -0
  45. package/src/libs/placeholder.ts +250 -0
  46. package/src/libs/rehype.ts +0 -17
  47. package/src/libs/shortcodes.ts +129 -0
  48. package/src/libs/site.ts +95 -0
  49. package/src/libs/toc.ts +40 -6
  50. package/src/libs/utils.ts +34 -82
  51. package/src/libs/vite.ts +45 -0
  52. package/src/scss/_anchor.scss +20 -16
  53. package/src/scss/_callouts.scss +29 -28
  54. package/src/scss/_content.scss +72 -103
  55. package/src/scss/_footer.scss +18 -19
  56. package/src/scss/_layout.scss +56 -61
  57. package/src/scss/_navbar.scss +19 -126
  58. package/src/scss/_placeholder-img.scss +11 -7
  59. package/src/scss/_scrolling.scss +14 -12
  60. package/src/scss/_search.scss +418 -0
  61. package/src/scss/_shiki.scss +120 -0
  62. package/src/scss/_sidebar.scss +137 -132
  63. package/src/scss/_skippy.scss +6 -4
  64. package/src/scss/_snippets.scss +181 -0
  65. package/src/scss/_toc.scss +97 -93
  66. package/src/scss/_vars.scss +89 -0
  67. package/src/scss/main.scss +75 -81
  68. package/src/js/icon-loader.js +0 -229
  69. package/src/libs/chassis.ts +0 -38
  70. package/src/scss/_brand.scss +0 -59
  71. package/src/scss/_buttons.scss +0 -33
  72. package/src/scss/_clipboard-js.scss +0 -63
  73. package/src/scss/_code.scss +0 -116
  74. package/src/scss/_colors.scss +0 -140
  75. package/src/scss/_docsearch.scss +0 -212
  76. package/src/scss/_masthead.scss +0 -124
  77. package/src/scss/_settings.scss +0 -29
  78. package/src/scss/_syntax.scss +0 -160
  79. package/src/scss/_variables.scss +0 -78
@@ -0,0 +1,95 @@
1
+ import os from 'os'
2
+
3
+ /** Resolved host and port for the local Astro development server. */
4
+ interface DevHost {
5
+ /** Hostname or IP address (e.g. `"localhost"` or a LAN IP when `--host` is passed). */
6
+ host: string
7
+ /** Port number the dev server is listening on. */
8
+ port: number
9
+ }
10
+
11
+ /**
12
+ * Minimum site configuration shape required by `getSiteUrl`.
13
+ * The consuming project's full config object satisfies this interface as long
14
+ * as it exposes a `baseURL` string.
15
+ */
16
+ export interface SiteConfig {
17
+ /** Canonical base URL used as a fallback in production (e.g. `"https://chassis-ui.com/css/"`). */
18
+ baseURL: string
19
+ }
20
+
21
+ /**
22
+ * Resolves the host and port for the local Astro development server.
23
+ *
24
+ * Resolution order for port: `--port` CLI flag → `PORT` env var → `4321` (Astro default).
25
+ * When `--host` is passed, the first non-internal IPv4 network interface address
26
+ * is used as the host so the dev URL is reachable on the LAN.
27
+ */
28
+ function getDevHost(): DevHost {
29
+ const hasHostFlag = process.argv.includes('--host')
30
+ let host = 'localhost'
31
+ let port = 4321
32
+
33
+ const portFlagIndex = process.argv.findIndex((arg) => arg === '--port')
34
+ if (portFlagIndex !== -1 && process.argv[portFlagIndex + 1]) {
35
+ const cliPort = parseInt(process.argv[portFlagIndex + 1], 10)
36
+ if (!isNaN(cliPort) && cliPort > 0 && cliPort < 65536) {
37
+ port = cliPort
38
+ }
39
+ }
40
+
41
+ if (process.env.PORT) {
42
+ const envPort = parseInt(process.env.PORT, 10)
43
+ if (!isNaN(envPort) && envPort > 0 && envPort < 65536) {
44
+ port = envPort
45
+ }
46
+ }
47
+
48
+ if (hasHostFlag) {
49
+ const interfaces = os.networkInterfaces()
50
+ for (const iface of Object.values(interfaces).flat()) {
51
+ if (iface?.family === 'IPv4' && !iface.internal) {
52
+ host = iface.address
53
+ break
54
+ }
55
+ }
56
+ }
57
+
58
+ return { host, port }
59
+ }
60
+
61
+ /**
62
+ * Determines the canonical site URL for the current environment.
63
+ *
64
+ * Resolution order:
65
+ * 1. `SITE_URL` env var — explicit override, takes precedence everywhere.
66
+ * 2. `NODE_ENV=development` — constructs a local `http://` URL from `getDevHost()`.
67
+ * 3. `VERCEL_ENV=production` — uses `config.baseURL` (the path-prefixed canonical
68
+ * URL) rather than `VERCEL_PROJECT_PRODUCTION_URL` (the sub-project custom domain)
69
+ * so sitemaps always point to the correct public URL.
70
+ * 4. `VERCEL_URL` present — Vercel preview/branch deployment; uses the auto-generated
71
+ * `https://` preview URL.
72
+ * 5. Fallback — `config.baseURL` from the project's `config.yml`.
73
+ *
74
+ * @param config - Site configuration providing the `baseURL` fallback.
75
+ */
76
+ export function getSiteUrl(config: SiteConfig): string {
77
+ if (process.env.SITE_URL) {
78
+ return process.env.SITE_URL
79
+ }
80
+
81
+ if (process.env.NODE_ENV === 'development') {
82
+ const { host, port } = getDevHost()
83
+ return `http://${host}:${port}`
84
+ }
85
+
86
+ if (process.env.VERCEL_ENV === 'production') {
87
+ return config.baseURL || `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
88
+ }
89
+
90
+ if (process.env.VERCEL_URL) {
91
+ return `https://${process.env.VERCEL_URL}`
92
+ }
93
+
94
+ return config.baseURL
95
+ }
package/src/libs/toc.ts CHANGED
@@ -1,8 +1,28 @@
1
1
  import type { MarkdownHeading } from 'astro'
2
- // import { getConfig } from './config'
3
2
 
4
- // Generate a tree like structure from a list of headings.
5
- export function generateToc(allHeadings: MarkdownHeading[], config: any) {
3
+ /**
4
+ * Minimum configuration shape required by `generateToc`.
5
+ * The consuming project's full config object satisfies this interface as long as
6
+ * it contains a `toc` section with `min` and `max` depth values.
7
+ */
8
+ export interface TocConfig {
9
+ toc: {
10
+ /** Minimum heading depth to include (e.g. `2` to start at `<h2>`). */
11
+ min: number
12
+ /** Maximum heading depth to include (e.g. `4` to stop at `<h4>`). */
13
+ max: number
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Generates a nested tree of TOC entries from a flat list of Markdown headings.
19
+ *
20
+ * Headings outside the depth range defined in `config.toc` are excluded. When
21
+ * a heading skips one or more levels (e.g. an `<h4>` follows an `<h2>` with no
22
+ * `<h3>` in between) it is attached to the deepest available parent rather than
23
+ * being silently dropped.
24
+ */
25
+ export function generateToc(allHeadings: MarkdownHeading[], config: TocConfig): TocEntry[] {
6
26
  const headings = allHeadings.filter(
7
27
  (heading) => heading.depth >= config.toc.min && heading.depth <= config.toc.max
8
28
  )
@@ -29,14 +49,28 @@ export function generateToc(allHeadings: MarkdownHeading[], config: any) {
29
49
  return toc
30
50
  }
31
51
 
52
+ /**
53
+ * Walks down the TOC tree to find the children array at the given relative
54
+ * `depth` below `entry`. If an intermediate level is missing (skipped heading),
55
+ * falls back to the deepest available children array so the heading is not lost.
56
+ */
32
57
  function getEntryChildrenAtDepth(entry: TocEntry, depth: number): TocEntry['children'] {
33
58
  if (!entry) {
34
59
  return []
35
60
  }
36
61
 
37
- return depth === 1
38
- ? entry.children
39
- : getEntryChildrenAtDepth(entry.children[entry.children.length - 1], depth - 1)
62
+ if (depth === 1) {
63
+ return entry.children
64
+ }
65
+
66
+ const lastChild = entry.children[entry.children.length - 1]
67
+
68
+ if (!lastChild) {
69
+ // Heading skipped a level — attach to the current entry's children instead.
70
+ return entry.children
71
+ }
72
+
73
+ return getEntryChildrenAtDepth(lastChild, depth - 1)
40
74
  }
41
75
 
42
76
  export interface TocEntry extends MarkdownHeading {
package/src/libs/utils.ts CHANGED
@@ -1,14 +1,20 @@
1
- import os from 'os'
2
1
  import { slug } from 'github-slugger'
3
2
  import { fromMarkdown } from 'mdast-util-from-markdown'
4
3
  import { toString } from 'mdast-util-to-string'
5
4
  import { remark } from 'remark'
6
5
  import remarkHtml from 'remark-html'
7
6
 
7
+ /** Returns `str` with its first character uppercased. */
8
8
  export function capitalizeFirstLetter(str: string) {
9
9
  return str.charAt(0).toUpperCase() + str.slice(1)
10
10
  }
11
11
 
12
+ /**
13
+ * Generates an inclusive numeric sequence from `start` to `end` with the given `step`.
14
+ *
15
+ * @example getSequence(1, 5) // [1, 2, 3, 4, 5]
16
+ * @example getSequence(0, 10, 2) // [0, 2, 4, 6, 8, 10]
17
+ */
12
18
  export function getSequence(start: number, end: number, step = 1) {
13
19
  const sequence = []
14
20
 
@@ -19,107 +25,53 @@ export function getSequence(start: number, end: number, step = 1) {
19
25
  return sequence
20
26
  }
21
27
 
22
- // This function is used in the docs sidebar to generate partial slugs and properly order the sidebar entries and also
23
- // to generate docs frontmatter sections slugs.
24
- // Note: this should be refactored and removed, the sidebar ordering defined in `site/data/sidebar.yml` should not rely
25
- // on slugified custom titles that are expected to generate a string matching the actual file names on disk, this is
26
- // error prone. Instead, custom sidebar titles should be defined in the frontmatter of the MDX files when needed and
27
- // `site/data/sidebar.yml` should only reference the actual file names and slug extracted from the docs content
28
- // collection. Same goes for the docs frontmatter sections.
28
+ /**
29
+ * Converts a string to a URL-safe slug, collapsing consecutive hyphens.
30
+ *
31
+ * Used by the docs sidebar to derive page slugs from sidebar entry titles and
32
+ * by `DocsLayout` to resolve frontmatter section slugs.
33
+ *
34
+ * @remarks
35
+ * **Known limitation:** the sidebar relies on slugified custom titles matching
36
+ * the actual filenames on disk, which is fragile. The long-term fix is to move
37
+ * slug generation into MDX frontmatter and have `sidebar.yml` reference file
38
+ * names directly. See the `DocsSidebar` component for related context.
39
+ */
29
40
  export function getSlug(str: string) {
30
41
  return slug(str).replace(/--+/g, '-')
31
42
  }
32
43
 
44
+ /** Removes leading and trailing slashes from a URL path segment. */
33
45
  export function trimLeadingAndTrailingSlashes(str: string) {
34
46
  return str.replace(/^\/+|\/+$/g, '')
35
47
  }
36
48
 
49
+ /**
50
+ * Strips Markdown formatting from a string, returning plain text.
51
+ * Useful for generating clean meta descriptions from Markdown content.
52
+ */
37
53
  export function stripMarkdown(str: string) {
38
54
  return toString(fromMarkdown(str))
39
55
  }
40
56
 
57
+ /**
58
+ * Converts a Markdown string to an HTML string synchronously.
59
+ * Intended for short inline content such as page descriptions.
60
+ */
41
61
  export function processMarkdownToHtml(markdown: string): string {
42
- // Use remark to process markdown to HTML
43
62
  const result = remark().use(remarkHtml).processSync(markdown)
44
63
  return result.toString()
45
64
  }
46
65
 
66
+ /**
67
+ * Converts a string to title case (first letter of each word uppercased,
68
+ * remaining letters lowercased).
69
+ *
70
+ * @example titleCase('hello world') // 'Hello World'
71
+ */
47
72
  export function titleCase(str: string) {
48
73
  return str.replace(
49
74
  /\w\S*/g,
50
75
  (text) => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
51
76
  )
52
77
  }
53
-
54
- /**
55
- * Gets the appropriate host and port for development server
56
- * @returns {object} Object with host and port properties
57
- */
58
- function getDevHost() {
59
- const hasHostFlag = process.argv.includes('--host')
60
- let host = 'localhost'
61
- let port = 4321
62
-
63
- // Check for --port command line argument (e.g., astro dev --port 4322)
64
- const portFlagIndex = process.argv.findIndex((arg) => arg === '--port')
65
- if (portFlagIndex !== -1 && process.argv[portFlagIndex + 1]) {
66
- const cliPort = parseInt(process.argv[portFlagIndex + 1], 10)
67
- if (!isNaN(cliPort) && cliPort > 0 && cliPort < 65536) {
68
- port = cliPort
69
- }
70
- }
71
-
72
- // Check for PORT environment variable (most common way to override port)
73
- if (process.env.PORT) {
74
- const envPort = parseInt(process.env.PORT, 10)
75
- if (!isNaN(envPort) && envPort > 0 && envPort < 65536) {
76
- port = envPort
77
- }
78
- }
79
-
80
- // Determine host based on --host flag
81
- if (hasHostFlag) {
82
- const interfaces = os.networkInterfaces()
83
- for (const iface of Object.values(interfaces).flat()) {
84
- if (iface?.family === 'IPv4' && !iface.internal) {
85
- host = iface.address
86
- break
87
- }
88
- }
89
- }
90
-
91
- return { host, port }
92
- }
93
-
94
- /**
95
- * Determines the site URL based on environment and deployment context
96
- * @returns {string} The appropriate site URL for the current environment
97
- */
98
- export function getSiteUrl(config: any) {
99
- // Check for explicit SITE_URL override first
100
- if (process.env.SITE_URL) {
101
- return process.env.SITE_URL
102
- }
103
-
104
- // Development: Local server with optional network access
105
- if (process.env.NODE_ENV === 'development') {
106
- const { host, port } = getDevHost()
107
- return `http://${host}:${port}`
108
- }
109
-
110
- // Vercel Production: Prefer config.baseURL because it already has the correct
111
- // path-prefixed chassis-ui.com URL (e.g. https://chassis-ui.com/tokens/).
112
- // VERCEL_PROJECT_PRODUCTION_URL is the sub-project's own custom domain
113
- // (e.g. tokens.chassis-ui.com) which is NOT the canonical URL we want in sitemaps.
114
- if (process.env.VERCEL_ENV === 'production') {
115
- return config.baseURL || `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
116
- }
117
-
118
- // Vercel Preview: Branch deployments and previews
119
- if (process.env.VERCEL_URL) {
120
- return `https://${process.env.VERCEL_URL}`
121
- }
122
-
123
- // Fallback: Use baseURL from config.yml
124
- return config.baseURL
125
- }
@@ -0,0 +1,45 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import type { Plugin } from 'vite'
4
+
5
+ // Virtual module URL served by Vite's module graph at /@id/__x00__chassis-bundle.
6
+ // Used to give the browser a single shared ESM instance of the chassis bundle in dev.
7
+ const CHASSIS_BUNDLE_VIRTUAL_URL = '/@id/__x00__chassis-bundle'
8
+
9
+ /**
10
+ * Vite plugin that resolves `@chassis-ui/css` to a virtual module in dev so
11
+ * both the `<script>` tag and any `import()` share one ESM instance.
12
+ *
13
+ * In build, `rollupOptions.external` + `paths` in the consuming `astro.config.ts`
14
+ * handles deduplication instead.
15
+ *
16
+ * @param getChassisCSSFsPath - Returns the absolute path to the compiled Chassis CSS dist folder.
17
+ */
18
+ export function chassisBundlePlugin(getChassisCSSFsPath: () => string) {
19
+ return {
20
+ plugin: {
21
+ name: 'chassis-ui-css',
22
+ enforce: 'pre',
23
+ apply: 'serve',
24
+ resolveId(id: string) {
25
+ if (id === '@chassis-ui/css') return '\0@chassis-ui/css'
26
+ if (id === '/@chassis-bundle') return '\0chassis-bundle'
27
+ },
28
+ load(id: string) {
29
+ if (id === '\0@chassis-ui/css') return `export * from "/@chassis-bundle"`
30
+ if (id === '\0chassis-bundle') {
31
+ const bundlePath = path.join(getChassisCSSFsPath(), 'js/chassis.bundle.js')
32
+ const content = fs.readFileSync(bundlePath, 'utf-8')
33
+ // Strip sourceMappingURL — the map isn't resolvable from a virtual module URL.
34
+ return content.replace(/^\/\/# sourceMappingURL=.+$/m, '')
35
+ }
36
+ }
37
+ } satisfies Plugin,
38
+ // __CHASSIS_JS_SRC__ is a @chassis-ui/docs extension point: sets the URL for the
39
+ // chassis JS <script> tag in dev mode. Points at the virtual module so the browser
40
+ // gets one shared ESM instance instead of a second copy from public/.
41
+ define: {
42
+ 'globalThis.__CHASSIS_JS_SRC__': JSON.stringify(CHASSIS_BUNDLE_VIRTUAL_URL)
43
+ }
44
+ }
45
+ }
@@ -1,21 +1,25 @@
1
- .anchor-link {
2
- padding: 0 .175rem;
3
- font-weight: 400;
4
- color: rgba($link-main, .5);
5
- text-decoration: none;
6
- opacity: 0;
7
- @include transition(color .15s ease-in-out, opacity .15s ease-in-out);
1
+ @use "@chassis-ui/css/scss/config" as *;
2
+ @use "@chassis-ui/css/scss/mixins" as *;
3
+ @use "@chassis-ui/css/scss/functions" as *;
8
4
 
9
- &::after {
10
- content: "#";
11
- }
12
-
13
- &:focus,
14
- &:hover,
15
- :hover > &,
16
- :target > & {
5
+ @layer custom {
6
+ .anchor-link {
7
+ padding: 0 .175rem;
8
+ font-weight: 400;
17
9
  color: $link-main;
18
10
  text-decoration: none;
19
- opacity: 1;
11
+ opacity: 0;
12
+ @include transition(color .15s ease-in-out, opacity .15s ease-in-out);
13
+
14
+ &::after {
15
+ content: "#";
16
+ }
17
+
18
+ &:focus,
19
+ &:hover,
20
+ :hover > &,
21
+ :target > & {
22
+ opacity: 1;
23
+ }
20
24
  }
21
25
  }
@@ -1,40 +1,41 @@
1
+ @use "./vars" as *;
2
+
1
3
  //
2
4
  // Callouts
3
5
  //
4
6
 
5
- .cxd-callout {
6
- --#{$prefix}link-main-color-rgb: var(--cxd-callout-link);
7
- --#{$prefix}code-color: var(--cxd-callout-code-color);
8
-
9
- padding: 1.25rem;
10
- margin-top: 1.25rem;
11
- margin-bottom: 1.25rem;
12
- color: var(--cxd-callout-color, inherit);
13
- background-color: var(--cxd-callout-bg, var(--cx-gray-100));
14
- border-left: .25rem solid var(--cxd-callout-border, var(--cx-gray-300));
7
+ @layer custom {
8
+ .cxd-callout {
9
+ padding: 1.25rem;
10
+ margin-block-start: 1.25rem;
11
+ margin-block-end: 1.25rem;
12
+ color: var(--cxd-callout-color, inherit);
13
+ background-color: var(--cxd-callout-bg, var(--cx-neutral-bg-even));
14
+ border-inline-start: .25rem solid var(--cxd-callout-border, var(--cx-neutral-border-main));
15
15
 
16
- h4 {
17
- margin-bottom: .25rem;
18
- }
16
+ h4 {
17
+ margin-block-end: .25rem;
18
+ }
19
19
 
20
- > :last-child {
21
- margin-bottom: 0;
22
- }
20
+ > :last-child {
21
+ margin-block-end: 0;
22
+ }
23
23
 
24
- + .cxd-callout {
25
- margin-top: -.25rem;
26
- }
24
+ + .cxd-callout {
25
+ margin-block-start: -.25rem;
26
+ }
27
27
 
28
- .highlight {
29
- background-color: rgba($black, .05);
28
+ .cxd-code {
29
+ background-color: rgba($black, .05);
30
+ }
30
31
  }
31
- }
32
32
 
33
- // Variations
34
- @each $variant in $cxd-callout-variants {
35
- .cxd-callout-#{$variant} {
36
- --cxd-callout-color: var(--cx-#{$variant}-fg-main);
37
- --cxd-callout-bg: var(--cx-#{$variant}-bg-even);
38
- --cxd-callout-border: var(--cx-#{$variant}-border-subtle);
33
+ // Variations
34
+ @each $variant in $cxd-callout-variants {
35
+ .cxd-callout-#{$variant} {
36
+ --cxd-callout-color: var(--cx-#{$variant}-fg-main);
37
+ --cxd-callout-bg: var(--cx-#{$variant}-bg-even);
38
+ --cxd-callout-border: var(--cx-#{$variant}-border-subtle);
39
+ }
39
40
  }
40
41
  }
@@ -1,141 +1,110 @@
1
+ @use "@chassis-ui/css/scss/config" as *;
2
+ @use "@chassis-ui/css/scss/mixins" as *;
3
+
1
4
  //
2
5
  // Chassis - CSS docs content theming
3
6
  //
4
7
 
5
- .cxd-content {
6
- padding-bottom: 2rem;
7
- > h2,
8
- > h3,
9
- > h4 {
10
- --cx-heading-color: var(--cx-fg-main);
11
- }
12
-
13
- // Offset content from fixed navbar when jumping to headings
14
- > h2:not(:first-child) {
15
- margin-top: 3rem;
16
- }
17
-
18
- > h3 {
19
- margin-top: 2rem;
20
- }
21
-
22
- > ul li,
23
- > ol li {
24
- margin-bottom: .25rem;
8
+ @layer custom {
9
+ .cxd-content {
10
+ padding-block-end: 2rem;
11
+ > h2,
12
+ > h3,
13
+ > h4 {
14
+ --cx-heading-color: var(--cx-fg-main);
15
+ }
25
16
 
26
- // stylelint-disable selector-max-type, selector-max-compound-selectors
27
- > p ~ ul {
28
- margin-top: -.5rem;
29
- margin-bottom: 1rem;
17
+ // Offset content from fixed navbar when jumping to headings
18
+ > h2:not(:first-child) {
19
+ margin-block-start: 3rem;
30
20
  }
31
- // stylelint-enable selector-max-type, selector-max-compound-selectors
32
- }
33
21
 
34
- // Override Chassis - CSS defaults
35
- > .table,
36
- > .table-responsive .table {
37
- // --cx-table-border-color: var(--cx-border-color);
22
+ > h3 {
23
+ margin-block-start: 2rem;
24
+ }
38
25
 
39
- max-width: 100%;
40
- margin-bottom: 1.5rem;
41
- @include font-size(.875rem);
26
+ > ul li,
27
+ > ol li {
28
+ margin-block-end: .25rem;
42
29
 
43
- @include media-breakpoint-down(large) {
44
- &.table-bordered {
45
- border: 0;
30
+ // stylelint-disable-next-line selector-max-type, selector-max-compound-selectors
31
+ > p ~ ul {
32
+ margin-block-start: -.5rem;
33
+ margin-block-end: 1rem;
46
34
  }
47
35
  }
48
36
 
49
- thead {
50
- border-bottom: 2px solid currentcolor;
37
+ > ol > li {
38
+ &:has(:where(h3, h4):first-child)::marker {
39
+ @include font-size(var(--cx-font-size-xlarge));
40
+ font-weight: var(--cx-font-weight-strong);
41
+ }
51
42
  }
52
43
 
53
- tbody:not(:first-child) {
54
- border-top: 2px solid currentcolor;
44
+ // Override Chassis - CSS defaults
45
+ > .table,
46
+ > .table-responsive .table {
47
+ max-width: 100%;
48
+ margin-block-end: 1.5rem;
49
+ th,
50
+ td:first-child > code { // stylelint-disable-line selector-max-compound-selectors
51
+ white-space: nowrap;
52
+ }
55
53
  }
56
54
 
57
- th,
58
- td {
59
- &:first-child {
60
- padding-left: 0;
61
- }
55
+ }
62
56
 
63
- &:not(:last-child) {
64
- padding-right: 1.5rem;
65
- }
57
+ a:has(code) {
58
+ text-decoration: none;
59
+ > code {
60
+ color: var(--cx-link-color);
66
61
  }
62
+ }
67
63
 
68
- th {
69
- color: var(--cx-fg-main);
64
+ .table-options {
65
+ td:nth-child(2) {
66
+ min-width: 160px;
70
67
  }
68
+ }
71
69
 
72
- strong {
70
+ .table-options td:last-child,
71
+ .table-utilities td:last-child {
72
+ min-width: 280px;
73
+ }
74
+
75
+ .table-swatches {
76
+ th {
73
77
  color: var(--cx-fg-main);
74
78
  }
75
79
 
76
- // Prevent breaking of code
77
- th,
78
- td:first-child > code { // stylelint-disable-line selector-max-compound-selectors
80
+ td code {
79
81
  white-space: nowrap;
80
82
  }
81
83
  }
82
- }
83
84
 
84
- .table-options {
85
- td:nth-child(2) {
86
- min-width: 160px;
85
+ .cxd-title {
86
+ --cx-heading-color: var(--cx-fg-main);
87
+ --cx-font-size: 3rem;
87
88
  }
88
- }
89
-
90
- .table-options td:last-child,
91
- .table-utilities td:last-child {
92
- min-width: 280px;
93
- }
94
89
 
95
- .table-swatches {
96
- th {
97
- color: var(--cx-fg-main);
90
+ .cxd-subtitle {
91
+ @include map-font($font-context-lead, "blockquote");
92
+ @include font();
98
93
  }
99
94
 
100
- td code {
101
- white-space: nowrap;
95
+ .border-large-start {
96
+ @include media-breakpoint-up(large) {
97
+ border-inline-start: var(--cx-border-width) solid var(--cx-border-color);
98
+ }
102
99
  }
103
- }
104
100
 
105
- .cxd-title {
106
- --cx-heading-color: var(--cx-fg-main);
107
- --cx-font-size: 3rem;
108
- }
109
-
110
- .cxd-subtitle {
111
- @include map-font($font-context-lead, "blockquote");
112
- @include font();
113
- // font-size: 1.2rem;
114
- // line-height: 1.5em;
115
- // font-family: var(--cx-font-family-display) !important;
116
- }
117
-
118
- .bi {
119
- width: 1em;
120
- height: 1em;
121
- vertical-align: -.125em;
122
- fill: currentcolor;
123
- }
101
+ .cxd-summary-link {
102
+ color: var(--cx-link-color);
124
103
 
125
- .border-large-start {
126
- @include media-breakpoint-up(large) {
127
- border-left: var(--cx-border-width) solid var(--cx-border-color);
104
+ &:hover,
105
+ details[open] > & { // stylelint-disable-line selector-no-qualifying-type
106
+ color: var(--cx-hover-color);
107
+ }
128
108
  }
129
- }
130
-
131
- // stylelint-disable selector-no-qualifying-type
132
- .cxd-summary-link {
133
- color: var(--cx-link-color);
134
109
 
135
- &:hover,
136
- details[open] > & {
137
- color: var(--cx-hover-color);
138
- }
139
110
  }
140
- // stylelint-enable selector-no-qualifying-type
141
-