Repository navigation
Releases: ptbdynamic/plinth
Release list
Plinth 0.1.1
Plinth is now on both registries:
composer require ptbdynamic/plinth
npm install @ptbdynamic/plinth
Fixes
- The npm package is
@ptbdynamic/plinth, under the same name as the GitHub organisation and the Composer package. Its subpaths are unchanged:@ptbdynamic/plinth/vue,/react,/tokens,/cssand the rest.
Everything in Plinth is listed in 0.1.0.
Plinth 0.1.0
The first release of Plinth.
composer require ptbdynamic/plinth
The npm package follows once its scope is reserved.
New
-
Give the callout its own component tokens,
--plinth-callout-<tone>-surfaceand-borderfor neutral, info, success, warning and danger, in light and dark. The tones are now a faint, translucent tint with a tinted hairline border, quieter than the status surfaces, which badges keep. Component tokens can now change with the theme (component.light.jsonandcomponent.dark.json), and a token's value may hold references inside it, such as acolor-mix(), which the CSS writes asvar()s. -
Add the callout: a note inside a page, in five tones (neutral, info, success, warning, danger) each with its own icon, with an optional title and actions, as a
note,statusoralert, in CSS, Blade, Vue and React. -
Add the code block: a block of code with an optional label, a copy button and optional language tabs, in CSS, Blade, Vue and React.
-
Add the confirmation dialog: a dialog that asks a person to confirm an action before it happens (
<x-plinth::confirm-dialog>,<PlinthConfirmDialog>), always an alert dialog that closes only through Cancel, Escape or its confirm button.kindissimple,type(the person typesphraseexactly; the browser blocks the confirm until it matches, and the confirm button looks disabled until then, with no script) orpassword(a password field the app checks, witherrorfor a wrong one andbusywhile it checks).tone="danger"makes the confirm button the danger variant. Its content is a<form method="dialog">: the app listens forsubmiton the dialog. It needsdialog.cssandmodal.csswithconfirm-dialog.css. A new token,--plinth-font-size-field(16px), is the text size of a field on a phone, so iOS doesn't zoom in when it takes focus. -
Add the dialog: a modal for a form, details or settings on a native
<dialog>, centred at every width (<x-plinth::dialog>,<PlinthDialog>).dismissibleset to false (:dismissible="false"in Blade and Vue,dismissible={false}in React) makes it an alert dialog with no close button that a tap on the backdrop leaves open, closing through its own buttons with Escape acting as Cancel;side-phone="bottom"makes it a bottom sheet below 768px. Its width is the new--plinth-dialog-widthtoken. What the dialog and the sheet share (the surface, the backdrop, the scroll lock, the motion, the safe areas and the header, body and footer) moves into one base,modal.css, which a page that loads the components one by one (dist/sheet.css,dist/dialog.css) must now load with them; with it, the sheet's markup and look don't change. -
Display sizes for marketing pages:
--plinth-font-size-5xl(48px),--plinth-font-size-6xl(64px) and--plinth-font-leading-display(1.05), also in the Tailwind theme astext-5xl,text-6xlandleading-display -
Add the drawer (
<x-plinth::drawer>,PlinthDrawer): a panel on the bottom edge of a phone that
the person drags, with optionalpeek,halfandfullsnap points, and a dialog or a sheet
from 768px up (desktop). Dragging is the browser's scroll snapping; each layer adds the few
lines that close it when it is swiped off (x-initin Blade,useSwipeToClosein Vue and React).Every bottom panel on a phone now has a grab handle and closes when it is swiped down: a sheet
whose side on a phone is the bottom, the menu sheet and a dismissible dialog with
side-phone="bottom". The dialog and the sheet print their parts in a new panel
(plinth-dialog-panel,plinth-sheet-panel), the root's only child, with the handle in it
(plinth-dialog-handle,plinth-sheet-handle). New token:--plinth-drawer-peek-height.Breaking: the dialog's and the sheet's parts are inside the panel now, so a project's CSS that
selected them as the root's children (.plinth-sheet > .plinth-sheet-body) selects them inside the
panel (.plinth-sheet .plinth-sheet-body), and hand-written markup adds the panel. On a phone, a
tap above a bottom panel closes it through the layers' script, no longer through the browser's
closedby="any"alone. -
Add the info colours (
--plinth-color-info,-info-surface,-info-text), a quiet blue in light and dark for neutral information such as an info callout. They stay blue when a project changes its accent. -
The Composer package is now
ptbdynamic/plinth, installed from Packagist withcomposer require ptbdynamic/plinth: a rootcomposer.jsonpoints at the Blade package, and the download holds only the Blade components, the Filament plugin and the built CSS and fonts. -
A React layer,
@bdynamic/plinth/react: React 19 components that print the same markup as Blade and Vue, starting withPlinthBadge,PlinthIcon,PlinthButtonandPlinthIconButton. -
Port the remaining components to React: avatar, list row, list card, pill row and pill, header, section menu and its items, sheet, menu sheet, and the data table with its column, sort button, row, cell and empty row. They take the Vue props by the same names, with slots as
childrenand node props (leading,trailing,actions,footer,account,head), andonCloseon the sheets is the dialog's close event. The shared lists and icons (avatarSizes,headingLevels,sheetPlacements,dataTableSorts,dataTableCellKindsand the rest) are exported as in Vue. -
A selected item is no longer shown by colour alone: the pressed icon button, the selected pill and the current section menu item take a 2px accent edge around the selection tint. A pressed button answers hover and press with the new
color.accent-subtle-hoverandcolor.accent-subtle-activetokens, in light and dark; a project that overridesaccent-subtleoverrides these two as well. -
The sheet comes from the side you pick.
sideisend(the default),start,toporbottom, honoured at every width, and logical, sostartandendswap in right-to-left text.side-phone(sidePhonein React) optionally picks another side below 768px:side="end" side-phone="bottom"is a side panel on a tablet or desktop and a bottom sheet on a phone. The CSS reads them fromdata-sideanddata-side-phoneon the root. The menu sheet is a sheet withside="end" side-phone="bottom", and looks as it did.Breaking:
placementis removed, withdata-placement, Blade'sSheetPlacementenum (nowSheetSide),sheetPlacementandsheetPlacementsin Vue and React (nowsheetSide,sheetSidePhoneandsheetSides), and the--plinth-sheet-widthtoken. A sheet withplacement="center"(or none) becomes a dialog,<x-plinth::dialog side-phone="bottom">for the same bottom sheet on a phone, with--plinth-dialog-widthfor its width;placement="end"becomesside="end" side-phone="bottom". A sheet withoutsideis now a side panel on the end edge at every width.
Fixes
- The badge shrinks and ends its label in an ellipsis inside a flex or grid container, such as a list row's trailing slot, instead of overflowing it
- Code block: a label slot the parent adds later (for example
<template v-if="file" #label>) now shows. The Vue component checked the slot once, in a computed value that Vue never ran again, so the label stayed hidden; it now checks the slot as it renders, as Blade and React do. - The icon button shows its pressed state in forced colours with the Highlight system colour, and its markup contract shows the link form and says a link never prints
aria-pressed. In Blade, a blanklabelnow falls back to thearia-labelattribute, as in Vue and React, instead of refusing to render. - An open dialog, sheet or drawer and its backdrop reach the edge of the screen where the scrollbar takes space. The browser never draws the top layer in the scrollbar gutter, so the modal base no longer keeps a stable gutter on the page and turns the gutter off while a modal is open; the page under the backdrop shifts by the scrollbar's width instead.
PlinthIconandPlinthIconButtonnow let a project's attribute win when it clashes with one they set, as Blade and the other components already do:aria-hidden="false"on an icon, oraria-pressed="mixed"on an icon button, is printed instead of being dropped. docs/adr/0002 records the rule for every layer.PlinthButtonandPlinthIconButtontakecommandforandcommandas typed props, so a TypeScript project can open and close a sheet or dialog with an invoker command without spreading the attributes in.@types/reactdoesn't list them yet; Plinth types them on its own buttons and leaves React's global types alone. The values are exported asInvokerCommand. A link form takes neither.