@junoput01/junoui 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +117 -0
  3. package/dist/android/colors.xml +94 -0
  4. package/dist/android/dimens.xml +49 -0
  5. package/dist/css/juno-fonts.css +45 -0
  6. package/dist/css/juno-tokens.css +345 -0
  7. package/dist/css/juno.css +4481 -0
  8. package/dist/flutter/juno_tokens.dart +143 -0
  9. package/dist/fonts/b612-400.woff2 +0 -0
  10. package/dist/fonts/b612-700.woff2 +0 -0
  11. package/dist/fonts/b612-mono-400.woff2 +0 -0
  12. package/dist/fonts/b612-mono-700.woff2 +0 -0
  13. package/dist/icons/juno-icons.svg +69 -0
  14. package/dist/ios/JunoTokens.swift +149 -0
  15. package/dist/js/tokens.d.ts +11 -0
  16. package/dist/js/tokens.js +244 -0
  17. package/dist/json/tokens.json +921 -0
  18. package/dist/scss/_juno-tokens.scss +176 -0
  19. package/package.json +92 -0
  20. package/src/css/base.css +120 -0
  21. package/src/css/components/accordion.css +83 -0
  22. package/src/css/components/alert.css +90 -0
  23. package/src/css/components/avatar.css +82 -0
  24. package/src/css/components/badge.css +55 -0
  25. package/src/css/components/breadcrumb.css +64 -0
  26. package/src/css/components/button.css +59 -0
  27. package/src/css/components/card.css +68 -0
  28. package/src/css/components/checkbox.css +89 -0
  29. package/src/css/components/chip.css +89 -0
  30. package/src/css/components/divider.css +50 -0
  31. package/src/css/components/dock.css +74 -0
  32. package/src/css/components/dot.css +35 -0
  33. package/src/css/components/drawer.css +80 -0
  34. package/src/css/components/field.css +37 -0
  35. package/src/css/components/gauge.css +78 -0
  36. package/src/css/components/icon.css +35 -0
  37. package/src/css/components/input.css +60 -0
  38. package/src/css/components/list.css +135 -0
  39. package/src/css/components/loader.css +159 -0
  40. package/src/css/components/menu.css +114 -0
  41. package/src/css/components/modal.css +161 -0
  42. package/src/css/components/navbar.css +103 -0
  43. package/src/css/components/pagination.css +72 -0
  44. package/src/css/components/pillbar.css +111 -0
  45. package/src/css/components/popover.css +73 -0
  46. package/src/css/components/rail.css +96 -0
  47. package/src/css/components/readout.css +45 -0
  48. package/src/css/components/segmented.css +99 -0
  49. package/src/css/components/select.css +38 -0
  50. package/src/css/components/skeleton.css +62 -0
  51. package/src/css/components/slider.css +117 -0
  52. package/src/css/components/spark.css +26 -0
  53. package/src/css/components/stepper.css +121 -0
  54. package/src/css/components/switch.css +131 -0
  55. package/src/css/components/table.css +443 -0
  56. package/src/css/components/tabs.css +66 -0
  57. package/src/css/components/thumb.css +69 -0
  58. package/src/css/components/toast.css +109 -0
  59. package/src/css/components/toggle-button.css +91 -0
  60. package/src/css/components/tooltip.css +155 -0
  61. package/src/css/density.css +40 -0
  62. package/src/css/fonts.css +45 -0
  63. package/src/css/layout.css +99 -0
  64. package/src/css/typescale.css +27 -0
  65. package/src/css/utilities.css +76 -0
  66. package/src/fonts/LICENSE +93 -0
  67. package/src/fonts/b612-400.woff2 +0 -0
  68. package/src/fonts/b612-700.woff2 +0 -0
  69. package/src/fonts/b612-mono-400.woff2 +0 -0
  70. package/src/fonts/b612-mono-700.woff2 +0 -0
  71. package/src/icons/LICENSE +21 -0
  72. package/src/icons/arrow-clockwise.svg +1 -0
  73. package/src/icons/arrow-down.svg +1 -0
  74. package/src/icons/arrow-left.svg +1 -0
  75. package/src/icons/arrow-right.svg +1 -0
  76. package/src/icons/arrow-up.svg +1 -0
  77. package/src/icons/arrows-clockwise.svg +1 -0
  78. package/src/icons/arrows-out.svg +1 -0
  79. package/src/icons/bell.svg +1 -0
  80. package/src/icons/calendar-blank.svg +1 -0
  81. package/src/icons/caret-down.svg +1 -0
  82. package/src/icons/caret-left.svg +1 -0
  83. package/src/icons/caret-right.svg +1 -0
  84. package/src/icons/caret-up.svg +1 -0
  85. package/src/icons/chat-circle.svg +1 -0
  86. package/src/icons/check-circle.svg +1 -0
  87. package/src/icons/check.svg +1 -0
  88. package/src/icons/clock.svg +1 -0
  89. package/src/icons/cloud-arrow-down.svg +1 -0
  90. package/src/icons/cloud.svg +1 -0
  91. package/src/icons/copy.svg +1 -0
  92. package/src/icons/cpu.svg +1 -0
  93. package/src/icons/dots-three-vertical.svg +1 -0
  94. package/src/icons/dots-three.svg +1 -0
  95. package/src/icons/download.svg +1 -0
  96. package/src/icons/envelope.svg +1 -0
  97. package/src/icons/eye-slash.svg +1 -0
  98. package/src/icons/eye.svg +1 -0
  99. package/src/icons/file.svg +1 -0
  100. package/src/icons/film-strip.svg +1 -0
  101. package/src/icons/floppy-disk.svg +1 -0
  102. package/src/icons/folder.svg +1 -0
  103. package/src/icons/funnel.svg +1 -0
  104. package/src/icons/gear.svg +1 -0
  105. package/src/icons/hard-drives.svg +1 -0
  106. package/src/icons/heart.svg +1 -0
  107. package/src/icons/hexagon.svg +1 -0
  108. package/src/icons/house.svg +1 -0
  109. package/src/icons/images.svg +1 -0
  110. package/src/icons/info.svg +1 -0
  111. package/src/icons/link.svg +1 -0
  112. package/src/icons/list.svg +1 -0
  113. package/src/icons/lock-open.svg +1 -0
  114. package/src/icons/lock.svg +1 -0
  115. package/src/icons/magnifying-glass.svg +1 -0
  116. package/src/icons/minus.svg +1 -0
  117. package/src/icons/moon.svg +1 -0
  118. package/src/icons/pencil-simple.svg +1 -0
  119. package/src/icons/play.svg +1 -0
  120. package/src/icons/plus.svg +1 -0
  121. package/src/icons/puzzle-piece.svg +1 -0
  122. package/src/icons/question.svg +1 -0
  123. package/src/icons/sliders-horizontal.svg +1 -0
  124. package/src/icons/sliders.svg +1 -0
  125. package/src/icons/squares-four.svg +1 -0
  126. package/src/icons/star.svg +1 -0
  127. package/src/icons/sun.svg +1 -0
  128. package/src/icons/trash.svg +1 -0
  129. package/src/icons/upload-simple.svg +1 -0
  130. package/src/icons/upload.svg +1 -0
  131. package/src/icons/user.svg +1 -0
  132. package/src/icons/users.svg +1 -0
  133. package/src/icons/warning-circle.svg +1 -0
  134. package/src/icons/warning.svg +1 -0
  135. package/src/icons/x-circle.svg +1 -0
  136. package/src/icons/x.svg +1 -0
