@sableui/react 0.0.0-stage → 0.1.1

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 (247) hide show
  1. package/AGENTS.md +157 -0
  2. package/CHANGELOG.md +55 -0
  3. package/CONTRIBUTING.md +221 -0
  4. package/DESIGN.md +548 -0
  5. package/LICENSE +21 -0
  6. package/README.md +194 -2
  7. package/THIRD_PARTY_NOTICES.md +44 -0
  8. package/bin/sable-lint.mjs +0 -0
  9. package/bin/sable.mjs +1223 -0
  10. package/dist/_contract-CYScOdf5.d.ts +150 -0
  11. package/dist/chunk-3IWZYBGH.js +398 -0
  12. package/dist/chunk-5Z5KLOAU.js +167 -0
  13. package/dist/chunk-7MG4SHYX.js +15 -0
  14. package/dist/chunk-ADLLDWLW.js +15 -0
  15. package/dist/chunk-EP55KSYA.js +14 -0
  16. package/dist/chunk-J23ELQQZ.js +9396 -0
  17. package/dist/chunk-JI7WJP2L.js +286 -0
  18. package/dist/chunk-K7RUHUGC.js +14 -0
  19. package/dist/chunk-KO3NAEBF.js +15 -0
  20. package/dist/chunk-L4IEIQQA.js +14 -0
  21. package/dist/chunk-L6Y46C62.js +270 -0
  22. package/dist/chunk-NEQNXI2G.js +25 -0
  23. package/dist/chunk-PAOZBZME.js +40 -0
  24. package/dist/chunk-RWP4XBSK.js +139 -0
  25. package/dist/chunk-SRQWQUTW.js +63 -0
  26. package/dist/chunk-YXBOYWBN.js +15 -0
  27. package/dist/foundations/index.d.ts +88 -0
  28. package/dist/foundations/index.js +792 -0
  29. package/dist/icon/index.d.ts +60 -0
  30. package/dist/icon/index.js +2 -0
  31. package/dist/icon-sets/brands.d.ts +44 -0
  32. package/dist/icon-sets/brands.js +147 -0
  33. package/dist/icon-sets/reicon.d.ts +8 -0
  34. package/dist/icon-sets/reicon.js +1 -0
  35. package/dist/index.d.ts +7013 -0
  36. package/dist/index.js +15462 -0
  37. package/dist/ios/chrome.css +83 -0
  38. package/dist/ios/frame.css +5 -0
  39. package/dist/ios/index.d.ts +70 -0
  40. package/dist/ios/index.js +313 -0
  41. package/dist/ios/preview.d.ts +64 -0
  42. package/dist/ios/preview.js +133 -0
  43. package/dist/ios/styles.css +77 -0
  44. package/dist/layout/index.d.ts +280 -0
  45. package/dist/layout/index.js +2 -0
  46. package/dist/meta-6dUzgC6M.d.ts +205 -0
  47. package/dist/patterns/index.d.ts +36 -0
  48. package/dist/patterns/index.js +934 -0
  49. package/dist/presets/index.d.ts +37 -0
  50. package/dist/presets/index.js +117 -0
  51. package/dist/registry-CyL28OzJ.d.ts +28 -0
  52. package/dist/styles.css +1893 -0
  53. package/dist/theme-provider-BWcizhAt.d.ts +105 -0
  54. package/dist/themes/atelier/atelier.css +213 -0
  55. package/dist/themes/atelier/index.d.ts +9 -0
  56. package/dist/themes/atelier/index.js +1 -0
  57. package/dist/themes/base/base.css +443 -0
  58. package/dist/themes/base/index.d.ts +9 -0
  59. package/dist/themes/base/index.js +1 -0
  60. package/dist/themes/ember/ember.css +270 -0
  61. package/dist/themes/ember/index.d.ts +9 -0
  62. package/dist/themes/ember/index.js +1 -0
  63. package/dist/themes/index.d.ts +10 -0
  64. package/dist/themes/index.js +8 -0
  65. package/dist/themes/meridian/index.d.ts +9 -0
  66. package/dist/themes/meridian/index.js +1 -0
  67. package/dist/themes/meridian/meridian.css +255 -0
  68. package/dist/themes/poppy/index.d.ts +6 -0
  69. package/dist/themes/poppy/index.js +1 -0
  70. package/dist/themes/poppy/poppy.css +174 -0
  71. package/dist/themes/prism/index.d.ts +6 -0
  72. package/dist/themes/prism/index.js +1 -0
  73. package/dist/themes/prism/prism.css +183 -0
  74. package/dist/themes/verdant/index.d.ts +9 -0
  75. package/dist/themes/verdant/index.js +1 -0
  76. package/dist/themes/verdant/verdant.css +210 -0
  77. package/dist/themes.css +30 -0
  78. package/llms/components/accordion.md +93 -0
  79. package/llms/components/app-header.md +70 -0
  80. package/llms/components/app-shell.md +117 -0
  81. package/llms/components/attachment.md +105 -0
  82. package/llms/components/avatar.md +141 -0
  83. package/llms/components/badge.md +117 -0
  84. package/llms/components/banner.md +119 -0
  85. package/llms/components/bottom-nav.md +80 -0
  86. package/llms/components/breadcrumbs.md +75 -0
  87. package/llms/components/browser.md +67 -0
  88. package/llms/components/bubble.md +119 -0
  89. package/llms/components/button.md +199 -0
  90. package/llms/components/calendar.md +75 -0
  91. package/llms/components/card.md +135 -0
  92. package/llms/components/carousel.md +87 -0
  93. package/llms/components/chat-composer.md +126 -0
  94. package/llms/components/checkbox-card.md +98 -0
  95. package/llms/components/checkbox.md +90 -0
  96. package/llms/components/code-block.md +81 -0
  97. package/llms/components/code.md +62 -0
  98. package/llms/components/collapsible.md +83 -0
  99. package/llms/components/color-field.md +100 -0
  100. package/llms/components/combobox.md +119 -0
  101. package/llms/components/command-menu.md +158 -0
  102. package/llms/components/context-card.md +73 -0
  103. package/llms/components/context-menu.md +79 -0
  104. package/llms/components/data-table.md +99 -0
  105. package/llms/components/date-picker.md +97 -0
  106. package/llms/components/description.md +96 -0
  107. package/llms/components/destructive-action-modal.md +76 -0
  108. package/llms/components/dialog.md +127 -0
  109. package/llms/components/dots-menu.md +64 -0
  110. package/llms/components/empty-state.md +113 -0
  111. package/llms/components/entity.md +67 -0
  112. package/llms/components/feedback.md +63 -0
  113. package/llms/components/fieldset.md +106 -0
  114. package/llms/components/file-dropzone.md +103 -0
  115. package/llms/components/form.md +111 -0
  116. package/llms/components/gliding-highlight.md +84 -0
  117. package/llms/components/inline-status.md +62 -0
  118. package/llms/components/input.md +127 -0
  119. package/llms/components/kbd.md +57 -0
  120. package/llms/components/label.md +73 -0
  121. package/llms/components/marker.md +99 -0
  122. package/llms/components/marquee.md +66 -0
  123. package/llms/components/menu.md +122 -0
  124. package/llms/components/message-scroller.md +110 -0
  125. package/llms/components/message.md +114 -0
  126. package/llms/components/meter.md +124 -0
  127. package/llms/components/middle-truncate.md +62 -0
  128. package/llms/components/note.md +81 -0
  129. package/llms/components/notification-badge.md +67 -0
  130. package/llms/components/number-field.md +70 -0
  131. package/llms/components/otp-field.md +101 -0
  132. package/llms/components/page-header.md +76 -0
  133. package/llms/components/page-loader.md +67 -0
  134. package/llms/components/pagination.md +92 -0
  135. package/llms/components/panel-group.md +120 -0
  136. package/llms/components/panel-section.md +122 -0
  137. package/llms/components/phone.md +70 -0
  138. package/llms/components/pill.md +73 -0
  139. package/llms/components/popover.md +79 -0
  140. package/llms/components/progress.md +98 -0
  141. package/llms/components/radio-card.md +90 -0
  142. package/llms/components/radio.md +86 -0
  143. package/llms/components/relative-time.md +60 -0
  144. package/llms/components/scroller.md +88 -0
  145. package/llms/components/scrub-field.md +97 -0
  146. package/llms/components/search-input.md +84 -0
  147. package/llms/components/select.md +106 -0
  148. package/llms/components/separator.md +70 -0
  149. package/llms/components/settings-menu.md +139 -0
  150. package/llms/components/sheet.md +97 -0
  151. package/llms/components/show-more.md +59 -0
  152. package/llms/components/side-nav.md +106 -0
  153. package/llms/components/sidebar.md +87 -0
  154. package/llms/components/skeleton.md +62 -0
  155. package/llms/components/slider.md +114 -0
  156. package/llms/components/spinner.md +87 -0
  157. package/llms/components/status-bar.md +91 -0
  158. package/llms/components/status-dot.md +70 -0
  159. package/llms/components/stepper.md +125 -0
  160. package/llms/components/streaming-text.md +86 -0
  161. package/llms/components/switch.md +87 -0
  162. package/llms/components/table.md +112 -0
  163. package/llms/components/tabs.md +84 -0
  164. package/llms/components/textarea.md +88 -0
  165. package/llms/components/theme-selector.md +95 -0
  166. package/llms/components/theme-switcher.md +71 -0
  167. package/llms/components/thinking-orb.md +91 -0
  168. package/llms/components/toast.md +130 -0
  169. package/llms/components/toggle.md +95 -0
  170. package/llms/components/toolbar.md +168 -0
  171. package/llms/components/tooltip.md +93 -0
  172. package/llms/components/tree.md +227 -0
  173. package/llms/components/video.md +66 -0
  174. package/llms/components/workspace.md +138 -0
  175. package/llms/foundations/accessibility.md +60 -0
  176. package/llms/foundations/motion.md +96 -0
  177. package/llms/foundations/scrolling.md +41 -0
  178. package/llms/foundations/shape.md +73 -0
  179. package/llms/foundations/spacing.md +82 -0
  180. package/llms/foundations/surfaces.md +69 -0
  181. package/llms/foundations/typography.md +120 -0
  182. package/llms/layout/aspect-box.md +37 -0
  183. package/llms/layout/bleed.md +31 -0
  184. package/llms/layout/center.md +37 -0
  185. package/llms/layout/columns.md +51 -0
  186. package/llms/layout/grid-overlay.md +40 -0
  187. package/llms/layout/grid.md +47 -0
  188. package/llms/layout/page.md +39 -0
  189. package/llms/layout/region.md +49 -0
  190. package/llms/layout/row.md +40 -0
  191. package/llms/layout/safe-area.md +37 -0
  192. package/llms/layout/spacer.md +39 -0
  193. package/llms/layout/split-pane.md +41 -0
  194. package/llms/layout/stack.md +39 -0
  195. package/llms/patterns/auth-page.md +68 -0
  196. package/llms/patterns/brand-landing-page.md +423 -0
  197. package/llms/patterns/chat-panel.md +210 -0
  198. package/llms/patterns/dashboard-page.md +170 -0
  199. package/llms/patterns/feed-page.md +103 -0
  200. package/llms/patterns/landing-page.md +122 -0
  201. package/llms/patterns/list-detail-page.md +100 -0
  202. package/llms/patterns/settings-page.md +121 -0
  203. package/llms/reference/token-intent.md +324 -0
  204. package/llms/reference/utilities.md +129 -0
  205. package/llms/tasks/adding-a-component.md +113 -0
  206. package/llms/tasks/auditing-an-app.md +216 -0
  207. package/llms/tasks/building-a-page.md +109 -0
  208. package/llms/tasks/building-a-tool.md +141 -0
  209. package/llms/tasks/building-an-ios-prototype.md +105 -0
  210. package/llms/tasks/building-with-sable.md +73 -0
  211. package/llms/tasks/choosing-a-component.md +109 -0
  212. package/llms/tasks/converting-an-app.md +139 -0
  213. package/llms/tasks/creating-a-preset.md +43 -0
  214. package/llms/tasks/creating-design-assets.md +96 -0
  215. package/llms/tasks/designing-a-surface.md +115 -0
  216. package/llms/tasks/developing-taste.md +157 -0
  217. package/llms/tasks/getting-started.md +63 -0
  218. package/llms/tasks/learning-from-builds.md +74 -0
  219. package/llms/tasks/reviewing-a-design.md +114 -0
  220. package/llms/tasks/reviewing-a-journey.md +84 -0
  221. package/llms/tasks/reviewing-motion.md +92 -0
  222. package/llms/tasks/using-presets.md +87 -0
  223. package/llms/taste/asset-plan.template.json +53 -0
  224. package/llms/taste/composition-follows-content.md +20 -0
  225. package/llms/taste/hierarchy-is-a-relationship.md +22 -0
  226. package/llms/taste/lessons.json +57 -0
  227. package/llms/taste/motion-needs-a-reason.md +21 -0
  228. package/llms/taste/surface-states-travel-together.md +20 -0
  229. package/llms-full.txt +14906 -0
  230. package/llms.txt +405 -0
  231. package/package.json +185 -3
  232. package/registry.json +18812 -0
  233. package/scripts/agent-setup.mjs +54 -0
  234. package/scripts/design-atlas.mjs +221 -0
  235. package/scripts/design-directions.mjs +123 -0
  236. package/scripts/design-memory.mjs +166 -0
  237. package/scripts/design-preferences.mjs +227 -0
  238. package/scripts/design-presets.mjs +48 -0
  239. package/scripts/grade.mjs +509 -0
  240. package/scripts/lint-rules.mjs +1065 -0
  241. package/scripts/review-evidence.mjs +120 -0
  242. package/scripts/skeleton.mjs +248 -0
  243. package/skills/entry/SKILL.md +34 -0
  244. package/skills/sable/SKILL.md +187 -0
  245. package/skills/sable/agents/openai.yaml +6 -0
  246. package/targets/ios.json +982 -0
  247. package/third-party/reicon-LICENSE.txt +20 -0
