@etoile-dev/react 0.1.1 → 0.1.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 (3) hide show
  1. package/README.md +22 -2
  2. package/dist/styles.css +128 -52
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -143,20 +143,40 @@ Add `dark` to the className:
143
143
 
144
144
  ### CSS Variables
145
145
 
146
- Customize the theme with CSS variables:
146
+ Every value is customizable. Here are the key variables:
147
147
 
148
148
  ```css
149
149
  .etoile-search {
150
+ /* Colors */
150
151
  --etoile-bg: #ffffff;
151
152
  --etoile-border: #e4e4e7;
152
153
  --etoile-text: #09090b;
153
154
  --etoile-text-muted: #71717a;
154
- --etoile-ring: #18181b;
155
155
  --etoile-selected: #f4f4f5;
156
+ --etoile-ring: #18181b;
157
+
158
+ /* Sizing */
156
159
  --etoile-radius: 12px;
160
+ --etoile-input-height: 44px;
161
+ --etoile-thumbnail-size: 40px;
162
+ --etoile-results-max-height: 300px;
163
+
164
+ /* Spacing */
165
+ --etoile-input-padding-x: 16px;
166
+ --etoile-result-gap: 16px;
167
+ --etoile-results-offset: 8px;
168
+
169
+ /* Typography */
170
+ --etoile-font-size-input: 15px;
171
+ --etoile-font-size-title: 14px;
172
+
173
+ /* Animation */
174
+ --etoile-transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
157
175
  }
158
176
  ```
159
177
 
178
+ See `styles.css` for the complete list of 40+ variables.
179
+
160
180
  ---
161
181
 
162
182
  ## Headless hook
package/dist/styles.css CHANGED
@@ -5,10 +5,16 @@
5
5
  * Usage:
6
6
  * import "@etoile-dev/react/styles.css";
7
7
  * <div className="etoile-search">...</div>
8
+ *
9
+ * All values are customizable via CSS variables.
8
10
  */
9
11
 
10
- /* CSS Variables */
12
+ /* ============================================
13
+ CSS Variables
14
+ ============================================ */
15
+
11
16
  .etoile-search {
17
+ /* Colors */
12
18
  --etoile-bg: #ffffff;
13
19
  --etoile-bg-subtle: #fafafa;
14
20
  --etoile-border: #e4e4e7;
@@ -20,17 +26,88 @@
20
26
  --etoile-accent-foreground: #fafafa;
21
27
  --etoile-ring: #18181b;
22
28
  --etoile-selected: #f4f4f5;
29
+
30
+ /* Border Radius */
23
31
  --etoile-radius: 12px;
24
32
  --etoile-radius-sm: 8px;
33
+ --etoile-radius-kbd: 6px;
34
+
35
+ /* Shadows */
25
36
  --etoile-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
26
37
  --etoile-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
27
- --etoile-transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
28
38
 
39
+ /* Animation */
40
+ --etoile-transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
41
+ --etoile-animation-duration: 150ms;
42
+ --etoile-spinner-duration: 600ms;
43
+
44
+ /* Typography */
45
+ --etoile-font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
46
+ --etoile-font-size-input: 15px;
47
+ --etoile-font-size-title: 14px;
48
+ --etoile-font-size-subtitle: 13px;
49
+ --etoile-font-size-small: 14px;
50
+ --etoile-font-size-kbd: 11px;
51
+ --etoile-font-weight-input: 450;
52
+ --etoile-font-weight-title: 500;
53
+ --etoile-font-weight-subtitle: 500;
54
+ --etoile-line-height: 1.3;
55
+
56
+ /* Input */
57
+ --etoile-input-height: 44px;
58
+ --etoile-input-padding-x: 16px;
59
+ --etoile-input-border-width: 1px;
60
+
61
+ /* Results Dropdown */
62
+ --etoile-results-offset: 8px;
63
+ --etoile-results-padding: 6px;
64
+ --etoile-results-gap: 4px;
65
+ --etoile-results-max-height: 300px;
66
+ --etoile-results-z-index: 50;
67
+
68
+ /* Result Item */
69
+ --etoile-result-padding-x: 12px;
70
+ --etoile-result-padding-y: 10px;
71
+ --etoile-result-gap: 16px;
72
+ --etoile-result-content-gap: 1px;
73
+
74
+ /* Thumbnail */
75
+ --etoile-thumbnail-size: 40px;
76
+
77
+ /* Icon */
78
+ --etoile-icon-size: 18px;
79
+ --etoile-icon-offset: 14px;
80
+ --etoile-input-padding-with-icon: 42px;
81
+
82
+ /* Keyboard Badge */
83
+ --etoile-kbd-height: 20px;
84
+ --etoile-kbd-padding-x: 4px;
85
+ --etoile-kbd-offset: 10px;
86
+ --etoile-input-padding-with-kbd: 48px;
87
+
88
+ /* Spinner */
89
+ --etoile-spinner-size: 16px;
90
+ --etoile-spinner-border-width: 2px;
91
+
92
+ /* Focus Ring */
93
+ --etoile-ring-width: 3px;
94
+ --etoile-ring-opacity: 0.1;
95
+
96
+ /* Empty/Loading States */
97
+ --etoile-empty-padding-x: 16px;
98
+ --etoile-empty-padding-y: 24px;
99
+ --etoile-loading-padding: 16px;
100
+ --etoile-loading-gap: 8px;
101
+
102
+ /* Base Styles */
29
103
  position: relative;
30
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
104
+ font-family: var(--etoile-font-family);
31
105
  }