@@ -0,0 +1,176 @@
1
+ // junoui design tokens — SCSS variables. Generated; do not edit.
2
+
3
+ $juno-color-colorblind-dark-nominal: #78A9FF !default;
4
+ $juno-color-colorblind-dark-active: #BE95FF !default;
5
+ $juno-color-colorblind-dark-target: #FF7EB6 !default;
6
+ $juno-color-colorblind-dark-caution: #F1C21B !default;
7
+ $juno-color-colorblind-dark-warning: #FF832B !default;
8
+ $juno-color-colorblind-dark-data: oklch(93% 0.008 85) !default;
9
+ $juno-color-colorblind-dark-label: oklch(63% 0.012 85) !default;
10
+ $juno-color-colorblind-dark-muted: oklch(48.5% 0.010 85) !default;
11
+ $juno-color-colorblind-dark-border: oklch(30% 0.012 85) !default;
12
+ $juno-color-colorblind-dark-s0: oklch(11% 0.010 85) !default;
13
+ $juno-color-colorblind-dark-s1: oklch(15% 0.012 85) !default;
14
+ $juno-color-colorblind-dark-s2: oklch(19% 0.012 85) !default;
15
+ $juno-color-colorblind-dark-s3: oklch(24% 0.012 85) !default;
16
+ $juno-color-colorblind-dark-data-dim: oklch(38% 0.010 85) !default;
17
+ $juno-color-colorblind-dark-border-strong: oklch(40% 0.012 85) !default;
18
+ $juno-color-colorblind-light-nominal: #0043CE !default;
19
+ $juno-color-colorblind-light-active: #6929C4 !default;
20
+ $juno-color-colorblind-light-target: #9F1853 !default;
21
+ $juno-color-colorblind-light-caution: #7D4F00 !default;
22
+ $juno-color-colorblind-light-warning: #BA4300 !default;
23
+ $juno-color-colorblind-light-data: oklch(14% 0.008 85) !default;
24
+ $juno-color-colorblind-light-label: oklch(42% 0.010 85) !default;
25
+ $juno-color-colorblind-light-muted: oklch(63% 0.008 85) !default;
26
+ $juno-color-colorblind-light-border: oklch(82% 0.010 85) !default;
27
+ $juno-color-colorblind-light-s0: oklch(97% 0.008 85) !default;
28
+ $juno-color-colorblind-light-s1: oklch(93% 0.010 85) !default;
29
+ $juno-color-colorblind-light-s2: oklch(89% 0.010 85) !default;
30
+ $juno-color-colorblind-light-s3: oklch(85% 0.010 85) !default;
31
+ $juno-color-colorblind-light-data-dim: oklch(70% 0.008 85) !default;
32
+ $juno-color-colorblind-light-border-strong: oklch(74% 0.010 85) !default;
33
+ $juno-color-soft-dark-nominal: oklch(63% 0.13 155) !default;
34
+ $juno-color-soft-dark-active: oklch(67% 0.12 210) !default;
35
+ $juno-color-soft-dark-target: oklch(58% 0.14 318) !default;
36
+ $juno-color-soft-dark-caution: oklch(72% 0.12 75) !default;
37
+ $juno-color-soft-dark-warning: oklch(62% 0.15 30) !default;
38
+ $juno-color-soft-dark-data: oklch(90% 0.008 88) !default;
39
+ $juno-color-soft-dark-label: oklch(63% 0.010 88) !default;
40
+ $juno-color-soft-dark-muted: oklch(48.5% 0.010 88) !default;
41
+ $juno-color-soft-dark-border: oklch(31% 0.010 88) !default;
42
+ $juno-color-soft-dark-s0: oklch(12% 0.012 88) !default;
43
+ $juno-color-soft-dark-s1: oklch(16% 0.012 88) !default;
44
+ $juno-color-soft-dark-s2: oklch(20% 0.012 88) !default;
45
+ $juno-color-soft-dark-s3: oklch(25% 0.012 88) !default;
46
+ $juno-color-soft-dark-data-dim: oklch(39% 0.010 88) !default;
47
+ $juno-color-soft-dark-border-strong: oklch(41% 0.010 88) !default;
48
+ $juno-color-soft-light-nominal: oklch(40% 0.11 155) !default;
49
+ $juno-color-soft-light-active: oklch(44% 0.11 210) !default;
50
+ $juno-color-soft-light-target: oklch(42% 0.12 318) !default;
51
+ $juno-color-soft-light-caution: oklch(50% 0.12 75) !default;
52
+ $juno-color-soft-light-warning: oklch(42% 0.13 30) !default;
53
+ $juno-color-soft-light-data: oklch(14% 0.008 88) !default;
54
+ $juno-color-soft-light-label: oklch(44% 0.010 88) !default;
55
+ $juno-color-soft-light-muted: oklch(62.5% 0.008 88) !default;
56
+ $juno-color-soft-light-border: oklch(84% 0.010 88) !default;
57
+ $juno-color-soft-light-s0: oklch(96% 0.010 88) !default;
58
+ $juno-color-soft-light-s1: oklch(92% 0.010 88) !default;
59
+ $juno-color-soft-light-s2: oklch(88% 0.010 88) !default;
60
+ $juno-color-soft-light-s3: oklch(84% 0.010 88) !default;
61
+ $juno-color-soft-light-data-dim: oklch(69% 0.008 88) !default;
62
+ $juno-color-soft-light-border-strong: oklch(76% 0.010 88) !default;
63
+ $juno-color-standard-dark-nominal: oklch(73% 0.22 148) !default;
64
+ $juno-color-standard-dark-active: oklch(76% 0.16 204) !default;
65
+ $juno-color-standard-dark-target: oklch(65% 0.26 324) !default;
66
+ $juno-color-standard-dark-caution: oklch(77% 0.17 73) !default;
67
+ $juno-color-standard-dark-warning: oklch(63% 0.22 28) !default;
68
+ $juno-color-standard-dark-data: oklch(93% 0.008 85) !default;
69
+ $juno-color-standard-dark-label: oklch(63% 0.012 85) !default;
70
+ $juno-color-standard-dark-muted: oklch(48.5% 0.010 85) !default;
71
+ $juno-color-standard-dark-border: oklch(30% 0.012 85) !default;
72
+ $juno-color-standard-dark-s0: oklch(11% 0.010 85) !default;
73
+ $juno-color-standard-dark-s1: oklch(15% 0.012 85) !default;
74
+ $juno-color-standard-dark-s2: oklch(19% 0.012 85) !default;
75
+ $juno-color-standard-dark-s3: oklch(24% 0.012 85) !default;
76
+ $juno-color-standard-dark-data-dim: oklch(38% 0.010 85) !default;
77
+ $juno-color-standard-dark-border-strong: oklch(40% 0.012 85) !default;
78
+ $juno-color-standard-light-nominal: oklch(42% 0.18 148) !default;
79
+ $juno-color-standard-light-active: oklch(47% 0.16 220) !default;
80
+ $juno-color-standard-light-target: oklch(45% 0.22 324) !default;
81
+ $juno-color-standard-light-caution: oklch(50% 0.17 73) !default;
82
+ $juno-color-standard-light-warning: oklch(42% 0.21 26) !default;
83
+ $juno-color-standard-light-data: oklch(14% 0.008 85) !default;
84
+ $juno-color-standard-light-label: oklch(42% 0.010 85) !default;
85
+ $juno-color-standard-light-muted: oklch(63% 0.008 85) !default;
86
+ $juno-color-standard-light-border: oklch(82% 0.010 85) !default;
87
+ $juno-color-standard-light-s0: oklch(97% 0.008 85) !default;
88
+ $juno-color-standard-light-s1: oklch(93% 0.010 85) !default;
89
+ $juno-color-standard-light-s2: oklch(89% 0.010 85) !default;
90
+ $juno-color-standard-light-s3: oklch(85% 0.010 85) !default;
91
+ $juno-color-standard-light-data-dim: oklch(70% 0.008 85) !default;
92
+ $juno-color-standard-light-border-strong: oklch(74% 0.010 85) !default;
93
+ $juno-border-width-1: 1px !default;
94
+ $juno-border-width-2: 2px !default;
95
+ $juno-border-width-3: 3px !default;
96
+ $juno-bp-sm: 640px !default;
97
+ $juno-bp-md: 768px !default;
98
+ $juno-bp-lg: 1024px !default;
99
+ $juno-bp-xl: 1280px !default;
100
+ $juno-bp-2xl: 1536px !default;
101
+ $juno-shadow-1: 0 1px 2px rgb(0 0 0 / 0.30) !default;
102
+ $juno-shadow-2: 0 4px 14px rgb(0 0 0 / 0.35) !default;
103
+ $juno-shadow-3: 0 12px 32px rgb(0 0 0 / 0.50) !default;
104
+ $juno-motion-duration-instant: 80ms !default;
105
+ $juno-motion-duration-quick: 140ms !default;
106
+ $juno-motion-duration-base: 200ms !default;
107
+ $juno-motion-duration-deliberate: 300ms !default;
108
+ $juno-motion-ease-decel: cubic-bezier(0.2, 0.8, 0.2, 1) !default;
109
+ $juno-motion-ease-accel: cubic-bezier(0.4, 0, 1, 1) !default;
110
+ $juno-motion-ease-standard: cubic-bezier(0.2, 0.7, 0.3, 1) !default;
111
+ $juno-motion-ease-spring: cubic-bezier(0.2, 0.9, 0.3, 1.2) !default;
112
+ $juno-opacity-disabled: 0.45 !default;
113
+ $juno-opacity-muted: 0.65 !default;
114
+ $juno-opacity-scrim: 0.62 !default;
115
+ $juno-radius-2: 2px !default;
116
+ $juno-radius-3: 3px !default;
117
+ $juno-radius-4: 4px !default;
118
+ $juno-radius-5: 5px !default;
119
+ $juno-radius-8: 8px !default;
120
+ $juno-size-tap-min: 24px !default;
121
+ $juno-size-tap-comfortable: 44px !default;
122
+ $juno-size-dot-sm: 8px !default;
123
+ $juno-size-dot-md: 10px !default;
124
+ $juno-space-2: 2px !default;
125
+ $juno-space-4: 4px !default;
126
+ $juno-space-8: 8px !default;
127
+ $juno-space-10: 10px !default;
128
+ $juno-space-12: 12px !default;
129
+ $juno-space-16: 16px !default;
130
+ $juno-space-20: 20px !default;
131
+ $juno-space-24: 24px !default;
132
+ $juno-space-28: 28px !default;
133
+ $juno-space-32: 32px !default;
134
+ $juno-space-40: 40px !default;
135
+ $juno-space-56: 56px !default;
136
+ $juno-space-72: 72px !default;
137
+ $juno-space-96: 96px !default;
138
+ $juno-font-family-sans: 'B612', sans-serif !default;
139
+ $juno-font-family-mono: 'B612 Mono', monospace !default;
140
+ $juno-font-weight-light: 300 !default;
141
+ $juno-font-weight-regular: 400 !default;
142
+ $juno-font-weight-medium: 500 !default;
143
+ $juno-font-weight-semibold: 600 !default;
144
+ $juno-font-weight-bold: 700 !default;
145
+ $juno-font-size-10: 10px !default;
146
+ $juno-font-size-11: 11px !default;
147
+ $juno-font-size-12: 12px !default;
148
+ $juno-font-size-13: 13px !default;
149
+ $juno-font-size-14: 14px !default;
150
+ $juno-font-size-16: 16px !default;
151
+ $juno-font-size-18: 18px !default;
152
+ $juno-font-size-20: 20px !default;
153
+ $juno-font-size-28: 28px !default;
154
+ $juno-font-size-32: 32px !default;
155
+ $juno-font-size-36: 36px !default;
156
+ $juno-font-size-38: 38px !default;
157
+ $juno-font-size-48: 48px !default;
158
+ $juno-font-size-52: 52px !default;
159
+ $juno-font-lineHeight-none: 1 !default;
160
+ $juno-font-lineHeight-tight: 1.1 !default;
161
+ $juno-font-lineHeight-snug: 1.2 !default;
162
+ $juno-font-lineHeight-normal: 1.4 !default;
163
+ $juno-font-lineHeight-relaxed: 1.5 !default;
164
+ $juno-font-lineHeight-loose: 1.7 !default;
165
+ $juno-font-tracking-tight: 0.02em !default;
166
+ $juno-font-tracking-normal: 0.06em !default;
167
+ $juno-font-tracking-label: 0.08em !default;
168
+ $juno-font-tracking-wide: 0.12em !default;
169
+ $juno-font-tracking-caps: 0.15em !default;
170
+ $juno-font-tracking-wider: 0.2em !default;
171
+ $juno-font-tracking-widest: 0.3em !default;
172
+ $juno-z-surface: 0 !default;
173
+ $juno-z-raised: 100 !default;
174
+ $juno-z-anchored: 2000 !default;
175
+ $juno-z-overlay: 4000 !default;
176
+ $juno-z-alert: 5000 !default;
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "@junoput01/junoui",
3
+ "version": "0.2.0",
4
+ "description": "junoui — a token-driven design system. Color carries semantic meaning, never decoration: every hue has one assigned role (NOMINAL / ACTIVE / TARGET / CAUTION / WARNING). Ships multi-platform tokens (CSS, SCSS, JS/TS, JSON, Android, iOS, Flutter) plus a framework-agnostic CSS component layer.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "junoput",
8
+ "publishConfig": {
9
+ "access": "public",
10
+ "provenance": true
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git@github.com-junoput:junoput/junoui.git"
15
+ },
16
+ "keywords": [
17
+ "design-system",
18
+ "design-tokens",
19
+ "style-dictionary",
20
+ "css-variables",
21
+ "theme",
22
+ "dark-mode",
23
+ "accessibility",
24
+ "colorblind",
25
+ "dashboard",
26
+ "icons"
27
+ ],
28
+ "main": "./dist/js/tokens.js",
29
+ "module": "./dist/js/tokens.js",
30
+ "types": "./dist/js/tokens.d.ts",
31
+ "sideEffects": [
32
+ "**/*.css"
33
+ ],
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/js/tokens.d.ts",
37
+ "import": "./dist/js/tokens.js",
38
+ "default": "./dist/js/tokens.js"
39
+ },
40
+ "./css": "./dist/css/juno.css",
41
+ "./css/tokens": "./dist/css/juno-tokens.css",
42
+ "./fonts.css": "./dist/css/juno-fonts.css",
43
+ "./scss": "./dist/scss/_juno-tokens.scss",
44
+ "./tokens.json": "./dist/json/tokens.json",
45
+ "./android/colors": "./dist/android/colors.xml",
46
+ "./android/dimens": "./dist/android/dimens.xml",
47
+ "./ios": "./dist/ios/JunoTokens.swift",
48
+ "./flutter": "./dist/flutter/juno_tokens.dart",
49
+ "./icons": "./dist/icons/juno-icons.svg",
50
+ "./package.json": "./package.json"
51
+ },
52
+ "files": [
53
+ "dist",
54
+ "src/css",
55
+ "src/icons",
56
+ "src/fonts",
57
+ "README.md",
58
+ "CHANGELOG.md"
59
+ ],
60
+ "scripts": {
61
+ "build:tokens": "node style-dictionary.config.mjs",
62
+ "build:icons": "node scripts/build-icons.mjs",
63
+ "build:css": "node scripts/bundle-css.mjs",
64
+ "build": "npm run build:tokens && npm run build:icons && npm run build:css",
65
+ "gen-docs": "node scripts/gen-docs.mjs",
66
+ "clean": "node -e \"import('node:fs').then(fs=>fs.rmSync('dist',{recursive:true,force:true}))\"",
67
+ "lint:css": "stylelint \"src/css/**/*.css\"",
68
+ "lint:css:fix": "stylelint \"src/css/**/*.css\" --fix",
69
+ "format": "prettier --write .",
70
+ "format:check": "prettier --check .",
71
+ "lint": "npm run lint:css && npm run format:check",
72
+ "test": "npm run build && node --test \"test/**/*.test.mjs\"",
73
+ "prepare": "npm run build",
74
+ "showcase": "npm run build && node scripts/serve.mjs",
75
+ "test:visual": "playwright test",
76
+ "test:visual:update": "playwright test --update-snapshots",
77
+ "changeset": "changeset",
78
+ "version": "changeset version",
79
+ "release": "npm run build && changeset publish"
80
+ },
81
+ "devDependencies": {
82
+ "@changesets/cli": "^2.31.0",
83
+ "@playwright/test": "^1.61.1",
84
+ "prettier": "^3.8.4",
85
+ "style-dictionary": "^4.4.0",
86
+ "stylelint": "^17.13.0",
87
+ "stylelint-config-standard": "^40.0.0"
88
+ },
89
+ "engines": {
90
+ "node": ">=18"
91
+ }
92
+ }
@@ -0,0 +1,120 @@
1
+ /* ════════════════════════════════════════════════════════════════════
2
+ * junoui — base layer
3
+ * Reset + document defaults. Sets B612 as the type family but does NOT
4
+ * fetch it — that would break under a strict CSP and phone home. Supply the
5
+ * fonts yourself, or opt into the self-hosted set: `import 'junoui/fonts.css'`
6
+ * (see src/css/fonts.css). Falls back to system sans/mono until then.
7
+ * ════════════════════════════════════════════════════════════════════ */
8
+
9
+ *,
10
+ *::before,
11
+ *::after { box-sizing: border-box; }
12
+
13
+ /* System color scheme. Without data-juno-mode the theme follows the OS
14
+ (`prefers-color-scheme`; see juno-tokens.css) — `dark light` here lets the
15
+ UA pick matching scrollbars/form chrome. An explicit mode pins both. */
16
+ :root { color-scheme: dark light; }
17
+ :root[data-juno-mode='dark'] { color-scheme: dark; }
18
+
19
+ /* Control surfaces. On dark panels the hairline border (~23% L) disappears, so
20
+ lift the control edge to `muted` and sit controls on `s2`; light mode keeps the
21
+ true border on `s0`. Form components read these instead of raw surface roles. */
22
+ :root,
23
+ :root[data-juno-mode='dark'] {
24
+ --juno-control-surface: var(--juno-s2);
25
+ --juno-control-edge: var(--juno-muted);
26
+
27
+ /* Knob + track-rim of the lever controls (switch / slider). Edge and knob
28
+ are lifted well clear of the track so the control reads at a squint: a
29
+ light grey lever (face hi→lo) with dark grip lines on a dark track. */
30
+ --juno-control-edge-strong: var(--juno-label);
31
+ --juno-knob-edge: var(--juno-label);
32
+ --juno-knob-face-hi: var(--juno-label);
33
+ --juno-knob-face-lo: var(--juno-muted);
34
+ --juno-knob-grip: var(--juno-s0);
35
+ }
36
+
37
+ :root[data-juno-mode='light'] {
38
+ color-scheme: light;
39
+
40
+ --juno-control-surface: var(--juno-s0);
41
+ --juno-control-edge: var(--juno-border);
42
+
43
+ /* Light mode inverts: a dark grey lever with light grip lines on a near-
44
+ white track. Same vars, so switch + slider stay in lockstep. */
45
+ --juno-control-edge-strong: var(--juno-label);
46
+ --juno-knob-edge: var(--juno-label);
47
+ --juno-knob-face-hi: var(--juno-muted);
48
+ --juno-knob-face-lo: var(--juno-label);
49
+ --juno-knob-grip: var(--juno-s0);
50
+ }
51
+
52
+ /* no data-juno-mode + a light OS → the light control surfaces above */
53
+ @media (prefers-color-scheme: light) {
54
+ :root:not([data-juno-mode]) {
55
+ --juno-control-surface: var(--juno-s0);
56
+ --juno-control-edge: var(--juno-border);
57
+ --juno-knob-face-hi: var(--juno-muted);
58
+ --juno-knob-face-lo: var(--juno-label);
59
+ }
60
+ }
61
+
62
+ * { margin: 0; padding: 0; }
63
+
64
+ html { -webkit-text-size-adjust: 100%; }
65
+
66
+ body {
67
+ font-family: var(--juno-font-family-sans);
68
+ font-size: var(--juno-font-size-14);
69
+ line-height: var(--juno-font-lineHeight-normal);
70
+ letter-spacing: var(--juno-font-tracking-tight);
71
+ color: var(--juno-data);
72
+ background: var(--juno-s0);
73
+ -webkit-font-smoothing: antialiased;
74
+ text-rendering: optimizelegibility;
75
+ }
76
+
77
+ code, kbd, samp, pre { font-family: var(--juno-font-family-mono); }
78
+
79
+ /* Accessible focus — uses the ACTIVE role so it tracks the theme. */
80
+ :where(a, button, input, select, textarea, [tabindex]):focus-visible {
81
+ outline: 2px solid var(--juno-active);
82
+ outline-offset: 2px;
83
+ border-radius: var(--juno-radius-2);
84
+ }
85
+
86
+ /* Touch ergonomics — on coarse pointers (finger, not mouse) every control
87
+ that sizes itself off the tap minimum grows to the comfortable target
88
+ (44px). A cascade override, not a token change: the token values stay
89
+ the contract; a phone just reads the bigger one. */
90
+ @media (pointer: coarse) {
91
+ :root { --juno-size-tap-min: var(--juno-size-tap-comfortable); }
92
+ }
93
+
94
+ @keyframes juno-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
95
+
96
+ @media (prefers-reduced-motion: reduce) {
97
+ *, *::before, *::after {
98
+ animation-duration: 0.01ms !important;
99
+ animation-iteration-count: 1 !important;
100
+ transition-duration: 0.01ms !important;
101
+ }
102
+ }
103
+
104
+ /* Higher-contrast preference: hairline seams step up to the strong border
105
+ so panel edges stop disappearing on users who asked for more contrast. */
106
+ @media (prefers-contrast: more) {
107
+ :root { --juno-border: var(--juno-border-strong); }
108
+ }
109
+
110
+ /* Windows High Contrast / forced-colors: opt into the system palette so
111
+ borders and focus stay visible when our colors are overridden. */
112
+ @media (forced-colors: active) {
113
+ *:focus-visible { outline-color: Highlight; }
114
+
115
+ .juno-badge,
116
+ .juno-btn,
117
+ .juno-card,
118
+ .juno-readout { border: 1px solid CanvasText; }
119
+ .juno-badge { forced-color-adjust: none; } /* keep status fill meaningful */
120
+ }
@@ -0,0 +1,83 @@
1
+ /* ════════════════════════════════════════════════════════════════════
2
+ * Component — Accordion / disclosure
3
+ * Stacked, expandable sections built on native <details>/<summary> —
4
+ * keyboard + screen-reader native, ZERO JS. A chevron rotates on open.
5
+ * Use a lone <details> for a single disclosure; group them in
6
+ * .juno-accordion for a bordered set.
7
+ * Usage:
8
+ * <div class="juno-accordion">
9
+ * <details class="juno-accordion__item" open>
10
+ * <summary class="juno-accordion__summary">Region · us-east-1</summary>
11
+ * <div class="juno-accordion__body">…</div>
12
+ * </details>
13
+ * <details class="juno-accordion__item">
14
+ * <summary class="juno-accordion__summary">Region · eu-west-1</summary>
15
+ * <div class="juno-accordion__body">…</div>
16
+ * </details>
17
+ * </div>
18
+ * ════════════════════════════════════════════════════════════════════ */
19
+
20
+ .juno-accordion {
21
+ border: var(--juno-border-width-1) solid var(--juno-border);
22
+ border-radius: var(--juno-radius-5);
23
+ overflow: hidden;
24
+ }
25
+
26
+ .juno-accordion__item {
27
+ border-block-end: var(--juno-border-width-1) solid var(--juno-border);
28
+ }
29
+
30
+ .juno-accordion__item:last-child { border-block-end: none; }
31
+
32
+ .juno-accordion__summary {
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: space-between;
36
+ gap: var(--juno-space-12);
37
+ padding: var(--juno-pad-control-block) var(--juno-pad-surface-inline);
38
+ background: var(--juno-s1);
39
+ font-family: var(--juno-font-family-sans);
40
+ font-size: var(--juno-font-size-13);
41
+ font-weight: var(--juno-font-weight-medium);
42
+ color: var(--juno-data);
43
+ cursor: pointer;
44
+ list-style: none;
45
+ user-select: none;
46
+ }
47
+
48
+ /* hide the native disclosure triangle (both engines) */
49
+ .juno-accordion__summary::-webkit-details-marker { display: none; }
50
+
51
+ .juno-accordion__summary:hover { background: var(--juno-s2); }
52
+
53
+ /* chevron — a rotated corner that flips when the item is open */
54
+ .juno-accordion__summary::after {
55
+ content: '';
56
+ flex-shrink: 0;
57
+ inline-size: var(--juno-space-8);
58
+ block-size: var(--juno-space-8);
59
+ border-inline-end: var(--juno-border-width-2) solid var(--juno-muted);
60
+ border-block-end: var(--juno-border-width-2) solid var(--juno-muted);
61
+ transform: translateY(-2px) rotate(45deg);
62
+ transition: transform var(--juno-motion-duration-quick) var(--juno-motion-ease-standard);
63
+ }
64
+
65
+ .juno-accordion__item[open] > .juno-accordion__summary::after {
66
+ transform: translateY(2px) rotate(-135deg);
67
+ }
68
+
69
+ .juno-accordion__body {
70
+ padding: var(--juno-space-12) var(--juno-pad-surface-inline) var(--juno-pad-surface-block);
71
+ background: var(--juno-s0);
72
+ border-block-start: var(--juno-border-width-1) solid var(--juno-border);
73
+ font-size: var(--juno-font-size-13);
74
+ line-height: var(--juno-font-lineHeight-relaxed);
75
+ color: var(--juno-label);
76
+ }
77
+
78
+ /* a lone disclosure (no .juno-accordion wrapper) gets its own frame */
79
+ details.juno-accordion__item:only-child {
80
+ border: var(--juno-border-width-1) solid var(--juno-border);
81
+ border-radius: var(--juno-radius-5);
82
+ overflow: hidden;
83
+ }
@@ -0,0 +1,90 @@
1
+ /* ════════════════════════════════════════════════════════════════════
2
+ * Component — Alert / inline notification
3
+ * A role-tinted banner for in-context messages: validation summaries,
4
+ * system status, callouts. Soft-fill by default with a role accent rail;
5
+ * icon + title + text + optional actions + optional dismiss. Color comes
6
+ * from --juno-role (set by a .juno--<role> class); default informational.
7
+ * Usage:
8
+ * <div class="juno-alert juno--warning" role="alert">
9
+ * <span class="juno-alert__icon" aria-hidden="true">⚠</span>
10
+ * <div class="juno-alert__body">
11
+ * <span class="juno-alert__title">Deploy blocked</span>
12
+ * <span class="juno-alert__text">Two checks are still failing.</span>
13
+ * </div>
14
+ * <button class="juno-alert__close" aria-label="Dismiss">✕</button>
15
+ * </div>
16
+ * ════════════════════════════════════════════════════════════════════ */
17
+
18
+ .juno-alert {
19
+ --juno-role: var(--juno-active);
20
+
21
+ display: flex;
22
+ align-items: flex-start;
23
+ gap: var(--juno-space-12);
24
+ padding: var(--juno-pad-surface-block) var(--juno-pad-surface-inline);
25
+ background: color-mix(in srgb, var(--juno-role) 10%, transparent);
26
+ border: var(--juno-border-width-1) solid color-mix(in srgb, var(--juno-role) 30%, transparent);
27
+ border-inline-start: var(--juno-border-width-3) solid var(--juno-role);
28
+ border-radius: var(--juno-radius-5);
29
+ color: var(--juno-data);
30
+ }
31
+
32
+ .juno-alert__icon {
33
+ flex-shrink: 0;
34
+ color: var(--juno-role);
35
+ font-size: var(--juno-font-size-16);
36
+ line-height: var(--juno-font-lineHeight-none);
37
+ }
38
+
39
+ .juno-alert__body {
40
+ flex: 1;
41
+ min-inline-size: 0;
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--juno-space-2);
45
+ }
46
+
47
+ .juno-alert__title {
48
+ font-family: var(--juno-font-family-sans);
49
+ font-weight: var(--juno-font-weight-semibold);
50
+ font-size: var(--juno-font-size-13);
51
+ color: var(--juno-data);
52
+ }
53
+
54
+ .juno-alert__text {
55
+ font-size: var(--juno-font-size-13);
56
+ line-height: var(--juno-font-lineHeight-relaxed);
57
+ color: var(--juno-label);
58
+ }
59
+
60
+ .juno-alert__actions {
61
+ display: flex;
62
+ gap: var(--juno-space-8);
63
+ margin-block-start: var(--juno-space-8);
64
+ }
65
+
66
+ .juno-alert__close {
67
+ flex-shrink: 0;
68
+ appearance: none;
69
+ padding: 0;
70
+ background: transparent;
71
+ border: none;
72
+ color: var(--juno-muted);
73
+ font-size: var(--juno-font-size-16);
74
+ line-height: var(--juno-font-lineHeight-none);
75
+ cursor: pointer;
76
+ }
77
+
78
+ .juno-alert__close:hover { color: var(--juno-data); }
79
+
80
+ /* solid — high-emphasis variant: full role fill, text on the base surface */
81
+ .juno-alert--solid {
82
+ background: var(--juno-role);
83
+ border-color: var(--juno-role);
84
+ color: var(--juno-s0);
85
+ }
86
+
87
+ .juno-alert--solid .juno-alert__icon,
88
+ .juno-alert--solid .juno-alert__title,
89
+ .juno-alert--solid .juno-alert__text,
90
+ .juno-alert--solid .juno-alert__close { color: var(--juno-s0); }
@@ -0,0 +1,82 @@
1
+ /* ════════════════════════════════════════════════════════════════════
2
+ * Component — Avatar · user / entity portrait
3
+ * A round (or squared) portrait that holds an <img>, initials, or an
4
+ * icon fallback. Sizes ride one custom property; an optional role ring
5
+ * marks status (online, alert…). Zero JS. Pairs with a
6
+ * .juno-skeleton--circle placeholder while the image loads.
7
+ * Usage:
8
+ * <span class="juno-avatar"><img src="…" alt="Ada Lovelace" /></span>
9
+ * <span class="juno-avatar juno-avatar--lg">AL</span>
10
+ * <span class="juno-avatar juno-avatar--ring juno--nominal">
11
+ * <svg class="juno-icon"><use href="…#juno-i-user" /></svg>
12
+ * </span>
13
+ * ════════════════════════════════════════════════════════════════════ */
14
+
15
+ .juno-avatar {
16
+ --juno-avatar-size: var(--juno-space-32);
17
+
18
+ display: inline-grid;
19
+ place-content: center;
20
+ flex-shrink: 0;
21
+ inline-size: var(--juno-avatar-size);
22
+ block-size: var(--juno-avatar-size);
23
+ overflow: hidden;
24
+ border-radius: 50%;
25
+ background: var(--juno-control-surface);
26
+ border: var(--juno-border-width-1) solid var(--juno-control-edge-strong);
27
+ color: var(--juno-label);
28
+ font-family: var(--juno-font-family-sans);
29
+
30
+ /* initials scale with the avatar (~40% of its box) */
31
+ font-size: calc(var(--juno-avatar-size) * 0.4);
32
+ font-weight: var(--juno-font-weight-semibold);
33
+ letter-spacing: var(--juno-font-tracking-tight);
34
+ text-transform: uppercase;
35
+ user-select: none;
36
+ }
37
+
38
+ /* the image fills the circle */
39
+ .juno-avatar img {
40
+ inline-size: 100%;
41
+ block-size: 100%;
42
+ object-fit: cover;
43
+ }
44
+
45
+ /* a square / rounded-rect portrait instead of a circle */
46
+ .juno-avatar--square {
47
+ border-radius: var(--juno-radius-4);
48
+ }
49
+
50
+ /* status ring — reads the role; pair with a label / title for meaning */
51
+ .juno-avatar--ring {
52
+ border-color: var(--juno-role);
53
+ box-shadow: 0 0 0 var(--juno-border-width-2) color-mix(in srgb, var(--juno-role) 30%, transparent);
54
+ }
55
+
56
+ /* sizes */
57
+ .juno-avatar--sm {
58
+ --juno-avatar-size: var(--juno-space-24);
59
+ }
60
+
61
+ .juno-avatar--lg {
62
+ --juno-avatar-size: var(--juno-space-40);
63
+ }
64
+
65
+ .juno-avatar--xl {
66
+ --juno-avatar-size: var(--juno-space-56);
67
+ }
68
+
69
+ /* overlapping cluster — a row of avatars that tuck under each other */
70
+ .juno-avatar-group {
71
+ display: inline-flex;
72
+ align-items: center;
73
+ }
74
+
75
+ .juno-avatar-group .juno-avatar {
76
+ border-color: var(--juno-s0);
77
+ border-width: var(--juno-border-width-2);
78
+ }
79
+
80
+ .juno-avatar-group .juno-avatar + .juno-avatar {
81
+ margin-inline-start: calc(var(--juno-avatar-size) * -0.3);
82
+ }