@ankhorage/zora 0.0.3 โ†’ 0.0.4

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/CHANGELOG.md +6 -0
  2. package/README.md +876 -18
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Expand the README into a full public API catalogue with collapsible property details, documented inherited prop surfaces, and Expo showcase usage instructions.
8
+
3
9
  ## 0.0.3
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -1,32 +1,890 @@
1
1
  # zora
2
2
 
3
- A UI framework for React Native and Web.
3
+ <!-- markdownlint-disable MD013 MD033 -->
4
4
 
5
- ## ๐ŸŽฏ What you get
6
- - Build full screens, not just primitives
7
- - Consistent spacing and typography
8
- - Works out of the box with Expo + Web
5
+ Opinionated React Native and React Native Web UI kit built on
6
+ `@ankhorage/surface`.
9
7
 
10
- ## โœจ Features
11
- - Ready-to-use UI components
12
- - Design consistency
13
- - Built on primitives
8
+ ZORA sits above Surface. Surface provides the foundation primitives, theme system,
9
+ and low-level controls; ZORA adds product-facing components, app layouts, and
10
+ ready-made patterns with stronger defaults.
11
+
12
+ ## Install
14
13
 
15
- ## ๐Ÿš€ Installation
16
14
  ```bash
17
15
  bun add @ankhorage/zora
18
16
  ```
19
17
 
20
- ## ๐Ÿ“ฆ Usage
18
+ Peer dependencies:
19
+
20
+ - `react >=18.2.0`
21
+ - `react-native >=0.72.0`
22
+ - `@expo/vector-icons >=14.0.0` when using icon specs
23
+ - `expo-font >=14.0.4` when using runtime font registration
24
+
25
+ ## Quick Start
26
+
27
+ Wrap your app in `ZoraProvider`, then import components from
28
+ `@ankhorage/zora`.
29
+
21
30
  ```tsx
22
- import { Button } from '@ankhorage/zora'
31
+ import React from 'react';
32
+ import { Button, Card, Page, PageHeader, ZoraProvider } from '@ankhorage/zora';
23
33
 
24
- <Button>Click me</Button>
34
+ export function App() {
35
+ return (
36
+ <ZoraProvider>
37
+ <Page header={<PageHeader title="Dashboard" description="Ready to build." />}>
38
+ <Card
39
+ actions={<Button>Continue</Button>}
40
+ description="ZORA provides composed UI surfaces for apps."
41
+ title="Welcome"
42
+ />
43
+ </Page>
44
+ </ZoraProvider>
45
+ );
46
+ }
25
47
  ```
26
48
 