32
106
 
33
- /* Dark mode */
107
+ /* ============================================
108
+ Dark Mode
109
+ ============================================ */
110
+
34
111
  .etoile-search.dark,
35
112
  .dark .etoile-search {
36
113
  --etoile-bg: #09090b;
@@ -44,6 +121,7 @@
44
121
  --etoile-accent-foreground: #18181b;
45
122
  --etoile-ring: #d4d4d8;
46
123
  --etoile-selected: #27272a;
124
+ --etoile-ring-opacity: 0.15;
47
125
  }
48
126
 
49
127
  /* ============================================
@@ -52,14 +130,14 @@
52
130
 
53
131
  .etoile-search input[role="combobox"] {
54
132
  width: 100%;
55
- height: 44px;
56
- padding: 0 16px;
133
+ height: var(--etoile-input-height);
134
+ padding: 0 var(--etoile-input-padding-x);
57
135
  background: var(--etoile-bg);
58
- border: 1px solid var(--etoile-border);
136
+ border: var(--etoile-input-border-width) solid var(--etoile-border);
59
137
  border-radius: var(--etoile-radius);
60
138
  color: var(--etoile-text);
61
- font-size: 15px;
62
- font-weight: 450;
139
+ font-size: var(--etoile-font-size-input);
140
+ font-weight: var(--etoile-font-weight-input);
63
141
  outline: none;
64
142
  transition: all var(--etoile-transition);
65
143
  }
@@ -74,12 +152,12 @@
74
152
 
75
153
  .etoile-search input[role="combobox"]:focus {
76
154
  border-color: var(--etoile-ring);
77
- box-shadow: 0 0 0 3px rgb(24 24 27 / 0.1);
155
+ box-shadow: 0 0 0 var(--etoile-ring-width) rgb(24 24 27 / var(--etoile-ring-opacity));
78
156
  }
79
157
 
80
158
  .dark .etoile-search input[role="combobox"]:focus,
81
159
  .etoile-search.dark input[role="combobox"]:focus {
82
- box-shadow: 0 0 0 3px rgb(212 212 216 / 0.15);
160
+ box-shadow: 0 0 0 var(--etoile-ring-width) rgb(212 212 216 / var(--etoile-ring-opacity));
83
161
  }
84
162
 
85
163
  /* ============================================
@@ -90,21 +168,19 @@
90
168
  position: absolute;
91
169
  display: flex;
92
170
  flex-direction: column;
93
- gap: 4px;
94
- top: calc(100% + 8px);
171
+ gap: var(--etoile-results-gap);
172
+ top: calc(100% + var(--etoile-results-offset));
95
173
  left: 0;
96
174
  right: 0;
97
- z-index: 50;
98
- max-height: 300px;
175
+ z-index: var(--etoile-results-z-index);
176
+ max-height: var(--etoile-results-max-height);
99
177
  overflow-y: auto;
100
- padding: 6px;
178
+ padding: var(--etoile-results-padding);
101
179
  background: var(--etoile-bg);
102
- border: 1px solid var(--etoile-border);
180
+ border: var(--etoile-input-border-width) solid var(--etoile-border);
103
181
  border-radius: var(--etoile-radius);
104
182
  box-shadow: var(--etoile-shadow-lg);
105
-
106
- /* Smooth entrance animation */
107
- animation: etoile-fade-in 150ms ease-out;
183
+ animation: etoile-fade-in var(--etoile-animation-duration) ease-out;
108
184
 
