Merge development for v5.1.0 - #650
Merged
Merged
Conversation
Checkboxes and radios now match the real Checkbox component's colour and shape (the shape fix needed an explicit override since Tailwind's Preflight reset beats the Forms plugin's zero-specificity :where() rule, same conflict the real Radio component already works around with rounded-full). The search field now reuses the actual .bw-input class and icon-prefix pattern instead of a hand-tuned lookalike, so it can't drift out of sync with Input again. Also fixes: header text alignment losing to a more specific thead th rule, a doubled border between the last visible row and the pagination footer on paginated grids (tr:last-child was matching the true last row in the DOM, not the last visible one), and a missing cursor:pointer on Clear selection.
The docs site's hand-rolled search dialog (blurred backdrop, rounded- 3xl panel, softly-rounded result cards, and a proper icon+heading+ description empty state) looked noticeably more polished than the actual Command Palette component it was meant to showcase. Brought the component's own CSS in line: backdrop-filter blur, bigger panel and item radii, a permanently-filled close button instead of hover- only, and a richer empty state with an icon badge and supporting description (new emptyDescription prop, backward compatible). The loading state now shows a spinning icon rather than plain text, done with a lightweight CSS animation instead of adding the Spinner package as a new dependency.
positionItems() computed the dropdown's fixed left/top from the trigger's viewport-relative getBoundingClientRect(), but an ancestor with transform, filter, perspective, contain, or backdrop-filter (e.g. modal's drop-shadow-2xl) becomes the containing block for position:fixed instead of the viewport — so a select opened inside a modal landed away from its trigger. Added a shared fixedPositioningOffset() helper that finds such an ancestor and compensates. The select trigger also carried bg-white, forcing a white box in light mode regardless of what it sat on, unlike the input field which is transparent by default. Switched to bg-transparent. Separately, #eab011c added border-2 to .bw-input to fix faint borders but never adjusted .form-label's top offsets for the extra 2px, so labels sat visibly closer to the top border than centered. Added the 2px back across all sizes and rebuilt the CSS bundle.
Today's date badge in month view and today's whole column in week/day view were always tinted with no way to turn it off. Gate both behind a new highlight-today prop (default false) in the PHP render and its JS client-navigation mirror alike. aria-current="date" stays unconditional either way, since that's a screen-reader signal, not a visual one.
Two bugs in month view's overflow toggle, reported against the docs site: 1. Clicking "Show less" hid every event in the cell, not just the overflow ones. The click handler's selector, [data-bw-calendar-overflow-event], matched the attribute's mere presence rather than its value, so it grabbed both data-bw-calendar-overflow-event="true" and ="false" markers alike. 2. Once expanded, every event row rendered at height: 0 with its text overlapping instead of stacking. .bw-calendar-event defaults to flex-shrink: 1 as a flex item of .bw-calendar-cell-events, so when the column ran out of room the browser crushed every row toward zero height instead of leaving them their natural size and letting the column's own overflow-y: auto scroll. Verified the added Playwright assertions actually catch both regressions by reverting each fix in turn and confirming the test fails, then restoring and confirming it passes.
The previous fix (fa04f52) gave event rows flex-shrink: 0 so they keep their real height instead of being crushed to zero -- correct, but it left the "+N more" button (a different class, .bw-calendar-event-more, not .bw-calendar-event) still shrinkable, and it turned out real, unshrunk heights for max-events-per-day's default of 3 rows plus the button don't quite fit the cell's existing budget. The button ended up needing a scroll to see even before expanding anything -- not what a first-time visitor expects from a plain "+N more" link, and not what the README already promised ("its own small internal scrollbar once +N more is expanded", i.e. only once expanded). Reclaimed the ~12px shortfall from the row layout itself rather than touching the calendar's overall fixed height, which already exactly fills its 40rem budget for a 6-week month: dropped events'/the more button's vertical padding in favour of line-height alone, tightened the row gap, and gave the button the same flex-shrink: 0. Confirmed the default collapsed state now fits with zero scroll needed, and that expanding still needs to scroll exactly when it should (verified the new assertion fails without this fix and passes with it).
Tailwind's own Preflight puts a default focus ring on every text-like input via box-shadow -- a property outline:none and border:0 don't touch, since it's a separate CSS declaration entirely. The ring only shows once :focus-visible actually matches (real keyboard-context focus, not a plain programmatic .focus() call), which is why it slipped through: any test or manual check that opens the palette and calls .focus() directly misses it, only a genuine click/keyboard-triggered focus reproduces it. Fixed by explicitly setting box-shadow: none on .bw-command-palette-input. Verified against a real click-triggered focus (checked :focus-visible actually matched), and confirmed the new Playwright assertion fails without the fix and passes with it.
# Conflicts: # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css
Was dot+date/time eyebrow, then title, then description -- title now comes first, followed by the dot+date line, then a separate time line (only present for timed events; empty and hidden via CSS :empty for all-day events), then description and link, unchanged. Split calendarFormatEventDateTime into calendarFormatEventDate and calendarFormatEventTime so the two lines can be populated independently.
* Reorder the event details drawer: title, then date, then time Was dot+date/time eyebrow, then title, then description -- title now comes first, followed by the dot+date line, then a separate time line (only present for timed events; empty and hidden via CSS :empty for all-day events), then description and link, unchanged. Split calendarFormatEventDateTime into calendarFormatEventDate and calendarFormatEventTime so the two lines can be populated independently. * Add spinner overlay to data-grid loading state
hide-input replaces mask (kept as a deprecated alias) and now actually works, since numeric mode was forcing every box back to type=number regardless of mask. Also fixes boxes accepting more than one digit, including the last box never releasing focus.
showDrawer() schedules its initial focus via requestAnimationFrame, which can resolve after something else (a script, assistive tech, or a fast Tab) already moved focus into the drawer, stealing it back to the first focusable element. Skip the auto-focus when focus is already inside the drawer by the time the frame runs. Fixes the flaky "modal focus wraps and stacked drawers close from the top" E2E test.
… !important PackageIdentityTest was failing because "bladewindui/bladewindui" had been dropped from composer.json's replace block. monorepo-builder's UpdateReplaceReleaseWorker regenerates that block from packages/* directories only, so it has no idea about the two manually-maintained former-name shim entries — it silently dropped this one during the v4.5.0 release run and it has been missing ever since. Re-added, at the same self.version marker as everything else. ConfigSurfaceTest was failing because code's new has_separator/hide_input props (added for the OTP separator/masking feature) were never added to the published packages/meta/config/bladewind.php, so a consumer had no way to discover them without reading the Blade source. CompiledCssTest was failing because .bw-data-grid-search-input used !important to win its padding-left override over .bw-input's own px-3 — exactly the pattern removed everywhere else in 4.4.0. Switched to a compound selector (.bw-data-grid-search-input.bw-input) for real specificity instead. Rebuilt the CSS bundle so the committed one matches, which the "Build CSS bundle" check was also failing on. Full local verification: vendor/bin/phpunit (555 passed), npm run test:js, vendor/bin/monorepo-builder validate.
All three shipped as complete components in v5.0.0 but were never added to the component tables here, so this README was already stale for the components it claims to document. Also fixes the license badge, which still pointed at the old bladewindui/bladewindui repo name.
…list item Rejects Tree view, Fieldset, Masked input, Rich text editor, Segmented control, Cascader, Mention input, Signature pad, Image cropper, Lightbox, Guided tour, Split button, Speed dial, Gantt chart, and Org chart as low-value for typical Laravel admin/SaaS apps. Adds Divider, Confirm dialog, Password strength meter, Currency input, Document preview, and Copy-to-clipboard button as candidates (tracked in GitHub issues #614-631). Also adds a completion-checklist item requiring new components to document Livewire wire:ignore guidance and fire native input/change events for wire:model compatibility, following up from #632.
Dropmenu, Popover, Select, Sortable, Datepicker, and Filepicker instantiated their JS widget in a script tag that wasn't guarded against re-execution, so a Livewire re-render created a duplicate instance and duplicate document-level listeners on every render. Datepicker was the worst case, appending a brand-new calendar popup to document.body each time. All six now guard on a data-bwInitialised flag, matching the convention already used by Data Grid, Sidebar, and Stepper. Sortable's guard was wrapped in a closure that broke its documented "read the order yourself" API (bare `list_name.toArray()` from another script tag), so its Sortable instance is now exposed via window instead of a block-scoped const. Added a setFieldValue() helper (core/helpers.js) that sets a field's value and dispatches a native change/input event, and wired it into every component that previously set .value directly with no dispatch: Rating, Colorpicker, Timepicker, Slider, Sortable, Datepicker, and Filepicker's base64 hidden inputs. wire:model now observes these without extra wiring. Updated the README for all 16 audited components with a Livewire section covering the above where it applies, or wire:ignore guidance for the components (Data Grid, Command Palette, Sidebar, Drawer, Tab, Stepper) whose interaction state lives in the DOM rather than Livewire state.
Wraps the long intro paragraph and realigns the component tables to a consistent column width; no content changes.
- modal: add dialog ARIA (role, aria-modal, aria-labelledby) and an accessible label on the icon-only close button - card, statistic, avatar (+N more): clickable divs are now keyboard operable, via role/tabindex plus the existing bwActivateOnKey() delegation pattern rather than inline handlers (a repo-enforced CSP test forbids those) - table, table-columns: onclick rows are keyboard operable via a new delegated data-bw-table-row-clickable listener - avatar: the alt prop is now actually applied to the <img> tag - popover: wire up aria-expanded/aria-haspopup/aria-controls and role="dialog", toggled by popover.js on show/hide - tooltip: set aria-describedby on the trigger while the bubble is shown - select: give the inline <style> block a CSP nonce; drop an untracked !important the compiled-CSS test couldn't see - number, textarea (Quill toolbar): route value changes through the existing setFieldValue() helper so wire:model observes them, and add a bwInitialised re-render guard matching the #632 pattern; the same fix applied to checkMinMax()'s clamp path in helpers.js since input shares it - tooltip, calendar, data-grid, command-palette, sidebar, drawer: replace hardcoded dark-mode hex colors with the shared --color-dark-* tokens - add missing test coverage for colorpicker, horizontal-line-graph, listview, popover, spinner, theme-switcher, timeline, timepicker, and tooltip (59 new tests)
New leaf package bladewind-divider (Content group): horizontal or vertical rule with an optional centered label, none/small/medium/large spacing, a colour override, and decorative vs semantic (role=separator) modes. Closes #626.
New leaf package bladewind-confirm-dialog (Content group), composing Modal rather than duplicating it: a danger/warning/info/primary tone picks the icon and confirm button colour, the backdrop cannot dismiss it by default, and an onConfirm JS expression can return a promise — while it is pending both buttons disable and the confirm button shows a spinner (runBwConfirmDialogAction in helpers.js), and a rejection re-enables them and leaves the dialog open. Closes #627.
New leaf package bladewind-context-menu (Navigation group): gives any region a right-click (or keyboard context-menu key) action menu, with icons, disabled items, separators, a danger tone, and arbitrarily nested submenus. Placement is viewport-aware for both the top-level menu and every submenu, flipping away from whichever edge it would otherwise overflow. A dedicated context-menu.js drives positioning, roving-tabindex keyboard navigation (arrows, Home/End, Enter/Space, Escape), and submenu open/close on hover, click, or the arrow keys — separate from Dropmenu's JS since it anchors to a pointer position rather than a trigger element and has no trigger of its own. Closes #614.
New leaf package bladewind-currency-input (Forms group), wrapping
Input's existing money mask rather than duplicating it: derives the
currency symbol, its position, and the decimal/thousands separators
from a currency code and locale via PHP's intl extension when it's
installed, falling back to a small built-in symbol table and
locale-independent defaults ('.', ',', 2 decimal places, 0 for
zero-decimal currencies like JPY) when it isn't. Every derived value
can be overridden individually. Closes #629.
New leaf package bladewind-password-meter (Forms group): a standalone companion that watches an existing password field by name/id (for prop) rather than wrapping it, so it works with any password field, BladewindUI's own or otherwise. Scores 0-4 on keystroke — up to two points for length (min_length, strong_length thresholds) and up to two for character variety (lower/upper/digit/symbol) — and reflects that as a 4-segment colour bar plus an optional translated label. Also fixes a pre-existing drift between the maintained lang/en source and the packages/core/lang/en copy Laravel actually loads at runtime (loadTranslationsFrom points at packages/core/lang) — "close" had been added to the former but never synced to the latter. Closes #628.
New leaf package bladewind-file-preview (Forms group): the read-only display counterpart to Filepicker. Shows a thumbnail or an extension-derived file-type icon, the filename, a human-formatted size (bytes in, B/KB/MB/GB out), and download/remove actions. The remove control defaults to removing itself from the DOM (delegated via a new [data-bw-file-preview-remove] listener in helpers.js, mirroring Tag's dismiss-button pattern) and is fully overridable with onRemove for server-backed removal. Closes #630.
New leaf package bladewind-transfer-list (Forms group): two panels,
"Available" and "Selected", with per-panel search, select-all, arrow
buttons to move checked or all items, and a double-click shortcut to
move a single row. Submits as a normal name[] array field — one
hidden input per item, enabled only while it sits in the "Selected"
panel, toggled in place rather than added/removed from the DOM.
items accepts an array or JSON string of {value, label} objects, with
valueKey/labelKey overrides matching Select's own convention.
Closes #615.
# Conflicts: # README.md # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css
# Conflicts: # COMPONENT_BACKLOG.md # README.md # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css
# Conflicts: # COMPONENT_BACKLOG.md # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css
# Conflicts: # README.md # composer.json # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css # packages/meta/config/bladewind.php
# Conflicts: # README.md # composer.json # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css # packages/meta/config/bladewind.php
# Conflicts: # COMPONENT_BACKLOG.md # README.md # composer.json # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css # packages/meta/config/bladewind.php
… section Left behind by the feature/scheduler merge conflict resolution.
# Conflicts: # composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css # packages/forms/composer.json # packages/meta/config/bladewind.php
Context Menu, Divider, Confirm Dialog, Transfer List, Inline Edit, Password Meter, Currency Input, File Preview, Carousel, Banner, Code Block, Kbd, Description List, Chat, Meter, Copy Button, Kanban, and Scheduler are all merged into development.
Their items-list wrapper carries permanent animate.css classes (animation-fill-mode: both never gets cleaned up), which browsers treat as an ongoing opacity animation and promote to its own stacking context with an implicit z-index of auto. That trapped the intended z-[9999] on the fixed/absolute items list inside a context that could lose a same-tier stacking tie to whatever comes later in the DOM, e.g. a code block below the demo on a docs page. Giving the wrapper itself an explicit position and z-index keeps it (and any nested submenu) at the intended stacking priority regardless of what surrounds it.
Combining 'hidden' with 'inline-flex' on the same element is unreliable: whichever utility's rule comes later in the compiled CSS wins the cascade, not the more specific-looking class. inline-flex was emitted after hidden, so the JS toggle never actually hid either icon.
Rounded corners (0.25rem, was 0.375rem) and no border, matching the solid-tinted look of calendar's event pills. Keeps scheduler's own open color palette (any Tailwind color name) rather than calendar's fixed info/success/warning/danger set.
The topmost hour label was centered exactly on the header/body boundary line like every other hour label, but unlike interior labels it has no row above it to share that space with, so it read as sitting right on the line. It now sits just inside its own row instead. Also raise the minimum event height from 18px to 32px: a 30-minute appointment at the default 30-minute grid was rendering at exactly one slot (24px), too short to fit both the label and time-range lines without clipping.
Every hour label centers on its own gridline via a -8px offset, which looks fine at interior boundaries where the previous row's whitespace absorbs it, but the first hour had nothing above it to absorb into: it sat flush against the header border while the last hour's label kept the full row's worth of natural trailing space below it. Added a one-row spacer above the grid, sized to match that trailing space, so the gap before the first label now matches the gap after the last one.
The earlier 32px minimum height fix for text clipping grew a 30-minute appointment's box beyond its real end time, eating into the following slot's space and leaving no visible room for a legitimately adjacent appointment to render. Now the box always matches its actual duration (floored only to 16px so it stays clickable); when that's too short for both the label and time-range lines, the time line is dropped and moved into a title tooltip instead of being clipped or shown at all.
Prism's own stylesheet sets padding: 1em on <pre>, which read as excessive vertical whitespace around short snippets. Override just the vertical component (!py-2, matching how !m-0 and !rounded-none already beat Prism's rules here) and leave the 1em horizontal padding as-is.
Prism's .line-highlight hardcodes margin-top: 1em to exactly cancel out its own default pre[data-line] padding: 1em. Our earlier !py-1 override changed that padding to 4px without updating the other half of that pairing, so every highlighted line rendered 10px below the line it was meant to mark. Its background is also a warm, low-opacity tint tuned for Prism's light theme and was nearly invisible against our dark background. Both are now overridden together, scoped to this component.
…let listview items forward attributes Context menu: - Add a target prop (CSS selector or bare element id) so the menu can bind to an element elsewhere on the page instead of requiring the trigger to be wrapped in the region slot, useful for menus scoped to a whole page or an element you don't want to restructure. - Drop the outer wrapper's hardcoded inline-block, which capped a block/w-full region's width to its own shrink-to-fit size instead of the actual container. - Swap focus: for focus-visible: on items so the first item doesn't look pre-highlighted the instant the menu opens (a mouse action), while keyboard navigation still highlights the focused item. - Fix danger tone: the icon's color was hardcoded regardless of tone, so only the label text turned red, not the icon. Listview: - Forward extra attributes (id, data-*, wire:key, ...) onto the <li> via $attributes->merge, needed to target individual list rows with the context menu's new target attribute, and generally useful on its own.
The document-level data-bw-modal-close delegation (added for strict CSP support, #608) never fired because clicks inside the modal box were swallowed with stopImmediatePropagation before they could bubble to the document listener. Every modal using the default close action for its Cancel or OK button was unclosable by that button. Replace the propagation-swallowing with a target check on the backdrop listener so it only closes on clicks that actually land on the backdrop, letting clicks elsewhere bubble normally.
# Conflicts: # README.md # composer.json # packages/calendar/resources/assets/css/calendar.css # packages/command-palette/resources/assets/css/command-palette.css # packages/content/composer.json # packages/core/public/css/bladewind-ui-no-preflight.min.css # packages/core/public/css/bladewind-ui.min.css # packages/data-grid/resources/assets/css/data-grid.css # packages/forms/composer.json # packages/meta/config/bladewind.php # packages/navigation/composer.json
…k, stale line-highlight test assertion CurrencyInputTest expected GH₵ for GHS, but with ext-intl installed (as CI has, unlike this sandbox) ICU's NumberFormatter has no real glyph for GHS in en-US and just echoes the currency code back as the "symbol". The component accepted that as a real resolved symbol, skipping past its own curated fallback map that already had the correct GH₵ entry. Only accept ICU's symbol when it actually differs from the currency code. CodeBlockTest still asserted the old margin-top: 0.25rem value for Prism's line-highlight override; the source moved to 1px in 074449b/ 868953c but the test wasn't updated then.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merges the v5.1.0 development cycle into main.
New components: Divider, Confirm Dialog (later removed, see below), Context Menu, Currency Input, Password Strength Meter, Document/File Preview, Transfer List, Inline Edit, Keyboard Key, Copy to Clipboard Button, Meter/Gauge, Description List, Banner (later removed, see below), Code Block, Chat, Carousel, Kanban, Scheduler, Credit Card.
Removed during this cycle: Confirm Dialog (duplicated existing Modal patterns), Banner (duplicated Alert).
Notable fixes: Calendar event details drawer and highlight-today, Command Palette focus ring and restyle, Data Grid checkbox/search/layout, select dropdown positioning, Copy Button icon state, Context Menu/Dropmenu stacking, Scheduler appointment styling and slot sizing, Credit Card controls and gradients, modal default close button, secondary button style, code block padding/line-highlight.
Root
composer.json's inter-package version constraints andreplaceblock were already manually bumped to 5.1.0 on this branch (46962e0, 5ac8b0e) ahead of merging.Test plan
vendor/bin/monorepo-builder validatepasses on main after merge