ionbase-ui 0.51.0 → 0.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/components/Accordion.d.ts +54 -0
  2. package/dist/components/Accordion.d.ts.map +1 -0
  3. package/dist/components/Accordion.js +68 -0
  4. package/dist/components/Accordion.js.map +1 -0
  5. package/dist/components/AgentActivity.d.ts +2 -1
  6. package/dist/components/AgentActivity.d.ts.map +1 -1
  7. package/dist/components/AgentActivity.js +4 -17
  8. package/dist/components/AgentActivity.js.map +1 -1
  9. package/dist/components/Breadcrumb.d.ts +45 -0
  10. package/dist/components/Breadcrumb.d.ts.map +1 -0
  11. package/dist/components/Breadcrumb.js +31 -0
  12. package/dist/components/Breadcrumb.js.map +1 -0
  13. package/dist/components/Calendar.d.ts +20 -0
  14. package/dist/components/Calendar.d.ts.map +1 -0
  15. package/dist/components/Calendar.js +151 -0
  16. package/dist/components/Calendar.js.map +1 -0
  17. package/dist/components/CalendarPopover.d.ts +26 -0
  18. package/dist/components/CalendarPopover.d.ts.map +1 -0
  19. package/dist/components/CalendarPopover.js +45 -0
  20. package/dist/components/CalendarPopover.js.map +1 -0
  21. package/dist/components/Checkbox.d.ts +2 -1
  22. package/dist/components/Checkbox.d.ts.map +1 -1
  23. package/dist/components/Checkbox.js +4 -2
  24. package/dist/components/Checkbox.js.map +1 -1
  25. package/dist/components/Combobox.d.ts +86 -0
  26. package/dist/components/Combobox.d.ts.map +1 -0
  27. package/dist/components/Combobox.js +261 -0
  28. package/dist/components/Combobox.js.map +1 -0
  29. package/dist/components/DateField.d.ts +15 -0
  30. package/dist/components/DateField.d.ts.map +1 -0
  31. package/dist/components/DateField.js +74 -0
  32. package/dist/components/DateField.js.map +1 -0
  33. package/dist/components/DatePicker.d.ts +81 -0
  34. package/dist/components/DatePicker.d.ts.map +1 -0
  35. package/dist/components/DatePicker.js +102 -0
  36. package/dist/components/DatePicker.js.map +1 -0
  37. package/dist/components/DateRangePicker.d.ts +117 -0
  38. package/dist/components/DateRangePicker.d.ts.map +1 -0
  39. package/dist/components/DateRangePicker.js +152 -0
  40. package/dist/components/DateRangePicker.js.map +1 -0
  41. package/dist/components/Drawer.d.ts +52 -0
  42. package/dist/components/Drawer.d.ts.map +1 -0
  43. package/dist/components/Drawer.js +66 -0
  44. package/dist/components/Drawer.js.map +1 -0
  45. package/dist/components/FileUpload.d.ts +79 -0
  46. package/dist/components/FileUpload.d.ts.map +1 -0
  47. package/dist/components/FileUpload.js +218 -0
  48. package/dist/components/FileUpload.js.map +1 -0
  49. package/dist/components/Header.d.ts +10 -0
  50. package/dist/components/Header.d.ts.map +1 -1
  51. package/dist/components/Header.js +18 -3
  52. package/dist/components/Header.js.map +1 -1
  53. package/dist/components/NumberInput.d.ts +63 -0
  54. package/dist/components/NumberInput.d.ts.map +1 -0
  55. package/dist/components/NumberInput.js +102 -0
  56. package/dist/components/NumberInput.js.map +1 -0
  57. package/dist/components/ProgressBar.d.ts +46 -0
  58. package/dist/components/ProgressBar.d.ts.map +1 -0
  59. package/dist/components/ProgressBar.js +52 -0
  60. package/dist/components/ProgressBar.js.map +1 -0
  61. package/dist/components/PromptInput.d.ts +89 -0
  62. package/dist/components/PromptInput.d.ts.map +1 -0
  63. package/dist/components/PromptInput.js +130 -0
  64. package/dist/components/PromptInput.js.map +1 -0
  65. package/dist/components/SegmentedControl.d.ts +63 -0
  66. package/dist/components/SegmentedControl.d.ts.map +1 -0
  67. package/dist/components/SegmentedControl.js +79 -0
  68. package/dist/components/SegmentedControl.js.map +1 -0
  69. package/dist/components/Select.d.ts +9 -2
  70. package/dist/components/Select.d.ts.map +1 -1
  71. package/dist/components/Select.js.map +1 -1
  72. package/dist/components/Sidebar.d.ts +109 -0
  73. package/dist/components/Sidebar.d.ts.map +1 -0
  74. package/dist/components/Sidebar.js +106 -0
  75. package/dist/components/Sidebar.js.map +1 -0
  76. package/dist/components/Skeleton.d.ts +39 -0
  77. package/dist/components/Skeleton.d.ts.map +1 -0
  78. package/dist/components/Skeleton.js +50 -0
  79. package/dist/components/Skeleton.js.map +1 -0
  80. package/dist/components/Spinner.d.ts +45 -0
  81. package/dist/components/Spinner.d.ts.map +1 -0
  82. package/dist/components/Spinner.js +44 -0
  83. package/dist/components/Spinner.js.map +1 -0
  84. package/dist/components/Stepper.d.ts +73 -0
  85. package/dist/components/Stepper.d.ts.map +1 -0
  86. package/dist/components/Stepper.js +82 -0
  87. package/dist/components/Stepper.js.map +1 -0
  88. package/dist/components/Toggle.d.ts +2 -1
  89. package/dist/components/Toggle.d.ts.map +1 -1
  90. package/dist/components/Toggle.js +4 -2
  91. package/dist/components/Toggle.js.map +1 -1
  92. package/dist/components/ToolCall.d.ts +66 -0
  93. package/dist/components/ToolCall.d.ts.map +1 -0
  94. package/dist/components/ToolCall.js +78 -0
  95. package/dist/components/ToolCall.js.map +1 -0
  96. package/dist/components/agent-status.d.ts +14 -0
  97. package/dist/components/agent-status.d.ts.map +1 -0
  98. package/dist/components/agent-status.js +16 -0
  99. package/dist/components/agent-status.js.map +1 -0
  100. package/dist/components/index.d.ts +33 -0
  101. package/dist/components/index.d.ts.map +1 -1
  102. package/dist/components/index.js +16 -0
  103. package/dist/components/index.js.map +1 -1
  104. package/dist/components/iso-date.d.ts +53 -0
  105. package/dist/components/iso-date.d.ts.map +1 -0
  106. package/dist/components/iso-date.js +102 -0
  107. package/dist/components/iso-date.js.map +1 -0
  108. package/dist/components/resolve-selection.d.ts +36 -0
  109. package/dist/components/resolve-selection.d.ts.map +1 -0
  110. package/dist/components/resolve-selection.js +14 -0
  111. package/dist/components/resolve-selection.js.map +1 -0
  112. package/dist/figma-descriptions.json +255 -145
  113. package/dist/figma-map.json +3205 -1860
  114. package/dist/meta/Accordion.json +123 -0
  115. package/dist/meta/AccordionItem.json +90 -0
  116. package/dist/meta/AgentActivityStep.json +2 -2
  117. package/dist/meta/Breadcrumb.json +87 -0
  118. package/dist/meta/BreadcrumbItem.json +78 -0
  119. package/dist/meta/Checkbox.json +18 -1
  120. package/dist/meta/Combobox.json +265 -0
  121. package/dist/meta/DatePicker.json +270 -0
  122. package/dist/meta/DateRangePicker.json +284 -0
  123. package/dist/meta/Drawer.json +234 -0
  124. package/dist/meta/EmptyState.json +1 -1
  125. package/dist/meta/FileUpload.json +246 -0
  126. package/dist/meta/Header.json +32 -2
  127. package/dist/meta/NumberInput.json +407 -0
  128. package/dist/meta/PhoneInput.json +39 -39
  129. package/dist/meta/Popover.json +3 -3
  130. package/dist/meta/ProgressBar.json +166 -0
  131. package/dist/meta/PromptInput.json +212 -0
  132. package/dist/meta/SegmentedControl.json +217 -0
  133. package/dist/meta/SegmentedControlItem.json +122 -0
  134. package/dist/meta/Select.json +4 -3
  135. package/dist/meta/Sidebar.json +150 -0
  136. package/dist/meta/SidebarItem.json +184 -0
  137. package/dist/meta/SidebarSection.json +131 -0
  138. package/dist/meta/Skeleton.json +120 -0
  139. package/dist/meta/Spinner.json +123 -0
  140. package/dist/meta/Stepper.json +135 -0
  141. package/dist/meta/StepperStep.json +148 -0
  142. package/dist/meta/Tabs.json +5 -0
  143. package/dist/meta/Toggle.json +18 -1
  144. package/dist/meta/ToolCall.json +192 -0
  145. package/dist/meta/Tooltip.json +3 -3
  146. package/dist/meta/components.json +6759 -2705
  147. package/dist/meta/contrast.json +11075 -3098
  148. package/dist/meta/index.json +266 -8
  149. package/dist/meta/patterns/AgentRun.json +27 -0
  150. package/dist/meta/patterns/Form.json +9 -0
  151. package/dist/meta/patterns/PageShell.json +43 -3
  152. package/dist/meta/patterns/Wizard.json +20 -1
  153. package/dist/meta/patterns/index.json +10 -1
  154. package/dist/styles/accordion.css +102 -0
  155. package/dist/styles/breadcrumb.css +72 -0
  156. package/dist/styles/combobox.css +154 -0
  157. package/dist/styles/date-picker.css +420 -0
  158. package/dist/styles/date-range-picker.css +280 -0
  159. package/dist/styles/drawer.css +181 -0
  160. package/dist/styles/empty-state.css +16 -4
  161. package/dist/styles/file-upload.css +236 -0
  162. package/dist/styles/header.css +26 -0
  163. package/dist/styles/index.css +23 -0
  164. package/dist/styles/number-input.css +83 -0
  165. package/dist/styles/progress-bar.css +107 -0
  166. package/dist/styles/prompt-input.css +127 -0
  167. package/dist/styles/segmented-control.css +182 -0
  168. package/dist/styles/sidebar.css +307 -0
  169. package/dist/styles/skeleton.css +76 -0
  170. package/dist/styles/spinner.css +70 -0
  171. package/dist/styles/stepper.css +250 -0
  172. package/dist/styles/tool-call.css +202 -0
  173. package/llms.txt +2 -2
  174. package/package.json +2 -1
