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
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
versioning follows [Semantic Versioning](https://semver.org/). While at 0.x,
minor releases may break. Releases are tagged `vX.Y.Z` and publish from CI.

## [Unreleased]

### Added

- `Toaster` takes `actionDismissAfter`, how long a toast with an action stays, 10000 milliseconds by default, as the next `@wordpress/components` release keeps a snackbar with an action 10 seconds.
- `docs/design-system/toasts.md` gives where a toast sits, how it looks, how long it stays, how a reader clears it and what a keyboard or a screen reader meets.

### Changed

- Toasts centre on the whole window, the sidebar included, as WordPress's new admin centres its snackbars.
- The toast region sits `--wpds-dimension-size-md` above the bottom edge, still 32px, as WordPress writes it.
- The toast action shows the design system focus ring in white in place of a dotted line, as the WordPress snackbar action does.
- Toasts move as the WordPress snackbar does. Each toast's space grows as it arrives and closes after it fades out, so the toasts above slide instead of jumping, and under a reduced motion preference a toast shows and goes at once.
- A toast keeps 4px corners and its action ring 2px corners at every `cornerRadius` preset, as WordPress fixes them on its snackbar.
- **Breaking.** `dismissLabel` defaults to "Dismiss this notice", WordPress's words, in place of "Dismiss", and is only the hint a screen reader hears on a toast with no action.
- **Breaking.** `dismissAfter` times only a toast with no action. A toast with an action stays `actionDismissAfter`.
- **Breaking.** A click anywhere on a toast clears it, with or without an action, and a toast with an action has no close button, so the `.godmin-toast__dismiss` class is gone. Only its action takes keyboard focus.
- **Breaking.** A toast now sits in `.godmin-toasts__item`, not directly in `.godmin-toasts`, so a selector such as `.godmin-toasts > .godmin-toast` no longer matches it.

### Removed

- **Breaking.** `useToaster().name` and the `nameLength` prop of `Toaster`. A toast shows a whole name and wraps it, as WordPress does, so put the name in the message as it is.
- The README browser note, since godmin no longer needs `Intl.Segmenter`.

## [0.27.0] - 2026-10-25

### Added
Expand Down
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ pnpm add @gopherium/godmin
The design system packages are peer dependencies, so your application resolves
and pins them. GodMin never redistributes them.

## Browsers

GodMin needs `Intl.Segmenter`, which every browser WordPress supports has:
Chrome and Edge 87, Safari 14.1 and Firefox 125 or newer.

## Setup

Import the stylesheet once at your entry point, then mount `AdminRoot` around
Expand Down
29 changes: 29 additions & 0 deletions docs/build-and-versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,35 @@ the same peer ranges.
follows the filter rules of that DataViews release. A list built on
another release gets a peer warning when it installs godmin.

## Upgrading from godmin 0.27.0

godmin 0.28.0 draws toasts as WordPress's new admin draws its
snackbars. Change your code in these places:

- `useToaster().name` and the `nameLength` prop of `Toaster` are gone.
Put the name in the message as it is. A long name wraps.
- `dismissAfter` now times only a toast with no action. Pass
`actionDismissAfter` to time a toast with an action. It stays 10
seconds when you pass nothing.
- A toast with an action has no close button. A click anywhere on it
clears it, so a test that pressed the close button clicks the toast
instead. A stylesheet that styles `.godmin-toast__dismiss` styles
nothing now.
- `dismissLabel` is now only the hint of a toast with no action, and
its default is `Dismiss this notice`, WordPress's words. A test that
reads the old hint, `Dismiss`, reads the new one.
- A toast now sits in a `.godmin-toasts__item` element inside
`.godmin-toasts`. A selector such as `.godmin-toasts > .godmin-toast`,
or code that reads the children of the region as toasts, reaches the
toast through that element.
- A toast now rises into place as it arrives, as
[Motion](./design-system/toasts.md#motion) shows. A browser test that
measures where a toast sits waits for that motion to end, or runs
with a reduced motion preference.

TypeScript points at each call to `name` and at `nameLength`. The rest
changes only what the reader sees.

## Upgrading from godmin 0.24.0

godmin 0.25.0 gives the sidebar parts the names WordPress gives them.
Expand Down
36 changes: 15 additions & 21 deletions docs/design-system/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ Except on a toast, every ring godmin draws is the same line,
| The menu button of the top bar | Inside the button |
| The title link of a `godmin-table`, a `godmin-table-scroll` box and a row of `RepeatRows` | 2px outside the part |
| A page tab | Around its label, not around the whole height of the tab |
| A toast | Its own rings, as [toasts](../loading-and-feedback.md#toasts) lists. A plain toast and its close button keep the browser's ring too |
| A toast | Its own rings, as [keyboard](./toasts.md#keyboard) on the toasts page shows. A plain toast keeps the browser's ring too |

godmin turns the browser's own ring off in three places only. A page
tab draws its own ring around the label instead. Back draws none on a
mouse focus. The toast region draws none, because only code ever
focuses it. Draw a ring of your own with the same line, on
`:focus-visible`, so it matches.
mouse focus. The toast region draws none. Tab never stops on it, and
only a toast that leaves or a click on a toast focuses it. Draw a
ring of your own with the same line, on `:focus-visible`, so it
matches.

## Where focus goes

Expand All @@ -70,9 +71,8 @@ The title of a sidebar screen never takes focus.
Some parts go away while they hold focus. godmin then moves focus to
a part that stays, so the keyboard reader keeps their place:

- A toast that leaves, as
[how a toast behaves](../loading-and-feedback.md#how-a-toast-behaves)
says.
- A toast that leaves, as [keyboard](./toasts.md#keyboard) on the
toasts page says.
- A list row that a run moved, as
[running an action over the picked rows](../lists.md#running-an-action-over-the-picked-rows)
says.
Expand Down Expand Up @@ -108,13 +108,11 @@ no region. So a screen reader meets the sidebar under one name only.
pass `label`.

Every control godmin draws is named in words. A glyph, a small
picture such as an icon or a cross, is never the name:
picture such as an icon, is never the name:

- Every icon godmin draws itself, such as a row icon, a chevron, the
Back glyph or the menu glyph, is hidden from screen readers. The
control around it carries the name.
- The cross on a toast is named by `dismissLabel`, never read as a
cross.
- The initials avatar is hidden, because the name beside it already
says who it is.

Expand All @@ -140,7 +138,7 @@ aloud when it changes.

| Part | What a screen reader hears | Set up in |
| --- | --- | --- |
| A toast | Its message, politely. Never its buttons | [How a toast behaves](../loading-and-feedback.md#how-a-toast-behaves) |
| A toast | Its message, politely. Never its action | [What a screen reader hears](./toasts.md#what-a-screen-reader-hears) |
| A loading ghost | The `label` sentence, from a visually hidden status. The grey shapes are hidden | [The ghosts](../loading-and-feedback.md#the-ghosts) |
| A count beside a row | The `label` sentence, in place of the bare number | [A count beside a row](../framing-an-application.md#a-count-beside-a-row) |
| An `ErrorNotice` | Its message, at once, as an alert | [ErrorNotice](../screens.md#errornotice) |
Expand Down Expand Up @@ -174,9 +172,9 @@ translates them.
[godmin's own words](../framing-an-application.md#godmins-own-words)
lists them and the languages they ship in. The props `label`,
`menuLabel` and `backLabel` put your own words in their place. One
default stays in English: the close button of a toast is named
Dismiss until you pass `dismissLabel`, as
[how a toast behaves](../loading-and-feedback.md#how-a-toast-behaves)
default stays in English: the hint a toast with no action gives a
screen reader, until you pass `dismissLabel`, as
[what a screen reader hears](./toasts.md#what-a-screen-reader-hears)
says. Every other word comes from your app, such as the `label` of a
loading ghost or a count. Pass each one through your translations.

Expand All @@ -187,18 +185,14 @@ gives no label a fixed width:
leave. A longer label wraps, and the row grows, since the row sets
only a smallest height.
- A long title on a sidebar screen breaks onto the next line.
- A toast grows with its message up to its widest, then wraps, even
inside a long word. The aside of a page and a log list break a long
word the same way.
- A toast grows with its message, then wraps, as
[size](./toasts.md#size) on the toasts page shows. The aside of a
page and a log list break a long word the same way.
- The actions of a page header move under the title once they no
longer fit beside it. A form row and the header line of a log list
wrap the same way.
- The page tabs keep each label on one line. A tab row too long for
its page scrolls and fades the edge it cuts.
- Where a toast cuts a name, it counts the characters a reader sees,
so an emoji is never split.
[Naming an item in a toast](../lists.md#naming-an-item-in-a-toast)
shows it.

In a right-to-left language the chevrons, the sub menu slide and the
fade of the tab row turn around, as
Expand Down
2 changes: 1 addition & 1 deletion docs/design-system/color.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ The theme provider also checks contrast when it works out colors from a seed. It

A raw color is a value written out, such as `#fff`, in place of a token. It stays the same whatever the seeds. `base.css` writes a few on purpose:

- The toast box is `rgb(0 0 0 / 0.85)`, a black that lets a blur of the page show through. Its text and its focus lines are `#fff`. These are the colors of the WordPress snackbar. [Toasts](../loading-and-feedback.md#toasts) describes the rest of the toast.
- A toast paints raw colors too: a see-through black box, white text and a white focus line, the colors of the WordPress snackbar. [Colors, corners and shadow](./toasts.md#colors-corners-and-shadow) gives each value.
- The backdrop is the dark layer behind the open drawer. It is `#000` at 0.5 opacity, as in the new WordPress admin. godmin sets the opacity through `--backdrop-opacity`. The `@wordpress/ui` drawer fades its black backdrop to that value, so the fade in and out still run.
- Shadows are black at a low opacity. [Elevation](./radius-and-elevation.md#elevation) lists them.
- The `#000` in `--godmin-page-tabs-fade` and `--godmin-page-tabs-fade-both` is a mask. The mask fades the ends of a long row of tabs. It paints nothing.
Expand Down
7 changes: 2 additions & 5 deletions docs/design-system/custom-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ values. This table says where each one is set and what it changes.

## Where each one is set

A value set on `:root` reaches every element on the page. So the
toast region reads the sidebar width and the canvas margin too. When
the sidebar is on screen, the region starts after it and ends where
the canvas ends, so the toasts stay centered on the canvas.
A value set on `:root` reaches every element on the page.

To change one of the four on `:root`, write a plain rule in your own
stylesheet. For example, a wider sidebar:
Expand All @@ -44,7 +41,7 @@ stylesheet. For example, a wider sidebar:

Your rule wins over godmin's, as
[changing the page appearance](../overview.md#changing-the-page-appearance)
explains. The sidebar, the drawer and the toast region all follow it.
explains. The sidebar and the drawer both follow it.

The canvas sets its two gutters on itself. So a gutter set on `:root`
changes nothing inside the canvas. Read them inside the canvas, for
Expand Down
2 changes: 1 addition & 1 deletion docs/design-system/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ as wide. A rule for the screens below it asks for one pixel less, as
| `SIDEBAR_BREAKPOINT` | `1024` | The sidebar becomes the top bar and the drawer |
| `EDGE_BREAKPOINT` | `782` | The canvas meets the screen edges. It is the WordPress medium breakpoint |
| `DENSE_BREAKPOINT` | `640` | The canvas side gutter narrows to 16px. A list from `useListView` takes its phone layout, as [the view in the address](../lists.md#the-view-in-the-address) shows. A table inside `godmin-table-scroll` scrolls sideways, as [stylesheet helpers](../screens.md#stylesheet-helpers) shows |
| `SHEET_BREAKPOINT` | `600` | Dialogs rise as sheets along the bottom of the screen and toasts widen to the screen, as [a form dialog](../lists.md#a-form-dialog) and [toasts](../loading-and-feedback.md#toasts) show. It is the WordPress small breakpoint |
| `SHEET_BREAKPOINT` | `600` | Dialogs rise as sheets along the bottom of the screen and toasts widen to the screen, as [a form dialog](../lists.md#a-form-dialog) and [toasts](./toasts.md#size) show. It is the WordPress small breakpoint |
| `TITLE_BREAKPOINT` | `404` | Nothing in the frame. The WordPress editor drops the document title from its header here, for an editor header of your own |
| `SMALL_VIEWPORT` | `(max-width: 1023px)` | The media query the frame folds its sidebar at |

Expand Down
47 changes: 26 additions & 21 deletions docs/design-system/motion.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
---
title: Motion
description: The sidebar slide and the fades of a godmin admin, the design tokens that time them, and what changes when a reader asks for less motion.
description: The sidebar slide, the toast motion and the fades of a godmin admin, the design tokens that time them, and what changes when a reader asks for less motion.
---

godmin's own motion is short and small. The sidebar slides a new
menu screen in. Toasts fade in and out. Ghosts, the grey shapes shown
menu screen in. Toasts grow in and fade, and the toasts around them
slide along. Ghosts, the grey shapes shown
while data loads, fade in, and so does the content that replaces
them. godmin's stylesheet animates nothing else. It sets no
transitions, so its own hover and focus looks change at once.
Expand All @@ -18,17 +19,20 @@ and the bars inside a ghost.
A design token is a value the WordPress Design System names, written
as a CSS custom property. A custom property is a CSS variable. A
duration is how long an animation takes. An easing is the curve its
speed follows from start to end. godmin times its fades with three
speed follows from start to end. godmin times its motion with five
design tokens:

| Token | Value | What it times |
| --- | --- | --- |
| `--wpds-motion-duration-md` | 200ms | A toast, a ghost or new content fading in |
| `--wpds-motion-duration-sm` | 100ms | A toast fading out |
| `--wpds-motion-easing-balanced` | `cubic-bezier(0.4, 0, 0.2, 1)` | Every fade |
| `--wpds-motion-duration-lg` | 300ms | Toast motion, see [Motion](./toasts.md#motion) |
| `--wpds-motion-duration-md` | 200ms | A ghost or new content fading in |
| `--wpds-motion-duration-sm` | 100ms | Toast motion, see [Motion](./toasts.md#motion) |
| `--wpds-motion-duration-xs` | 50ms | Toast motion, see [Motion](./toasts.md#motion) |
| `--wpds-motion-easing-balanced` | `cubic-bezier(0.4, 0, 0.2, 1)` | The fades of ghosts and new content |

Two lengths have no token: the sidebar slide and the wait before a
ghost shows. The sections below cover both.
Some values have no token: the sidebar slide, the wait before a ghost
shows, and the rest of the toast motion. The sections below cover
them.

## The sidebar slide

Expand Down Expand Up @@ -69,12 +73,11 @@ shows how.

## Toasts

A toast fades in when it arrives. When it leaves, it fades out and
stays hidden at the end. A leaving toast stays on the page until its
fade ends. Nobody can press it in that time. If the browser cuts the
fade short, the toast still goes.
[How a toast behaves](../loading-and-feedback.md#how-a-toast-behaves)
says how long a toast stays before it leaves.
Toasts move as the WordPress snackbar does. An arriving toast grows
its space in the column and fades in. A leaving toast fades out, then
its space closes. So the other toasts slide instead of jumping.
[Motion](./toasts.md#motion) on the toasts page gives every duration
and curve, and says what a leaving toast does.

## Loading

Expand All @@ -100,17 +103,19 @@ A reader can ask their system for less motion. The browser then
reports `prefers-reduced-motion: reduce` to CSS, and godmin changes
two things:

- The fades of toasts, ghosts and new content last 1ms. They still
run and still end. So a leaving toast still goes, and a ghost
still waits its delay and then stays visible.
- The fades of ghosts and new content last 1ms. They still run and
still end. So a ghost still waits its delay and then stays visible.
- Every toast animation lasts 1ms and starts at once, with no wait.
It still runs and still ends, so a leaving toast still goes. A toast
shows in its place at once and goes at once, and the toasts above
move in one step, as in WordPress.
- The sidebar slide lasts 0s, as in the WordPress Site Editor, even
when you set your own slide duration. It does not play, and the new
screen shows at once in its place.

These rules change only how long each animation lasts. They keep
the delay, the animation itself, and the setting that holds a ghost
visible after its fade. Turning the animation off would leave a
ghost transparent for good.
These rules keep each animation itself and the setting that holds a
ghost visible after its fade. They keep the delay of a ghost too.
Turning an animation off would leave a ghost transparent for good.

The bars inside a ghost stop their pulse too. Their WordPress
package does that on its own.
14 changes: 10 additions & 4 deletions docs/design-system/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ godmin looks. It says where each part of the screen sits, how big
things are, how they move and which colors they take. A new product
can follow these pages without reading any godmin code.

These pages hold the values the whole admin shares. A value that
belongs to one part, such as the size of a
[toast](../loading-and-feedback.md#toasts), sits on the page that
shows how to use that part.
These pages hold the values the whole admin shares. A part with a
page of its own, such as [toasts](./toasts.md), keeps its values
there. Every other part keeps its values on the page that shows how
to use it.

godmin builds on the WordPress Design System, WPDS for short. For
layout, sizes and motion it follows WordPress's new admin and the
Expand Down Expand Up @@ -99,3 +99,9 @@ layer.
landmarks, what a screen reader hears, and text length.
- [Custom properties](./custom-properties.md): every godmin custom
property, where it is set and what it changes.

One more page covers a single part, how it looks and how it behaves:

- [Toasts](./toasts.md): where a toast sits, how it looks, how long it
stays, how a reader clears it, and what a keyboard or a screen reader
meets.
Loading
Loading