@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,242 @@
1
+ @use '../../quark/typography';
2
+
3
+ @keyframes ippon-button-loading-pulse {
4
+ 0%,
5
+ 100% {
6
+ opacity: 1;
7
+ }
8
+
9
+ 50% {
10
+ opacity: 0.5;
11
+ }
12
+ }
13
+
14
+ @keyframes ippon-button-loading-spin {
15
+ from {
16
+ rotate: 0deg;
17
+ }
18
+
19
+ to {
20
+ rotate: 360deg;
21
+ }
22
+ }
23
+
24
+ .ippon-button {
25
+ @include typography.label-medium;
26
+
27
+ --_color-primary: var(--ippon-color-brand-surface-primary);
28
+ --_color-primary-hover: var(--ippon-color-brand-surface-primary-hover);
29
+ --_color-primary-active: var(--ippon-color-brand-surface-primary-active);
30
+ --_color-secondary: var(--ippon-color-brand-surface-secondary);
31
+ --_color-secondary-hover: var(--ippon-color-brand-surface-secondary-hover);
32
+ --_color-secondary-active: var(--ippon-color-brand-surface-secondary-active);
33
+ --_color-outline: transparent;
34
+ --_color-text-primary: var(--ippon-color-brand-text-icon-on-primary);
35
+ --_color-text-secondary: var(--ippon-color-brand-text-icon-on-secondary);
36
+ --_color-border: var(--ippon-color-brand-border);
37
+ --_icon-size: var(--ippon-size-20);
38
+ --_padding-vertical: var(--ippon-size-8);
39
+ --_padding-horizontal: var(--ippon-size-16);
40
+ --_background-color: var(--_color-primary);
41
+ --_border-color: var(--_color-primary);
42
+ --_color: var(--_color-text-primary);
43
+ --_border-width: 1px;
44
+ --_inner-padding-vertical: calc(var(--_padding-vertical) - var(--_border-width));
45
+ --_inner-padding-horizontal: calc(var(--_padding-horizontal) - var(--_border-width));
46
+
47
+ display: inline-flex;
48
+ gap: var(--ippon-size-8);
49
+ align-items: center;
50
+ border: var(--_border-width) solid var(--_border-color);
51
+ border-radius: var(--ippon-radius-m);
52
+ background-color: var(--_background-color);
53
+ padding: var(--_inner-padding-vertical) var(--_inner-padding-horizontal);
54
+ vertical-align: middle;
55
+ color: var(--_color);
56
+ cursor: pointer;
57
+
58
+ &:has(&--icon:is(:last-child)) {
59
+ padding-right: var(--_inner-padding-vertical);
60
+ }
61
+
62
+ &:has(&--icon:is(:first-child)) {
63
+ padding-left: var(--_inner-padding-vertical);
64
+ }
65
+
66
+ &--icon {
67
+ line-height: 1;
68
+ font-size: var(--_icon-size);
69
+ font-weight: 400;
70
+ }
71
+
72
+ &.-small {
73
+ @include typography.label-small;
74
+
75
+ --_padding-vertical: var(--ippon-size-8);
76
+ --_padding-horizontal: var(--ippon-size-12);
77
+ --_icon-size: var(--ippon-size-16);
78
+ }
79
+
80
+ &.-large {
81
+ @include typography.label-large;
82
+
83
+ --_padding-vertical: var(--ippon-size-12);
84
+ --_padding-horizontal: var(--ippon-size-16);
85
+ --_icon-size: var(--ippon-size-24);
86
+ }
87
+
88
+ &:hover {
89
+ --_background-color: var(--_color-primary-hover);
90
+ --_border-color: var(--_color-primary-hover);
91
+ }
92
+
93
+ &:active {
94
+ --_background-color: var(--_color-primary-active);
95
+ --_border-color: var(--_color-primary-active);
96
+ }
97
+
98
+ &:disabled:not(.-loading) {
99
+ --_background-color: var(--ippon-color-neutral-200);
100
+ --_border-color: var(--ippon-color-neutral-200);
101
+ --_color: var(--ippon-color-neutral-500);
102
+
103
+ cursor: not-allowed;
104
+ }
105
+
106
+ &.-secondary {
107
+ --_background-color: var(--_color-secondary);
108
+ --_border-color: var(--_color-secondary);
109
+ --_color: var(--_color-text-secondary);
110
+
111
+ &:hover {
112
+ --_background-color: var(--_color-secondary-hover);
113
+ --_border-color: var(--_color-secondary-hover);
114
+ }
115
+
116
+ &:active {
117
+ --_background-color: var(--_color-secondary-active);
118
+ --_border-color: var(--_color-secondary-active);
119
+ }
120
+
121
+ &:disabled:not(.-loading) {
122
+ --_background-color: var(--ippon-color-neutral-200);
123
+ --_border-color: var(--ippon-color-neutral-200);
124
+ --_color: var(--ippon-color-neutral-500);
125
+ }
126
+ }
127
+
128
+ &.-outline {
129
+ --_background-color: var(--_color-outline);
130
+ --_color: var(--_color-text-secondary);
131
+ --_border-color: var(--_color-border);
132
+
133
+ &:hover {
134
+ --_background-color: var(--_color-secondary-hover);
135
+ }
136
+
137
+ &:active {
138
+ --_background-color: var(--_color-secondary-active);
139
+ }
140
+
141
+ &:disabled:not(.-loading) {
142
+ --_background-color: var(--ippon-color-neutral-200);
143
+ --_border-color: var(--ippon-color-neutral-200);
144
+ --_color: var(--ippon-color-neutral-500);
145
+ }
146
+ }
147
+
148
+ &.-text {
149
+ --_background-color: transparent;
150
+ --_border-color: transparent;
151
+ --_color: var(--_color-text-secondary);
152
+
153
+ &:hover {
154
+ --_background-color: var(--_color-secondary-hover);
155
+ --_border-color: transparent;
156
+ }
157
+
158
+ &:active {
159
+ --_background-color: var(--_color-secondary-active);
160
+ --_border-color: transparent;
161
+ }
162
+
163
+ &:disabled:not(.-loading) {
164
+ --_background-color: transparent;
165
+ --_border-color: transparent;
166
+ }
167
+ }
168
+
169
+ &.-loading {
170
+ animation: ippon-button-loading-pulse 1.5s ease-in-out infinite;
171
+ cursor: progress;
172
+ }
173
+
174
+ &--icon.-loading {
175
+ animation: ippon-button-loading-spin 1s linear infinite;
176
+ }
177
+
178
+ &.-success {
179
+ --_color-primary: var(--ippon-color-success-surface-primary);
180
+ --_color-primary-hover: var(--ippon-color-success-surface-primary-hover);
181
+ --_color-primary-active: var(--ippon-color-success-surface-primary-active);
182
+ --_color-secondary: var(--ippon-color-success-surface-secondary);
183
+ --_color-secondary-hover: var(--ippon-color-success-surface-secondary-hover);
184
+ --_color-secondary-active: var(--ippon-color-success-surface-secondary-active);
185
+ --_color-outline: transparent;
186
+ --_color-text-primary: var(--ippon-color-success-text-icon-on-primary);
187
+ --_color-text-secondary: var(--ippon-color-success-text-icon-on-secondary);
188
+ --_color-border: var(--ippon-color-success-border);
189
+ }
190
+
191
+ &.-error {
192
+ --_color-primary: var(--ippon-color-error-surface-primary);
193
+ --_color-primary-hover: var(--ippon-color-error-surface-primary-hover);
194
+ --_color-primary-active: var(--ippon-color-error-surface-primary-active);
195
+ --_color-secondary: var(--ippon-color-error-surface-secondary);
196
+ --_color-secondary-hover: var(--ippon-color-error-surface-secondary-hover);
197
+ --_color-secondary-active: var(--ippon-color-error-surface-secondary-active);
198
+ --_color-outline: var(--ippon-color-neutral-surface-secondary);
199
+ --_color-text-primary: var(--ippon-color-error-text-icon-on-primary);
200
+ --_color-text-secondary: var(--ippon-color-error-text-icon-on-secondary);
201
+ --_color-border: var(--ippon-color-error-border);
202
+ }
203
+
204
+ &.-information {
205
+ --_color-primary: var(--ippon-color-information-2-surface-primary);
206
+ --_color-primary-hover: var(--ippon-color-information-2-surface-primary-hover);
207
+ --_color-primary-active: var(--ippon-color-information-2-surface-primary-active);
208
+ --_color-secondary: var(--ippon-color-information-2-surface-secondary);
209
+ --_color-secondary-hover: var(--ippon-color-information-2-surface-secondary-hover);
210
+ --_color-secondary-active: var(--ippon-color-information-2-surface-secondary-active);
211
+ --_color-outline: transparent;
212
+ --_color-text-primary: var(--ippon-color-information-2-text-icon-on-primary);
213
+ --_color-text-secondary: var(--ippon-color-information-2-text-icon-on-secondary);
214
+ --_color-border: var(--ippon-color-information-2-border);
215
+ }
216
+
217
+ &.-warning {
218
+ --_color-primary: var(--ippon-color-warning-surface-primary);
219
+ --_color-primary-hover: var(--ippon-color-warning-surface-primary-hover);
220
+ --_color-primary-active: var(--ippon-color-warning-surface-primary-active);
221
+ --_color-secondary: var(--ippon-color-warning-surface-secondary);
222
+ --_color-secondary-hover: var(--ippon-color-warning-surface-secondary-hover);
223
+ --_color-secondary-active: var(--ippon-color-warning-surface-secondary-active);
224
+ --_color-outline: var(--ippon-color-neutral-surface-secondary);
225
+ --_color-text-primary: var(--ippon-color-warning-text-icon-on-primary);
226
+ --_color-text-secondary: var(--ippon-color-warning-text-icon-on-secondary);
227
+ --_color-border: var(--ippon-color-warning-border);
228
+ }
229
+
230
+ &.-neutral {
231
+ --_color-primary: var(--ippon-color-neutral-surface-primary);
232
+ --_color-primary-hover: var(--ippon-color-neutral-surface-primary-hover);
233
+ --_color-primary-active: var(--ippon-color-neutral-surface-primary-active);
234
+ --_color-secondary: var(--ippon-color-neutral-surface-secondary);
235
+ --_color-secondary-hover: var(--ippon-color-neutral-surface-secondary-hover);
236
+ --_color-secondary-active: var(--ippon-color-neutral-surface-secondary-active);
237
+ --_color-outline: var(--ippon-color-neutral-surface-secondary);
238
+ --_color-text-primary: var(--ippon-color-neutral-text-icon-on-primary);
239
+ --_color-text-secondary: var(--ippon-color-neutral-text-icon-on-secondary);
240
+ --_color-border: var(--ippon-color-neutral-border);
241
+ }
242
+ }
@@ -0,0 +1,38 @@
1
+ include /atom/ion/ion.mixin.pug
2
+
3
+ include button.mixin.pug
4
+
5
+ mixin ippon-button-example-variants(options)
6
+ - const { color, size } = options || {};
7
+ - const variants = [null, 'secondary', 'outline', 'text'];
8
+ - const ucFirst = (string) => (string ? string.charAt(0).toUpperCase() + string.slice(1) : '');
9
+ - const sizeSuffix = size ? ` (${size})` : '';
10
+ each variant in variants
11
+ +ippon-button({ color, variant: variant, size })
12
+ = `${ucFirst(color || 'default')} ${variant || 'primary'}${sizeSuffix}`
13
+ +ippon-button({ size, color, disabled: true })
14
+ = 'disabled'
15
+ +ippon-button({ size, color, loading: true })
16
+ = 'loading'
17
+
18
+ mixin ippon-button-example-colors
19
+ - const colors = ['success', 'error', 'information', 'warning', 'neutral'];
20
+
21
+ each color in colors
22
+ +ippon-button-example-variants({ color })
23
+
24
+ mixin ippon-button-example-icons(size)
25
+ +ippon-button({ size, icon: { name: 'heart' } })
26
+ +ippon-button({ size, variant: 'secondary', iconLeft: { name: 'logo-angular' } }) Icon left
27
+ +ippon-button({ size, variant: 'outline', iconRight: { name: 'search' } }) Icon right
28
+ +ippon-button({ size, variant: 'text', iconLeft: { name: 'remove' }, iconRight: { name: 'add' } }) Icon both
29
+ +ippon-button({ size, disabled: true, iconLeft: { name: 'remove' }, iconRight: { name: 'add' } }) Disabled
30
+ +ippon-button({ size, loading: true, iconLeft: { name: 'remove' }, iconRight: { name: 'add' } }) Loading
31
+
32
+ +ippon-button-example-variants({ size: 'small' })
33
+ +ippon-button-example-variants
34
+ +ippon-button-example-variants({ size: 'large' })
35
+ +ippon-button-example-colors
36
+ +ippon-button-example-icons('small')
37
+ +ippon-button-example-icons
38
+ +ippon-button-example-icons('large')
@@ -0,0 +1,31 @@
1
+ ## Button
2
+
3
+ **Colors:**
4
+
5
+ - Default
6
+ - Success `-success`
7
+ - Error `-error`
8
+ - Information `-information`
9
+ - Warning `-warning`
10
+ - Neutral `-neutral`
11
+
12
+ **Variants:**
13
+
14
+ - Primary
15
+ - Secondary `-secondary`
16
+ - Outline `-outline`
17
+ - Text `-text`
18
+
19
+ **States:**
20
+
21
+ - Loading `-loading` (adds `disabled` and `aria-busy="true"`)
22
+ - When a right icon is present, replace it with a `sync` icon (the CSS animation is handled by `-loading`)
23
+
24
+ **Icons:**
25
+
26
+ If you use [icons]([[TIKUI_BASEPATH]]icons/index.html), don't forget to wrap each child in a **part**:
27
+
28
+ - `icon-button--icon` for the icon
29
+ - `icon-button--text` for the text
30
+
31
+ > It's because the space before and after the icon is different from a _text_ or an _icon_.
@@ -0,0 +1,30 @@
1
+ include /atom/ion/ion.mixin.pug
2
+
3
+ mixin ippon-button(options)
4
+ - const { disabled, loading, color, variant, icon, iconLeft, iconRight, size, command, commandfor } = options || {};
5
+ - const colorClass = color ? `-${color}` : null;
6
+ - const variantClass = variant ? `-${variant}` : null;
7
+ - const sizeClass = size ? `-${size}` : null;
8
+ - const loadingClass = loading ? '-loading' : null;
9
+ - const realIconLeft = iconLeft ?? icon;
10
+ - const realIconRight = loading && iconRight ? { name: 'sync' } : iconRight;
11
+ - const iconRightClass = loading && iconRight ? 'ippon-button--icon -loading' : 'ippon-button--icon';
12
+ - const hasIcon = !!(realIconLeft || realIconRight);
13
+
14
+ button.ippon-button(
15
+ class=[colorClass, variantClass, sizeClass, loadingClass],
16
+ disabled=disabled || loading,
17
+ aria-busy=loading ? 'true' : undefined,
18
+ command=command,
19
+ commandfor=commandfor
20
+ )
21
+ if realIconLeft
22
+ +ippon-ion({ ...realIconLeft, additionalClass: 'ippon-button--icon' })
23
+ if block
24
+ if hasIcon
25
+ span.ippon-button--text
26
+ block
27
+ else
28
+ block
29
+ if realIconRight
30
+ +ippon-ion({ ...realIconRight, additionalClass: iconRightClass })
@@ -0,0 +1,13 @@
1
+ extends /layout
2
+
3
+ block body
4
+ div(
5
+ style='display: grid; grid-template-columns: repeat(6, auto); gap: 1rem; justify-items: left; align-items: center'
6
+ )
7
+ div Primary
8
+ div Secondary
9
+ div Outline
10
+ div Text
11
+ div Disabled
12
+ div Loading
13
+ include button.code.pug
@@ -0,0 +1,8 @@
1
+ @use '../../quark/font';
2
+
3
+ .ippon-icon {
4
+ line-height: 1;
5
+
6
+ @include font.sizes;
7
+ @include font.colors;
8
+ }
@@ -0,0 +1,5 @@
1
+ include icon.mixin.pug
2
+
3
+ +ippon-icon({ name: 'add' })
4
+ +ippon-icon({ name: 'close', size: 24 })
5
+ +ippon-icon({ name: 'close', color: 'brand-primary' })
@@ -0,0 +1,11 @@
1
+ ## Icon
2
+
3
+ The `icon` atom represents a graphical icon element from the Ionicons library.
4
+
5
+ **Usage**
6
+
7
+ Icons are rendered using the `ippon-icon` class with the `ippon-ion-{name}` classes to specify which icon to display from the Ionicons library.
8
+
9
+ **Sizing**
10
+
11
+ Icons inherit their size from the parent element's font size. They maintain a 1:1 aspect ratio.
@@ -0,0 +1,8 @@
1
+ include /atom/ion/ion.mixin.pug
2
+
3
+ mixin ippon-icon(options)
4
+ - const { color, additionalClass, size } = options;
5
+ - const sizeClass = size ? `-size-${size}` : null;
6
+ - const colorClass = color ? `-color-${color}` : null;
7
+ - const ionOptions = { additionalClass: ['ippon-icon', sizeClass, colorClass, additionalClass], ...options };
8
+ +ippon-ion(ionOptions)
@@ -0,0 +1,7 @@
1
+ extends /layout
2
+
3
+ block body
4
+ div(
5
+ style='font-size: 2rem; display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(2rem, 1fr)); justify-items: center; align-items: center'
6
+ )
7
+ include icon.code.pug
@@ -0,0 +1,8 @@
1
+ include ion.mixin.pug
2
+
3
+ +ippon-ion({ name: 'home', variant: 'filled' })
4
+ +ippon-ion({ name: 'home', variant: 'outline' })
5
+ +ippon-ion({ name: 'home', variant: 'sharp' })
6
+ +ippon-ion({ name: 'logo-angular' })
7
+ +ippon-ion({ name: 'logo-react' })
8
+ +ippon-ion({ name: 'logo-vue' })
@@ -0,0 +1,11 @@
1
+ ## Ion (Icons)
2
+
3
+ Ion are based on _Ionicons_, the set is [available here]([[TIKUI_BASEPATH]]icons/index.html).
4
+
5
+ There is two kinds of icons:
6
+
7
+ - Classic ones: start with `ippon-ion-` followed by suffix (Variant):
8
+ - Nothing: the default one (**Filled**).
9
+ - `-outline` for the **outline** version.
10
+ - `-sharp` for the **sharp** version.
11
+ - Logo ones: start with `ippon-ion-logo-` followed by the name of the logo.
@@ -0,0 +1,8 @@
1
+ mixin ippon-ion(options)
2
+ - const { name, variant, additionalClass, clickable } = options || {};
3
+ - const safeVariant = ['outline', 'sharp'].includes(variant) ? variant : null;
4
+ - const suffix = safeVariant ? `-${safeVariant}` : '';
5
+ - const iconClass = `ippon-ion-${name}${suffix}`;
6
+ - const selector = clickable ? 'button' : 'span';
7
+ - const role = clickable ? null : 'presentation';
8
+ #{selector}(class=[additionalClass, iconClass], role=role)
@@ -0,0 +1,7 @@
1
+ extends /layout
2
+
3
+ block body
4
+ div(
5
+ style='font-size: 2rem; display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(2rem, 1fr)); justify-items: center; align-items: center'
6
+ )
7
+ include ion.code.pug
@@ -0,0 +1,23 @@
1
+ .ippon-meter {
2
+ --_bar-color: var(--ippon-color-information-2-surface-primary);
3
+ --_background-color: var(--ippon-color-neutral-surface-tertiary);
4
+ --_height: var(--ippon-size-8);
5
+ --ippon-meter-percentage: 0%;
6
+
7
+ display: block;
8
+ position: relative;
9
+ background-color: var(--_background-color);
10
+ width: 100%;
11
+ height: var(--_height);
12
+ overflow: hidden;
13
+
14
+ &::before {
15
+ position: absolute;
16
+ inset: 0 auto 0 0;
17
+ transition: width 0.3s ease-in-out;
18
+ border-radius: var(--_border-radius);
19
+ background-color: var(--_bar-color);
20
+ width: var(--ippon-meter-percentage);
21
+ content: '';
22
+ }
23
+ }
@@ -0,0 +1,8 @@
1
+ include meter.mixin.pug
2
+
3
+ +ippon-meter({ min: 0, max: 100, value: 0 })
4
+ +ippon-meter({ min: 0, max: 100, value: 25 })
5
+ +ippon-meter({ min: 0, max: 100, value: 50 })
6
+ +ippon-meter({ min: 0, max: 100, value: 75 })
7
+ +ippon-meter({ min: 0, max: 100, value: 100 })
8
+ +ippon-meter({ min: 0, max: 200, value: 150 })
@@ -0,0 +1,7 @@
1
+ ## Meter
2
+
3
+ A meter component to display a gauge indicator with a minimum, current, and maximum value.
4
+
5
+ **Accessibility:**
6
+
7
+ Uses ARIA `role="meter"` with `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` attributes for proper accessibility support.
@@ -0,0 +1,12 @@
1
+ mixin ippon-meter(options)
2
+ - const { min = 0, max = 100, value = 0 } = options || {};
3
+ - const percentage = ((value - min) / (max - min)) * 100;
4
+ - const style = `--ippon-meter-percentage: ${Math.min(Math.max(percentage, 0), 100)}%`;
5
+
6
+ .ippon-meter(
7
+ role='meter',
8
+ aria-valuenow=value,
9
+ aria-valuemin=min,
10
+ aria-valuemax=max,
11
+ style=style
12
+ )
@@ -0,0 +1,5 @@
1
+ extends /layout
2
+
3
+ block body
4
+ div(style='display: grid; gap: 1rem')
5
+ include meter.code.pug
@@ -0,0 +1,23 @@
1
+ .ippon-progress {
2
+ --_bar-color: var(--ippon-color-information-2-surface-primary);
3
+ --_background-color: var(--ippon-color-neutral-surface-tertiary);
4
+ --_height: var(--ippon-size-8);
5
+ --ippon-progress-percentage: 0%;
6
+
7
+ display: block;
8
+ position: relative;
9
+ background-color: var(--_background-color);
10
+ width: 100%;
11
+ height: var(--_height);
12
+ overflow: hidden;
13
+
14
+ &::before {
15
+ position: absolute;
16
+ inset: 0 auto 0 0;
17
+ transition: width 0.3s ease-in-out;
18
+ border-radius: var(--_border-radius);
19
+ background-color: var(--_bar-color);
20
+ width: var(--ippon-progress-percentage);
21
+ content: '';
22
+ }
23
+ }
@@ -0,0 +1,8 @@
1
+ include progress.mixin.pug
2
+
3
+ +ippon-progress({ min: 0, max: 100, value: 0 })
4
+ +ippon-progress({ min: 0, max: 100, value: 25 })
5
+ +ippon-progress({ min: 0, max: 100, value: 50 })
6
+ +ippon-progress({ min: 0, max: 100, value: 75 })
7
+ +ippon-progress({ min: 0, max: 100, value: 100 })
8
+ +ippon-progress({ min: 0, max: 200, value: 150 })
@@ -0,0 +1,7 @@
1
+ ## Progress
2
+
3
+ A progress component to display the completion progress of a task.
4
+
5
+ **Accessibility:**
6
+
7
+ Uses ARIA `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` attributes for proper accessibility support.
@@ -0,0 +1,14 @@
1
+ mixin ippon-progress(options)
2
+ - const { min = 0, max = 100, value = 0 } = options || {};
3
+ - const percentage = ((value - min) / (max - min)) * 100;
4
+ - const style = `--ippon-progress-percentage: ${Math.min(Math.max(percentage, 0), 100)}%`;
5
+ - const busy = value < max;
6
+
7
+ .ippon-progress(
8
+ role='progressbar',
9
+ aria-valuenow=value,
10
+ aria-valuemin=min,
11
+ aria-valuemax=max,
12
+ aria-busy=busy,
13
+ style=style
14
+ )
@@ -0,0 +1,5 @@
1
+ extends /layout
2
+
3
+ block body
4
+ div(style='display: grid; gap: 1rem')
5
+ include progress.code.pug
@@ -0,0 +1,48 @@
1
+ @use '../../quark/typography';
2
+
3
+ .ippon-tab {
4
+ appearance: none;
5
+ display: inline-flex;
6
+ position: relative;
7
+ gap: var(--ippon-size-4);
8
+ border: 0;
9
+ background: transparent;
10
+ padding: var(--ippon-size-8) var(--ippon-size-12) var(--ippon-size-10);
11
+ overflow: hidden;
12
+ text-decoration: none;
13
+ color: inherit;
14
+ cursor: pointer;
15
+
16
+ @include typography.body-medium-bold;
17
+
18
+ &:hover {
19
+ color: var(--ippon-color-information-2-text-icon-secondary);
20
+ }
21
+
22
+ &[aria-selected='true'] {
23
+ color: var(--ippon-color-information-2-text-icon-secondary);
24
+ cursor: default;
25
+ }
26
+
27
+ &[aria-selected='true']::after {
28
+ bottom: calc(-1 * var(--_height));
29
+ }
30
+
31
+ &::after {
32
+ --_height: var(--ippon-size-2);
33
+ --_double-height: calc(var(--_height) * 2);
34
+ --_radius: var(--ippon-radius-m);
35
+ --_padding: var(--ippon-size-8);
36
+
37
+ box-sizing: border-box;
38
+ display: block;
39
+ position: absolute;
40
+ right: var(--_padding);
41
+ bottom: calc(-1 * var(--_double-height));
42
+ left: var(--_padding);
43
+ border: var(--_height) solid var(--ippon-color-information-2-surface-primary);
44
+ border-radius: var(--_radius);
45
+ height: var(--_double-height);
46
+ content: '';
47
+ }
48
+ }
@@ -0,0 +1,5 @@
1
+ include tab.mixin.pug
2
+
3
+ +ippon-tab({ id: 'tab-1', controls: 'panel-id' }) Tab 1
4
+ +ippon-tab({ id: 'tab-2', controls: 'panel-id', selected: true }) Tab 2
5
+ +ippon-tab({ id: 'tab-3', controls: 'panel-id', href: '#tab3' }) Tab 3
@@ -0,0 +1 @@
1
+ ## Tab
@@ -0,0 +1,14 @@
1
+ mixin ippon-tab(options)
2
+ - const { id, controls, selected, href } = options || {};
3
+ - const selector = href ? 'a' : 'button';
4
+ - ariaSelected = selected ? 'true' : null;
5
+ - tabindex = selected ? -1 : null;
6
+ #{selector}.ippon-tab(
7
+ role='tab',
8
+ id=id,
9
+ aria-controls=controls,
10
+ aria-selected=ariaSelected,
11
+ href=href,
12
+ tabindex=tabindex
13
+ )
14
+ block
@@ -0,0 +1,4 @@
1
+ extends /layout
2
+
3
+ block body
4
+ include tab.code.pug