@@ -0,0 +1,122 @@
1
+ {
2
+ "name": "SegmentedControlItem",
3
+ "source": "src/components/SegmentedControl.tsx",
4
+ "propsType": "SegmentedControlItemProps",
5
+ "import": "import { SegmentedControlItem } from 'ionbase-ui';",
6
+ "status": "stable",
7
+ "summary": "One segment: a radio drawn as part of the track, with an optional icon.",
8
+ "useWhen": [
9
+ "inside a SegmentedControl, once per option"
10
+ ],
11
+ "useInstead": [
12
+ {
13
+ "when": "outside a segmented track",
14
+ "use": "Radio"
15
+ }
16
+ ],
17
+ "slots": {
18
+ "children": {
19
+ "accepts": "text",
20
+ "note": "one or two words. Segments do not wrap, and a long label truncates"
21
+ },
22
+ "icon": {
23
+ "accepts": "Icon",
24
+ "note": "decorative beside a label; with no label, pass aria-label"
25
+ }
26
+ },
27
+ "a11y": {
28
+ "requires": [
29
+ "`aria-label` when the segment has an icon and no text — the accessible name otherwise comes from its children"
30
+ ]
31
+ },
32
+ "antiPatterns": [
33
+ {
34
+ "dont": "using it outside SegmentedControl",
35
+ "why": "it reads its selection state from the group, and throws without one"
36
+ }
37
+ ],
38
+ "stylesheet": "src/styles/segmented-control.css",
39
+ "tokens": [
40
+ "--border-width-thick",
41
+ "--font-family-sans",
42
+ "--font-weight-medium",
43
+ "--icon-size-md",
44
+ "--icon-size-sm",
45
+ "--ion-duration-base",
46
+ "--ion-ease-out",
47
+ "--ion-segmented-font-size",
48
+ "--ion-segmented-icon-size",
49
+ "--ion-segmented-item-gap",
50
+ "--ion-segmented-item-height",
51
+ "--ion-segmented-item-padding-x",
52
+ "--ion-segmented-line-height",
53
+ "--radius-lg",
54
+ "--radius-md",
55
+ "--ring-focus",
56
+ "--spacing-12",
57
+ "--spacing-16",
58
+ "--spacing-2",
59
+ "--spacing-20",
60
+ "--spacing-24",
61
+ "--spacing-32",
62
+ "--spacing-4",
63
+ "--spacing-40",
64
+ "--spacing-6",
65
+ "--spacing-8",
66
+ "--surface-default",
67
+ "--surface-hover",
68
+ "--surface-muted",
69
+ "--surface-page",
70
+ "--text-default",
71
+ "--text-disabled",
72
+ "--text-tertiary",
73
+ "--type-body",
74
+ "--type-body-lg",
75
+ "--type-body-lg-line-height",
76
+ "--type-body-line-height",
77
+ "--type-body-sm",
78
+ "--type-body-sm-line-height"
79
+ ],
80
+ "props": {
81
+ "value": {
82
+ "type": "string",
83
+ "required": true,
84
+ "origin": "own",
85
+ "description": "The value this segment selects."
86
+ },
87
+ "icon": {
88
+ "type": "React.ReactNode",
89
+ "required": false,
90
+ "origin": "own",
91
+ "description": "Icon before the label. `aria-hidden` is applied for you."
92
+ },
93
+ "aria-label": {
94
+ "type": "string | undefined",
95
+ "required": false,
96
+ "origin": "own",
97
+ "description": "Required when the segment has no visible text — an icon-only segment is\notherwise announced as an unnamed radio button."
98
+ },
99
+ "isDisabled": {
100
+ "type": "boolean | undefined",
101
+ "required": false,
102
+ "origin": "own",
103
+ "default": false
104
+ },
105
+ "children": {
106
+ "type": "React.ReactNode",
107
+ "required": false,
108
+ "origin": "own"
109
+ },
110
+ "className": {
111
+ "type": "string | undefined",
112
+ "required": false,
113
+ "origin": "own"
114
+ }
115
+ },
116
+ "propCounts": {
117
+ "own": 6,
118
+ "aria": 0,
119
+ "dom": 0,
120
+ "other": 0
121
+ }
122
+ }
@@ -13,7 +13,8 @@
13
13
  "useInstead": [
14
14
  {
15
15
  "when": "the list is long enough to need search or type-ahead beyond the native behaviour",
16
- "use": "a combobox — not yet in this system"
16
+ "use": "Combobox",
17
+ "why": "a native <select> list is the browser's, and cannot be filtered"
17
18
  },
18
19
  {
19
20
  "when": "the rows need icons, avatars or two lines of text",
@@ -126,10 +127,10 @@
126
127
  "default": "md"
127
128
  },
128
129
  "options": {
129
- "type": "SelectOption[] | undefined",
130
+ "type": "readonly SelectOption[] | undefined",
130
131
  "required": false,
131
132
  "origin": "own",
132
- "description": "The options to render. Omit and pass `children` for grouped options."
133
+ "description": "The options to render. Omit and pass `children` for grouped options.\n\n`readonly` because an options list is almost always a module-level constant,\nand `as const` on one produces a readonly array that a mutable parameter\nrejects. The component only ever maps over it, so demanding a mutable array\nbought nothing and cost callers a spread or a cast."
133
134
  },
134
135
  "placeholder": {
135
136
  "type": "string | undefined",
@@ -0,0 +1,150 @@
1
+ {
2
+ "name": "Sidebar",
3
+ "source": "src/components/Sidebar.tsx",
4
+ "propsType": "SidebarProps",
5
+ "description": "Sidebar — an application's navigation, as a column.\n\nDISCLOSURE NAVIGATION, NOT `role=\"tree\"`\n\nA file-tree look invites the tree role, and the tree role is wrong here.\nA treeview takes the arrow keys, allows one tab stop for the whole widget,\nand does not permit interactive content inside an item — so the `…` and `+`\nbuttons on a row, which are half the point of a workspace sidebar, could not\nexist in it. This is the WAI-ARIA disclosure navigation pattern instead:\nnested lists of links, each expandable level behind a real button with\n`aria-expanded`, and everything reachable with Tab.\n\nAN ITEM THAT IS A LINK AND HAS CHILDREN GETS TWO CONTROLS\n\nA button cannot sit inside a link. So a row that navigates AND expands\nrenders the link and a separate chevron button beside it; a row with no\n`href` is one button that expands. The actions slot is a sibling of both,\nnever nested inside either.\n\nTHE CURRENT PAGE IS NEVER FOLDED AWAY\n\nAn item whose subtree contains the current page starts open. A sidebar that\nloads with the user's location collapsed inside a closed group tells a\nsighted user nothing and a screen-reader user less.\n\nExpansion is per item, controlled or not. Remembering it across visits is the\ncaller's job — this component cannot know where that state should live.",
6
+ "import": "import { Sidebar } from 'ionbase-ui';",
7
+ "status": "stable",
8
+ "summary": "An application's navigation as a column: pinned header and footer that take any component, a scrolling body of titled, collapsible sections, and nested items that expand.",
9
+ "useWhen": [
10
+ "an app has more destinations than fit in a header — workspaces, projects, saved views",
11
+ "the navigation is hierarchical and users need to see where they are inside it",
12
+ "rows need their own actions — create inside this space, rename, favourite"
13
+ ],
14
+ "useInstead": [
15
+ {
16
+ "when": "there are five or fewer top-level destinations and no hierarchy",
17
+ "use": "Header",
18
+ "why": "a sidebar spends a column of width on what a header row carries in its height"
19
+ },
20
+ {
21
+ "when": "the hierarchy describes the current page's position rather than offering destinations",
22
+ "use": "Breadcrumb"
23
+ },
24
+ {
25
+ "when": "sections of content collapse, not destinations",
26
+ "use": "Accordion",
27
+ "why": "Accordion's headings belong to the document outline; a sidebar is a navigation landmark"
28
+ }
29
+ ],
30
+ "composition": {
31
+ "order": [
32
+ "Sidebar",
33
+ "SidebarSection",
34
+ "SidebarItem"
35
+ ],
36
+ "note": "Items always go inside a section, because a section renders the list. Anything that is not an item — a Divider, a promotional Alert — goes directly in Sidebar between sections, or in `header` / `footer`. On narrow screens, put the Sidebar inside a Drawer; it does not collapse itself.",
37
+ "example": "<Sidebar label=\"Workspace\" header={<WorkspaceMenu />} footer={<Button>Invite</Button>}><SidebarSection><SidebarItem label=\"Home\" href=\"/\" isCurrent /></SidebarSection><Divider /><SidebarSection title=\"Spaces\" isCollapsible><SidebarItem label=\"Team Space\" href=\"/team\"><SidebarItem label=\"Projects\" href=\"/team/projects\" /></SidebarItem></SidebarSection></Sidebar>"
38
+ },
39
+ "slots": {
40
+ "header": {
41
+ "accepts": "Menu",
42
+ "note": "pinned above the scroll — a workspace switcher, search, icon Buttons"
43
+ },
44
+ "footer": {
45
+ "accepts": "Button",
46
+ "note": "pinned below the scroll — Invite, Help, a trial notice in an Alert"
47
+ },
48
+ "children": {
49
+ "accepts": "SidebarSection",
50
+ "note": "and Divider or other non-item content between sections"
51
+ }
52
+ },
53
+ "a11y": {
54
+ "role": "navigation",
55
+ "requires": [
56
+ "`label` — the accessible name of the navigation landmark. Pages with a sidebar usually have a second nav, and two unnamed ones cannot be told apart"
57
+ ],
58
+ "guarantees": [
59
+ "only the body scrolls; the header and footer stay reachable at any scroll position"
60
+ ],
61
+ "notes": [
62
+ "it is disclosure navigation, not a treeview: everything is reachable with Tab, and rows can hold buttons. The tree role forbids interactive content inside items and would have ruled out row actions"
63
+ ]
64
+ },
65
+ "antiPatterns": [
66
+ {
67
+ "dont": "role=\"tree\" on a sidebar with row actions",
68
+ "why": "a treeview item cannot contain buttons, and its arrow-key model hides every action from Tab"
69
+ },
70
+ {
71
+ "dont": "a SidebarItem placed directly in Sidebar, outside a section",
72
+ "do": "wrap it in an untitled <SidebarSection>",
73
+ "why": "the item renders an <li>, which is only valid inside the list a section provides"
74
+ },
75
+ {
76
+ "dont": "a sidebar that is only ever a hamburger menu on desktop",
77
+ "why": "hierarchical navigation that is hidden by default is navigation nobody uses; hide it only where the width forces it"
78
+ }
79
+ ],
80
+ "stylesheet": "src/styles/sidebar.css",
81
+ "tokens": [
82
+ "--border-focus",
83
+ "--border-subtle",
84
+ "--border-width-default",
85
+ "--border-width-thick",
86
+ "--font-family-sans",
87
+ "--font-weight-medium",
88
+ "--icon-disabled",
89
+ "--icon-primary",
90
+ "--icon-secondary",
91
+ "--icon-size-sm",
92
+ "--icon-tertiary",
93
+ "--ion-duration-base",
94
+ "--ion-ease-out",
95
+ "--radius-md",
96
+ "--radius-sm",
97
+ "--radius-xs",
98
+ "--spacing-12",
99
+ "--spacing-16",
100
+ "--spacing-2",
101
+ "--spacing-24",
102
+ "--spacing-32",
103
+ "--spacing-4",
104
+ "--spacing-8",
105
+ "--surface-default",
106
+ "--surface-hover",
107
+ "--surface-selected",
108
+ "--surface-selected-hover",
109
+ "--text-default",
110
+ "--text-disabled",
111
+ "--text-secondary",
112
+ "--text-tertiary",
113
+ "--type-body-sm",
114
+ "--type-body-sm-line-height",
115
+ "--type-caption",
116
+ "--type-caption-line-height"
117
+ ],
118
+ "props": {
119
+ "label": {
120
+ "type": "string",
121
+ "required": true,
122
+ "origin": "own",
123
+ "description": "Names the navigation landmark. Required: a page with a sidebar usually has\na second `<nav>` too, and \"navigation, navigation\" tells nobody which is\nwhich."
124
+ },
125
+ "header": {
126
+ "type": "React.ReactNode",
127
+ "required": false,
128
+ "origin": "own",
129
+ "description": "Pinned above the scrolling body — a workspace switcher, a search trigger,\nicon buttons. Any component."
130
+ },
131
+ "footer": {
132
+ "type": "React.ReactNode",
133
+ "required": false,
134
+ "origin": "own",
135
+ "description": "Pinned below the scrolling body — an Invite button, help, a trial notice.\nAny component."
136
+ },
137
+ "children": {
138
+ "type": "React.ReactNode",
139
+ "required": false,
140
+ "origin": "own",
141
+ "description": "`SidebarSection`s, and anything that sits between them — a `Divider`, a\npromotional card. Items themselves always go inside a section."
142
+ }
143
+ },
144
+ "propCounts": {
145
+ "own": 4,
146
+ "aria": 0,
147
+ "dom": 277,
148
+ "other": 0
149
+ }
150
+ }
@@ -0,0 +1,184 @@
1
+ {
2
+ "name": "SidebarItem",
3
+ "source": "src/components/Sidebar.tsx",
4
+ "propsType": "SidebarItemProps",
5
+ "import": "import { SidebarItem } from 'ionbase-ui';",
6
+ "status": "stable",
7
+ "summary": "One sidebar row: a link or a button, with an icon, a count, actions revealed on hover or focus, and nested items that expand.",
8
+ "useWhen": [
9
+ "inside a SidebarSection, or nested inside another SidebarItem"
10
+ ],
11
+ "useInstead": [
12
+ {
13
+ "when": "it is a link in a header bar",
14
+ "use": "NavItem",
15
+ "why": "NavItem recolours on hover without a fill, as measured for the header; sidebar rows fill"
16
+ },
17
+ {
18
+ "when": "it is a row in a dropdown",
19
+ "use": "MenuItem"
20
+ }
21
+ ],
22
+ "slots": {
23
+ "icon": {
24
+ "accepts": "Icon",
25
+ "note": "decorative; label names the row"
26
+ },
27
+ "badge": {
28
+ "accepts": "text",
29
+ "note": "a count or short status, trailing"
30
+ },
31
+ "actions": {
32
+ "accepts": "Button",
33
+ "note": "icon-only Buttons with aria-label, or a Menu trigger for more. Keep to two"
34
+ },
35
+ "children": {
36
+ "accepts": "SidebarItem",
37
+ "note": "nested items; their presence makes the row expandable"
38
+ }
39
+ },
40
+ "a11y": {
41
+ "requires": [
42
+ "`label` — the row's name, and the name of its expand button when it has children"
43
+ ],
44
+ "guarantees": [
45
+ "`isCurrent` sets aria-current=\"page\" on the link",
46
+ "a row with `href` and children renders the link and a separate expand button beside it — a button cannot be nested in a link",
47
+ "a row with children and no `href` is a single button with aria-expanded",
48
+ "a row whose subtree holds the current page starts expanded",
49
+ "actions stay in the tab order and become visible when focus reaches them; they are always visible on touch screens"
50
+ ]
51
+ },
52
+ "antiPatterns": [
53
+ {
54
+ "dont": "onClick on a row to navigate",
55
+ "do": "href",
56
+ "why": "a real link opens in a new tab, shows its address and is announced as a link"
57
+ },
58
+ {
59
+ "dont": "actions nested inside the label or icon",
60
+ "do": "the actions prop",
61
+ "why": "interactive content inside a link is invalid and unreachable by keyboard in most browsers"
62
+ },
63
+ {
64
+ "dont": "marking a parent isCurrent because a child page is open",
65
+ "why": "only the page the user is on is current; its ancestors are opened for them instead"
66
+ }
67
+ ],
68
+ "stylesheet": "src/styles/sidebar.css",
69
+ "tokens": [
70
+ "--border-focus",
71
+ "--border-subtle",
72
+ "--border-width-default",
73
+ "--border-width-thick",
74
+ "--font-family-sans",
75
+ "--font-weight-medium",
76
+ "--icon-disabled",
77
+ "--icon-primary",
78
+ "--icon-secondary",
79
+ "--icon-size-sm",
80
+ "--icon-tertiary",
81
+ "--ion-duration-base",
82
+ "--ion-ease-out",
83
+ "--radius-md",
84
+ "--radius-sm",
85
+ "--radius-xs",
86
+ "--spacing-12",
87
+ "--spacing-16",
88
+ "--spacing-2",
89
+ "--spacing-24",
90
+ "--spacing-32",
91
+ "--spacing-4",
92
+ "--spacing-8",
93
+ "--surface-default",
94
+ "--surface-hover",
95
+ "--surface-selected",
96
+ "--surface-selected-hover",
97
+ "--text-default",
98
+ "--text-disabled",
99
+ "--text-secondary",
100
+ "--text-tertiary",
101
+ "--type-body-sm",
102
+ "--type-body-sm-line-height",
103
+ "--type-caption",
104
+ "--type-caption-line-height"
105
+ ],
106
+ "props": {
107
+ "label": {
108
+ "type": "string",
109
+ "required": true,
110
+ "origin": "own",
111
+ "description": "The item's text. A string, because it also names the expand button of an\nitem that has children."
112
+ },
113
+ "icon": {
114
+ "type": "React.ReactNode",
115
+ "required": false,
116
+ "origin": "own",
117
+ "description": "Leading icon. Decorative — `label` names the item."
118
+ },
119
+ "href": {
120
+ "type": "string | undefined",
121
+ "required": false,
122
+ "origin": "own",
123
+ "description": "Where it goes. Omit for an item that only groups its children."
124
+ },
125
+ "onPress": {
126
+ "type": "(() => void) | undefined",
127
+ "required": false,
128
+ "origin": "own",
129
+ "description": "For an item that acts rather than navigates. Ignored with `href`."
130
+ },
131
+ "isCurrent": {
132
+ "type": "boolean | undefined",
133
+ "required": false,
134
+ "origin": "own",
135
+ "description": "The page the user is on. Marked `aria-current=\"page\"`."
136
+ },
137
+ "isDisabled": {
138
+ "type": "boolean | undefined",
139
+ "required": false,
140
+ "origin": "own"
141
+ },
142
+ "badge": {
143
+ "type": "React.ReactNode",
144
+ "required": false,
145
+ "origin": "own",
146
+ "description": "Trailing text — a count, a shortcut, a status."
147
+ },
148
+ "actions": {
149
+ "type": "React.ReactNode",
150
+ "required": false,
151
+ "origin": "own",
152
+ "description": "Controls for this row — `…` and `+`. Revealed on hover and whenever focus\nis inside the row; always shown on touch screens. Icon-only buttons need\ntheir own `aria-label`."
153
+ },
154
+ "defaultExpanded": {
155
+ "type": "boolean | undefined",
156
+ "required": false,
157
+ "origin": "own",
158
+ "description": "Uncontrolled: whether the children start open. Defaults to open when the\ncurrent page is somewhere inside."
159
+ },
160
+ "isExpanded": {
161
+ "type": "boolean | undefined",
162
+ "required": false,
163
+ "origin": "own",
164
+ "description": "Controlled: whether the children are open."
165
+ },
166
+ "onExpandedChange": {
167
+ "type": "((isExpanded: boolean) => void) | undefined",
168
+ "required": false,
169
+ "origin": "own"
170
+ },
171
+ "children": {
172
+ "type": "React.ReactNode",
173
+ "required": false,
174
+ "origin": "own",
175
+ "description": "Nested `SidebarItem`s. Their presence is what makes the item expandable."
176
+ }
177
+ },
178
+ "propCounts": {
179
+ "own": 12,
180
+ "aria": 0,
181
+ "dom": 277,
182
+ "other": 0
183
+ }
184
+ }
@@ -0,0 +1,131 @@
1
+ {
2
+ "name": "SidebarSection",
3
+ "source": "src/components/Sidebar.tsx",
4
+ "propsType": "SidebarSectionProps",
5
+ "import": "import { SidebarSection } from 'ionbase-ui';",
6
+ "status": "stable",
7
+ "summary": "A group of sidebar items under an optional title, which can fold away and carry its own actions.",
8
+ "useWhen": [
9
+ "inside a Sidebar, once per group — the untitled top group, then Favorites, Spaces"
10
+ ],
11
+ "useInstead": [
12
+ {
13
+ "when": "the grouping is one item and its children",
14
+ "use": "SidebarItem",
15
+ "why": "an item with nested items already expands; a section per parent doubles the structure"
16
+ }
17
+ ],
18
+ "slots": {
19
+ "children": {
20
+ "accepts": "SidebarItem",
21
+ "note": "items only — the section renders a list"
22
+ },
23
+ "actions": {
24
+ "accepts": "Button",
25
+ "note": "beside the title — a + to create in this group. Icon-only buttons need aria-label"
26
+ }
27
+ },
28
+ "a11y": {
29
+ "guarantees": [
30
+ "a titled section's list is named by its title, so a screen reader announces \"Spaces, list, 4 items\"",
31
+ "a collapsible title is a button with aria-expanded and aria-controls; the folded list is hidden, not unmounted"
32
+ ]
33
+ },
34
+ "antiPatterns": [
35
+ {
36
+ "dont": "isCollapsible with no title",
37
+ "why": "there is nothing to press; the prop is ignored"
38
+ },
39
+ {
40
+ "dont": "collapsing the section that holds the current page by default",
41
+ "why": "the user's location is hidden on arrival — leave it open, or open it when the page is inside"
42
+ }
43
+ ],
44
+ "stylesheet": "src/styles/sidebar.css",
45
+ "tokens": [
46
+ "--border-focus",
47
+ "--border-subtle",
48
+ "--border-width-default",
49
+ "--border-width-thick",
50
+ "--font-family-sans",
51
+ "--font-weight-medium",
52
+ "--icon-disabled",
53
+ "--icon-primary",
54
+ "--icon-secondary",
55
+ "--icon-size-sm",
56
+ "--icon-tertiary",
57
+ "--ion-duration-base",
58
+ "--ion-ease-out",
59
+ "--radius-md",
60
+ "--radius-sm",
61
+ "--radius-xs",
62
+ "--spacing-12",
63
+ "--spacing-16",
64
+ "--spacing-2",
65
+ "--spacing-24",
66
+ "--spacing-32",
67
+ "--spacing-4",
68
+ "--spacing-8",
69
+ "--surface-default",
70
+ "--surface-hover",
71
+ "--surface-selected",
72
+ "--surface-selected-hover",
73
+ "--text-default",
74
+ "--text-disabled",
75
+ "--text-secondary",
76
+ "--text-tertiary",
77
+ "--type-body-sm",
78
+ "--type-body-sm-line-height",
79
+ "--type-caption",
80
+ "--type-caption-line-height"
81
+ ],
82
+ "props": {
83
+ "title": {
84
+ "type": "string | undefined",
85
+ "required": false,
86
+ "origin": "own",
87
+ "description": "The group's name — \"Spaces\", \"Favorites\". Omit for the top group."
88
+ },
89
+ "isCollapsible": {
90
+ "type": "boolean | undefined",
91
+ "required": false,
92
+ "origin": "own",
93
+ "description": "Lets the title fold the section away. Needs a `title`."
94
+ },
95
+ "defaultExpanded": {
96
+ "type": "boolean | undefined",
97
+ "required": false,
98
+ "origin": "own",
99
+ "description": "Uncontrolled: whether a collapsible section starts open."
100
+ },
101
+ "isExpanded": {
102
+ "type": "boolean | undefined",
103
+ "required": false,
104
+ "origin": "own",
105
+ "description": "Controlled: whether a collapsible section is open."
106
+ },
107
+ "onExpandedChange": {
108
+ "type": "((isExpanded: boolean) => void) | undefined",
109
+ "required": false,
110
+ "origin": "own"
111
+ },
112
+ "actions": {
113
+ "type": "React.ReactNode",
114
+ "required": false,
115
+ "origin": "own",
116
+ "description": "Controls beside the title — a `+` Button to create a space. Icon-only\nbuttons need their own `aria-label`."
117
+ },
118
+ "children": {
119
+ "type": "React.ReactNode",
120
+ "required": false,
121
+ "origin": "own",
122
+ "description": "`SidebarItem`s only — the section renders a list."
123
+ }
124
+ },
125
+ "propCounts": {
126
+ "own": 7,
127
+ "aria": 0,
128
+ "dom": 276,
129
+ "other": 0
130
+ }
131
+ }