asma-ui-core 3.88.1 → 3.90.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 (31) hide show
  1. package/Readme.md +107 -0
  2. package/dist/asma-ui-core.css +1 -1
  3. package/dist/components/feedback/minimizable-dialog/MinimizableDialog.js +6 -6
  4. package/dist/components/utils/bottom-sheet/StyledBottomSheet.js +137 -0
  5. package/dist/components/utils/bottom-sheet/StyledBottomSheet.module.js +4 -0
  6. package/dist/components/utils/bottom-sheet/formatResultsLabel.js +4 -0
  7. package/dist/components/utils/bottom-sheet/useDragToDismiss.hook.js +40 -0
  8. package/dist/components/utils/popover/PopoverAnatomy.js +46 -0
  9. package/dist/components/utils/popover/PopoverSheet.js +165 -0
  10. package/dist/hooks/useBodyScrollLock.hook.js +13 -0
  11. package/dist/hooks/useDebouncedValue.hook.js +15 -0
  12. package/dist/hooks/useMediaQuery.hook.js +10 -9
  13. package/dist/index.js +184 -178
  14. package/dist/src/components/utils/bottom-sheet/StyledBottomSheet.d.ts +59 -0
  15. package/dist/src/components/utils/bottom-sheet/formatResultsLabel.d.ts +9 -0
  16. package/dist/src/components/utils/bottom-sheet/formatResultsLabel.test.d.ts +1 -0
  17. package/dist/src/components/utils/bottom-sheet/index.d.ts +2 -0
  18. package/dist/src/components/utils/bottom-sheet/story/BottomSheetCases.d.ts +1 -0
  19. package/dist/src/components/utils/bottom-sheet/story/BottomSheetDemo.d.ts +22 -0
  20. package/dist/src/components/utils/bottom-sheet/useDragToDismiss.hook.d.ts +22 -0
  21. package/dist/src/components/utils/popover/PopoverAnatomy.d.ts +36 -0
  22. package/dist/src/components/utils/popover/PopoverSheet.d.ts +86 -0
  23. package/dist/src/components/utils/popover/index.d.ts +1 -0
  24. package/dist/src/components/utils/popover/story/PopoverCases.d.ts +1 -0
  25. package/dist/src/components/utils/popover/story/PopoverGallery.d.ts +1 -0
  26. package/dist/src/components/utils/popover/story/popoverStoryFixtures.d.ts +21 -0
  27. package/dist/src/hooks/useBodyScrollLock.hook.d.ts +7 -0
  28. package/dist/src/hooks/useDebouncedValue.hook.d.ts +2 -0
  29. package/dist/src/hooks/useMediaQuery.hook.d.ts +2 -0
  30. package/dist/src/index.d.ts +1 -0
  31. package/package.json +1 -1
package/Readme.md CHANGED
@@ -238,6 +238,113 @@ field does not pay for one. `onChange` reports digits only — the country trave
238
238
  The picker has two shapes: below 744 px it is a full-screen sheet with its own search box, above it
239
239
  the trigger itself is the combobox. Both are keyboard-operable and share one listbox.
240
240
 
