@tribepad/themis 1.9.2 → 1.9.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tribepad/themis",
3
- "version": "1.9.2",
3
+ "version": "1.9.3",
4
4
  "description": "Accessible React component library built on React Aria primitives",
5
5
  "author": "Tribepad <mbasford@tribepad.com>",
6
6
  "license": "MIT",
@@ -229,6 +229,76 @@ export const TabbedModal: Story = {
229
229
  ),
230
230
  };
231
231
 
232
+ /**
233
+ * Tabbed Modal — Long Content
234
+ *
235
+ * A tabbed modal whose active panel far exceeds the 85vh box cap. The header
236
+ * and full-width tab strip stay pinned while only `Modal.Body` scrolls — the
237
+ * canonical "header tabs + tall form" layout. This is the scenario that
238
+ * regresses if the dialog wrapper drops out of the flex column: without
239
+ * `flex-1 min-h-0 flex-col` on the dialog, `Modal.Body`'s `flex-1
240
+ * overflow-y-auto` has no flex parent and the content is clipped with no
241
+ * scrollbar instead of scrolling.
242
+ */
243
+ export const TabbedModalLongContent: Story = {
244
+ render: () => (
245
+ <Modal>
246
+ <Modal.Trigger>
247
+ <Button>Edit field</Button>
248
+ </Modal.Trigger>
249
+ <Modal.Content size="lg">
250
+ <Modal.Header>
251
+ <Modal.Title>Edit field</Modal.Title>
252
+ <Modal.Description>
253
+ The body scrolls; the title, tab strip, and footer stay pinned.
254
+ </Modal.Description>
255
+ </Modal.Header>
256
+ <Tabs
257
+ defaultSelectedKey="content"
258
+ className="flex min-h-0 flex-1 flex-col"
259
+ >
260
+ <Modal.Tabs>
261
+ <TabList aria-label="Field sections">
262
+ <Tab id="content">Content</Tab>
263
+ <Tab id="settings">Settings</Tab>
264
+ <Tab id="validation">Validation</Tab>
265
+ </TabList>
266
+ </Modal.Tabs>
267
+ <Modal.Body>
268
+ <TabPanel id="content">
269
+ <div className="space-y-6">
270
+ {Array.from({ length: 20 }, (_, i) => (
271
+ <div key={i} className="space-y-2">
272
+ <p className="text-sm font-medium">Field {i + 1}</p>
273
+ <p className="text-sm text-[var(--muted-foreground)]">
274
+ A row of configuration that pushes the panel well beyond
275
+ the modal&apos;s 85vh cap so the body has to scroll.
276
+ </p>
277
+ </div>
278
+ ))}
279
+ </div>
280
+ </TabPanel>
281
+ <TabPanel id="settings">
282
+ <p className="text-sm">Settings for this field.</p>
283
+ </TabPanel>
284
+ <TabPanel id="validation">
285
+ <p className="text-sm">Validation rules for this field.</p>
286
+ </TabPanel>
287
+ </Modal.Body>
288
+ </Tabs>
289
+ <Modal.Footer>
290
+ <Modal.Close>
291
+ <Button variant="outline">Cancel</Button>
292
+ </Modal.Close>
293
+ <Modal.Close>
294
+ <Button>Save changes</Button>
295
+ </Modal.Close>
296
+ </Modal.Footer>
297
+ </Modal.Content>
298
+ </Modal>
299
+ ),
300
+ };
301
+
232
302
  /**
233
303
  * Long Content
234
304
  * Modal with scrolling content