@ikonai/sdk-react-ui 1.6.0 → 1.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikonai/sdk-react-ui",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -1,284 +1,293 @@
1
1
  /* Ikon app-shell styles: the connection overlays, the toast strip and the hero layout.
2
2
 
3
- Override any of this from your own src/app.css — unlayered rules always win over these,
4
- whatever their specificity or import order. */
5
- @layer ikon {
6
- .ikon-app {
7
- display: flex;
8
- align-items: center;
9
- justify-content: center;
10
- padding: 32px max(20px, env(safe-area-inset-left)) calc(32px + env(safe-area-inset-bottom));
11
- box-sizing: border-box;
12
- }
3
+ Override any of them from your own src/app.css, which loads after this sheet: at equal
4
+ specificity yours wins, with no `!important`. A few rules here are more specific than one class
5
+ — `.ikon-hero h1`, `.ikon-reconnecting-chip span`, the `:hover` and `:focus` states — so match
6
+ that shape to override those. */
7
+ .ikon-app {
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ padding: 32px max(20px, env(safe-area-inset-left)) calc(32px + env(safe-area-inset-bottom));
12
+ box-sizing: border-box;
13
+ }
13
14
 
14
- .ikon-hero {
15
- position: relative;
16
- z-index: 1;
17
- display: flex;
18
- flex-direction: column;
19
- align-items: center;
20
- gap: 16px;
21
- max-width: 460px;
22
- text-align: center;
23
- }
15
+ .ikon-hero {
16
+ position: relative;
17
+ z-index: 1;
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ gap: 16px;
22
+ max-width: 460px;
23
+ text-align: center;
24
+ }
24
25
 
25
- .ikon-hero h1 {
26
- margin: 0;
27
- font-family: var(--ikon-font-display);
28
- font-size: clamp(24px, 7vw, 40px);
29
- font-weight: 600;
30
- line-height: 1.15;
31
- letter-spacing: -0.02em;
32
- color: var(--ikon-text-primary);
33
- text-wrap: balance;
34
- }
26
+ .ikon-hero h1 {
27
+ margin: 0;
28
+ font-family: var(--ikon-font-display);
29
+ font-size: clamp(24px, 7vw, 40px);
30
+ font-weight: 600;
31
+ line-height: 1.15;
32
+ letter-spacing: -0.02em;
33
+ color: var(--ikon-text-primary);
34
+ text-wrap: balance;
35
+ }
35
36
 
36
- .ikon-info {
37
- margin: 0;
38
- font-size: 15px;
39
- line-height: 1.6;
40
- color: var(--ikon-text-secondary);
41
- text-wrap: pretty;
42
- }
37
+ .ikon-info {
38
+ margin: 0;
39
+ font-size: 15px;
40
+ line-height: 1.6;
41
+ color: var(--ikon-text-secondary);
42
+ text-wrap: pretty;
43
+ }
43
44
 
44
- .ikon-error {
45
- margin: 0;
46
- font-family: var(--ikon-font-mono);
47
- font-size: 13px;
48
- line-height: 1.5;
49
- color: var(--ikon-status-error);
50
- word-break: break-word;
51
- }
45
+ .ikon-error {
46
+ margin: 0;
47
+ font-family: var(--ikon-font-mono);
48
+ font-size: 13px;
49
+ line-height: 1.5;
50
+ color: var(--ikon-status-error);
51
+ word-break: break-word;
52
+ }
52
53
 
53
- .ikon-connecting-overlay {
54
- position: fixed;
55
- top: 0;
56
- left: 0;
57
- right: 0;
58
- display: flex;
59
- justify-content: center;
60
- padding-top: max(16px, env(safe-area-inset-top));
61
- z-index: 9998;
62
- pointer-events: none;
63
- }
54
+ .ikon-connecting-overlay {
55
+ position: fixed;
56
+ top: 0;
57
+ left: 0;
58
+ right: 0;
59
+ display: flex;
60
+ justify-content: center;
61
+ padding-top: max(16px, env(safe-area-inset-top));
62
+ z-index: 9998;
63
+ pointer-events: none;
64
+ }
64
65
 
65
- .ikon-connecting-chip {
66
- display: flex;
67
- align-items: center;
68
- gap: 8px;
69
- padding: 8px 14px;
70
- background: var(--ikon-bg-card);
71
- border: 1px solid var(--ikon-border-secondary);
72
- border-radius: var(--ikon-radius-full);
73
- color: var(--ikon-text-secondary);
74
- font-family: var(--ikon-font-body);
75
- font-size: 13px;
76
- font-weight: 500;
77
- pointer-events: auto;
78
- animation: ikon-fade-in 0.3s ease-out;
79
- }
66
+ .ikon-connecting-chip {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: 8px;
70
+ padding: 8px 14px;
71
+ background: var(--ikon-bg-card);
72
+ border: 1px solid var(--ikon-border-secondary);
73
+ border-radius: var(--ikon-radius-full);
74
+ color: var(--ikon-text-secondary);
75
+ font-family: var(--ikon-font-body);
76
+ font-size: 13px;
77
+ font-weight: 500;
78
+ pointer-events: auto;
79
+ animation: ikon-fade-in 0.3s ease-out;
80
+ }
80
81
 
81
- .ikon-connecting-spinner {
82
- width: 13px;
83
- height: 13px;
84
- border: 2px solid var(--ikon-border-primary);
85
- border-top-color: var(--ikon-text-tertiary);
86
- border-radius: var(--ikon-radius-full);
87
- animation: ikon-spin 0.9s linear infinite;
88
- }
82
+ .ikon-connecting-spinner {
83
+ width: 13px;
84
+ height: 13px;
85
+ border: 2px solid var(--ikon-border-primary);
86
+ border-top-color: var(--ikon-text-tertiary);
87
+ border-radius: var(--ikon-radius-full);
88
+ animation: ikon-spin 0.9s linear infinite;
89
+ }
89
90
 
90
- .ikon-reconnecting-overlay,
91
- .ikon-offline-overlay {
92
- position: fixed;
93
- inset: 0;
94
- display: flex;
95
- align-items: center;
96
- justify-content: center;
97
- padding: 24px;
98
- z-index: 9999;
99
- background: var(--ikon-overlay-scrim);
100
- backdrop-filter: blur(8px);
101
- -webkit-backdrop-filter: blur(8px);
102
- animation: ikon-fade-in 0.4s ease-out;
103
- }
91
+ .ikon-reconnecting-overlay,
92
+ .ikon-offline-overlay {
93
+ position: fixed;
94
+ /* The `inset` shorthand is Chromium 87; the longhands position this on older screens. */
95
+ top: 0;
96
+ right: 0;
97
+ bottom: 0;
98
+ left: 0;
99
+ inset: 0;
100
+ display: flex;
101
+ align-items: center;
102
+ justify-content: center;
103
+ padding: 24px;
104
+ z-index: 9999;
105
+ background: var(--ikon-overlay-scrim);
106
+ backdrop-filter: blur(8px);
107
+ -webkit-backdrop-filter: blur(8px);
108
+ animation: ikon-fade-in 0.4s ease-out;
109
+ }
104
110
 
105
- .ikon-reconnecting-chip,
106
- .ikon-offline-chip {
107
- box-sizing: border-box;
108
- display: flex;
109
- flex-direction: column;
110
- align-items: center;
111
- gap: 8px;
112
- width: 100%;
113
- max-width: 380px;
114
- text-align: center;
115
- color: var(--ikon-text-primary);
116
- font-family: var(--ikon-font-body);
117
- }
111
+ .ikon-reconnecting-chip,
112
+ .ikon-offline-chip {
113
+ box-sizing: border-box;
114
+ display: flex;
115
+ flex-direction: column;
116
+ align-items: center;
117
+ gap: 8px;
118
+ width: 100%;
119
+ max-width: 380px;
120
+ text-align: center;
121
+ color: var(--ikon-text-primary);
122
+ font-family: var(--ikon-font-body);
123
+ }
118
124
 
119
- .ikon-reconnecting-spinner {
120
- width: 28px;
121
- height: 28px;
122
- margin-bottom: 4px;
123
- border: 2px solid var(--ikon-border-primary);
124
- border-top-color: var(--ikon-text-tertiary);
125
- border-radius: var(--ikon-radius-full);
126
- animation: ikon-spin 0.9s linear infinite;
127
- }
125
+ .ikon-reconnecting-spinner {
126
+ width: 28px;
127
+ height: 28px;
128
+ margin-bottom: 4px;
129
+ border: 2px solid var(--ikon-border-primary);
130
+ border-top-color: var(--ikon-text-tertiary);
131
+ border-radius: var(--ikon-radius-full);
132
+ animation: ikon-spin 0.9s linear infinite;
133
+ }
128
134
 
129
- .ikon-reconnecting-chip span {
130
- font-size: 15px;
131
- font-weight: 500;
132
- color: var(--ikon-text-secondary);
133
- }
135
+ .ikon-reconnecting-chip span {
136
+ font-size: 15px;
137
+ font-weight: 500;
138
+ color: var(--ikon-text-secondary);
139
+ }
134
140
 
135
- .ikon-offline-title {
136
- font-family: var(--ikon-font-display);
137
- font-size: clamp(20px, 5.5vw, 24px);
138
- font-weight: 600;
139
- line-height: 1.25;
140
- letter-spacing: -0.015em;
141
- text-wrap: balance;
142
- }
141
+ .ikon-offline-title {
142
+ font-family: var(--ikon-font-display);
143
+ font-size: clamp(20px, 5.5vw, 24px);
144
+ font-weight: 600;
145
+ line-height: 1.25;
146
+ letter-spacing: -0.015em;
147
+ text-wrap: balance;
148
+ }
143
149
 
144
- .ikon-offline-message {
145
- font-size: 14px;
146
- line-height: 1.6;
147
- color: var(--ikon-text-secondary);
148
- text-wrap: pretty;
149
- }
150
+ .ikon-offline-message {
151
+ font-size: 14px;
152
+ line-height: 1.6;
153
+ color: var(--ikon-text-secondary);
154
+ text-wrap: pretty;
155
+ }
150
156
 
151
- .ikon-offline-error {
152
- margin-top: 6px;
153
- font-family: var(--ikon-font-mono);
154
- font-size: 12px;
155
- line-height: 1.5;
156
- color: var(--ikon-text-quaternary);
157
- max-width: 100%;
158
- word-break: break-word;
159
- }
157
+ .ikon-offline-error {
158
+ margin-top: 6px;
159
+ font-family: var(--ikon-font-mono);
160
+ font-size: 12px;
161
+ line-height: 1.5;
162
+ color: var(--ikon-text-quaternary);
163
+ max-width: 100%;
164
+ word-break: break-word;
165
+ }
160
166
 
161
- /* An installed PWA has no reload control the user can reach, so this button is the only way back
162
- into the app — sized for a thumb rather than as a secondary affordance. */
163
- .ikon-offline-action {
164
- display: flex;
165
- align-items: center;
166
- justify-content: center;
167
- min-width: 160px;
168
- min-height: 44px;
169
- margin-top: 12px;
170
- padding: 0 20px;
171
- background: var(--ikon-bg-solid);
172
- border: 1px solid transparent;
173
- border-radius: var(--ikon-radius-md);
174
- font-family: inherit;
175
- font-size: 15px;
176
- font-weight: 500;
177
- line-height: 1;
178
- cursor: pointer;
179
- transition: background-color 0.15s ease;
180
- }
167
+ /* An installed PWA has no reload control the user can reach, so this button is the only way back
168
+ into the app — sized for a thumb rather than as a secondary affordance. */
169
+ .ikon-offline-action {
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ min-width: 160px;
174
+ min-height: 44px;
175
+ margin-top: 12px;
176
+ padding: 0 20px;
177
+ background: var(--ikon-bg-solid);
178
+ border: 1px solid transparent;
179
+ border-radius: var(--ikon-radius-md);
180
+ font-family: inherit;
181
+ font-size: 15px;
182
+ font-weight: 500;
183
+ line-height: 1;
184
+ cursor: pointer;
185
+ transition: background-color 0.15s ease;
186
+ }
181
187
 
182
- /* Crosswind's preflight resets `button { color: inherit }` unlayered, and an unlayered rule beats
183
- a layered one whatever its specificity — so colouring the button itself loses the contrast and
184
- paints the label in the chip's text colour on the solid fill. The span is not something the
185
- reset targets, which keeps this a normal cascade an app can still override without !important. */
186
- .ikon-offline-action-label {
187
- color: var(--ikon-text-on-solid);
188
- }
188
+ /* Crosswind's preflight resets `button { color: inherit }` unlayered, and an unlayered rule beats
189
+ a layered one whatever its specificity — so colouring the button itself loses the contrast and
190
+ paints the label in the chip's text colour on the solid fill. The span is not something the
191
+ reset targets, which keeps this a normal cascade an app can still override without !important. */
192
+ .ikon-offline-action-label {
193
+ color: var(--ikon-text-on-solid);
194
+ }
189
195
 
190
- .ikon-offline-action:hover {
191
- background: var(--ikon-bg-solid-hover);
192
- }
196
+ .ikon-offline-action:hover {
197
+ background: var(--ikon-bg-solid-hover);
198
+ }
193
199
 
194
- .ikon-offline-action:focus-visible {
195
- outline: 2px solid var(--ikon-focus-ring);
196
- outline-offset: 2px;
197
- }
200
+ .ikon-offline-action:focus {
201
+ outline: 2px solid var(--ikon-focus-ring);
202
+ outline-offset: 2px;
203
+ }
198
204
 
199
- @keyframes ikon-fade-in {
200
- from { opacity: 0; }
201
- to { opacity: 1; }
202
- }
205
+ .ikon-offline-action:focus:not(:focus-visible) {
206
+ outline: none;
207
+ }
203
208
 
204
- @media (prefers-reduced-motion: reduce) {
205
- .ikon-connecting-spinner,
206
- .ikon-reconnecting-spinner {
207
- animation-duration: 2.4s;
208
- }
209
- }
209
+ @keyframes ikon-fade-in {
210
+ from { opacity: 0; }
211
+ to { opacity: 1; }
212
+ }
210
213
 
211
- .ikon-toast-overlay {
212
- position: fixed;
213
- top: 0;
214
- left: 0;
215
- right: 0;
216
- display: flex;
217
- flex-direction: column;
218
- align-items: center;
219
- gap: 8px;
220
- padding-top: max(16px, env(safe-area-inset-top));
221
- z-index: 9998;
222
- pointer-events: none;
214
+ @media (prefers-reduced-motion: reduce) {
215
+ .ikon-connecting-spinner,
216
+ .ikon-reconnecting-spinner {
217
+ animation-duration: 2.4s;
223
218
  }
219
+ }
224
220
 
225
- .ikon-toast-overlay-chip {
226
- display: flex;
227
- align-items: center;
228
- gap: 8px;
229
- max-width: min(440px, calc(100vw - 32px));
230
- padding: 8px 14px;
231
- border: 1px solid var(--ikon-border-secondary);
232
- border-radius: var(--ikon-radius-lg);
233
- background: var(--ikon-bg-card);
234
- color: var(--ikon-text-primary);
235
- font-family: var(--ikon-font-body);
236
- font-size: 13px;
237
- font-weight: 500;
238
- pointer-events: auto;
239
- cursor: pointer;
240
- animation: ikon-fade-in 0.3s ease-out;
241
- }
221
+ .ikon-toast-overlay {
222
+ position: fixed;
223
+ top: 0;
224
+ left: 0;
225
+ right: 0;
226
+ display: flex;
227
+ flex-direction: column;
228
+ align-items: center;
229
+ gap: 8px;
230
+ padding-top: max(16px, env(safe-area-inset-top));
231
+ z-index: 9998;
232
+ pointer-events: none;
233
+ }
242
234
 
243
- .ikon-toast-overlay-chip--warn {
244
- border-left: 3px solid var(--ikon-status-warning);
245
- }
235
+ .ikon-toast-overlay-chip {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 8px;
239
+ max-width: min(440px, calc(100vw - 32px));
240
+ padding: 8px 14px;
241
+ border: 1px solid var(--ikon-border-secondary);
242
+ border-radius: var(--ikon-radius-lg);
243
+ background: var(--ikon-bg-card);
244
+ color: var(--ikon-text-primary);
245
+ font-family: var(--ikon-font-body);
246
+ font-size: 13px;
247
+ font-weight: 500;
248
+ pointer-events: auto;
249
+ cursor: pointer;
250
+ animation: ikon-fade-in 0.3s ease-out;
251
+ }
246
252
 
247
- .ikon-toast-overlay-chip--warn .ikon-toast-overlay-icon {
248
- color: var(--ikon-status-warning);
249
- }
253
+ .ikon-toast-overlay-chip--warn {
254
+ border-left: 3px solid var(--ikon-status-warning);
255
+ }
250
256
 
251
- .ikon-toast-overlay-chip--error {
252
- border-left: 3px solid var(--ikon-status-error);
253
- }
257
+ .ikon-toast-overlay-chip--warn .ikon-toast-overlay-icon {
258
+ color: var(--ikon-status-warning);
259
+ }
254
260
 
255
- .ikon-toast-overlay-chip--error .ikon-toast-overlay-icon {
256
- color: var(--ikon-status-error);
257
- }
261
+ .ikon-toast-overlay-chip--error {
262
+ border-left: 3px solid var(--ikon-status-error);
263
+ }
258
264
 
259
- .ikon-toast-overlay-icon {
260
- flex-shrink: 0;
261
- font-size: 13px;
262
- line-height: 1;
263
- }
265
+ .ikon-toast-overlay-chip--error .ikon-toast-overlay-icon {
266
+ color: var(--ikon-status-error);
267
+ }
264
268
 
265
- .ikon-toast-overlay-content {
266
- display: flex;
267
- align-items: baseline;
268
- gap: 6px;
269
- min-width: 0;
270
- }
269
+ .ikon-toast-overlay-icon {
270
+ flex-shrink: 0;
271
+ font-size: 13px;
272
+ line-height: 1;
273
+ }
271
274
 
272
- .ikon-toast-overlay-component {
273
- flex: none;
274
- font-family: var(--ikon-font-mono);
275
- font-size: 11px;
276
- color: var(--ikon-text-quaternary);
277
- }
275
+ .ikon-toast-overlay-content {
276
+ display: flex;
277
+ align-items: baseline;
278
+ gap: 6px;
279
+ min-width: 0;
280
+ }
278
281
 
279
- .ikon-toast-overlay-message {
280
- font-size: 13px;
281
- white-space: pre-wrap;
282
- word-break: break-word;
283
- }
282
+ .ikon-toast-overlay-component {
283
+ flex: none;
284
+ font-family: var(--ikon-font-mono);
285
+ font-size: 11px;
286
+ color: var(--ikon-text-quaternary);
287
+ }
288
+
289
+ .ikon-toast-overlay-message {
290
+ font-size: 13px;
291
+ white-space: pre-wrap;
292
+ word-break: break-word;
284
293
  }