241
+ ### Popover
242
+
243
+ `PopoverSheet` is the Design System popover (ASMA-8183): an anchored surface with an optional
244
+ title, a close control and two optional footer rows. One implementation, two variants picked by
245
+ **content** rather than by breakpoint.
246
+
247
+ ```tsx
248
+ import { StyledButton, PopoverSheet } from 'asma-ui-core'
249
+
250
+ <PopoverSheet
251
+ dataTest='case-filter'
252
+ variant='action'
253
+ title='Filtrer søknader'
254
+ renderTrigger={({ ref, triggerProps }) => (
255
+ <StyledButton dataTest='case-filter-trigger' refLink={ref} type='button' {...triggerProps}>
256
+ {activeCount > 0 ? `Filter (${activeCount})` : 'Filter'}
257
+ </StyledButton>
258
+ )}
259
+ viewResultsAction={({ close }) => (
260
+ <StyledButton dataTest='case-filter-view' type='button' variant='text' onClick={close}>
261
+ {`Vis resultater (${matchCount})`}
262
+ </StyledButton>
263
+ )}
264
+ resetAction={
265
+ <StyledButton dataTest='case-filter-reset' type='button' variant='text' onClick={clearFilters}>
266
+ Nullstill
267
+ </StyledButton>
268
+ }
269
+ >
270
+ <CaseFilterForm value={filters} onChange={setFilters} />
271
+ </PopoverSheet>
272
+ ```
273
+
274
+ The two footer rows come straight from Figma. The **Reset filter** row is `space-between`:
275
+ `viewResultsAction` on the left (the live match count, which closes the surface — the filter has
276
+ already applied) and `resetAction` on the right. The **Actions** row (`footerActions`) is a single
277
+ right-aligned outlined button. Each of those slots, like `children`, may be a render-prop receiving
278
+ `close()`. In Storybook, **`AllCases`** gives every case its own trigger to open and operate, and
279
+ **`Gallery`** shows the same anatomies side by side, statically, for visual comparison.
280
+
281
+ `info` is read-only: a plain container the trigger points at with `aria-describedby`, not focus
282
+ trapped, so `Tab` walks out of it and closes it. `action` is a `role="dialog"` with a focus trap,
283
+ and covers both the Filter pattern (every change applies immediately — there is no apply step,
284
+ `Nullstill` clears) and the Actions pattern (a list of buttons; `children` may be a render-prop
285
+ receiving `close()` so activating one closes the surface).
286
+
287
+ There is deliberately **no `role="menu"` and no arrow-key navigation**: menu semantics bring a
288
+ keyboard contract that cannot coexist with the dialog model Filter uses, so everything inside is
289
+ reached with `Tab`. There is no arrow or anchor pointer either — the surface is edge-aligned to its
290
+ trigger at an 8px offset.
291
+
292
+ The consumer owns the trigger element (spread `triggerProps`, wire `ref` — `refLink` on
293
+ `StyledButton`), the filter state, and the `aria-live` region that announces the new result count.
294
+ Below 744px an `info` popover takes `100vw - 32px` and is pinned below its trigger, while an
295
+ `action` popover renders as a **Bottom Sheet** with the same props (see below).
296
+
297
+ ### Bottom sheet
298
+
299
+ `StyledBottomSheet` (ASMA-8184) is the mobile (0–743px) form of the Action popover. You rarely use
300
+ it directly — `PopoverSheet variant='action'` switches to it below 744px — but it is exported for
301
+ screens that only ever show a sheet.
302
+
303
+ ```tsx
304
+ <StyledBottomSheet
305
+ dataTest='row-actions'
306
+ open={open}
307
+ onClose={() => setOpen(false)}
308
+ title='Handlinger — søknad 4417'
309
+ >
310
+ {({ close }) => <RowActionButtons onDone={close} />}
311
+ </StyledBottomSheet>
312
+ ```
313
+
314
+ A modal sheet on a native `<dialog>`: dimmed scrim, page scroll locked and made `inert`, top corners
315
+ 28px, width up to 640px, height fitting the content up to 90vh with an internally scrolling body (a
316
+ full-screen dialog at `max-height: 480px`). Five equivalent dismiss routes — close button, *Vis
317
+ resultater*, scrim, `Esc`, dragging down past 30% — and none of them commits anything. Focus goes to
318
+ the sheet on open so the title is read first, and back to the trigger on close; the grabber is
319
+ decorative.
320
+
321
+ Pass **`resultCount`** (to the sheet or the popover) for the standard *Vis resultater (N)* control:
322
+ debounced ~500ms, `Ingen treff` at zero and still enabled, capped at `9999+`, and announced from a
323
+ live region inside the sheet — the list behind is inert, so its own live region cannot. The label
324
+ comes from the exported `formatResultsLabel`. Title the sheet after the object, not the action: a
325
+ sheet detaches from its trigger, so `Handlinger` alone does not say which row was opened.
326
+
327
+ `StyledPopover` is a different, older thing and stays permanently: the MUI-`Popover`-parity
328
+ positioning primitive that `StyledMenu`, the date-picker calendar, `CountryCodeSelect` and four table
329
+ components (`RowActionMenu`, `HeaderActionMenu`, `TableRowCountSelect`, `TablePagination`) build on.
330
+ New code should reach for `PopoverSheet` — but it is **not** a drop-in replacement for
331
+ `StyledPopover`, and most of those consumers should never move to it:
332
+
333
+ - `StyledMenu`, `RowActionMenu` and (through it) `ToolbarActionGroup` render `role="menu"` with roving
334
+ tabindex and arrow-key navigation — semantics `PopoverSheet` deliberately excludes.
335
+ - `TableRowCountSelect`, `TablePagination` and `CountryCodeSelect`'s desktop panel are `role="listbox"`
336
+ / combobox pickers, not Info or Action content.
337
+ - The date-picker calendar is a day grid with its own mobile `Drawer` fallback already, which would
338
+ collide with `PopoverSheet`'s built-in <744px sheet swap.
339
+
340
+ `StyledFilterMenu` is the one real migration candidate — its `popoverContent({isOpen, onClose})` +
341
+ `anchorNode` render-props are exactly the shape `PopoverSheet`'s Filter pattern
342
+ (`resetAction`/`viewResultsAction`/`resultCount`) was modeled on — but the render-prop shapes differ
343
+ enough (`{isOpen, onClose}` vs `{close}`, `anchorNode` vs `renderTrigger`) that it needs its own
344
+ rewrite, not an import swap; tracked as a follow-up, not done here. `HeaderActionMenu` (plain
345
+ buttons/checkboxes, no menu role) is a plausible second candidate for the same reason, with its
346
+ drag-and-drop reordering needing its own verification inside a focus trap.
347
+
241
348
  ### Icons
242
349
 
243
350
  Around 180 icons ship on a dedicated subpath so you only pay for the ones you use — each is its own