109
185
  /* Hide scrollbar */
110
186
  scrollbar-width: none;
@@ -133,8 +209,8 @@
133
209
  .etoile-search [role="option"] {
134
210
  display: flex;
135
211
  align-items: center;
136
- gap: 16px;
137
- padding: 10px 12px;
212
+ gap: var(--etoile-result-gap);
213
+ padding: var(--etoile-result-padding-y) var(--etoile-result-padding-x);
138
214
  border-radius: var(--etoile-radius-sm);
139
215
  cursor: pointer;
140
216
  outline: none;
@@ -155,8 +231,8 @@
155
231
  ============================================ */
156
232
 
157
233
  .etoile-search [role="option"] img {
158
- width: 40px;
159
- height: 40px;
234
+ width: var(--etoile-thumbnail-size);
235
+ height: var(--etoile-thumbnail-size);
160
236
  object-fit: cover;
161
237
  border-radius: var(--etoile-radius-sm);
162
238
  background: var(--etoile-bg-subtle);
@@ -170,27 +246,27 @@
170
246
  .etoile-search .etoile-result-content {
171
247
  display: flex;
172
248
  flex-direction: column;
173
- gap: 1px;
249
+ gap: var(--etoile-result-content-gap);
174
250
  flex: 1;
175
251
  min-width: 0;
176
252
  text-align: left;
177
253
  }
178
254
 
179
255
  .etoile-search .etoile-result-title {
180
- font-size: 14px;
181
- font-weight: 500;
256
+ font-size: var(--etoile-font-size-title);
257
+ font-weight: var(--etoile-font-weight-title);
182
258
  color: var(--etoile-text);
183
- line-height: 1.3;
259
+ line-height: var(--etoile-line-height);
184
260
  overflow: hidden;
185
261
  text-overflow: ellipsis;
186
262
  white-space: nowrap;
187
263
  }
188
264
 
189
265
  .etoile-search .etoile-result-subtitle {
190
- font-size: 13px;
191
- font-weight: 500;
266
+ font-size: var(--etoile-font-size-subtitle);
267
+ font-weight: var(--etoile-font-weight-subtitle);
192
268
  color: var(--etoile-text-muted);
193
- line-height: 1.3;
269
+ line-height: var(--etoile-line-height);
194
270
  overflow: hidden;
195
271
  text-overflow: ellipsis;
196
272
  white-space: nowrap;
@@ -202,10 +278,10 @@
202
278
  ============================================ */
203
279
 
204
280
  .etoile-search .etoile-empty {
205
- padding: 24px 16px;
281
+ padding: var(--etoile-empty-padding-y) var(--etoile-empty-padding-x);
206
282
  text-align: center;
207
283
  color: var(--etoile-text-muted);
208
- font-size: 14px;
284
+ font-size: var(--etoile-font-size-small);
209
285
  }
210
286
 
211
287
  /* ============================================
@@ -216,19 +292,19 @@
216
292
  display: flex;
217
293
  align-items: center;
218
294
  justify-content: center;
219
- padding: 16px;
295
+ padding: var(--etoile-loading-padding);
220
296
  color: var(--etoile-text-muted);
221
- font-size: 14px;
222
- gap: 8px;
297
+ font-size: var(--etoile-font-size-small);
298
+ gap: var(--etoile-loading-gap);
223
299
  }
224
300
 
225
301
  .etoile-search .etoile-spinner {
226
- width: 16px;
227
- height: 16px;
228
- border: 2px solid var(--etoile-border);
302
+ width: var(--etoile-spinner-size);
303
+ height: var(--etoile-spinner-size);
304
+ border: var(--etoile-spinner-border-width) solid var(--etoile-border);
229
305
  border-top-color: var(--etoile-text-muted);
230
306
  border-radius: 50%;
231
- animation: etoile-spin 600ms linear infinite;
307
+ animation: etoile-spin var(--etoile-spinner-duration) linear infinite;
232
308
  }
233
309
 
234
310
  @keyframes etoile-spin {
@@ -245,13 +321,13 @@
245
321
  display: inline-flex;
246
322
  align-items: center;
247
323
  justify-content: center;
248
- height: 20px;
249
- padding: 0 4px;
324
+ height: var(--etoile-kbd-height);
325
+ padding: 0 var(--etoile-kbd-padding-x);
250
326
  background: var(--etoile-bg-subtle);
251
- border: 1px solid var(--etoile-border);
252
- border-radius: 6px;
327
+ border: var(--etoile-input-border-width) solid var(--etoile-border);
328
+ border-radius: var(--etoile-radius-kbd);
253
329
  color: var(--etoile-text-placeholder);
254
- font-size: 11px;
330
+ font-size: var(--etoile-font-size-kbd);
255
331
  font-family: inherit;
256
332
  pointer-events: none;
257
333
  }
@@ -267,10 +343,10 @@
267
343
  .etoile-search .etoile-input-wrapper svg {
268
344
  position: absolute;
269
345
  top: 50%;
270
- left: 14px;
346
+ left: var(--etoile-icon-offset);
271
347
  transform: translateY(-50%);
272
- width: 18px;
273
- height: 18px;
348
+ width: var(--etoile-icon-size);
349
+ height: var(--etoile-icon-size);
274
350
  color: var(--etoile-text-muted);
275
351
  pointer-events: none;
276
352
  transition: color var(--etoile-transition);
@@ -281,14 +357,14 @@
281
357
  }
282
358
 
283
359
  .etoile-search .etoile-input-wrapper input[role="combobox"] {
284
- padding-left: 42px;
285
- padding-right: 48px;
360
+ padding-left: var(--etoile-input-padding-with-icon);
361
+ padding-right: var(--etoile-input-padding-with-kbd);
286
362
  }
287
363
 
288
364
  .etoile-search .etoile-input-wrapper .etoile-kbd {
289
365
  position: absolute;
290
366
  top: 50%;
291
- right: 10px;
367
+ right: var(--etoile-kbd-offset);
292
368
  transform: translateY(-50%);
293
369
  }
294
370
 
@@ -297,5 +373,5 @@
297
373
  ============================================ */
298
374
 
299
375
  .etoile-search .etoile-input-wrapper:not(:has(svg)) input[role="combobox"] {
300
- padding-left: 16px;
376
+ padding-left: var(--etoile-input-padding-x);
301
377
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etoile-dev/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Official React primitives for Étoile - Headless, composable search components",
5
5
  "keywords": [
6
6
  "etoile",