@ippon-ui/ui 0.0.2

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 (246) hide show
  1. package/.agents/agents/component-library-create-from-pattern-library.agent.md +37 -0
  2. package/.agents/agents/patten-library-create-component.agent.md +30 -0
  3. package/.agents/skills/component-library/SKILL.md +169 -0
  4. package/.agents/skills/pattern-library/SKILL.md +277 -0
  5. package/.github/workflows/build.yml +34 -0
  6. package/.gitlab-ci.yml +12 -0
  7. package/.prettierignore +6 -0
  8. package/AGENTS.md +50 -0
  9. package/LICENSE +202 -0
  10. package/ci/build.yml +15 -0
  11. package/ci/common.yml +42 -0
  12. package/ci/deploy.yml +20 -0
  13. package/icons/LICENCE +202 -0
  14. package/icons/index.ts +69 -0
  15. package/icons/package.json +25 -0
  16. package/icons/tsconfig.json +11 -0
  17. package/lefthook.yml +10 -0
  18. package/mise.toml +55 -0
  19. package/package.json +26 -0
  20. package/pnpm-workspace.yaml +9 -0
  21. package/prettier.config.mts +8 -0
  22. package/react/LICENCE +202 -0
  23. package/react/README.md +75 -0
  24. package/react/eslint.config.js +22 -0
  25. package/react/package.json +63 -0
  26. package/react/src/CAP.ts +14 -0
  27. package/react/src/Card.ts +2 -0
  28. package/react/src/DataSelectable.ts +7 -0
  29. package/react/src/Grid.ts +33 -0
  30. package/react/src/IpponBadge.tsx +62 -0
  31. package/react/src/IpponButton.tsx +93 -0
  32. package/react/src/IpponButtonCard.tsx +34 -0
  33. package/react/src/IpponCard.tsx +30 -0
  34. package/react/src/IpponContainer.tsx +15 -0
  35. package/react/src/IpponGrid.tsx +56 -0
  36. package/react/src/IpponHSpace.tsx +56 -0
  37. package/react/src/IpponIcon.tsx +15 -0
  38. package/react/src/IpponImportFile.tsx +128 -0
  39. package/react/src/IpponIon.tsx +45 -0
  40. package/react/src/IpponMeter.tsx +43 -0
  41. package/react/src/IpponProgress.tsx +45 -0
  42. package/react/src/IpponText.tsx +56 -0
  43. package/react/src/IpponTitle.tsx +45 -0
  44. package/react/src/IpponVSpace.tsx +43 -0
  45. package/react/src/Optional.ts +177 -0
  46. package/react/src/Tokens.ts +36 -0
  47. package/react/src/index.ts +16 -0
  48. package/react/test/File.fixture.ts +13 -0
  49. package/react/test/IpponBadge.spec.tsx +245 -0
  50. package/react/test/IpponButton.spec.tsx +666 -0
  51. package/react/test/IpponButtonCard.spec.tsx +162 -0
  52. package/react/test/IpponCard.spec.tsx +133 -0
  53. package/react/test/IpponContainer.spec.tsx +56 -0
  54. package/react/test/IpponGrid.spec.tsx +140 -0
  55. package/react/test/IpponHSpace.spec.tsx +107 -0
  56. package/react/test/IpponIcon.spec.tsx +37 -0
  57. package/react/test/IpponImportFile.spec.tsx +431 -0
  58. package/react/test/IpponIon.spec.tsx +52 -0
  59. package/react/test/IpponMeter.spec.tsx +59 -0
  60. package/react/test/IpponProgress.spec.tsx +68 -0
  61. package/react/test/IpponText.spec.tsx +149 -0
  62. package/react/test/IpponTitle.spec.tsx +242 -0
  63. package/react/test/IpponVSpace.spec.tsx +91 -0
  64. package/react/tsconfig.app.json +24 -0
  65. package/react/tsconfig.json +4 -0
  66. package/react/tsconfig.node.json +23 -0
  67. package/react/vite.config.ts +30 -0
  68. package/react/vitest.config.ts +21 -0
  69. package/styles/.editorconfig +12 -0
  70. package/styles/.stylelintrc.json +75 -0
  71. package/styles/LICENCE +202 -0
  72. package/styles/README.md +107 -0
  73. package/styles/logo.svg +26 -0
  74. package/styles/package.json +67 -0
  75. package/styles/src/atom/_atom.scss +9 -0
  76. package/styles/src/atom/atom.pug +34 -0
  77. package/styles/src/atom/badge/_badge.scss +108 -0
  78. package/styles/src/atom/badge/badge.code.pug +29 -0
  79. package/styles/src/atom/badge/badge.md +1 -0
  80. package/styles/src/atom/badge/badge.mixin.pug +24 -0
  81. package/styles/src/atom/badge/badge.render.pug +7 -0
  82. package/styles/src/atom/button/_button.scss +242 -0
  83. package/styles/src/atom/button/button.code.pug +38 -0
  84. package/styles/src/atom/button/button.md +31 -0
  85. package/styles/src/atom/button/button.mixin.pug +30 -0
  86. package/styles/src/atom/button/button.render.pug +13 -0
  87. package/styles/src/atom/icon/_icon.scss +8 -0
  88. package/styles/src/atom/icon/icon.code.pug +5 -0
  89. package/styles/src/atom/icon/icon.md +11 -0
  90. package/styles/src/atom/icon/icon.mixin.pug +8 -0
  91. package/styles/src/atom/icon/icon.render.pug +7 -0
  92. package/styles/src/atom/ion/ion.code.pug +8 -0
  93. package/styles/src/atom/ion/ion.md +11 -0
  94. package/styles/src/atom/ion/ion.mixin.pug +8 -0
  95. package/styles/src/atom/ion/ion.render.pug +7 -0
  96. package/styles/src/atom/meter/_meter.scss +23 -0
  97. package/styles/src/atom/meter/meter.code.pug +8 -0
  98. package/styles/src/atom/meter/meter.md +7 -0
  99. package/styles/src/atom/meter/meter.mixin.pug +12 -0
  100. package/styles/src/atom/meter/meter.render.pug +5 -0
  101. package/styles/src/atom/progress/_progress.scss +23 -0
  102. package/styles/src/atom/progress/progress.code.pug +8 -0
  103. package/styles/src/atom/progress/progress.md +7 -0
  104. package/styles/src/atom/progress/progress.mixin.pug +14 -0
  105. package/styles/src/atom/progress/progress.render.pug +5 -0
  106. package/styles/src/atom/tab/_tab.scss +48 -0
  107. package/styles/src/atom/tab/tab.code.pug +5 -0
  108. package/styles/src/atom/tab/tab.md +1 -0
  109. package/styles/src/atom/tab/tab.mixin.pug +14 -0
  110. package/styles/src/atom/tab/tab.render.pug +4 -0
  111. package/styles/src/atom/text/_text.scss +74 -0
  112. package/styles/src/atom/text/text.code.pug +19 -0
  113. package/styles/src/atom/text/text.md +5 -0
  114. package/styles/src/atom/text/text.mixin.pug +12 -0
  115. package/styles/src/atom/text/text.render.pug +7 -0
  116. package/styles/src/atom/title/_title.scss +68 -0
  117. package/styles/src/atom/title/title.code.pug +25 -0
  118. package/styles/src/atom/title/title.md +9 -0
  119. package/styles/src/atom/title/title.mixin.pug +12 -0
  120. package/styles/src/atom/title/title.render.pug +5 -0
  121. package/styles/src/atom/title-display/_title-display.scss +26 -0
  122. package/styles/src/atom/title-display/title-display.code.pug +9 -0
  123. package/styles/src/atom/title-display/title-display.md +5 -0
  124. package/styles/src/atom/title-display/title-display.mixin.pug +6 -0
  125. package/styles/src/atom/title-display/title-display.render.pug +4 -0
  126. package/styles/src/doc.scss +2 -0
  127. package/styles/src/favicon.ico +0 -0
  128. package/styles/src/function/_conversion.scss +9 -0
  129. package/styles/src/index.pug +59 -0
  130. package/styles/src/layout-documentation.pug +14 -0
  131. package/styles/src/layout.pug +17 -0
  132. package/styles/src/molecule/_molecule.scss +2 -0
  133. package/styles/src/molecule/import-file/_import-file.scss +38 -0
  134. package/styles/src/molecule/import-file/import-file.code.pug +4 -0
  135. package/styles/src/molecule/import-file/import-file.md +1 -0
  136. package/styles/src/molecule/import-file/import-file.mixin.pug +15 -0
  137. package/styles/src/molecule/import-file/import-file.render.pug +5 -0
  138. package/styles/src/molecule/molecule.pug +20 -0
  139. package/styles/src/molecule/tabs/_tabs.scss +4 -0
  140. package/styles/src/molecule/tabs/tabs.code.pug +9 -0
  141. package/styles/src/molecule/tabs/tabs.md +1 -0
  142. package/styles/src/molecule/tabs/tabs.mixin.pug +4 -0
  143. package/styles/src/molecule/tabs/tabs.render.pug +4 -0
  144. package/styles/src/molecule/toggle/_toggle.scss +68 -0
  145. package/styles/src/molecule/toggle/toggle.code.pug +26 -0
  146. package/styles/src/molecule/toggle/toggle.md +1 -0
  147. package/styles/src/molecule/toggle/toggle.mixin.pug +36 -0
  148. package/styles/src/molecule/toggle/toggle.render.pug +5 -0
  149. package/styles/src/organism/_abstract-card.scss +36 -0
  150. package/styles/src/organism/_docorganism.scss +1 -0
  151. package/styles/src/organism/_organism.scss +8 -0
  152. package/styles/src/organism/button-card/_button-card.scss +22 -0
  153. package/styles/src/organism/button-card/button-card.code.pug +31 -0
  154. package/styles/src/organism/button-card/button-card.md +28 -0
  155. package/styles/src/organism/button-card/button-card.mixin.pug +8 -0
  156. package/styles/src/organism/button-card/button-card.render.pug +7 -0
  157. package/styles/src/organism/card/_card.scss +6 -0
  158. package/styles/src/organism/card/card.code.pug +9 -0
  159. package/styles/src/organism/card/card.md +23 -0
  160. package/styles/src/organism/card/card.mixin.pug +7 -0
  161. package/styles/src/organism/card/card.render.pug +7 -0
  162. package/styles/src/organism/container/_container.scss +3 -0
  163. package/styles/src/organism/container/container.code.pug +13 -0
  164. package/styles/src/organism/container/container.md +5 -0
  165. package/styles/src/organism/container/container.mixin.pug +3 -0
  166. package/styles/src/organism/container/container.render.pug +4 -0
  167. package/styles/src/organism/grid/_docgrid.scss +11 -0
  168. package/styles/src/organism/grid/_grid.scss +84 -0
  169. package/styles/src/organism/grid/grid.code.pug +25 -0
  170. package/styles/src/organism/grid/grid.md +1 -0
  171. package/styles/src/organism/grid/grid.mixin.pug +7 -0
  172. package/styles/src/organism/grid/grid.render.pug +5 -0
  173. package/styles/src/organism/h-space/_h-space.scss +49 -0
  174. package/styles/src/organism/h-space/h-space.code.pug +56 -0
  175. package/styles/src/organism/h-space/h-space.md +22 -0
  176. package/styles/src/organism/h-space/h-space.mixin.pug +14 -0
  177. package/styles/src/organism/h-space/h-space.render.pug +5 -0
  178. package/styles/src/organism/header/_header.scss +8 -0
  179. package/styles/src/organism/header/header.code.pug +14 -0
  180. package/styles/src/organism/header/header.md +1 -0
  181. package/styles/src/organism/header/header.mixin.pug +7 -0
  182. package/styles/src/organism/header/header.render.pug +4 -0
  183. package/styles/src/organism/modal/_modal.scss +58 -0
  184. package/styles/src/organism/modal/modal.code.pug +68 -0
  185. package/styles/src/organism/modal/modal.md +1 -0
  186. package/styles/src/organism/modal/modal.mixin.pug +25 -0
  187. package/styles/src/organism/modal/modal.render.pug +4 -0
  188. package/styles/src/organism/organism.pug +30 -0
  189. package/styles/src/organism/v-space/_v-space.scss +45 -0
  190. package/styles/src/organism/v-space/v-space.code.pug +41 -0
  191. package/styles/src/organism/v-space/v-space.md +20 -0
  192. package/styles/src/organism/v-space/v-space.mixin.pug +7 -0
  193. package/styles/src/organism/v-space/v-space.render.pug +5 -0
  194. package/styles/src/quark/_breakpoint.scss +12 -0
  195. package/styles/src/quark/_font.scss +38 -0
  196. package/styles/src/quark/_gap.scss +34 -0
  197. package/styles/src/quark/_placeholder.scss +27 -0
  198. package/styles/src/quark/_shadow.scss +13 -0
  199. package/styles/src/quark/_typography.scss +146 -0
  200. package/styles/src/template/_template.scss +1 -0
  201. package/styles/src/template/layout/_layout.scss +20 -0
  202. package/styles/src/template/layout/layout.code.pug +11 -0
  203. package/styles/src/template/layout/layout.md +1 -0
  204. package/styles/src/template/layout/layout.mixin.pug +11 -0
  205. package/styles/src/template/layout/layout.render.pug +4 -0
  206. package/styles/src/template/template.pug +16 -0
  207. package/styles/src/tikui.scss +5 -0
  208. package/styles/src/token/_doctable.scss +14 -0
  209. package/styles/src/token/_doctoken.scss +1 -0
  210. package/styles/src/token/_size.scss +9 -0
  211. package/styles/src/token/_token.scss +5 -0
  212. package/styles/src/token/color/_color.scss +9 -0
  213. package/styles/src/token/color/color/_base.scss +65 -0
  214. package/styles/src/token/color/color/_brand.scss +13 -0
  215. package/styles/src/token/color/color/_error.scss +13 -0
  216. package/styles/src/token/color/color/_information-2.scss +13 -0
  217. package/styles/src/token/color/color/_information.scss +13 -0
  218. package/styles/src/token/color/color/_neutral.scss +20 -0
  219. package/styles/src/token/color/color/_semantic.scss +69 -0
  220. package/styles/src/token/color/color/_success.scss +13 -0
  221. package/styles/src/token/color/color/_warning.scss +13 -0
  222. package/styles/src/token/color/color.js +31 -0
  223. package/styles/src/token/color/color.mixin.pug +19 -0
  224. package/styles/src/token/color/color.pug +9 -0
  225. package/styles/src/token/color/color.render.pug +13 -0
  226. package/styles/src/token/radius/_radius.scss +8 -0
  227. package/styles/src/token/radius/radius.js +54 -0
  228. package/styles/src/token/radius/radius.mixin.pug +14 -0
  229. package/styles/src/token/radius/radius.pug +9 -0
  230. package/styles/src/token/radius/radius.render.pug +11 -0
  231. package/styles/src/token/shadow/_shadow.scss +22 -0
  232. package/styles/src/token/shadow/shadow.js +45 -0
  233. package/styles/src/token/shadow/shadow.mixin.pug +13 -0
  234. package/styles/src/token/shadow/shadow.pug +9 -0
  235. package/styles/src/token/shadow/shadow.render.pug +9 -0
  236. package/styles/src/token/token.js +38 -0
  237. package/styles/src/token/token.pug +25 -0
  238. package/styles/src/token/typography/_typography.scss +103 -0
  239. package/styles/src/token/typography/typography.js +32 -0
  240. package/styles/src/token/typography/typography.mixin.pug +17 -0
  241. package/styles/src/token/typography/typography.pug +9 -0
  242. package/styles/src/token/typography/typography.render.pug +19 -0
  243. package/styles/test/function/conversion.test.scss +20 -0
  244. package/styles/test/function/sass.spec.ts +6 -0
  245. package/styles/tikuiconfig.json +14 -0
  246. package/styles/tsconfig.json +10 -0
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: component-library-create-from-pattern-library
3
+ description: Create a component in the Component Library based on a component from the Pattern Library
4
+ skills:
5
+ - component-library
6
+ - pattern-library
7
+ ---
8
+
9
+ ## Task
10
+
11
+ As input, you are given the component name to create in the Component Library (based on an existing Pattern Library component).
12
+
13
+ ## Steps
14
+
15
+ 1. Check if a component already exists in `react/src/` that covers this need by searching for existing `Ippon<ComponentName>` components
16
+
17
+ 2. Read the Pattern Library component documentation from the node module `@ippon-ui/styles` located in `node_modules/@ippon-ui/styles/dist`:
18
+ - Locate `src/<level>/<component-name>/<component-name>.mixin.pug` (where `<level>` is atom, molecule, organism, or template)
19
+ - Understand the HTML structure, alternatives (CAP `-variant`), and parts (CAP `--part`)
20
+ - Read `<component-name>.md` for component details
21
+
22
+ 3. Write unit tests in `react/test/Ippon<ComponentName>.spec.tsx`:
23
+ - Create tests for all expected props: variants, colors, sizes
24
+ - Include tests for children rendering and `dataSelector` binding
25
+ - Follow the test structure from Component Library "Unit Tests" section
26
+ - Run `cd app && pnpm test:unit` to verify tests are red before implementing
27
+
28
+ 4. Implement the React component in `react/src/Ippon<ComponentName>.tsx`:
29
+ - Follow the structure and conventions from Component Library "Creating a Component" section
30
+ - Type props using `DataSelectable` or `DataSelectableWithChildren`
31
+ - Build CSS classes using `clsx` and helpers from `CAP.ts`
32
+ - Create sub-components for any parts (CAP `--part`)
33
+ - Run tests with `cd app && pnpm test:unit` until all tests pass
34
+
35
+ 5. Export the component from `react/src/index.ts`:
36
+ - Add `export { IpponComponent } from './IpponComponent.tsx';`
37
+ - If applicable, also export any sub-components or parts
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: pattern-library-create-component
3
+ description: Create a component on the Pattern Library
4
+ skills:
5
+ - pattern-library
6
+ ---
7
+
8
+ ## Task
9
+
10
+ As input, you are given the level and name of the component to create.
11
+
12
+ ## Steps
13
+
14
+ 1. Review the instructions in `.github/instructions/pattern-library.instructions.md` to understand:
15
+ - The Atomic Design principles (atoms, molecules, organisms, templates)
16
+ - The Tikui component architecture
17
+ - The CAP (Component Alternative Part) naming convention
18
+ - Token and Quark concepts
19
+
20
+ 2. Generate the component using the tikui command with the proper format:
21
+
22
+ ```shell
23
+ mise styles-create-component <component> --path <path>
24
+ ```
25
+
26
+ Where:
27
+ - `<component>` is the component name in `kebab-case`
28
+ - `<path>` where default is 'atom' to create inside `src/atom`
29
+
30
+ 3. Ensure the generated component follows the CAP convention for alternatives and parts
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: 'component-library'
3
+ description: 'Component Library with React components used by the application.'
4
+ ---
5
+
6
+ # Component Library
7
+
8
+ Component Library is a part of react folder, you can find it in the `react/src` folder.
9
+
10
+ It's a bounded context dedicated to React Components.
11
+
12
+ ## Concept
13
+
14
+ The Component Library concept is not especially linked to a technology. The idea is to represent the mechanical part of each component.
15
+
16
+ It therefore provides React components that will be consumed by another bounded context.
17
+
18
+ ## Integration with Pattern Library
19
+
20
+ The Component Library consume the Pattern Library, it uses the provided documentation to know classes and structure to use for each component. The CSS is linked using a `link` tag in the `index.html` file of the React application.
21
+
22
+ When implementing a component in the Component Library:
23
+
24
+ 1. Refer to the Pattern Library documentation for the correct CSS classes and structure
25
+ 2. Follow the CAP (Component Alternative Part) naming convention for variants and parts
26
+ 3. Use the semantic colors and tokens defined in the Pattern Library
27
+ 4. Ensure visual consistency by adhering to the Atomic Design hierarchy (atoms, molecules, organisms)
28
+
29
+ ## Creating a Component
30
+
31
+ ### File Organization
32
+
33
+ Each component is defined by:
34
+
35
+ - **Component file**: `react/src/Ippon<ComponentName>.tsx` (PascalCase)
36
+ - **Test file**: `react/test/Ippon<ComponentName>.spec.tsx`
37
+ - **Export**: added to `react/src/index.ts`
38
+
39
+ ### React Component Structure
40
+
41
+ A component file follows this structure:
42
+
43
+ ```typescriptreact
44
+ import type { DataSelectableWithChildren } from './DataSelectable.ts';
45
+ import { clsx } from 'clsx';
46
+ import { optionalToAlternativeClass } from './CAP.ts';
47
+
48
+ type IpponComponentProps = DataSelectableWithChildren<{
49
+ variant?: 'primary' | 'secondary';
50
+ color?: IpponTokenTextColor;
51
+ }>;
52
+
53
+ export const IpponComponent = (props: IpponComponentProps) => (
54
+ <div
55
+ className={clsx(
56
+ 'ippon-component',
57
+ optionalToAlternativeClass(props.variant),
58
+ optionalToAlternativeClass(props.color),
59
+ )}
60
+ data-selector={props.dataSelector}
61
+ >
62
+ {props.children}
63
+ </div>
64
+ );
65
+ ```
66
+
67
+ ### Key Conventions
68
+
69
+ #### Props Typing
70
+
71
+ - Extend `DataSelectable<T>` for components without children
72
+ - Extend `DataSelectableWithChildren<T>` for components with children
73
+ - Always include `dataSelector?: string` (via `DataSelectable`)
74
+ - Use types from `Tokens.ts` for colors and sizes (e.g., `IpponTokenTextColor`, `IpponTokenSize`)
75
+ - Model alternatives (CAP `-variant`) as union types
76
+ - Model booleans like `border` or `placeholder` as optional props
77
+
78
+ #### CSS Class Building
79
+
80
+ - Use `clsx()` from the `clsx` library to conditionally build class names
81
+ - Import helpers from `CAP.ts`:
82
+ - `optionalToAlternativeClass(value)` → converts `'primary'` to `'-primary'`
83
+ - `optionalToPrefixedAlternativeClass(prefix)(value)` → converts `'l1'` with prefix `'shadow'` to `'-shadow-l1'`
84
+ - `toAlternativeClass(value)` → always converts to alternative class (non-optional)
85
+
86
+ #### Parts and Sub-components
87
+
88
+ If the Pattern Library component has parts (CSS classes like `ippon-component--part`):
89
+
90
+ - Create a dedicated sub-component `IpponComponentPart` for parts with significant props
91
+ - Export both the main component and the part(s) from the same file
92
+ - Use `clsx('ippon-component--part', ...)` for part class names
93
+
94
+ Example with slots:
95
+
96
+ ```typescriptreact
97
+ export const IpponVSpaceSlot = (props: IpponVSpaceSlotProps) => (
98
+ <div
99
+ className={clsx('ippon-v-space--slot', optionalToAlternativeClass(props.align))}
100
+ data-selector={props.dataSelector}
101
+ >
102
+ {props.children}
103
+ </div>
104
+ );
105
+ ```
106
+
107
+ #### Exporting Components
108
+
109
+ Add each new component to `react/src/index.ts`:
110
+
111
+ ```typescript
112
+ export { IpponComponent } from './IpponComponent.tsx';
113
+ export { IpponComponentPart } from './IpponComponent.tsx'; // if applicable
114
+ ```
115
+
116
+ ### Unit Tests
117
+
118
+ Tests are located in `react/test/` and use Vitest + Testing Library.
119
+
120
+ #### Running Tests
121
+
122
+ ```shell
123
+ cd react
124
+
125
+ pnpm test:unit:ci
126
+ ```
127
+
128
+ #### Test Structure
129
+
130
+ Each component test should:
131
+
132
+ 1. Verify the component renders with the correct base class name
133
+ 2. Test each prop variant (alternatives, colors, sizes)
134
+ 3. Test children rendering
135
+ 4. Test `dataSelector` binding
136
+ 5. Test custom HTML tags if applicable (via `tag` prop)
137
+
138
+ Example test:
139
+
140
+ ```typescriptreact
141
+ import { describe, it, expect, afterEach } from 'vitest';
142
+ import { render, screen, configure, cleanup } from '@testing-library/react';
143
+ import '@testing-library/jest-dom/vitest';
144
+ import { IpponComponent } from '../src';
145
+
146
+ configure({
147
+ testIdAttribute: 'data-selector',
148
+ });
149
+
150
+ describe('IpponComponent', () => {
151
+ afterEach(cleanup);
152
+
153
+ it('should be like pattern library', () => {
154
+ render(<IpponComponent dataSelector="ippon-component">Content</IpponComponent>);
155
+
156
+ const component = screen.getByTestId('ippon-component');
157
+
158
+ expect(component).toHaveClass('ippon-component');
159
+ });
160
+
161
+ it.each(['primary', 'secondary'] as const)('should have variant %s', (variant) => {
162
+ render(<IpponComponent variant={variant} dataSelector="ippon-component" />);
163
+
164
+ const component = screen.getByTestId('ippon-component');
165
+
166
+ expect(component).toHaveClass(`-${variant}`);
167
+ });
168
+ });
169
+ ```
@@ -0,0 +1,277 @@
1
+ ---
2
+ name: 'pattern-library'
3
+ description: 'Pattern Libreary which allows representing graphical components. Provides CSS and uses HTML as a template language. This is where tokens, quarks, atoms, molecules, organisms, templates are defined.'
4
+ ---
5
+
6
+ # Pattern Library
7
+
8
+ The Pattern Library allows representing graphical elements.
9
+
10
+ The Pattern Library concept is not especially linked to a technology. The idea is to represent the visual part of each component, the states but not the mechanical part.
11
+
12
+ In the project, the Pattern Library applies to the web.
13
+
14
+ It therefore provides:
15
+
16
+ - CSS that will be consumed by another application
17
+ - Documentation for each component with:
18
+ - A description of the component
19
+ - A rendering of the component
20
+ - The source code of the component (HTML and pug)
21
+
22
+ So it's possible to consume the Pattern Library in any web application, regardless of the technology used (React, Vue, Angular, etc…).
23
+
24
+ It is organized following Atomic Design.
25
+
26
+ [Tikui](https://tikui.org/) is used to generate the documentation of the Pattern Library.
27
+
28
+ ## Component
29
+
30
+ A component in Tikui is defined according to the following architecture:
31
+
32
+ ```
33
+ <component>/
34
+ <component>.mixin.pug
35
+ <component>.code.pug
36
+ <component>.render.pug
37
+ _<component>.scss
38
+ ```
39
+
40
+ The command to generate a component is as follows:
41
+
42
+ ```shell
43
+ mise styles-create-component <component> --path <path>
44
+ ```
45
+
46
+ - `<component>` is the name of the component, in `kebab-case`
47
+ - `<path>` is the path to the folder where the component will be created, default is `atom` to create inside `src/atom`
48
+ - The prefix is `ippon` using `mise`
49
+
50
+ To generate the `Button` atom with the `ippon` prefix:
51
+
52
+ ```shell
53
+ mise styles-create-component button --path atom
54
+ ```
55
+
56
+ - ippon is used as the prefix
57
+ - button is the name of the component
58
+ - src/atom is the path to the folder where the component (atom) will be created
59
+
60
+ ## Atomic Design
61
+
62
+ Atomic Design is proposed by Brad Frost. The idea is to hierarchically compose graphical components into five levels:
63
+
64
+ - Atoms: indivisible elements such as a button, form field, or icon
65
+ - Molecules: groups of atoms to compose to form small components
66
+ - Organisms: groups of molecules to assemble to form more complex elements
67
+ - Templates: groups of organisms, molecules, or atoms to assemble to form pages
68
+ - Pages: instances of templates with real content (it is the applications consuming the Pattern Library that will create the pages)
69
+
70
+ In Tikui, these concepts are represented by folders:
71
+
72
+ ```
73
+ src/
74
+ atom/
75
+ atom.pug
76
+ _atom.scss
77
+ molecule/
78
+ molecules.pug
79
+ _molecule.scss
80
+ organism/
81
+ organism.pug
82
+ _organism.scss
83
+ template/
84
+ template.pug
85
+ _template.scss
86
+ index.pug
87
+ tikui.scss
88
+ ```
89
+
90
+ ## CAP
91
+
92
+ A component follows CAP (Component Alternative Part):
93
+
94
+ - Component: the name of the component in `kebab-case`
95
+ - Alternative: an alternative of the component or a part that starts with a `-`, followed by the name of the alternative in `kebab-case`
96
+ - Part: a part of the component or an alternative that starts with `--`, followed by the name of the part in `kebab-case`
97
+
98
+ An example with a button:
99
+
100
+ In SCSS:
101
+
102
+ ```scss
103
+ .ippon-button {
104
+ // button styles
105
+
106
+ &.-primary {
107
+ // primary alternative styles
108
+ }
109
+
110
+ &.-secondary {
111
+ // secondary alternative styles
112
+ }
113
+
114
+ &--icon {
115
+ // icon part styles
116
+ }
117
+
118
+ &--text {
119
+ // text part styles
120
+ }
121
+ }
122
+ ```
123
+
124
+ In HTML:
125
+
126
+ ```html
127
+ <button class="ippon-button -primary">
128
+ <span class="ippon-button--icon">Icon</span>
129
+ <span class="ippon-button--text">Text</span>
130
+ </button>
131
+ ```
132
+
133
+ ## Tikui
134
+
135
+ To document with Tikui, simply include the component's Markdown file in the file where you want to document it.
136
+
137
+ You will use:
138
+
139
+ - `componentDoc` for atoms, molecules, and organisms
140
+ - A size can be specified for the component rendering with the `height` option (example: `height=300`)
141
+ - `templateDoc` for templates
142
+ - There is no size since the rendering area represents a button to go to the rendering
143
+
144
+ For a `Button` atom:
145
+
146
+ ```pug
147
+ include:componentDoc(height=300) button/button.md
148
+ ```
149
+
150
+ For a `Layout` template:
151
+
152
+ ```pug
153
+ include:templateDoc layout/layout.md
154
+ ```
155
+
156
+ ## Token
157
+
158
+ A token is a style property. This can be a color, a font, a spacing, etc… It's a concept, so, even if it's possible to use variables to represent tokens, it's important to not confuse tokens and variables.
159
+
160
+ In the Patten Library, tokens are defined inside the `tokens` folder:
161
+
162
+ ```
163
+ src/
164
+ token/
165
+ _token.scss
166
+ token.pug
167
+ ```
168
+
169
+ ### Color
170
+
171
+ A color token can be directly the color with a quantity represented by a number from 0 to 999.
172
+
173
+ For the color `green`, it can be represented by the following tokens:
174
+
175
+ ```
176
+ --ippon-color-green-100, --ippon-color-green-200, --ippon-color-green-300, --ippon-color-green-400, --ippon-color-green-500, --ippon-color-green-600, --ippon-color-green-700, --ippon-color-green-800, --ippon-color-green-900
177
+ ```
178
+
179
+ But it stills a base color, the base color itself can't be used directly for a component, it must be used by a semantic color.
180
+
181
+ #### Semantic color
182
+
183
+ A semantic color is a color token that represents a meaning. For example, the `positive` semantic color use the `green` base color. The `semantic` color has also a quantity.
184
+
185
+ Here is an example for the `positive` semantic color:
186
+
187
+ ```scss
188
+ :root {
189
+ --ippon-color-positive-100: var(--ippon-color-green-100);
190
+ --ippon-color-positive-200: var(--ippon-color-green-200);
191
+ --ippon-color-positive-300: var(--ippon-color-green-300);
192
+ --ippon-color-positive-400: var(--ippon-color-green-400);
193
+ --ippon-color-positive-500: var(--ippon-color-green-500);
194
+ --ippon-color-positive-600: var(--ippon-color-green-600);
195
+ --ippon-color-positive-700: var(--ippon-color-green-700);
196
+ --ippon-color-positive-800: var(--ippon-color-green-800);
197
+ --ippon-color-positive-900: var(--ippon-color-green-900);
198
+ }
199
+ ```
200
+
201
+ Another level of semantic color exists, more relative to the usage. There is the following semantic color groups:
202
+
203
+ - `surface`
204
+ - `text-icon`
205
+ - `border`
206
+
207
+ It's also possible to find alternatives like 'primary', 'secondary', 'tertiary', etc…
208
+
209
+ So it's possible to define a text or icon color `on` a surface color, for example `on-primary` or `on-secondary`.
210
+
211
+ Here is an example for the `success` semantic color:
212
+
213
+ ```scss
214
+ :root {
215
+ --ippon-color-success-surface-primary: var(--ippon-color-positive-700);
216
+ --ippon-color-success-surface-primary-hover: var(--ippon-color-positive-800);
217
+ --ippon-color-success-surface-primary-active: var(--ippon-color-positive-900);
218
+ --ippon-color-success-surface-secondary: var(--ippon-color-positive-100);
219
+ --ippon-color-success-surface-secondary-hover: var(--ippon-color-positive-200);
220
+ --ippon-color-success-surface-secondary-active: var(--ippon-color-positive-300);
221
+ --ippon-color-success-text-icon-primary: var(--ippon-color-positive-600);
222
+ --ippon-color-success-text-icon-secondary: var(--ippon-color-positive-800);
223
+ --ippon-color-success-text-icon-on-primary: var(--ippon-color-neutral-0);
224
+ --ippon-color-success-text-icon-on-secondary: var(--ippon-color-positive-700);
225
+ --ippon-color-success-border: var(--ippon-color-positive-500);
226
+ }
227
+ ```
228
+
229
+ ## Quark
230
+
231
+ A quark is a portion of an atom, molecule, or organism that is not usable without being part of a component. Generally, we use SCSS `@mixin` to represent quarks but it's not mandatory, it's a concept. For example, for a `Text` and a `Title` atom, we can imagine a set quark to represent weight alternatives:
232
+
233
+ ```scss
234
+ @mixin weights {
235
+ &.-light {
236
+ font-weight: 300;
237
+ }
238
+
239
+ &.-regular {
240
+ font-weight: 400;
241
+ }
242
+
243
+ &.-medium {
244
+ font-weight: 500;
245
+ }
246
+
247
+ &.-bold {
248
+ font-weight: 700;
249
+ }
250
+ }
251
+ ```
252
+
253
+ So it's possible to use this `weights` quark for both `Text` and `Title` atoms:
254
+
255
+ **Text:**
256
+
257
+ ```scss
258
+ .ippon-text {
259
+ @include weights;
260
+ }
261
+ ```
262
+
263
+ **Title:**
264
+
265
+ ```scss
266
+ .ippon-title {
267
+ @include weights;
268
+ }
269
+ ```
270
+
271
+ In the Pattern Library, quarks are defined in the `quark` folder:
272
+
273
+ ```
274
+ src/
275
+ quark/
276
+ _quark.scss
277
+ ```
@@ -0,0 +1,34 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: pnpm/action-setup@v4
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 24.14.1
21
+ cache: pnpm
22
+ - run: pnpm -r install --frozen-lockfile
23
+ - run: pnpm format:ci
24
+ - run: pnpm lint:ci
25
+ - run: pnpm test:unit:ci
26
+ - run: pnpm build
27
+ - uses: actions/upload-artifact@v4
28
+ with:
29
+ name: build-artifacts
30
+ path: |
31
+ icons/dist
32
+ icons/types
33
+ styles/dist
34
+ retention-days: 1
package/.gitlab-ci.yml ADDED
@@ -0,0 +1,12 @@
1
+ include:
2
+ - local: 'ci/common.yml'
3
+ - local: 'ci/build.yml'
4
+ - local: 'ci/deploy.yml'
5
+
6
+ default-build:
7
+ stage: build
8
+ script:
9
+ - echo "Nothing to build"
10
+ rules:
11
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
12
+ when: never
@@ -0,0 +1,6 @@
1
+ /*/dist/
2
+ /pnpm-lock.yaml
3
+ /icons/svg/
4
+ /styles/.tikui-cache/
5
+ /icons/types/
6
+ /.pnpm-store/
package/AGENTS.md ADDED
@@ -0,0 +1,50 @@
1
+ Code must be in English.
2
+
3
+ ## Monorepo Structure
4
+
5
+ The project is a monorepo composed of the following projects:
6
+
7
+ - **styles**: Contains a Pattern Library with visual components, organized following Atomic Design.
8
+ - **icons**: Allows generating an icon font from SVG files from Ionicons
9
+
10
+ ## Commands
11
+
12
+ You should use `mise` to run commands linked to this project. If you need to add more operations or a new command, please edit the `mise.toml` file, so the command will be available.
13
+
14
+ Run from the **monorepo root** unless noted otherwise.
15
+
16
+ | Task | Command |
17
+ | ---------------------------- | ------------------- |
18
+ | Trust mise | `mise trust` |
19
+ | Install mise | `mise install` |
20
+ | Install dependencies | `mise setup` |
21
+ | Start all in dev mode | `mise dev` |
22
+ | Build all packages | `mise build` |
23
+ | Format (fix) | `mise format` |
24
+ | Format (check only) | `mise format-ci` |
25
+ | Lint (fix) | `mise lint` |
26
+ | Lint (check only) | `mise lint-ci` |
27
+ | Unit tests (not interactive) | `mise unit-test-ci` |
28
+
29
+ ## Pattern Library (`styles`)
30
+
31
+ The Pattern Library uses [Tikui](https://tikui.org) and follows [Atomic Design](http://atomicdesign.bradfrost.com/table-of-contents/):
32
+
33
+ ```
34
+ src/
35
+ quark/ # SCSS variables, mixins, fonts reused inside atoms/molecules/organisms (no rendered output)
36
+ token/ # Design tokens (colors, shadows, typography, sizes)
37
+ atom/ # Smallest components: badge, button, icon, ion, meter, text, title, tab
38
+ molecule/ # Composed atoms: import-file, tabs, toggle
39
+ organism/ # Layout-level components: card, container, h-space, v-space, grid, header, modal, button-card
40
+ template/ # Full page layouts
41
+ ```
42
+
43
+ CSS class naming uses an alternative-prefix convention: base class + `-<modifier>` (e.g. `ippon-card -shadow-2 -border`).
44
+
45
+ To develop the Pattern Library: `mise styles-dev` (serves on port 4220).
46
+
47
+ To add a component: `mise styles-create-component <component> --path <path>` where:
48
+
49
+ - component: component name in `kebab-case` (e.g. `button-card`)
50
+ - path: default is 'atom' to create inside `src/atom` from the styles directory