@pnx-mixtape/mxds 0.1.0-rc.4 → 0.1.0-rc.6

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 (236) hide show
  1. package/.claude/skills/create-mxds-component/SKILL.md +77 -0
  2. package/DESIGN.md +595 -0
  3. package/README.md +2 -3
  4. package/dist/build/accordion.entry.js +2 -1
  5. package/dist/build/autocomplete.entry.js +1 -1
  6. package/dist/build/back-to-top.css +1 -0
  7. package/dist/build/back-to-top.entry.js +1 -0
  8. package/dist/build/base.css +1 -1
  9. package/dist/build/button.css +1 -1
  10. package/dist/build/card.css +1 -1
  11. package/dist/build/chunks/Accordion-Bqe8vTNR.js +44 -0
  12. package/dist/build/chunks/AccordionGroup-BYtoAFxg.js +47 -0
  13. package/dist/build/chunks/AccordionMobile-D517oXYZ.js +26 -0
  14. package/dist/build/chunks/Autocomplete-kRo8RNbC.js +135 -0
  15. package/dist/build/chunks/BackToTop-4M-Wl7z3.js +64 -0
  16. package/dist/build/chunks/ClosableAlert-CZ114JsL.js +55 -0
  17. package/dist/build/chunks/CookieConsent-wd8gQ2Oe.js +18 -0
  18. package/dist/build/chunks/Dialog-DoYcGqhW.js +48 -0
  19. package/dist/build/chunks/DropMenu-CSTZq0Zt.js +68 -0
  20. package/dist/build/chunks/FeedbackForm-BsL7fv8s.js +64 -0
  21. package/dist/build/chunks/Gallery-DqJPujX5.js +165 -0
  22. package/dist/build/chunks/GlobalToggle-7H3F1Wvc.js +82 -0
  23. package/dist/build/chunks/InPageNavigation-D7m3IN89.js +86 -0
  24. package/dist/build/chunks/Navigation-CRModT40.js +142 -0
  25. package/dist/build/chunks/Popover-CiTAftNU.js +30 -0
  26. package/dist/build/chunks/Sticky-C1H8MNqK.js +51 -0
  27. package/dist/build/chunks/Tabs-BJD3kABL.js +160 -0
  28. package/dist/build/chunks/Translate-yAgySwet.js +46 -0
  29. package/dist/build/chunks/cookie-compliance-CG6x-TcV.js +119 -0
  30. package/dist/build/chunks/enums-BrHxPZZ_.js +36 -0
  31. package/dist/build/chunks/polyfills-D-qh1a_2.js +33 -0
  32. package/dist/build/chunks/utilities-B9mNRs7V.js +255 -0
  33. package/dist/build/content-block.css +1 -1
  34. package/dist/build/cookie-consent.entry.js +1 -1
  35. package/dist/build/dialog.entry.js +1 -1
  36. package/dist/build/drop-menu.entry.js +1 -1
  37. package/dist/build/elements.js +147 -1
  38. package/dist/build/feedback-form.css +1 -0
  39. package/dist/build/feedback-form.entry.js +1 -0
  40. package/dist/build/filters.entry.js +145 -1
  41. package/dist/build/form.css +1 -1
  42. package/dist/build/gallery.entry.js +1 -1
  43. package/dist/build/global-alert.entry.js +1 -1
  44. package/dist/build/header.css +1 -1
  45. package/dist/build/header.entry.js +1 -1
  46. package/dist/build/icon.css +1 -1
  47. package/dist/build/in-page-navigation.entry.js +1 -1
  48. package/dist/build/navigation.css +1 -1
  49. package/dist/build/navigation.entry.js +1 -1
  50. package/dist/build/pagination.css +1 -1
  51. package/dist/build/popover.entry.js +1 -1
  52. package/dist/build/react.js +2291 -1
  53. package/dist/build/side-navigation.css +1 -1
  54. package/dist/build/sidebar.css +1 -1
  55. package/dist/build/sticky.entry.js +1 -1
  56. package/dist/build/tabs.entry.js +1 -1
  57. package/dist/build/translate.css +1 -0
  58. package/dist/build/translate.entry.js +1 -0
  59. package/dist/build/utility-list.entry.js +53 -1
  60. package/dist/types/Component/BackToTop/BackToTop.d.ts +20 -0
  61. package/dist/types/Component/BackToTop/BackToTop.d.ts.map +1 -0
  62. package/dist/types/Component/BackToTop/Elements/BackToTop.d.ts +27 -0
  63. package/dist/types/Component/BackToTop/Elements/BackToTop.d.ts.map +1 -0
  64. package/dist/types/Component/BackToTop/back-to-top.entry.d.ts +2 -0
  65. package/dist/types/Component/BackToTop/back-to-top.entry.d.ts.map +1 -0
  66. package/dist/types/Component/DropMenu/DropMenu.d.ts +2 -1
  67. package/dist/types/Component/DropMenu/DropMenu.d.ts.map +1 -1
  68. package/dist/types/Component/Navigation/Elements/Navigation.d.ts +2 -3
  69. package/dist/types/Component/Navigation/Elements/Navigation.d.ts.map +1 -1
  70. package/dist/types/Component/SideNavigation/Components/SideNavigationTree.d.ts +3 -3
  71. package/dist/types/Component/SideNavigation/Components/SideNavigationTree.d.ts.map +1 -1
  72. package/dist/types/Component/SideNavigation/SideNavigation.d.ts +3 -1
  73. package/dist/types/Component/SideNavigation/SideNavigation.d.ts.map +1 -1
  74. package/dist/types/Component/Tabs/Components/TabDropMenu.d.ts.map +1 -1
  75. package/dist/types/Component/Tabs/Elements/Tabs.d.ts.map +1 -1
  76. package/dist/types/Component/Translate/Elements/Translate.d.ts +23 -0
  77. package/dist/types/Component/Translate/Elements/Translate.d.ts.map +1 -0
  78. package/dist/types/Component/Translate/Translate.d.ts +37 -0
  79. package/dist/types/Component/Translate/Translate.d.ts.map +1 -0
  80. package/dist/types/Component/Translate/languages.d.ts +11 -0
  81. package/dist/types/Component/Translate/languages.d.ts.map +1 -0
  82. package/dist/types/Component/Translate/translate.entry.d.ts +2 -0
  83. package/dist/types/Component/Translate/translate.entry.d.ts.map +1 -0
  84. package/dist/types/Form/FeedbackForm/Elements/FeedbackForm.d.ts +37 -0
  85. package/dist/types/Form/FeedbackForm/Elements/FeedbackForm.d.ts.map +1 -0
  86. package/dist/types/Form/FeedbackForm/FeedbackForm.d.ts +36 -0
  87. package/dist/types/Form/FeedbackForm/FeedbackForm.d.ts.map +1 -0
  88. package/dist/types/Form/FeedbackForm/feedback-form.entry.d.ts +2 -0
  89. package/dist/types/Form/FeedbackForm/feedback-form.entry.d.ts.map +1 -0
  90. package/dist/types/Utility/Elements/google-translate-widget.d.ts +91 -0
  91. package/dist/types/Utility/Elements/google-translate-widget.d.ts.map +1 -0
  92. package/dist/types/Utility/utilities.d.ts +2 -0
  93. package/dist/types/Utility/utilities.d.ts.map +1 -1
  94. package/dist/types/elements.d.ts +3 -0
  95. package/dist/types/elements.d.ts.map +1 -1
  96. package/dist/types/enums.d.ts +3 -1
  97. package/dist/types/enums.d.ts.map +1 -1
  98. package/dist/types/react.d.ts +3 -0
  99. package/dist/types/react.d.ts.map +1 -1
  100. package/dist/types/tokens.d.ts +1 -0
  101. package/dist/types/tokens.d.ts.map +1 -1
  102. package/docs/API.md +1215 -0
  103. package/docs/CSSGuidelines.md +893 -0
  104. package/docs/CodeQuality.md +940 -0
  105. package/docs/ComponentArchitecture.md +714 -0
  106. package/docs/Contributing.md +626 -0
  107. package/docs/MemoryManagement.md +598 -0
  108. package/docs/Migrations.md +6 -0
  109. package/docs/README.md +100 -0
  110. package/docs/Security.md +444 -0
  111. package/docs/Testing.md +739 -0
  112. package/docs/Troubleshooting.md +674 -0
  113. package/package.json +9 -6
  114. package/src/Atom/Button/Button.tsx +1 -1
  115. package/src/Atom/Button/__snapshots__/Button.stories.tsx.snap +2 -2
  116. package/src/Atom/Button/_buttons.css +1 -0
  117. package/src/Atom/Icon/README.md +1 -1
  118. package/src/Atom/Icon/_icon.css +1 -0
  119. package/src/Atom/Icon/images/thumb.svg +1 -0
  120. package/src/Atom/Link/_links.css +1 -0
  121. package/src/Atom/Media/__snapshots__/Media.stories.ts.snap +4 -9
  122. package/src/Atom/Media/media.twig +4 -5
  123. package/src/Component/BackToTop/BackToTop.stories.ts +127 -0
  124. package/src/Component/BackToTop/BackToTop.stories.tsx +53 -0
  125. package/src/Component/BackToTop/BackToTop.tsx +120 -0
  126. package/src/Component/BackToTop/Elements/BackToTop.ts +119 -0
  127. package/src/Component/BackToTop/README.md +164 -0
  128. package/src/Component/BackToTop/__snapshots__/BackToTop.stories.ts.snap +24 -0
  129. package/src/Component/BackToTop/__snapshots__/BackToTop.stories.tsx.snap +3 -0
  130. package/src/Component/BackToTop/back-to-top.css +70 -0
  131. package/src/Component/BackToTop/back-to-top.entry.js +1 -0
  132. package/src/Component/BackToTop/back-to-top.twig +26 -0
  133. package/src/Component/Card/Components/CardContent.tsx +1 -1
  134. package/src/Component/Card/Components/CardMedia.tsx +1 -1
  135. package/src/Component/Card/__snapshots__/Card.stories.tsx.snap +3 -3
  136. package/src/Component/Card/card.css +1 -1
  137. package/src/Component/Carousel/Carousel.stories.ts +66 -36
  138. package/src/Component/Carousel/__snapshots__/Carousel.stories.tsx.snap +5 -5
  139. package/src/Component/ContentBlock/Components/ContentBlockMedia.tsx +1 -1
  140. package/src/Component/ContentBlock/content-block.css +1 -1
  141. package/src/Component/DropMenu/DropMenu.stories.ts +21 -2
  142. package/src/Component/DropMenu/DropMenu.tsx +14 -4
  143. package/src/Component/DropMenu/__snapshots__/DropMenu.stories.ts.snap +3 -3
  144. package/src/Component/DropMenu/__snapshots__/DropMenu.stories.tsx.snap +2 -2
  145. package/src/Component/DropMenu/drop-menu.twig +7 -1
  146. package/src/Component/HeroBanner/__snapshots__/HeroBanner.stories.tsx.snap +1 -1
  147. package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.ts.snap +48 -13
  148. package/src/Component/InPageNavigation/in-page-navigation.twig +4 -6
  149. package/src/Component/ListItem/Components/ListItemMedia.tsx +1 -1
  150. package/src/Component/Navigation/Elements/Navigation.ts +25 -29
  151. package/src/Component/Navigation/README.md +11 -10
  152. package/src/Component/Navigation/__snapshots__/Navigation.stories.ts.snap +8 -8
  153. package/src/Component/Navigation/_navigation-dropdown.css +9 -11
  154. package/src/Component/Navigation/_navigation-mega.css +5 -11
  155. package/src/Component/Navigation/_navigation.css +5 -3
  156. package/src/Component/Navigation/menu.twig +1 -1
  157. package/src/Component/Navigation/navigation.twig +0 -1
  158. package/src/Component/Pagination/Pagination.stories.ts +57 -27
  159. package/src/Component/Pagination/pagination.css +16 -7
  160. package/src/Component/Popover/__snapshots__/Popover.stories.tsx.snap +3 -3
  161. package/src/Component/SideNavigation/Components/SideNavigationTree.tsx +68 -24
  162. package/src/Component/SideNavigation/README.md +78 -32
  163. package/src/Component/SideNavigation/SideNavigation.stories.ts +41 -2
  164. package/src/Component/SideNavigation/SideNavigation.stories.tsx +31 -0
  165. package/src/Component/SideNavigation/SideNavigation.tsx +13 -3
  166. package/src/Component/SideNavigation/__snapshots__/SideNavigation.stories.ts.snap +87 -3
  167. package/src/Component/SideNavigation/__snapshots__/SideNavigation.stories.tsx.snap +2 -0
  168. package/src/Component/SideNavigation/side-navigation.css +3 -3
  169. package/src/Component/SideNavigation/side-navigation.twig +10 -3
  170. package/src/Component/Tabs/Components/TabDropMenu.tsx +7 -1
  171. package/src/Component/Tabs/Elements/Tabs.ts +13 -3
  172. package/src/Component/Tabs/Tabs.stories.ts +33 -12
  173. package/src/Component/Tabs/Tabs.stories.tsx +28 -14
  174. package/src/Component/Tabs/__snapshots__/Tabs.stories.ts.snap +3 -3
  175. package/src/Component/Tabs/__snapshots__/Tabs.stories.tsx.snap +2 -2
  176. package/src/Component/Translate/Elements/Translate.ts +76 -0
  177. package/src/Component/Translate/README.md +285 -0
  178. package/src/Component/Translate/Translate.stories.ts +87 -0
  179. package/src/Component/Translate/Translate.stories.tsx +77 -0
  180. package/src/Component/Translate/Translate.tsx +213 -0
  181. package/src/Component/Translate/__snapshots__/Translate.stories.ts.snap +18 -0
  182. package/src/Component/Translate/__snapshots__/Translate.stories.tsx.snap +3 -0
  183. package/src/Component/Translate/languages.ts +39 -0
  184. package/src/Component/Translate/translate.css +62 -0
  185. package/src/Component/Translate/translate.entry.js +1 -0
  186. package/src/Component/Translate/translate.twig +44 -0
  187. package/src/Form/Autocomplete/Autocomplete.stories.tsx +2 -1
  188. package/src/Form/FeedbackForm/Elements/FeedbackForm.ts +122 -0
  189. package/src/Form/FeedbackForm/FeedbackForm.stories.ts +99 -0
  190. package/src/Form/FeedbackForm/FeedbackForm.stories.tsx +73 -0
  191. package/src/Form/FeedbackForm/FeedbackForm.tsx +196 -0
  192. package/src/Form/FeedbackForm/README.md +233 -0
  193. package/src/Form/FeedbackForm/__snapshots__/FeedbackForm.stories.ts.snap +125 -0
  194. package/src/Form/FeedbackForm/__snapshots__/FeedbackForm.stories.tsx.snap +5 -0
  195. package/src/Form/FeedbackForm/feedback-form.css +74 -0
  196. package/src/Form/FeedbackForm/feedback-form.entry.js +1 -0
  197. package/src/Form/FeedbackForm/feedback-form.twig +80 -0
  198. package/src/Form/form.css +17 -19
  199. package/src/Introduction.mdx +1 -1
  200. package/src/Layout/Footer/__snapshots__/Footer.stories.ts.snap +3 -3
  201. package/src/Layout/Header/Components/GlobalToggle.tsx +1 -1
  202. package/src/Layout/Header/Header.stories.ts +53 -48
  203. package/src/Layout/Header/Header.stories.tsx +35 -22
  204. package/src/Layout/Header/Header.tsx +2 -2
  205. package/src/Layout/Header/__snapshots__/Header.stories.ts.snap +18 -14
  206. package/src/Layout/Header/__snapshots__/Header.stories.tsx.snap +2 -2
  207. package/src/Layout/Header/_toggles.css +7 -7
  208. package/src/Layout/Page/__snapshots__/Page.stories.tsx.snap +1 -1
  209. package/src/Layout/Sidebar/sidebar.css +10 -3
  210. package/src/Utility/Elements/google-translate-widget.ts +293 -0
  211. package/src/Utility/global.d.ts +4 -0
  212. package/src/Utility/utilities.ts +2 -0
  213. package/src/_custom-media.css +2 -0
  214. package/src/elements.ts +3 -0
  215. package/src/enums.ts +2 -0
  216. package/src/react.ts +3 -0
  217. package/src/tokens.js +1 -0
  218. package/dist/build/chunks/Accordion-GN0sME4W.js +0 -1
  219. package/dist/build/chunks/AccordionGroup-Bzqp5__q.js +0 -1
  220. package/dist/build/chunks/AccordionMobile-DG5jSe8Q.js +0 -1
  221. package/dist/build/chunks/Autocomplete-B4RtkAyh.js +0 -1
  222. package/dist/build/chunks/ClosableAlert-DEhj8Nxm.js +0 -1
  223. package/dist/build/chunks/CookieConsent-BkCMRVST.js +0 -1
  224. package/dist/build/chunks/Dialog-Haahn-Yn.js +0 -1
  225. package/dist/build/chunks/DropMenu-1baQc8Yc.js +0 -1
  226. package/dist/build/chunks/Gallery-D8NGXy2Q.js +0 -1
  227. package/dist/build/chunks/GlobalToggle-B52fdBQu.js +0 -1
  228. package/dist/build/chunks/InPageNavigation-Dyn2TR-N.js +0 -1
  229. package/dist/build/chunks/Navigation-hOrfLq7h.js +0 -1
  230. package/dist/build/chunks/Popover-Cxg-s5Jn.js +0 -1
  231. package/dist/build/chunks/Sticky-BGCuuEJK.js +0 -1
  232. package/dist/build/chunks/Tabs-DYy1YTdU.js +0 -15
  233. package/dist/build/chunks/cookie-compliance-Bbm-0vpj.js +0 -1
  234. package/dist/build/chunks/enums-DLV_1NAf.js +0 -1
  235. package/dist/build/chunks/polyfills-C7pRt54M.js +0 -1
  236. package/dist/build/chunks/utilities-_Bq3TxAQ.js +0 -1
