Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .changeset/dialog-backdrop-containment.md

This file was deleted.

32 changes: 0 additions & 32 deletions .changeset/dialog-close-on-back.md

This file was deleted.

32 changes: 0 additions & 32 deletions .changeset/dialog-exit-animation.md

This file was deleted.

29 changes: 0 additions & 29 deletions .changeset/overlay-packages.md

This file was deleted.

58 changes: 58 additions & 0 deletions packages/core/dialog/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,63 @@
# @dunky.dev/dialog

## 0.2.0

### Minor Changes

- [#27](https://github.com/dunky-dev/ui/pull/27) [`f0d5ca4`](https://github.com/dunky-dev/ui/commit/f0d5ca4432774f5f88c1f0cc54ad7410a3c7d2fb) Thanks [@ivanbanov](https://github.com/ivanbanov)! - Add `closeOnBack` — the host's Back navigation closes the open dialog instead
of leaving the page, the pattern mobile users expect from a full-screen
overlay. Off by default.

```tsx
<Dialog closeOnBack onBackNavigation={event => /* preventDefault() vetoes */ {}}>
</Dialog>
```

It follows the shared dismissal contract: `onBackNavigation` fires first and
`preventDefault()` vetoes, a controlled dialog only records the intent (close
it from your own state as usual), a nested stack unwinds one layer per Back
press, and it composes with `animated` (Back plays the exit animation). The
decision — gate, veto, controlled — lives once in the core's `backNavigate`;
substrates only wire their host's mechanics to it.

The web mechanics ship as their own framework-free util,
`@dunky.dev/dom-navigation` (`interceptBackNavigation`) — a session
history guard any overlaid layer can use, not just the dialog: opening
plants a guard entry in the session history and Back consumes it. A dialog
closed any other way consumes its own entry too, so no leftover ever swallows
a later Back press — including across reopen races (React StrictMode's
double-invoked effects adopt the entry in place rather than queueing a
history traversal, which browsers don't reliably deliver once another entry
is pushed).

- [#26](https://github.com/dunky-dev/ui/pull/26) [`f4628e7`](https://github.com/dunky-dev/ui/commit/f4628e733f657695099b54991bd29c0487293557) Thanks [@ivanbanov](https://github.com/ivanbanov)! - Add exit-animation support via a new `animated` option. An animated dialog
closes through a `closing` state — every part carries it as
`data-state="closing"`, the styling hook for the exit — and unmounts when its
transition or animation on Content ends (with a fallback ceiling, and skipped
entirely under `prefers-reduced-motion`).

```tsx
<Dialog animated>…</Dialog>
```

```css
[data-state='closing'] {
opacity: 0;
transition: opacity 150ms;
}
```

The exit window lives in the core machine, not in per-substrate unmount
deferral, so reopening mid-exit is a named transition instead of a timing
race, and every substrate inherits identical behavior. The exit is cosmetic
by design: the close is reported, focus returns, and the page becomes
interactive the moment closing starts — the still-painting layer is made
`inert` until it leaves. Enter animations need no option: parts mount
straight into `data-state="open"`, so CSS animations (or transitions via
`@starting-style`) play from mount. Default (`animated: false`) behavior is
unchanged.

## 0.1.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/dialog/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dunky.dev/dialog",
"version": "0.1.0",
"version": "0.2.0",
"description": "Framework-agnostic dialog interaction, modeled as a state machine.",
"license": "MIT",
"repository": {
Expand Down
28 changes: 28 additions & 0 deletions packages/core/utils/overlay/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# @dunky.dev/overlay

## 0.1.0

### Minor Changes

- [#29](https://github.com/dunky-dev/ui/pull/29) [`89ed3f7`](https://github.com/dunky-dev/ui/commit/89ed3f7f9c1e5c6909ff2cfaa4c5ed952846518e) Thanks [@ivanbanov](https://github.com/ivanbanov)! - Add `@dunky.dev/overlay` and `@dunky.dev/dom-overlay` — the shared overlay
coordination the whole overlay family (dialog, drawer, alert-dialog, popover,
menu, combobox) builds on, so the behavior is implemented once instead of
forked per primitive.
- `@dunky.dev/overlay` is the agnostic half: a stack of open layers and the
rule for which is topmost (deepest nesting, open order breaking ties). No
DOM, no framework — a future native substrate reuses it.
- `@dunky.dev/dom-overlay` is the DOM realization on top of it: the layer
stack wired to assistive-tech containment (`aria-hidden` + `inert`), the
exit window (`hideExitingLayer` / `watchExitAnimation`), and initial focus
(`getInitialFocus`).

```ts
import { createLayerStack, type OverlayLayer } from '@dunky.dev/overlay'
import { registerLayer, isTopmostLayer } from '@dunky.dev/dom-overlay'
```

This replaces `@dunky.dev/dom-dialog`, which is removed — its behavior was
never dialog-specific, only its name was. `@dunky.dev/react-dialog` now
consumes `@dunky.dev/dom-overlay`; its public API and behavior are unchanged
(`registerDialog` / `isTopmostDialog` become `registerLayer` /
`isTopmostLayer` internally).
2 changes: 1 addition & 1 deletion packages/core/utils/overlay/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dunky.dev/overlay",
"version": "0.0.0",
"version": "0.1.0",
"description": "Agnostic overlay-layer stack: registration and topmost resolution, shared by every overlay primitive across substrates.",
"license": "MIT",
"repository": {
Expand Down
32 changes: 32 additions & 0 deletions packages/dom/utils/navigation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# @dunky.dev/dom-navigation

## 0.1.0

### Minor Changes

- [#27](https://github.com/dunky-dev/ui/pull/27) [`f0d5ca4`](https://github.com/dunky-dev/ui/commit/f0d5ca4432774f5f88c1f0cc54ad7410a3c7d2fb) Thanks [@ivanbanov](https://github.com/ivanbanov)! - Add `closeOnBack` — the host's Back navigation closes the open dialog instead
of leaving the page, the pattern mobile users expect from a full-screen
overlay. Off by default.

```tsx
<Dialog closeOnBack onBackNavigation={event => /* preventDefault() vetoes */ {}}>
</Dialog>
```

It follows the shared dismissal contract: `onBackNavigation` fires first and
`preventDefault()` vetoes, a controlled dialog only records the intent (close
it from your own state as usual), a nested stack unwinds one layer per Back
press, and it composes with `animated` (Back plays the exit animation). The
decision — gate, veto, controlled — lives once in the core's `backNavigate`;
substrates only wire their host's mechanics to it.

The web mechanics ship as their own framework-free util,
`@dunky.dev/dom-navigation` (`interceptBackNavigation`) — a session
history guard any overlaid layer can use, not just the dialog: opening
plants a guard entry in the session history and Back consumes it. A dialog
closed any other way consumes its own entry too, so no leftover ever swallows
a later Back press — including across reopen races (React StrictMode's
double-invoked effects adopt the entry in place rather than queueing a
history traversal, which browsers don't reliably deliver once another entry
is pushed).
2 changes: 1 addition & 1 deletion packages/dom/utils/navigation/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dunky.dev/dom-navigation",
"version": "0.0.0",
"version": "0.1.0",
"description": "Framework-free browser-navigation helpers: a session-history guard so the host's Back dismisses a layer instead of leaving the page.",
"license": "MIT",
"repository": {
Expand Down
60 changes: 60 additions & 0 deletions packages/dom/utils/overlay/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# @dunky.dev/dom-overlay

## 0.1.0

### Minor Changes

- [#26](https://github.com/dunky-dev/ui/pull/26) [`f4628e7`](https://github.com/dunky-dev/ui/commit/f4628e733f657695099b54991bd29c0487293557) Thanks [@ivanbanov](https://github.com/ivanbanov)! - Add exit-animation support via a new `animated` option. An animated dialog
closes through a `closing` state — every part carries it as
`data-state="closing"`, the styling hook for the exit — and unmounts when its
transition or animation on Content ends (with a fallback ceiling, and skipped
entirely under `prefers-reduced-motion`).

```tsx
<Dialog animated>…</Dialog>
```

```css
[data-state='closing'] {
opacity: 0;
transition: opacity 150ms;
}
```

The exit window lives in the core machine, not in per-substrate unmount
deferral, so reopening mid-exit is a named transition instead of a timing
race, and every substrate inherits identical behavior. The exit is cosmetic
by design: the close is reported, focus returns, and the page becomes
interactive the moment closing starts — the still-painting layer is made
`inert` until it leaves. Enter animations need no option: parts mount
straight into `data-state="open"`, so CSS animations (or transitions via
`@starting-style`) play from mount. Default (`animated: false`) behavior is
unchanged.

- [#29](https://github.com/dunky-dev/ui/pull/29) [`89ed3f7`](https://github.com/dunky-dev/ui/commit/89ed3f7f9c1e5c6909ff2cfaa4c5ed952846518e) Thanks [@ivanbanov](https://github.com/ivanbanov)! - Add `@dunky.dev/overlay` and `@dunky.dev/dom-overlay` — the shared overlay
coordination the whole overlay family (dialog, drawer, alert-dialog, popover,
menu, combobox) builds on, so the behavior is implemented once instead of
forked per primitive.
- `@dunky.dev/overlay` is the agnostic half: a stack of open layers and the
rule for which is topmost (deepest nesting, open order breaking ties). No
DOM, no framework — a future native substrate reuses it.
- `@dunky.dev/dom-overlay` is the DOM realization on top of it: the layer
stack wired to assistive-tech containment (`aria-hidden` + `inert`), the
exit window (`hideExitingLayer` / `watchExitAnimation`), and initial focus
(`getInitialFocus`).

```ts
import { createLayerStack, type OverlayLayer } from '@dunky.dev/overlay'
import { registerLayer, isTopmostLayer } from '@dunky.dev/dom-overlay'
```

This replaces `@dunky.dev/dom-dialog`, which is removed — its behavior was
never dialog-specific, only its name was. `@dunky.dev/react-dialog` now
consumes `@dunky.dev/dom-overlay`; its public API and behavior are unchanged
(`registerDialog` / `isTopmostDialog` become `registerLayer` /
`isTopmostLayer` internally).

### Patch Changes

- Updated dependencies [[`89ed3f7`](https://github.com/dunky-dev/ui/commit/89ed3f7f9c1e5c6909ff2cfaa4c5ed952846518e)]:
- @dunky.dev/overlay@0.1.0
2 changes: 1 addition & 1 deletion packages/dom/utils/overlay/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dunky.dev/dom-overlay",
"version": "0.0.0",
"version": "0.1.0",
"description": "Framework-free DOM behavior for overlay substrates: the shared layer stack with assistive-tech containment, the exit window, and initial focus.",
"license": "MIT",
"repository": {
Expand Down
Loading
Loading