@@ -0,0 +1,49 @@
1
+ # Region
2
+
3
+ **Status:** stable
4
+
5
+ The page region: fluid, edge-to-edge with the fluid page inset (--page-inset). Opt-in centered max cap picked by ROLE (prose/form/feed/content/wide/full), never a global page max-width. The root of nearly every route.
6
+
7
+ **Keywords:** region, page width, container, layout
8
+
9
+ ## Usage
10
+
11
+ Use Region as the page-width primitive that applies fluid page inset and an optional purpose-named max width.
12
+
13
+ ### Best practices
14
+
15
+ - Do: Choose the max value by content role, such as prose, form, feed, content, wide, or full.
16
+ - Do: Use Region near the route or section boundary so inner layout stays intentional.
17
+ - Don't: Do not use Region as a global wrapper that forces every page into the same max width.
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | as | ElementType | "div" | Semantic element to render (e.g. "main", "section", "nav"). |
24
+ | inset | boolean | true | Apply the fluid horizontal page inset (--page-inset). |
25
+ | max | "prose" \| "form" \| "feed" \| "content" \| "wide" \| "full" \| CSS length | — | Opt-in centered max-width cap, purpose-named: prose 65ch (long-form reading) · form 480px (auth, narrow single-column forms) · feed 640px (single-column timeline) · content 896px (settings/admin panes) · wide 1280px (dashboards, tables, card grids) · full 1536px (full-bleed ceiling). Omit for fully fluid. |
26
+ | bleed | boolean | false | Full-bleed: edge to edge with no inset. Overrides inset. |
27
+ | safeArea | boolean \| ("top"\|"bottom"\|"left"\|"right")[] | false | env(safe-area-inset-*) padding for fixed or native-shell surfaces. true pads top+bottom; pass an edge array to target edges. |
28
+
29
+ ## Related
30
+
31
+ - Components: Page, Grid, Columns
32
+
33
+ ## Examples
34
+
35
+ ### Settings pane
36
+
37
+ ```tsx
38
+ import { PageHeader, Region } from "@sableui/react"
39
+
40
+ <Region as="main" max="content"><PageHeader title="Settings" /></Region>
41
+ ```
42
+
43
+ ### Fluid dashboard region
44
+
45
+ ```tsx
46
+ import { Card, CardHeader, CardTitle, Grid, Region } from "@sableui/react"
47
+
48
+ <Region max="wide"><Grid minItemWidth="16rem"><Card><CardHeader><CardTitle>Revenue</CardTitle></CardHeader></Card><Card><CardHeader><CardTitle>Collects</CardTitle></CardHeader></Card></Grid></Region>
49
+ ```
@@ -0,0 +1,40 @@
1
+ # Row
2
+
3
+ **Status:** stable
4
+
5
+ Horizontal flex flow — inline rows of controls, toolbars, action clusters. Defaults to center-aligned, no wrap.
6
+
7
+ **Keywords:** row, toolbar, horizontal, layout
8
+
9
+ ## Usage
10
+
11
+ Use Row for horizontal clusters such as action groups, toolbars, metadata, and inline controls.
12
+
13
+ ### Best practices
14
+
15
+ - Do: Use wrap when controls may not fit on smaller screens.
16
+ - Do: Use justify and align intentionally so clusters scan as one unit.
17
+ - Don't: Do not use Row for navigation menus or dense tabular structure.
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | gap | number \| string | 2 | Horizontal gap. Number = rhythm units (×8px); string = raw CSS. |
24
+ | align | "start" \| "center" \| "end" \| "stretch" | "center" | Cross-axis alignment. |
25
+ | justify | "start" \| "center" \| "end" \| "between" | "start" | Main-axis distribution. |
26
+ | wrap | boolean | false | Allow items to wrap. |
27
+
28
+ ## Related
29
+
30
+ - Components: Stack, Button, Spacer
31
+
32
+ ## Examples
33
+
34
+ ### Action cluster
35
+
36
+ ```tsx
37
+ import { Button, Row } from "@sableui/react"
38
+
39
+ <Row gap={2} justify="end"><Button variant="ghost">Cancel</Button><Button>Save changes</Button></Row>
40
+ ```
@@ -0,0 +1,37 @@
1
+ # SafeArea
2
+
3
+ **Status:** stable
4
+
5
+ Pads for device safe-areas (notch, home indicator) on fixed or native-shell surfaces. Wrap fixed bars; content in normal flow rarely needs it.
6
+
7
+ **Keywords:** safe area, notch, home indicator, fixed chrome
8
+
9
+ ## Usage
10
+
11
+ Use SafeArea to pad fixed or native-shell surfaces away from device notches and home indicators.
12
+
13
+ ### Best practices
14
+
15
+ - Do: Use it around fixed headers, bottom bars, and native-shell surfaces.
16
+ - Do: Target only the edges that need device inset padding when possible.
17
+ - Don't: Do not wrap normal document-flow content in SafeArea unless it actually touches unsafe edges.
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | edges | ("top" \| "bottom" \| "left" \| "right")[] | all four | Which edges get env(safe-area-inset-*) padding. |
24
+
25
+ ## Related
26
+
27
+ - Components: BottomNav, AppHeader, AppShell
28
+
29
+ ## Examples
30
+
31
+ ### Fixed bottom bar
32
+
33
+ ```tsx
34
+ import { Button, Row, SafeArea } from "@sableui/react"
35
+
36
+ <SafeArea edges={["bottom"]} className="fixed inset-x-0 bottom-0 bg-card border-t border-border"><Row gap={2} justify="between" className="p-3"><span className="text-label-md">1 item selected</span><Button size="sm">Continue</Button></Row></SafeArea>
37
+ ```
@@ -0,0 +1,39 @@
1
+ # Spacer
2
+
3
+ **Status:** stable
4
+
5
+ Explicit space on the rhythm, or a flexible grow pusher between siblings (e.g. pushing a footer item to the end of a Row).
6
+
7
+ **Keywords:** spacer, spacing, grow, layout
8
+
9
+ ## Usage
10
+
11
+ Use Spacer for explicit rhythm space or a flex grow pusher between siblings.
12
+
13
+ ### Best practices
14
+
15
+ - Do: Use grow inside Row when one side of a cluster should push to the far edge.
16
+ - Do: Use fixed size only when the space has semantic rhythm value.
17
+ - Don't: Do not use Spacer to patch broad layout problems that should be solved by Stack, Row, Grid, or Region.
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | size | number | 1 | Fixed size in rhythm units (×8px; fractions ok). Ignored when grow. |
24
+ | axis | "vertical" \| "horizontal" | "vertical" | Axis the fixed size applies to. |
25
+ | grow | boolean | — | Flex-grow to push siblings apart (fills available space). |
26
+
27
+ ## Related
28
+
29
+ - Components: Row, Stack
30
+
31
+ ## Examples
32
+
33
+ ### Push actions to the end
34
+
35
+ ```tsx
36
+ import { Button, Row, Spacer } from "@sableui/react"
37
+
38
+ <Row><span className="text-title-sm">Members</span><Spacer grow /><Button size="sm">Invite</Button></Row>
39
+ ```
@@ -0,0 +1,41 @@
1
+ # SplitPane
2
+
3
+ **Status:** stable
4
+
5
+ Responsive two-pane layout: side-by-side at/above a breakpoint, stacked (primary first) below. List-detail, media + metadata.
6
+
7
+ **Keywords:** split pane, two pane, list detail, responsive
8
+
9
+ ## Usage
10
+
11
+ Use SplitPane for responsive two-pane layouts where a primary pane and supporting pane stay conceptually linked.
12
+
13
+ ### Best practices
14
+
15
+ - Do: Use it for media-detail, list-detail, or editor-preview workflows.
16
+ - Do: Pick a ratio that reflects the actual priority of the panes.
17
+ - Don't: Do not use SplitPane for unrelated columns or uniform grids.
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | primary | ReactNode | — | The leading / larger pane (e.g. the media column). |
24
+ | secondary | ReactNode | — | The trailing / supporting pane (e.g. the detail column). |
25
+ | collapseBelow | "sm" \| "md" \| "lg" \| "xl" | "lg" | Breakpoint at/above which panes sit side by side. |
26
+ | ratio | string | "1/1" | Primary:secondary width ratio as "a/b" fr units (e.g. "2/1"). |
27
+ | gap | number \| string | var(--grid-gutter) | Gap between panes. |
28
+
29
+ ## Related
30
+
31
+ - Components: Columns, Grid, Sheet
32
+
33
+ ## Examples
34
+
35
+ ### Media + detail
36
+
37
+ ```tsx
38
+ import { AspectBox, Button, SplitPane, Stack } from "@sableui/react"
39
+
40
+ <SplitPane ratio="2/1" primary={<AspectBox ratio={1}><img src={post.imageUrl} alt={post.title} className="size-full object-cover" /></AspectBox>} secondary={<Stack gap={2}><h1 className="text-heading-1">{post.title}</h1><p className="text-body-md text-muted-foreground">{post.description}</p><Button>Collect</Button></Stack>} />
41
+ ```
@@ -0,0 +1,39 @@
1
+ # Stack
2
+
3
+ **Status:** stable
4
+
5
+ Vertical flow on the 8px rhythm — the default container for stacked content. Gap by role: tight within a group (1.5–2), looser between groups (3–4), generous between sections (6+).
6
+
7
+ **Keywords:** stack, vertical rhythm, layout, spacing
8
+
9
+ ## Usage
10
+
11
+ Use Stack for vertical flow where child spacing should follow the Sable rhythm scale.
12
+
13
+ ### Best practices
14
+
15
+ - Do: Use smaller gaps within a group and larger gaps between sections.
16
+ - Do: Use Stack instead of ad hoc margins when siblings form a vertical composition.
17
+ - Don't: Do not use Stack to create page width or grid structure; pair it with Region, Grid, or Columns.
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | gap | number \| string | 2 | Vertical gap. Number = rhythm units (×8px, fractions ok — 2 = 16px); string = raw CSS. |
24
+ | align | "start" \| "center" \| "end" \| "stretch" | "stretch" | Cross-axis alignment. |
25
+ | justify | "start" \| "center" \| "end" \| "between" | "start" | Main-axis distribution. |
26
+
27
+ ## Related
28
+
29
+ - Components: Row, Page, Fieldset
30
+
31
+ ## Examples
32
+
33
+ ### Form field group
34
+
35
+ ```tsx
36
+ import { Field, Input, Stack, Textarea } from "@sableui/react"
37
+
38
+ <Stack gap={2}><Field label="Display name"><Input name="name" /></Field><Field label="Bio"><Textarea name="bio" /></Field></Stack>
39
+ ```
@@ -0,0 +1,68 @@
1
+ # AuthPage
2
+
3
+ Centered auth card: a form-width region vertically centered in the viewport, one Card holding the Form, an alternate-action divider, and a quiet switch-to-sign-up link beneath it.
4
+
5
+ **Intent:** Reach for this for sign-in, sign-up, forgot-password, and any single-purpose one-column form route (invite accept, unsubscribe). Not for multi-section forms (use SettingsPage).
6
+
7
+ ## Notes
8
+
9
+ - Region cap is `form` (480px) — the narrowest named cap; auth never needs more.
10
+ - The card is the only surface on the page: no app chrome, no sidebar — minimal exit paths.
11
+ - min-h-dvh + grid place-items-center centers the card without magic offsets.
12
+ - Field handles label/error wiring; the submit button is full-width — the primary (and only) action.
13
+ - Secondary actions (here, switch to sign-up; add forgot password the same way) are quiet `link-underline` links, never competing buttons.
14
+
15
+ ## Accessibility
16
+
17
+ - The route renders inside <main> with the page h1 in the card header (an h1 inside CardTitle, which carries the type).
18
+ - Field auto-wires labels, describedby, and invalid state onto the inputs.
19
+ - Autocomplete attributes (email, current-password) keep password managers working.
20
+
21
+ ## Source
22
+
23
+ ```tsx
24
+ import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Field, Form, Input, Region, Separator, Stack } from "@sableui/react"
25
+
26
+ export function AuthPage() {
27
+ return (
28
+ <main className="grid min-h-dvh place-items-center bg-background">
29
+ <Region max="form" safeArea={["top", "bottom"]}>
30
+ <Stack gap={3}>
31
+ <Card>
32
+ <CardHeader>
33
+ {/* CardTitle carries the type; the h1 inside it is the page heading. */}
34
+ <CardTitle>
35
+ <h1>Sign in</h1>
36
+ </CardTitle>
37
+ <CardDescription>Welcome back — pick up where you left off.</CardDescription>
38
+ </CardHeader>
39
+ <CardContent>
40
+ <Form onSubmit={(event) => event.preventDefault()}>
41
+ <Field label="Email" required>
42
+ <Input type="email" name="email" autoComplete="email" placeholder="you@example.com" />
43
+ </Field>
44
+ <Field label="Password" required>
45
+ <Input type="password" name="password" autoComplete="current-password" />
46
+ </Field>
47
+ <Button type="submit" className="w-full">
48
+ Sign in
49
+ </Button>
50
+ <Separator label="or" />
51
+ <Button variant="outline" className="w-full">
52
+ Continue with wallet
53
+ </Button>
54
+ </Form>
55
+ </CardContent>
56
+ </Card>
57
+ <p className="text-center text-body-sm text-muted-foreground">
58
+ No account?{" "}
59
+ <a href="/signup" className="link-underline motion-interactive text-foreground">
60
+ Create one
61
+ </a>
62
+ </p>
63
+ </Stack>
64
+ </Region>
65
+ </main>
66
+ )
67
+ }
68
+ ```