27
- ## ๐Ÿงช Use Cases
28
- - Rapid app development
29
- - UI standardization across teams
49
+ ## Shared Types
50
+
51
+ These unions appear across the catalogue:
52
+
53
+ - `ZoraTone` comes from Surface `ButtonProps['tone']`.
54
+ - `ZoraEmphasis` comes from Surface `ButtonProps['variant']`.
55
+ - `ZoraBadgeEmphasis` comes from Surface `BadgeProps['variant']`.
56
+ - `ZoraControlSize` comes from Surface `ButtonProps['size']`.
57
+ - `ZoraCardTone = 'default' | 'subtle' | 'outline'`.
58
+ - `ZoraContentWidth = 'narrow' | 'default' | 'wide'`.
59
+
60
+ Width presets:
61
+
62
+ - Dialog widths: `narrow=420`, `default=520`, `wide=560`.
63
+ - Page widths: `narrow=760`, `default=1040`, `wide=1280`.
64
+
65
+ ## Components
66
+
67
+ ### `Button`
68
+
69
+ Action button with ZORA defaults for tone, emphasis, size, and icons.
70
+
71
+ ```tsx
72
+ <Button leadingIcon={{ name: 'checkmark-circle-outline' }}>Save</Button>
73
+ ```
74
+
75
+ <details>
76
+ <summary>Props</summary>
77
+
78
+ ZORA props:
79
+
80
+ | Prop | Type | Default | Notes |
81
+ | --- | --- | --- | --- |
82
+ | `children` | `React.ReactNode` | - | Button label or content. |
83
+ | `tone` | `ZoraTone` | `'primary'` | Passed to Surface as `tone`. |
84
+ | `emphasis` | `ZoraEmphasis` | `'solid'` | Passed to Surface as `variant`. |
85
+ | `size` | `ZoraControlSize` | `'l'` | Passed to Surface as `size`. |
86
+ | `leadingIcon` | `ButtonIconSpec` | - | Surface icon spec rendered before content. |
87
+ | `trailingIcon` | `ButtonIconSpec` | - | Surface icon spec rendered after content. |
88
+
89
+ Inherited props:
90
+
91
+ Inherits all Surface `ButtonProps` except `children`, `size`, `tone`, and
92
+ `variant`. This includes Surface button behavior such as `loading`,
93
+ `fullWidth`, pressability props, disabled state, accessibility props allowed by
94
+ Surface, and `testID`.
95
+
96
+ </details>
97
+
98
+ ### `Badge`
99
+
100
+ Small status label with ZORA tone, emphasis, and size defaults.
101
+
102
+ ```tsx
103
+ <Badge tone="success">Active</Badge>
104
+ ```
105
+
106
+ <details>
107
+ <summary>Props</summary>
108
+
109
+ ZORA props:
110
+
111
+ | Prop | Type | Default | Notes |
112
+ | --- | --- | --- | --- |
113
+ | `children` | `React.ReactNode` | - | Rendered as Surface badge `content`. |
114
+ | `tone` | `ZoraTone` | `'primary'` | Passed to Surface as `tone`. |
115
+ | `emphasis` | `ZoraBadgeEmphasis` | `'soft'` | Passed to Surface as `variant`. |
116
+ | `size` | `ZoraControlSize` | `'m'` | Passed to Surface as `size`. |
117
+
118
+ Inherited props:
119
+
120
+ Inherits all Surface `BadgeProps` except `content`, `size`, `tone`, and
121
+ `variant`. The remaining inherited prop is `testID`.
122
+
123
+ </details>
124
+
125
+ ### `Card`
126
+
127
+ Composed content surface with optional header, actions, footer, and ZORA card
128
+ tones.
129
+
130
+ ```tsx
131
+ <Card
132
+ actions={<Button>Open</Button>}
133
+ description="A reusable product surface."
134
+ title="Project"
135
+ />
136
+ ```
137
+
138
+ <details>
139
+ <summary>Props</summary>
140
+
141
+ ZORA props:
142
+
143
+ | Prop | Type | Default | Notes |
144
+ | --- | --- | --- | --- |
145
+ | `children` | `React.ReactNode` | - | Main card body. |
146
+ | `title` | `React.ReactNode` | - | Header title. |
147
+ | `description` | `React.ReactNode` | - | Header description. |
148
+ | `eyebrow` | `React.ReactNode` | - | Small muted text above the title. |
149
+ | `actions` | `React.ReactNode` | - | Header action area. |
150
+ | `footer` | `React.ReactNode` | - | Footer area below body content. |
151
+ | `tone` | `ZoraCardTone` | `'default'` | Maps to Surface variants: `default -> raised`, `subtle -> subtle`, `outline -> outline`. |
152
+ | `compact` | `boolean` | `false` | Uses tighter padding and heading scale. |
153
+
154
+ Inherited props:
155
+
156
+ Inherits all Surface `CardProps` except `children`, `p`, `radius`, `style`, and
157
+ `variant`. ZORA owns spacing, radius, and variant selection for this wrapper.
158
+
159
+ </details>
160
+
161
+ ### `Input`
162
+
163
+ Text input wrapper with ZORA sizing and optional Surface icon specs.
164
+
165
+ ```tsx
166
+ <Input
167
+ autoCapitalize="none"
168
+ keyboardType="email-address"
169
+ leadingIcon={{ name: 'mail-outline' }}
170
+ placeholder="you@example.com"
171
+ />
172
+ ```
173
+
174
+ <details>
175
+ <summary>Props</summary>
176
+
177
+ ZORA props:
178
+
179
+ | Prop | Type | Default | Notes |
180
+ | --- | --- | --- | --- |
181
+ | `size` | `ZoraControlSize` | `'l'` | Passed to Surface as `size`. |
182
+ | `leadingIcon` | `ButtonIconSpec` | - | Rendered as Surface `leadingAccessory`. |
183
+ | `trailingIcon` | `ButtonIconSpec` | - | Rendered as Surface `trailingAccessory`. |
184
+
185
+ Inherited props:
186
+
187
+ Inherits all Surface `TextInputProps` except `leadingAccessory`, `size`, and
188
+ `trailingAccessory`. Surface `TextInputProps` also inherit React Native
189
+ `TextInputProps` except `defaultValue`, `editable`, `onChangeText`,
190
+ `placeholderTextColor`, `style`, `testID`, and `value`; Surface re-exposes
191
+ `value`, `defaultValue`, `onChangeText`, `placeholder`, `disabled`, `readOnly`,
192
+ `invalid`, `style`, and `testID`.
193
+
194
+ </details>
195
+
196
+ ### `Textarea`
197
+
198
+ Multiline text input wrapper with ZORA sizing and optional Surface icon specs.
199
+
200
+ ```tsx
201
+ <Textarea leadingIcon={{ name: 'document-text-outline' }} rows={5} />
202
+ ```
203
+
204
+ <details>
205
+ <summary>Props</summary>
206
+
207
+ ZORA props:
208
+
209
+ | Prop | Type | Default | Notes |
210
+ | --- | --- | --- | --- |
211
+ | `size` | `ZoraControlSize` | `'l'` | Passed to Surface as `size`. |
212
+ | `leadingIcon` | `ButtonIconSpec` | - | Rendered as Surface `leadingAccessory`. |
213
+ | `trailingIcon` | `ButtonIconSpec` | - | Rendered as Surface `trailingAccessory`. |
214
+
215
+ Inherited props:
216
+
217
+ Inherits all Surface `TextareaProps` except `leadingAccessory`, `size`, and
218
+ `trailingAccessory`. Surface `TextareaProps` extend Surface `TextInputProps`
219
+ except `multiline`, so React Native text input props are available through
220
+ Surface with the same Surface exclusions and re-exposed values listed for
221
+ `Input`.
222
+
223
+ </details>
224
+
225
+ ### `Modal`
226
+
227
+ Centered overlay shell with optional header, body, footer, and width preset.
228
+
229
+ ```tsx
230
+ <Modal
231
+ footer={<Button>Done</Button>}
232
+ onDismiss={close}
233
+ title="Details"
234
+ visible={visible}
235
+ />
236
+ ```
237
+
238
+ <details>
239
+ <summary>Props</summary>
240
+
241
+ ZORA props:
242
+
243
+ | Prop | Type | Default | Notes |
244
+ | --- | --- | --- | --- |
245
+ | `children` | `React.ReactNode` | - | Modal body. |
246
+ | `title` | `React.ReactNode` | - | Header title. |
247
+ | `description` | `React.ReactNode` | - | Header description. |
248
+ | `footer` | `React.ReactNode` | - | Footer area. |
249
+ | `width` | `ZoraContentWidth` | `'default'` | Resolves to `420`, `520`, or `560` pixels. |
250
+
251
+ Inherited props:
252
+
253
+ Picks these Surface `ModalProps`: `closeOnBackdrop`, `onDismiss`, `testID`, and
254
+ `visible`.
255
+
256
+ </details>
257
+
258
+ ### `Drawer`
259
+
260
+ Side overlay shell with optional header, body, and footer.
261
+
262
+ ```tsx
263
+ <Drawer onDismiss={close} title="Filters" visible={visible}>
264
+ {content}
265
+ </Drawer>
266
+ ```
267
+
268
+ <details>
269
+ <summary>Props</summary>
270
+
271
+ ZORA props:
272
+
273
+ | Prop | Type | Default | Notes |
274
+ | --- | --- | --- | --- |
275
+ | `children` | `React.ReactNode` | - | Drawer body. |
276
+ | `title` | `React.ReactNode` | - | Header title. |
277
+ | `description` | `React.ReactNode` | - | Header description. |
278
+ | `footer` | `React.ReactNode` | - | Footer area. |
279
+
280
+ Inherited props:
281
+
282
+ Picks these Surface `DrawerProps`: `closeOnBackdrop`, `onDismiss`, `position`,
283
+ `testID`, and `visible`.
284
+
285
+ </details>
286
+
287
+ ## Layouts
288
+
289
+ ### `Page`
290
+
291
+ Constrained page container with optional header and footer slots.
292
+
293
+ ```tsx
294
+ <Page header={<PageHeader title="Projects" />} width="wide">
295
+ {content}
296
+ </Page>
297
+ ```
298
+
299
+ <details>
300
+ <summary>Props</summary>
301
+
302
+ ZORA props:
303
+
304
+ | Prop | Type | Default | Notes |
305
+ | --- | --- | --- | --- |
306
+ | `children` | `React.ReactNode` | - | Page body. |
307
+ | `header` | `React.ReactNode` | - | Rendered above body content. |
308
+ | `footer` | `React.ReactNode` | - | Rendered below body content. |
309
+ | `width` | `ZoraContentWidth` | `'default'` | Resolves to `760`, `1040`, or `1280` pixels. |
310
+ | `testID` | `string` | - | Forwarded to the root Surface container. |
311
+
312
+ Inherited props:
313
+
314
+ No inherited props. `PageProps` is declared directly by ZORA.
315
+
316
+ </details>
317
+
318
+ ### `PageHeader`
319
+
320
+ Top-level page heading with optional eyebrow, metadata, and actions.
321
+
322
+ ```tsx
323
+ <PageHeader actions={<Button>New</Button>} title="Projects" />
324
+ ```
325
+
326
+ <details>
327
+ <summary>Props</summary>
328
+
329
+ ZORA props:
330
+
331
+ | Prop | Type | Default | Notes |
332
+ | --- | --- | --- | --- |
333
+ | `title` | `React.ReactNode` | - | Required page title. |
334
+ | `description` | `React.ReactNode` | - | Supporting copy below title. |
335
+ | `eyebrow` | `React.ReactNode` | - | Small muted text above title. |
336
+ | `actions` | `React.ReactNode` | - | Action area opposite the heading. |
337
+ | `meta` | `React.ReactNode` | - | Extra content below description. |
338
+ | `testID` | `string` | - | Forwarded to the root Surface stack. |
339
+
340
+ Inherited props:
341
+
342
+ No inherited props. `PageHeaderProps` is declared directly by ZORA.
343
+
344
+ </details>
345
+
346
+ ### `PageSection`
347
+
348
+ Section wrapper that optionally renders a `SectionHeader`.
349
+
350
+ ```tsx
351
+ <PageSection actions={<Button>Refresh</Button>} title="Recent activity">
352
+ {content}
353
+ </PageSection>
354
+ ```
355
+
356
+ <details>
357
+ <summary>Props</summary>
358
+
359
+ ZORA props:
360
+
361
+ | Prop | Type | Default | Notes |
362
+ | --- | --- | --- | --- |
363
+ | `title` | `React.ReactNode` | - | Section title; when absent, no header is rendered. |
364
+ | `description` | `React.ReactNode` | - | Passed to the section header. |
365
+ | `actions` | `React.ReactNode` | - | Passed to the section header. |
366
+ | `children` | `React.ReactNode` | - | Section body. |
367
+ | `testID` | `string` | - | Forwarded to the root Surface stack. |
368
+
369
+ Inherited props:
370
+
371
+ No inherited props. `PageSectionProps` is declared directly by ZORA.
372
+
373
+ </details>
374
+
375
+ ### `SidebarLayout`
376
+
377
+ Responsive shell with required sidebar, main content, and optional aside.
378
+
379
+ ```tsx
380
+ <SidebarLayout sidebar={navigation} aside={details}>
381
+ {content}
382
+ </SidebarLayout>
383
+ ```
384
+
385
+ <details>
386
+ <summary>Props</summary>
387
+
388
+ ZORA props:
389
+
390
+ | Prop | Type | Default | Notes |
391
+ | --- | --- | --- | --- |
392
+ | `sidebar` | `React.ReactNode` | - | Required left column content. |
393
+ | `children` | `React.ReactNode` | - | Main content. |
394
+ | `aside` | `React.ReactNode` | - | Optional right column content. |
395
+ | `sidebarWidth` | `number` | `280` | Desktop sidebar width. |
396
+ | `asideWidth` | `number` | `280` | Desktop aside width. |
397
+ | `testID` | `string` | - | Forwarded to the root Surface stack. |
398
+
399
+ Inherited props:
400
+
401
+ No inherited props. `SidebarLayoutProps` is declared directly by ZORA.
402
+
403
+ </details>
404
+
405
+ ### `TopbarLayout`
406
+
407
+ Top navigation shell with optional sidebar composition.
408
+
409
+ ```tsx
410
+ <TopbarLayout topbar={topbar} sidebar={sidebar}>
411
+ {content}
412
+ </TopbarLayout>
413
+ ```
414
+
415
+ <details>
416
+ <summary>Props</summary>
417
+
418
+ ZORA props:
419
+
420
+ | Prop | Type | Default | Notes |
421
+ | --- | --- | --- | --- |
422
+ | `topbar` | `React.ReactNode` | - | Required topbar content. |
423
+ | `children` | `React.ReactNode` | - | Main content. |
424
+ | `sidebar` | `React.ReactNode` | - | Optional sidebar; when present, content is rendered through `SidebarLayout`. |
425
+ | `testID` | `string` | - | Forwarded to the root Surface stack. |
426
+
427
+ Inherited props:
428
+
429
+ No inherited props. `TopbarLayoutProps` is declared directly by ZORA.
430
+
431
+ </details>
432
+
433
+ ### `SettingsLayout`
434
+
435
+ Reusable settings shell with page header, sidebar, and content region.
436
+
437
+ ```tsx
438
+ <SettingsLayout actions={<Button>Save</Button>} sidebar={nav} title="Settings">
439
+ {content}
440
+ </SettingsLayout>
441
+ ```
442
+
443
+ <details>
444
+ <summary>Props</summary>
445
+
446
+ ZORA props:
447
+
448
+ | Prop | Type | Default | Notes |
449
+ | --- | --- | --- | --- |
450
+ | `title` | `React.ReactNode` | - | Optional page title; when absent, no page header is rendered. |
451
+ | `description` | `React.ReactNode` | - | Header description. |
452
+ | `sidebar` | `React.ReactNode` | - | Required settings navigation or context sidebar. |
453
+ | `children` | `React.ReactNode` | - | Settings content. |
454
+ | `actions` | `React.ReactNode` | - | Header action area. |
455
+ | `testID` | `string` | - | Forwarded to `Page`. |
456
+
457
+ Inherited props:
458
+
459
+ No inherited props. `SettingsLayoutProps` is declared directly by ZORA.
460
+
461
+ </details>
462
+
463
+ ### `AuthLayout`
464
+
465
+ Centered authentication-style shell for sign-in, onboarding, and recovery
466
+ screens.
467
+
468
+ ```tsx
469
+ <AuthLayout description="Sign in to continue" title="Welcome back">
470
+ {form}
471
+ </AuthLayout>
472
+ ```
473
+
474
+ <details>
475
+ <summary>Props</summary>
476
+
477
+ ZORA props:
478
+
479
+ | Prop | Type | Default | Notes |
480
+ | --- | --- | --- | --- |
481
+ | `title` | `React.ReactNode` | - | Card title. |
482
+ | `description` | `React.ReactNode` | - | Card description. |
483
+ | `eyebrow` | `React.ReactNode` | - | Card eyebrow. |
484
+ | `children` | `React.ReactNode` | - | Form or auth content. |
485
+ | `footer` | `React.ReactNode` | - | Card footer. |
486
+ | `testID` | `string` | - | Forwarded to the root Surface center. |
487
+
488
+ Inherited props:
489
+
490
+ No inherited props. `AuthLayoutProps` is declared directly by ZORA.
491
+
492
+ </details>
493
+
494
+ ## Patterns
495
+
496
+ ### `FormField`
497
+
498
+ Form field wrapper with rich label composition, description, helper text, and
499
+ Surface field state.
500
+
501
+ ```tsx
502
+ <FormField helperText="We only use this for sign-in." label="Email">
503
+ <Input keyboardType="email-address" />
504
+ </FormField>
505
+ ```
506
+
507
+ <details>
508
+ <summary>Props</summary>
509
+
510
+ ZORA props:
511
+
512
+ | Prop | Type | Default | Notes |
513
+ | --- | --- | --- | --- |
514
+ | `label` | `React.ReactNode` | - | Required field label. |
515
+ | `description` | `React.ReactNode` | - | Rendered under the label. |
516
+ | `helperText` | `React.ReactNode` | - | Passed to Surface `Field` as `helperText`. |
517
+
518
+ Inherited props:
519
+
520
+ Picks these Surface `FieldProps`: `children`, `disabled`, `errorText`,
521
+ `invalid`, `readOnly`, `required`, and `testID`.
522
+
523
+ </details>
524
+
525
+ ### `Notice`
526
+
527
+ Semantic notice surface with badge eyebrow, optional body, and actions.
528
+
529
+ ```tsx
530
+ <Notice actions={<Button>Review</Button>} title="Publish pipeline ready" tone="success" />
531
+ ```
532
+
533
+ <details>
534
+ <summary>Props</summary>
535
+
536
+ ZORA props:
537
+
538
+ | Prop | Type | Default | Notes |
539
+ | --- | --- | --- | --- |
540
+ | `title` | `React.ReactNode` | - | Required notice title. |
541
+ | `description` | `React.ReactNode` | - | Notice description. |
542
+ | `children` | `React.ReactNode` | - | Optional body content. |
543
+ | `actions` | `React.ReactNode` | - | Optional action area. |
544
+ | `tone` | `ZoraTone` | `'primary'` | Drives the badge eyebrow tone. |
545
+ | `testID` | `string` | - | Forwarded to the underlying `Card`. |
546
+
547
+ Inherited props:
548
+
549
+ No inherited props. `NoticeProps` is declared directly by ZORA.
550
+
551
+ </details>
552
+
553
+ ### `Panel`
554
+
555
+ Named composition surface that currently forwards to `Card`.
556
+
557
+ ```tsx
558
+ <Panel description="Release details" title="Release Candidate">
559
+ {content}
560
+ </Panel>
561
+ ```
562
+
563
+ <details>
564
+ <summary>Props</summary>
565
+
566
+ ZORA props:
567
+
568
+ | Prop | Type | Default | Notes |
569
+ | --- | --- | --- | --- |
570
+ | `title` | `React.ReactNode` | - | Header title. |
571
+ | `description` | `React.ReactNode` | - | Header description. |
572
+ | `eyebrow` | `React.ReactNode` | - | Small muted text above the title. |
573
+ | `actions` | `React.ReactNode` | - | Header action area. |
574
+ | `footer` | `React.ReactNode` | - | Footer area below body content. |
575
+ | `children` | `React.ReactNode` | - | Panel body. |
576
+ | `tone` | `ZoraCardTone` | `'default'` | Same tone behavior as `Card`. |
577
+ | `compact` | `boolean` | `false` | Same compact behavior as `Card`. |
578
+ | `testID` | `string` | - | Forwarded through `Card`. |
579
+
580
+ Inherited props:
581
+
582
+ No inherited props. `PanelProps` is declared directly by ZORA.
583
+
584
+ </details>
585
+
586
+ ### `SectionHeader`
587
+
588
+ Reusable section heading with optional eyebrow, description, and actions.
589
+
590
+ ```tsx
591
+ <SectionHeader actions={<Badge>Live</Badge>} title="Activity" />
592
+ ```
593
+
594
+ <details>
595
+ <summary>Props</summary>
596
+
597
+ ZORA props:
598
+
599
+ | Prop | Type | Default | Notes |
600
+ | --- | --- | --- | --- |
601
+ | `title` | `React.ReactNode` | - | Required heading title. |
602
+ | `description` | `React.ReactNode` | - | Supporting copy. |
603
+ | `eyebrow` | `React.ReactNode` | - | Small muted text above the title. |
604
+ | `actions` | `React.ReactNode` | - | Action area opposite the heading. |
605
+ | `testID` | `string` | - | Forwarded to the root Surface stack. |
606
+
607
+ Inherited props:
608
+
609
+ No inherited props. `SectionHeaderProps` is declared directly by ZORA.
610
+
611
+ </details>
612
+
613
+ ### `SettingsRow`
614
+
615
+ Compact settings row with optional metadata, control, and press handling.
616
+
617
+ ```tsx
618
+ <SettingsRow control={<Switch value={enabled} />} title="Notifications" />
619
+ ```
620
+
621
+ <details>
622
+ <summary>Props</summary>
623
+
624
+ ZORA props:
625
+
626
+ | Prop | Type | Default | Notes |
627
+ | --- | --- | --- | --- |
628
+ | `title` | `React.ReactNode` | - | Required row title. |
629
+ | `description` | `React.ReactNode` | - | Row description. |
630
+ | `meta` | `React.ReactNode` | - | Small muted metadata below the row content. |
631
+ | `control` | `React.ReactNode` | - | Trailing control or action content. |
632
+ | `onPress` | `() => void` | - | Makes the underlying card pressable. |
633
+ | `disabled` | `boolean` | `false` | Forwarded to the underlying card. |
634
+ | `testID` | `string` | - | Forwarded to the underlying card. |
635
+
636
+ Inherited props:
637
+
638
+ No inherited props. `SettingsRowProps` is declared directly by ZORA.
639
+
640
+ </details>
641
+
642
+ ### `EmptyState`
643
+
644
+ No-data surface with title, optional supporting text, actions, and footer.
645
+
646
+ ```tsx
647
+ <EmptyState
648
+ primaryAction={{ label: 'Create project', onPress: createProject }}
649
+ title="Nothing here yet"
650
+ />
651
+ ```
652
+
653
+ <details>
654
+ <summary>Props</summary>
655
+
656
+ ZORA props:
657
+
658
+ | Prop | Type | Default | Notes |
659
+ | --- | --- | --- | --- |
660
+ | `title` | `React.ReactNode` | - | Required empty-state title. |
661
+ | `description` | `React.ReactNode` | - | Supporting copy. |
662
+ | `eyebrow` | `React.ReactNode` | - | Card eyebrow. |
663
+ | `primaryAction` | `EmptyStateAction` | - | Primary action button. |
664
+ | `secondaryAction` | `EmptyStateAction` | - | Secondary action button; defaults to `tone="neutral"` and `emphasis="soft"` when omitted on the action. |
665
+ | `footer` | `React.ReactNode` | - | Footer content below actions. |
666
+ | `testID` | `string` | - | Forwarded to the underlying card. |
667
+
668
+ `EmptyStateAction`:
669
+
670
+ | Prop | Type | Default | Notes |
671
+ | --- | --- | --- | --- |
672
+ | `label` | `React.ReactNode` | - | Button label. |
673
+ | `onPress` | `() => void` | - | Button handler. |
674
+ | `tone` | `ZoraTone` | - | Button tone. |
675
+ | `emphasis` | `ZoraEmphasis` | - | Button emphasis. |
676
+
677
+ Inherited props:
678
+
679
+ No inherited props. `EmptyStateProps` and `EmptyStateAction` are declared
680
+ directly by ZORA.
681
+
682
+ </details>
683
+
684
+ ### `ConfirmDialog`
685
+
686
+ Narrow confirmation modal for destructive or high-signal decisions.
687
+
688
+ ```tsx
689
+ <ConfirmDialog
690
+ confirmLabel="Archive"
691
+ confirmTone="danger"
692
+ onCancel={close}
693
+ onConfirm={archive}
694
+ title="Archive project?"
695
+ visible={visible}
696
+ />
697
+ ```
698
+
699
+ <details>
700
+ <summary>Props</summary>
701
+
702
+ ZORA props:
703
+
704
+ | Prop | Type | Default | Notes |
705
+ | --- | --- | --- | --- |
706
+ | `visible` | `boolean` | - | Required modal visibility. |
707
+ | `title` | `React.ReactNode` | - | Required dialog title. |
708
+ | `description` | `React.ReactNode` | - | Dialog description. |
709
+ | `children` | `React.ReactNode` | - | Dialog body. |
710
+ | `confirmLabel` | `React.ReactNode` | `'Confirm'` | Confirm button label. |
711
+ | `cancelLabel` | `React.ReactNode` | `'Cancel'` | Cancel button label. |
712
+ | `confirmTone` | `ZoraTone` | `'danger'` | Confirm button tone. |
713
+ | `confirmEmphasis` | `ZoraEmphasis` | `'solid'` | Confirm button emphasis. |
714
+ | `busy` | `boolean` | `false` | Passed to the confirm button as `loading`. |
715
+ | `closeOnBackdrop` | `boolean` | `true` | Passed to the underlying modal. |
716
+ | `onConfirm` | `() => void` | - | Confirm button handler. |
717
+ | `onCancel` | `() => void` | - | Cancel button and modal dismiss handler. |
718
+ | `testID` | `string` | - | Forwarded to the underlying modal. |
719
+
720
+ Confirm dialogs always use `Modal` with `width="narrow"`.
721
+
722
+ Inherited props:
723
+
724
+ No inherited props. `ConfirmDialogProps` is declared directly by ZORA.
725
+
726
+ </details>
727
+
728
+ ## Theme
729
+
730
+ ### `ZoraProvider`
731
+
732
+ Theme provider that creates the ZORA theme and passes it to Surface
733
+ `ThemeProvider`.
734
+
735
+ ```tsx
736
+ <ZoraProvider initialMode="dark">
737
+ <App />
738
+ </ZoraProvider>
739
+ ```
740
+
741
+ <details>
742
+ <summary>Props</summary>
743
+
744
+ ZORA props:
745
+
746
+ | Prop | Type | Default | Notes |
747
+ | --- | --- | --- | --- |
748
+ | `children` | `React.ReactNode` | - | Required app content. |
749
+ | `initialConfig` | `ZoraThemeOverride` | - | Partial Surface `ThemeConfig` override merged into `zoraTheme`. |
750
+ | `initialMode` | `'light' \| 'dark'` | `'light'` | Initial theme mode passed to Surface. |
751
+
752
+ Inherited props:
753
+
754
+ No inherited props. `ZoraProviderProps` is declared directly by ZORA.
755
+
756
+ </details>
757
+
758
+ ### `createZoraTheme`
759
+
760
+ Creates a Surface `ThemeConfig` by deep-merging overrides into `zoraTheme`.
761
+
762
+ ```tsx
763
+ const theme = createZoraTheme({
764
+ light: {
765
+ primaryColor: '#1d4ed8',
766
+ },
767
+ });
768
+ ```
769
+
770
+ <details>
771
+ <summary>API</summary>
772
+
773
+ ```ts
774
+ type ZoraThemeOverride = Partial<ThemeConfig>;
775
+
776
+ function createZoraTheme(overrides?: ZoraThemeOverride): ThemeConfig;
777
+ ```
778
+
779
+ The returned theme keeps `id: 'zora'` unless explicitly changed by the merge
780
+ input.
781
+
782
+ </details>
783
+
784
+ ### `zoraTheme`
785
+
786
+ Default ZORA Surface theme preset.
787
+
788
+ <details>
789
+ <summary>Value</summary>
790
+
791
+ ```ts
792
+ const zoraTheme: ThemeConfig = {
793
+ id: 'zora',
794
+ name: 'ZORA',
795
+ light: {
796
+ primaryColor: '#0f766e',
797
+ harmony: 'analogous',
798
+ systemTone: 'jewel',
799
+ },
800
+ dark: {
801
+ primaryColor: '#2dd4bf',
802
+ harmony: 'analogous',
803
+ systemTone: 'jewel',
804
+ },
805
+ };
806
+ ```
807
+
808
+ </details>
809
+
810
+ ## Public Exports
811
+
812
+ ```ts
813
+ export {
814
+ AuthLayout,
815
+ Badge,
816
+ Button,
817
+ Card,
818
+ ConfirmDialog,
819
+ createZoraTheme,
820
+ Drawer,
821
+ EmptyState,
822
+ FormField,
823
+ Input,
824
+ Modal,
825
+ Notice,
826
+ Page,
827
+ PageHeader,
828
+ PageSection,
829
+ Panel,
830
+ SectionHeader,
831
+ SettingsLayout,
832
+ SettingsRow,
833
+ SidebarLayout,
834
+ Textarea,
835
+ TopbarLayout,
836
+ ZoraProvider,
837
+ zoraTheme,
838
+ };
839
+
840
+ export type {
841
+ AuthLayoutProps,
842
+ BadgeProps,
843
+ ButtonProps,
844
+ CardProps,
845
+ ConfirmDialogProps,
846
+ DrawerProps,
847
+ EmptyStateAction,
848
+ EmptyStateProps,
849
+ FormFieldProps,
850
+ InputProps,
851
+ ModalProps,
852
+ NoticeProps,
853
+ PageHeaderProps,
854
+ PageProps,
855
+ PageSectionProps,
856
+ PanelProps,
857
+ SectionHeaderProps,
858
+ SettingsLayoutProps,
859
+ SettingsRowProps,
860
+ SidebarLayoutProps,
861
+ TextareaProps,
862
+ TopbarLayoutProps,
863
+ ZoraProviderProps,
864
+ ZoraThemeOverride,
865
+ };
866
+ ```
867
+
868
+ ## Example App
869
+
870
+ A complete Expo showcase lives in `examples/expo-showcase`. It renders every
871
+ current ZORA component, pattern, layout, and theme entry point on one screen.
872
+
873
+ Run it locally:
874
+
875
+ ```bash
876
+ cd examples/expo-showcase
877
+ npm install
878
+ npm run web
879
+ ```
880
+
881
+ The example imports `@ankhorage/zora` and demonstrates the package API in
882
+ `examples/expo-showcase/App.tsx`.
883
+
884
+ ## Changelog
885
+
886
+ Version history is maintained in [CHANGELOG.md](./CHANGELOG.md).
887
+
888
+ ## License
30
889
 
31
- ## ๐Ÿง  Why this exists
32
- Building UI from scratch is slow. Zora speeds up development with reusable patterns.
890
+ MIT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.4",
5
5
  "description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
6
6
  "homepage": "https://github.com/ankhorage/zora#readme",
7
7
  "bugs": {