@ankhorage/zora 0.0.2 → 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 +12 -0
  2. package/README.md +812 -119
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
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
+
9
+ ## 0.0.3
10
+
11
+ ### Patch Changes
12
+
13
+ - Refresh the README copy so the published package overview, installation, usage, and positioning match the current messaging.
14
+
3
15
  ## 0.0.2
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -1,196 +1,889 @@
1
- # ZORA
1
+ # zora
2
2
 
3
- **ZORA** = **ZerO-config React-native design system Architecture**
3
+ <!-- markdownlint-disable MD013 MD033 -->
4
4
 
5
- An opinionated UI kit for **React Native + Web**, built on top of `@ankhorage/surface`.
5
+ Opinionated React Native and React Native Web UI kit built on
6
+ `@ankhorage/surface`.
6
7
 
7
- ZORA gives you ready-to-use, production-grade UI patterns with a consistent design language — without forcing a complex setup.
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.
8
11
 
9
- ---
12
+ ## Install
10
13
 
11
- ## What is ZORA?
14
+ ```bash
15
+ bun add @ankhorage/zora
16
+ ```
17
+
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
12
24
 
13
- ZORA is the **design system layer** on top of Surface.
25
+ ## Quick Start
14
26
 
15
- - **Surface** foundation (primitives, tokens, interactions)
16
- - **ZORA** → UI kit (patterns, layouts, polished components)
27
+ Wrap your app in `ZoraProvider`, then import components from
28
+ `@ankhorage/zora`.
17
29
 
18
- Think:
30
+ ```tsx
31
+ import React from 'react';
32
+ import { Button, Card, Page, PageHeader, ZoraProvider } from '@ankhorage/zora';
19
33
 
20
- - Surface = engine
21
- - ZORA = car
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
+ }
47
+ ```
22
48
 
23
- ---
49
+ ## Shared Types
24
50
 
25
- ## Why the name "Zora"?
51
+ These unions appear across the catalogue:
26
52
 
27
- **Zora** is a Slavic name meaning **dawn**, **sunrise**, or **aurora**.
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'`.
28
59
 
29
- That fits the package well: Surface is the foundation, while ZORA is the layer where that foundation becomes visible, expressive, and product-ready.
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
+ ```
30
74
 
31
- ---
75
+ <details>
76
+ <summary>Props</summary>
32
77
 
33
- ## Why use it?
78
+ ZORA props:
34
79
 
35
- Surface gives you flexibility.
36
- ZORA gives you **speed and consistency**.
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. |
37
88
 
38
- With ZORA you get:
89
+ Inherited props:
39
90
 
40
- - prebuilt UI patterns
41
- - opinionated defaults
42
- - consistent spacing, colors, and typography
43
- - ready-to-use layouts
44
- - production-ready components
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`.
45
95
 
46
- ---
96
+ </details>
47
97
 
48
- ## Quick example
98
+ ### `Badge`
99
+
100
+ Small status label with ZORA tone, emphasis, and size defaults.
49
101
 
50
102
  ```tsx
51
- import { Page, PageHeader, FormField, Input, Button } from '@ankhorage/zora'
103
+ <Badge tone="success">Active</Badge>
104
+ ```
52
105
 