@@ -0,0 +1,893 @@
1
+ # CSS Guidelines
2
+
3
+ CSS/Styling conventions for the Mixtape Design System.
4
+
5
+ ## Table of Contents
6
+
7
+ - [PostCSS Pipeline](#postcss-pipeline)
8
+ - [BEM Naming](#bem-naming)
9
+ - [File Organization](#file-organization)
10
+ - [Custom Media](#custom-media)
11
+ - [Design Tokens](#design-tokens)
12
+ - [Custom Property Fallbacks](#custom-property-fallbacks)
13
+ - [Color Scheme (light-dark)](#color-scheme-light-dark)
14
+ - [Logical Properties](#logical-properties)
15
+ - [Cascade Layers](#cascade-layers)
16
+
17
+ ---
18
+
19
+ ## PostCSS Pipeline
20
+
21
+ The build process transforms non-standard CSS syntax into valid browser CSS. Understanding these transforms is essential for reading and writing component styles.
22
+
23
+ ### Plugins & What They Do
24
+
25
+ | Plugin | Syntax it handles | Output |
26
+ |---|---|---|
27
+ | `postcss-design-tokens` | `token("spacing.m")` | CSS custom property value |
28
+ | `@csstools/postcss-global-data` | `@media (--medium-up)` | Custom media available globally |
29
+ | `postcss-mixins` | `@define-mixin`, `@add-mixin` | Inline CSS |
30
+ | `postcss-preset-env` (stage 0) | Modern CSS syntax | Cross-browser CSS |
31
+ | `postcss-prepend-layer` | (automatic) | Wraps all CSS in `@layer design-system.*` |
32
+
33
+ ### token() Function
34
+
35
+ The `token()` function is provided by `postcss-design-tokens` and resolves values from `src/tokens.js` at build time:
36
+
37
+ ```css
38
+ /* Source */
39
+ @custom-media --medium-up (width >= token("breakpoint.m"));
40
+ padding: token("spacing.m");
41
+
42
+ /* Compiled output */
43
+ @custom-media --medium-up (width >= 900px);
44
+ padding: 1rem;
45
+ ```
46
+
47
+ Token paths mirror the structure of `src/tokens.js`. See the [Design Tokens](#design-tokens) section for available categories.
48
+
49
+ ### SVG Images
50
+
51
+ SVG files are referenced with a plain `url()` — Vite inlines them as a data URI (or hashes them as an asset) at build time:
52
+
53
+ ```css
54
+ background-image: url("../images/icon-close.svg");
55
+ ```
56
+
57
+ ### Custom Media Queries
58
+
59
+ Custom media queries (defined in `src/_custom-media.css`) use `@csstools/postcss-global-data` to make them available to every file without needing an explicit `@import`. At build time they compile to standard `@media` queries:
60
+
61
+ ```css
62
+ /* Source */
63
+ @media (--medium-up) { ... }
64
+
65
+ /* Compiled output */
66
+ @media (width >= 900px) { ... }
67
+ ```
68
+
69
+ The full list of available custom media names is in the [Custom Media](#custom-media) section.
70
+
71
+ ---
72
+
73
+ ## BEM Naming
74
+
75
+ ### Structure
76
+
77
+ Block Element Modifier (BEM) methodology is **strictly enforced** by Stylelint.
78
+
79
+ ```css
80
+ /* Block: Component/standalone entity */
81
+ .mx-card {
82
+ }
83
+
84
+ /* Element: Part of block */
85
+ .mx-card__header {
86
+ }
87
+ .mx-card__body {
88
+ }
89
+ .mx-card__footer {
90
+ }
91
+
92
+ /* Modifier: Variation of block or element */
93
+ .mx-card--reversed {
94
+ }
95
+ .mx-card--block {
96
+ }
97
+ .mx-card__header--large {
98
+ }
99
+ ```
100
+
101
+ ### Naming Rules
102
+
103
+ ✅ **Allowed:**
104
+
105
+ ```css
106
+ .mx-component /* Block */
107
+ .mx-component__element /* Element */
108
+ .mx-component--modifier /* Modifier */
109
+ .mx-component__element--modifier /* Element with modifier */
110
+ ```
111
+
112
+ ❌ **Not Allowed:**
113
+
114
+ ```css
115
+ .mx-component-element /* Wrong separator */
116
+ .mx-component.modifier /* Not BEM */
117
+ .mx-componentElement /* camelCase not allowed */
118
+ .component /* Missing mx- prefix */
119
+ ```
120
+
121
+ ### Prefix Convention
122
+
123
+ All design system classes use the `mx-` prefix:
124
+
125
+ - **mx** = Mixtape
126
+ - Prevents conflicts with consumer styles
127
+ - Clear namespace for design system components
128
+
129
+ ### Nesting with &
130
+
131
+ ```css
132
+ /* ✅ GOOD - Use & for nesting, reduce specificity */
133
+ .mx-card {
134
+ display: flex;
135
+ }
136
+
137
+ .mx-card--reversed {
138
+ flex-direction: row-reverse;
139
+ }
140
+
141
+ .mx-card__media {
142
+ & img {
143
+ aspect-ratio: var(--ratio);
144
+ }
145
+ }
146
+ ```
147
+
148
+ ### Stylelint Enforcement
149
+
150
+ Your `.stylelintrc.json` enforces BEM:
151
+
152
+ ```javascript
153
+ "selector-class-pattern": [
154
+ "^([a-z])([a-z0-9]+)((-[a-z0-9]+)+)?(((--)?(__)?)([a-z0-9]+)((-[a-z0-9]+)+)?)?(((--)?(__)?)([a-z0-9]+)((-[a-z0-9]+)+)?)?$",
155
+ {
156
+ message: "Expected class selector to be BEM selector matching either .block__element or .block--modifier"
157
+ }
158
+ ]
159
+ ```
160
+
161
+ ---
162
+
163
+ ## File Organization
164
+
165
+ ### Component Structure
166
+
167
+ Components provide multiple CSS files for flexibility:
168
+
169
+ ```
170
+ Component/
171
+ ├── component.css # Public API - imports all partials
172
+ ├── _component-base.css # Base styles (partial)
173
+ ├── _component-modifiers.css # Modifier variations (partial)
174
+ ```
175
+
176
+ #### Example: Button component
177
+
178
+ ```
179
+ Button/
180
+ ├── button.css # Full button styles (imports both partials)
181
+ ├── _buttons.css # Base button styles
182
+ └── _buttons-styles.css # Button style variations
183
+ ```
184
+
185
+ ### Import Patterns
186
+
187
+ You can import the **full component** or **individual partials** depending on your needs:
188
+
189
+ #### Option 1: Import Full Component (Recommended)
190
+
191
+ ```css
192
+ /* Gets all button styles */
193
+ @import "@pnx-mixtape/mxds/src/Atom/Button/button.css";
194
+ ```
195
+
196
+ This is the simplest approach and includes all styles for the component.
197
+
198
+ #### Option 2: Import Partials (Granular Control)
199
+
200
+ ```css
201
+ /* Import only what you need */
202
+ @import "@pnx-mixtape/mxds/src/Atom/Button/_buttons.css";
203
+ @import "@pnx-mixtape/mxds/src/Atom/Button/_buttons-styles.css";
204
+
205
+ /* Then override specific styles */
206
+ .mx-button--primary {
207
+ --button-background: var(--colour-brand-primary);
208
+ }
209
+ ```
210
+
211
+ Use this when you:
212
+
213
+ - Only need specific parts of a component
214
+ - Want to customize before other styles load
215
+ - Need finer control over what's included
216
+
217
+ ### Partial Files Convention
218
+
219
+ Files prefixed with underscore are **partials**:
220
+
221
+ - `_component-base.css` - Internal partial, can be imported separately
222
+ - `component.css` - Public API, imports all partials
223
+
224
+ **Why use partials?**
225
+
226
+ - Modular - Import only what you need
227
+ - Customizable - Override between partial imports
228
+ - Flexible - Mix and match for your use case
229
+
230
+ ---
231
+
232
+ ## Custom Media
233
+
234
+ ### Always Import
235
+
236
+ This is only required if you're not using something like [@csstools/postcss-global-data](https://www.npmjs.com/package/@csstools/postcss-global-data).
237
+
238
+ Import custom media in every CSS file that uses them:
239
+
240
+ ```css
241
+ /* MUST be first import in every file */
242
+ @import "../../_custom-media.css";
243
+
244
+ .mx-component {
245
+ display: block;
246
+
247
+ @media (--medium-up) {
248
+ display: flex;
249
+ }
250
+ }
251
+ ```
252
+
253
+ ### Available Breakpoints
254
+
255
+ ```css
256
+ /* Mobile first breakpoints */
257
+ @media (--x-small-up) /* >= 375px */
258
+ @media (--small-up) /* >= 600px */
259
+ @media (--medium-up) /* >= 900px */
260
+ @media (--large-up) /* >= 1200px */
261
+ @media (--x-large-up) /* >= 1800px */
262
+
263
+ /* Desktop first breakpoints */
264
+ @media (--x-small-down) /* < 375px */
265
+ @media (--small-down) /* < 600px */
266
+ @media (--medium-down) /* < 900px */
267
+ @media (--large-down) /* < 1200px */
268
+ @media (--x-large-down) /* < 1800px */
269
+
270
+ /* Between breakpoints */
271
+ @media (--x-small-to-small) /* 375px to 600px */
272
+ @media (--small-to-medium) /* 600px to 900px */
273
+ @media (--medium-to-large) /* 900px to 1200px */
274
+ @media (--large-to-x-large) /* 1200px to 1800px */
275
+
276
+ /* Special breakpoints */
277
+ @media (--global-nav-up) /* >= 720px - Navigation breakpoint */
278
+ @media (--global-nav-down) /* < 720px */
279
+ @media (--collapse-card-up) /* >= 400px - Card collapse */
280
+ @media (--collapse-card-down) /* < 400px */
281
+ @media (--sidebar-up) /* >= 720px - Sidebar breakpoint */
282
+ @media (--sidebar-down) /* < 720px */
283
+
284
+ /* Interaction */
285
+ @media (--touch) /* Touch devices (no hover) */
286
+ @media (--mouse) /* Mouse devices (has hover) */
287
+ ```
288
+
289
+ ### Mobile First Approach
290
+
291
+ ```css
292
+ /* ✅ GOOD - Mobile first */
293
+ .mx-component {
294
+ /* Mobile styles (default) */
295
+ display: block;
296
+ padding: 1rem;
297
+
298
+ /* Tablet */
299
+ @media (--medium-up) {
300
+ display: flex;
301
+ padding: 2rem;
302
+ }
303
+
304
+ /* Desktop */
305
+ @media (--large-up) {
306
+ padding: 3rem;
307
+ }
308
+ }
309
+
310
+ /* ❌ BAD - Desktop first */
311
+ .mx-component {
312
+ display: flex; /* Desktop default */
313
+
314
+ @media (--medium-down) {
315
+ display: block; /* Override for mobile */
316
+ }
317
+ }
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Design Tokens
323
+
324
+ ### How Tokens Work
325
+
326
+ Design tokens in `src/tokens.js` are used during the build process to generate `src/constants.css`, which defines all CSS custom properties. Load this file once at the page level to make all custom properties available globally. Components can then use these custom properties for consistent styling.
327
+
328
+ **Workflow:**
329
+
330
+ 1. Define/override tokens in `src/tokens.js`
331
+ 2. Build process generates `src/constants.css` with CSS custom properties
332
+ 3. Components use the custom properties
333
+
334
+ ### Using Custom Properties
335
+
336
+ ```css
337
+ .mx-component {
338
+ /* Colors */
339
+ color: var(--colour-foreground);
340
+ background: var(--colour-background);
341
+
342
+ /* Spacing */
343
+ padding: var(--spacing-m);
344
+ margin-block-start: var(--spacing-l);
345
+
346
+ /* Typography */
347
+ font-size: var(--font-size-m);
348
+ line-height: var(--line-height);
349
+
350
+ /* Layout */
351
+ max-inline-size: var(--container-max-width);
352
+ gap: var(--spacing-s);
353
+
354
+ /* Borders */
355
+ border-radius: var(--border-radius);
356
+ }
357
+ ```
358
+
359
+ ### Available Token Categories
360
+
361
+ The `src/tokens.js` file defines tokens in these categories:
362
+
363
+ - `colour.*` - Colors (text, background, brand, etc.)
364
+ - `spacing.*` - Spacing scale (xxs, xs, s, m, l, xl, xxl)
365
+ - `font.*` - Typography (size, family, weight, lineHeight)
366
+ - `layout.*` - Layout values (measure, gutter, etc.)
367
+ - `radius.*` - Border radius (s, m, l)
368
+ - `border.*` - Border properties
369
+ - `breakpoint.*` - Breakpoint values
370
+ - `shadow.*` - Box shadows
371
+ - `transition.*` - Transition values
372
+
373
+ These are converted to CSS custom properties like:
374
+
375
+ - `colour.text.primary` → `--colour-text-primary`
376
+ - `spacing.m` → `--spacing-m`
377
+ - `font.size.body` → `--font-size-m`
378
+
379
+ ### Overriding Tokens
380
+
381
+ In your project, override tokens before the build process:
382
+
383
+ ```javascript
384
+ // project-tokens.js
385
+ import tokens from "@pnx-mixtape/mxds/tokens"
386
+
387
+ // Override existing tokens
388
+ tokens.colour.brand.primary = "rgb(0, 92, 250)"
389
+ tokens.spacing.m = "1.5rem"
390
+
391
+ // Add new tokens
392
+ tokens.colour.brand.tertiary = "rgb(100, 200, 50)"
393
+
394
+ export default tokens
395
+ ```
396
+
397
+ Then configure your build tool (Vite, Webpack, etc.) with [postcss-design-tokens](https://www.npmjs.com/package/postcss-design-tokens) to use your project tokens instead of the default ones.
398
+
399
+ The build process will generate custom properties based on your overridden tokens.
400
+
401
+ #### Swapping the type scale
402
+
403
+ Every `--font-size-*` (other than `--font-size-m`, which is the anchor) is derived from a single ratio via `pow()`, so swapping `font.size.ratio` reshapes the whole scale at once. The `global.typeScales` table exposes the eight standard musical scales — pick the named ratio rather than hard-coding a number:
404
+
405
+ ```javascript
406
+ import tokens, { global } from "@pnx-mixtape/mxds/tokens"
407
+
408
+ // Tighter UI-style scale (less display-y, denser)
409
+ tokens.font.size.ratio = global.typeScales.perfectFourth // 1.333
410
+ tokens.font.size.ratioSmall = global.typeScales.majorSecond // 1.125
411
+
412
+ // Or editorial / display-heavy
413
+ tokens.font.size.ratio = global.typeScales.goldenRatio // 1.618
414
+ ```
415
+
416
+ Available scales:
417
+
418
+ | Name | Ratio | Feel |
419
+ | ----------------- | ----- | -------------------------------------------- |
420
+ | `minorSecond` | 1.067 | Very tight — UI/dense data |
421
+ | `majorSecond` | 1.125 | Tight |
422
+ | `minorThird` | 1.2 | Compact (current mobile default) |
423
+ | `majorThird` | 1.25 | Balanced |
424
+ | `perfectFourth` | 1.333 | Generous body / UI hybrid |
425
+ | `augmentedFourth` | 1.414 | Display-leaning (current desktop default) |
426
+ | `perfectFifth` | 1.5 | Punchy display |
427
+ | `goldenRatio` | 1.618 | Editorial / magazine |
428
+
429
+ `ratio` controls the desktop scale; `ratioSmall` is applied automatically below the `--medium-down` breakpoint, so you can pick a more dramatic ratio for desktop and a tighter one for mobile without writing any media queries.
430
+
431
+ ### Generated Custom Properties
432
+
433
+ The `src/constants.css` file (generated from tokens by PostCSS) looks like this:
434
+
435
+ ```css
436
+ :root {
437
+ --colour-text-primary: rgb(0, 0, 0);
438
+ --colour-background-secondary: rgb(245, 245, 245);
439
+ --spacing-m: 1rem;
440
+ --font-size-m: 1rem;
441
+ /* ... many more custom properties ... */
442
+ }
443
+ ```
444
+
445
+ **Load this file once at the page level** - it defines all custom properties in `:root`, making them available globally to all components without duplication.
446
+
447
+ ---
448
+
449
+ ## Custom Property Fallbacks
450
+
451
+ ### Cascading Fallback Pattern
452
+
453
+ Components use a **cascading fallback pattern** with custom properties, allowing consumers to override values at different levels without modifying component CSS.
454
+
455
+ **Pattern:**
456
+
457
+ ```css
458
+ property: var(--override, var(--default));
459
+ ```
460
+
461
+ This creates an override point that consumers can set, falling back to the design system default if not set.
462
+
463
+ ### Example: Background Component
464
+
465
+ ```css
466
+ .mx-background--primary {
467
+ /* Allows consumer override, falls back to design system default */
468
+ background-color: var(--background, var(--colour-background));
469
+ color: var(--foreground, var(--colour-foreground));
470
+
471
+ /* Multiple fallback levels for flexibility */
472
+ --scheme: var(--primary-scheme, var(--colour-primary-scheme, var(--colour-scheme)));
473
+ }
474
+ ```
475
+
476
+ ### How It Works
477
+
478
+ **1. Component defines fallback chain:**
479
+
480
+ ```css
481
+ .mx-card {
482
+ padding: var(--card-padding, var(--spacing-m));
483
+ background: var(--card-background, var(--colour-background));
484
+ border: var(--line-width, 2px) solid var(--line-colour, var(--colour-border));
485
+ }
486
+ ```
487
+
488
+ **2. Consumer overrides at any level:**
489
+
490
+ ```css
491
+ /* Override globally */
492
+ :root {
493
+ --line-colour: blue; /* Changes all components using --line-colour */
494
+ }
495
+
496
+ /* Override specific component */
497
+ .mx-card {
498
+ --card-padding: 2rem; /* Only affects cards */
499
+ }
500
+
501
+ /* Override specific instance */
502
+ .hero-card {
503
+ --card-background: var(--colour-primary);
504
+ }
505
+ ```
506
+
507
+ ### Common Override Points
508
+
509
+ Components expose these common override variables:
510
+
511
+ **Spacing:**
512
+
513
+ - `--card-padding` → `--spacing-m`
514
+ - `--section-gap` → `--spacing-xl`
515
+ - `--gap` → `--spacing-s`
516
+
517
+ **Colors:**
518
+
519
+ - `--background` → `--colour-background`
520
+ - `--foreground` → `--colour-foreground`
521
+ - `--line-colour` → `--colour-border`
522
+
523
+ **Borders:**
524
+
525
+ - `--line-width` → `1px` or `2px`
526
+ - `--border-radius` → design system default
527
+
528
+ **Typography:**
529
+
530
+ - `--font-weight` → `--font-weight-bold`
531
+ - `--font-size` → size-specific default
532
+
533
+ ### Benefits
534
+
535
+ ✅ **No component CSS modification** - Override via custom properties
536
+ ✅ **Scoped changes** - Target specific components or instances
537
+ ✅ **Global changes** - Set at `:root` for site-wide updates
538
+ ✅ **Graceful fallbacks** - Always falls back to design system defaults
539
+ ✅ **Inheritance** - Child elements inherit parent overrides
540
+
541
+ ### Real Example
542
+
543
+ ```css
544
+ /* Component CSS (in design system) */
545
+ .mx-blockquote {
546
+ padding-inline-start: var(--line-gap, var(--gap));
547
+ border-inline-start: var(--line-width, 6px) solid var(--line-colour, var(--colour-border));
548
+ }
549
+
550
+ /* Consumer override (in your project) */
551
+ .special-quote {
552
+ --line-colour: var(--colour-accent);
553
+ --line-width: 10px;
554
+ }
555
+ ```
556
+
557
+ **Result:** The blockquote uses custom colors and width without touching component CSS.
558
+
559
+ ---
560
+
561
+ ## Color Scheme (light-dark)
562
+
563
+ ### Automatic Light/Dark Mode
564
+
565
+ The design system uses the CSS `light-dark()` function and `color-scheme` property for automatic light/dark mode support.
566
+
567
+ ### How It Works
568
+
569
+ **1. Set color-scheme:**
570
+
571
+ ```css
572
+ .mx-background--primary {
573
+ color-scheme: var(--scheme, var(--colour-scheme));
574
+ }
575
+ ```
576
+
577
+ The `color-scheme` property tells the browser which color scheme is in use (light or dark), affecting system UI and enabling `light-dark()`.
578
+
579
+ **2. Use light-dark() for colors:**
580
+
581
+ ```css
582
+ .mx-background--primary {
583
+ --line-colour: light-dark(var(--colour-primary-darker), var(--colour-primary-lighter));
584
+ }
585
+ ```
586
+
587
+ The `light-dark()` function automatically picks the first value in light mode, second value in dark mode.
588
+
589
+ ### Background Component Example
590
+
591
+ ```css
592
+ :where([class*="mx-background--"]) {
593
+ background-color: var(--background, var(--colour-background));
594
+ color: var(--foreground, var(--colour-foreground));
595
+ color-scheme: var(--scheme, var(--colour-scheme));
596
+ }
597
+
598
+ .mx-background--primary {
599
+ --scheme: var(--primary-scheme, var(--colour-primary-scheme, var(--colour-scheme)));
600
+ --background: var(--colour-primary);
601
+ --line-colour: light-dark(var(--colour-primary-darker), var(--colour-primary-lighter));
602
+ --colour-foreground-alt: var(--colour-primary-light);
603
+ }
604
+
605
+ .mx-background--reverse {
606
+ --scheme: var(--reverse-scheme, var(--colour-reverse-scheme, dark));
607
+ }
608
+ ```
609
+
610
+ ### Setting Color Scheme
611
+
612
+ **Global (page level):**
613
+
614
+ ```css
615
+ :root {
616
+ --colour-scheme: light; /* or dark */
617
+ }
618
+ ```
619
+
620
+ **Per section:**
621
+
622
+ ```css
623
+ .dark-section {
624
+ --scheme: dark;
625
+ }
626
+
627
+ .light-section {
628
+ --scheme: light;
629
+ }
630
+ ```
631
+
632
+ **Automatic (user preference):**
633
+
634
+ ```css
635
+ :root {
636
+ color-scheme: light dark; /* Supports both */
637
+ }
638
+
639
+ @media (prefers-color-scheme: dark) {
640
+ :root {
641
+ --colour-scheme: dark;
642
+ }
643
+ }
644
+ ```
645
+
646
+ ### Using light-dark()
647
+
648
+ **Syntax:**
649
+
650
+ ```css
651
+ property: light-dark(<light-value>, <dark-value>);
652
+ ```
653
+
654
+ **Examples:**
655
+
656
+ ```css
657
+ /* Text colors */
658
+ color: light-dark(var(--colour-text-dark), var(--colour-text-light));
659
+
660
+ /* Backgrounds */
661
+ background: light-dark(#ffffff, #000000);
662
+
663
+ /* Borders */
664
+ border-color: light-dark(var(--colour-primary), var(--colour-primary-light));
665
+
666
+ /* Shadows */
667
+ box-shadow: light-dark(0 2px 8px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(255, 255, 255, 0.1));
668
+ ```
669
+
670
+ ### When to Use
671
+
672
+ **Use `light-dark()` for:**
673
+
674
+ - Colors that need to adapt to light/dark mode
675
+ - UI elements with different appearances per mode
676
+ - Borders, shadows, and subtle UI details
677
+
678
+ **Use `color-scheme` for:**
679
+
680
+ - Declaring which mode a section uses
681
+ - Enabling `light-dark()` function
682
+ - Affecting browser chrome (scrollbars, form controls)
683
+
684
+ ### Benefits
685
+
686
+ ✅ **Automatic switching** - Browser handles light/dark logic
687
+ ✅ **No JavaScript required** - Pure CSS solution
688
+ ✅ **Respects user preference** - Works with `prefers-color-scheme`
689
+ ✅ **Scoped modes** - Different sections can use different schemes
690
+ ✅ **System integration** - Browser chrome matches color scheme
691
+
692
+ ### Complete Example
693
+
694
+ ```css
695
+ /* Define color scheme modes in constants.css */
696
+ :root {
697
+ --colour-scheme: light;
698
+ --colour-primary: #003366;
699
+ --colour-primary-light: #6699cc;
700
+ }
701
+
702
+ /* Component uses light-dark() */
703
+ .mx-component {
704
+ color-scheme: var(--colour-scheme);
705
+ border-color: light-dark(var(--colour-primary), var(--colour-primary-light));
706
+ }
707
+
708
+ /* Consumer changes scheme for a section */
709
+ .dark-hero {
710
+ --scheme: dark;
711
+ }
712
+ ```
713
+
714
+ **Result:** The hero section automatically uses dark mode colors while rest of page uses light mode.
715
+
716
+ ---
717
+
718
+ ## Logical Properties
719
+
720
+ ### Use Logical Properties
721
+
722
+ **ENFORCED** by stylelint-use-logical-spec plugin.
723
+
724
+ ```css
725
+ /* ✅ GOOD - Logical properties (RTL-friendly) */
726
+ .mx-component {
727
+ padding-inline: 1rem; /* left/right in LTR, right/left in RTL */
728
+ padding-block: 2rem; /* top/bottom always */
729
+ margin-inline-start: 1rem; /* left in LTR, right in RTL */
730
+ margin-block-start: 1rem; /* top always */
731
+ border-inline-end: 1px solid; /* right in LTR, left in RTL */
732
+ inset-inline-start: 0; /* left in LTR, right in RTL */
733
+ }
734
+
735
+ /* ❌ BAD - Physical properties */
736
+ .mx-component {
737
+ padding-left: 1rem; /* Doesn't flip for RTL */
738
+ padding-right: 1rem;
739
+ margin-top: 1rem; /* OK but inconsistent */
740
+ border-right: 1px; /* Doesn't flip for RTL */
741
+ left: 0; /* Doesn't flip for RTL */
742
+ }
743
+ ```
744
+
745
+ ### Property Mapping
746
+
747
+ | Physical | Logical |
748
+ | ---------------- | ---------------------- |
749
+ | `padding-left` | `padding-inline-start` |
750
+ | `padding-right` | `padding-inline-end` |
751
+ | `padding-top` | `padding-block-start` |
752
+ | `padding-bottom` | `padding-block-end` |
753
+ | `margin-left` | `margin-inline-start` |
754
+ | `margin-right` | `margin-inline-end` |
755
+ | `border-left` | `border-inline-start` |
756
+ | `border-right` | `border-inline-end` |
757
+ | `left` | `inset-inline-start` |
758
+ | `right` | `inset-inline-end` |
759
+ | `top` | `inset-block-start` |
760
+ | `bottom` | `inset-block-end` |
761
+ | `width` | `inline-size` |
762
+ | `height` | `block-size` |
763
+ | `max-width` | `max-inline-size` |
764
+ | `min-height` | `min-block-size` |
765
+
766
+ ### Shorthand Logical Properties
767
+
768
+ ```css
769
+ /* Inline (horizontal in LTR) */
770
+ padding-inline: 1rem; /* Both sides */
771
+ margin-inline: 1rem 2rem; /* Start and end */
772
+
773
+ /* Block (vertical) */
774
+ padding-block: 1rem; /* Top and bottom */
775
+ margin-block: 1rem 2rem; /* Start and end */
776
+
777
+ /* Inset (position) */
778
+ inset: 0; /* All sides */
779
+ inset-inline: 0; /* Left and right in LTR */
780
+ inset-block: 0; /* Top and bottom */
781
+ ```
782
+
783
+ ### Exception: Float
784
+
785
+ `float` is exempt from logical properties (no logical equivalent):
786
+
787
+ ```css
788
+ .mx-component {
789
+ float: left; /* OK - Exception defined in config */
790
+ }
791
+ ```
792
+
793
+ ---
794
+
795
+ ## Cascade Layers
796
+
797
+ All design system CSS is wrapped in cascade layers for **proper specificity control**.
798
+
799
+ ### Layer Order
800
+
801
+ ```css
802
+ @layer popover-polyfill, design-system.defaults, design-system.atoms, design-system.layouts, design-system.utilities, design-system.components;
803
+ ```
804
+
805
+ ### Using Layers
806
+
807
+ ```css
808
+ /* Automatically handled by build process */
809
+ @layer design-system.components {
810
+ .mx-card {
811
+ /* Component styles */
812
+ }
813
+ }
814
+
815
+ @layer design-system.utilities {
816
+ .mx-text--center {
817
+ /* Utility styles */
818
+ }
819
+ }
820
+ ```
821
+
822
+ ### Layer Benefits
823
+
824
+ - ✅ **Predictable specificity** - Layers override regardless of selector specificity
825
+ - ✅ **Easy overrides** - Consumer styles automatically override design system
826
+ - ✅ **No !important needed** - Layer order handles precedence
827
+ - ✅ **Better organization** - Clear separation of concerns
828
+
829
+ ### Consumer Overrides
830
+
831
+ Consumers can easily override design system styles:
832
+
833
+ ```css
834
+ /* Consumer styles (unlayered) always win */
835
+ .mx-card {
836
+ padding: 3rem; /* Overrides design system */
837
+ }
838
+
839
+ /* Or use their own layers */
840
+ @layer my-app {
841
+ .mx-card {
842
+ padding: 3rem; /* Also overrides */
843
+ }
844
+ }
845
+ ```
846
+
847
+ ---
848
+
849
+ ## CSS Checklist
850
+
851
+ Before shipping styles:
852
+
853
+ - [ ] BEM naming convention followed
854
+ - [ ] `mx-` prefix on all classes
855
+ - [ ] Custom media imported at top of file (if needed)
856
+ - [ ] Mobile-first responsive approach
857
+ - [ ] Custom properties used (not hardcoded values)
858
+ - [ ] Logical properties used (not physical)
859
+ - [ ] Cascade layers applied
860
+ - [ ] Stylelint passes (`pnpm lint-css`)
861
+ - [ ] Styles work in RTL mode
862
+ - [ ] Tested across breakpoints
863
+ - [ ] No descending specificity issues
864
+ - [ ] Performance checked (no expensive selectors)
865
+
866
+ ---
867
+
868
+ ## Stylelint Configuration
869
+
870
+ Key rules from `.stylelintrc.json`:
871
+
872
+ ```javascript
873
+ {
874
+ "extends": ["stylelint-config-standard"],
875
+ "plugins": ["stylelint-use-logical-spec"],
876
+ "rules": {
877
+ "selector-class-pattern": "...", // BEM enforcement
878
+ "selector-nested-pattern": "^&", // Must nest with &
879
+ "liberty/use-logical-spec": [true, { "except": ["float"] }],
880
+ "no-descending-specificity": null, // Disabled for flexibility
881
+ "import-notation": "string"
882
+ }
883
+ }
884
+ ```
885
+
886
+ ---
887
+
888
+ ## Related Documentation
889
+
890
+ - [Code Quality Guidelines](./CodeQuality.md)
891
+ - [Component Architecture](./ComponentArchitecture.md)
892
+ - [Design Tokens](../src/tokens.js)
893
+ - [Custom Media](../src/_custom-media.css)