53
- export function Login() {
54
- return (
55
- <Page>
56
- <PageHeader title="Sign in" />
106
+ <details>
107
+ <summary>Props</summary>
57
108
 
58
- <FormField label="Email">
59
- <Input placeholder="you@example.com" />
60
- </FormField>
109
+ ZORA props:
61
110
 
62
- <FormField label="Password">
63
- <Input secureTextEntry />
64
- </FormField>
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`. |
65
117
 
66
- <Button tone="primary">Sign in</Button>
67
- </Page>
68
- )
69
- }
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
+ />
70
136
  ```
71
137
 
72
- ---
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.
73
158
 
74
- ## What you get
159
+ </details>
75
160
 
76
- ### Core components
161
+ ### `Input`
77
162
 
78
- - Button
79
- - Input / Textarea
80
- - Card
81
- - Modal / Drawer
82
- - Badge
163
+ Text input wrapper with ZORA sizing and optional Surface icon specs.
83
164
 
84
- ### Patterns
165
+ ```tsx
166
+ <Input
167
+ autoCapitalize="none"
168
+ keyboardType="email-address"
169
+ leadingIcon={{ name: 'mail-outline' }}
170
+ placeholder="you@example.com"
171
+ />
172
+ ```
85
173
 
86
- - FormField
87
- - Panel
88
- - Notice
89
- - EmptyState
90
- - ConfirmDialog
91
- - SettingsRow
174
+ <details>
175
+ <summary>Props</summary>
92
176
 
93
- ### Layouts
177
+ ZORA props:
94
178
 
95
- - Page
96
- - PageHeader
97
- - PageSection
98
- - SidebarLayout
99
- - TopbarLayout
100
- - SettingsLayout
101
- - AuthLayout
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`. |
102
184
 
103
- ---
185
+ Inherited props:
104
186
 
105
- ## Philosophy
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`.
106
193
 
107
- ### 1. Opinionated by default
194
+ </details>
108
195
 
109
- ZORA reduces decision fatigue with strong defaults.
196
+ ### `Textarea`
110
197
 
111
- ### 2. Built on Surface
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
+ ```
112
203
 
113
- No duplicated logic — everything composes on `@ankhorage/surface`.
204
+ <details>
205
+ <summary>Props</summary>
114
206
 
115
- ### 3. Cross-platform first
207
+ ZORA props:
116
208
 
117
- Works with:
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`. |
118
214
 
119
- - React Native
120
- - Expo
121
- - React Native Web
215
+ Inherited props:
122
216
 
123
- ### 4. Composable
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`.
124
222
 
125
- You can always drop down to Surface if needed.
223
+ </details>
126
224
 
127
- ---
225
+ ### `Modal`
128
226
 
129
- ## What ZORA is NOT
227
+ Centered overlay shell with optional header, body, footer, and width preset.
130
228
 
131
- - ❌ Not a low-code system
132
- - ❌ Not a backend framework
133
- - ❌ Not a navigation/router solution
134
- - ❌ Not tied to a specific product
229
+ ```tsx
230
+ <Modal
231
+ footer={<Button>Done</Button>}
232
+ onDismiss={close}
233
+ title="Details"
234
+ visible={visible}
235
+ />
236
+ ```
135
237
 
136
- ---
238
+ <details>
239
+ <summary>Props</summary>
137
240
 
138
- ## Relationship to Studio
241
+ ZORA props:
139
242
 
140
- ZORA is designed to be used by Studio as a **design-system preset**, not as a hard dependency.
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. |
141
250
 
142
- Studio can:
251
+ Inherited props:
143
252
 
144
- - render Surface-based apps
145
- - render ZORA-based apps
146
- - switch between design systems
253
+ Picks these Surface `ModalProps`: `closeOnBackdrop`, `onDismiss`, `testID`, and
254
+ `visible`.
147
255
 
148
- ---
256
+ </details>
149
257
 
150
- ## Installation
258
+ ### `Drawer`
151
259
 
152
- ```bash
153
- bun add @ankhorage/zora @ankhorage/surface
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>
154
266
  ```
155
267
 
156
- ---
268
+ <details>
269
+ <summary>Props</summary>
157
270
 
158
- ## Expo example
271
+ ZORA props:
159
272
 
160
- There is a runnable Expo showcase app in [`examples/expo-showcase`](./examples/expo-showcase).
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. |
161
279
 
162
- The example uses the published package by default, so you can install and start it directly:
280
+ Inherited props:
163
281
 
164
- ```bash
165
- cd examples/expo-showcase
166
- npm install
167
- npm run start
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>
168
297
  ```
169
298
 
170
- Useful variants:
299
+ <details>
300
+ <summary>Props</summary>
171
301
 
172
- ```bash
173
- npm run ios
174
- npm run android
175
- npm run web
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>
176
561
  ```
177
562
 
178
- The showcase uses all current ZORA exports:
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.
179
639
 
180
- - core components
181
- - patterns
182
- - layouts
183
- - `ZoraProvider` with `createZoraTheme(...)`
640
+ </details>
184
641
 
185
- If you want the example to consume unpublished local repo changes instead, switch `@ankhorage/zora` in `examples/expo-showcase/package.json` back to `file:../..`, then run a root build before installing the example.
642
+ ### `EmptyState`
186
643
 
187
- ---
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
+ ```
188
880
 
189
- ## Status
881
+ The example imports `@ankhorage/zora` and demonstrates the package API in
882
+ `examples/expo-showcase/App.tsx`.
190
883
 
191
- - v0.0.2 – Bootstrap phase
884
+ ## Changelog
192
885
 
193
- ---
886
+ Version history is maintained in [CHANGELOG.md](./CHANGELOG.md).
194
887
 
195
888
  ## License
196
889
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "0.0.2",
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": {