Commit Graph
29 Commits
Author SHA1 Message Date
Andreas Reinhold / reiniandClaude Opus 5 c040925cd4 Draw the menu item without Tailwind
<x-menu-item> renders data-md-menu-item, data-md-description and its
aria-* state, with data-md-keep-open renamed from data-keep-open;
menu-item.css draws SegmentedMenuTokens' 48px row, 16px sides, 12px
gaps, 4/12px corners, the selected/current colours and the shared
--md-menu-item-ink icon-class outranks except when disabled
(ACT-11/19/27/28); a submenu's popover shares its container colour
with the menu it opens from and menu.js follows the rename (plan
step 36, actions).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 16:11:56 +02:00
Andreas Reinhold / reiniandClaude Opus 5 2f8fb2183f Draw the menu group without Tailwind
<x-menu-group> renders data-md-menu-group with data-md-gap and no
class list; menu-group.css draws the plain cluster's 4px padding and
the gapped Expressive layout's 2px item gap and 8px cluster margin
from SegmentedMenuTokens (plan step 36, actions).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 16:08:25 +02:00
Andreas Reinhold / reiniandClaude Opus 5 2acd9ab492 Draw the paginators without Tailwind
Laravel's and Livewire's paginator views render data-md-pagination
hooks; pagination.css draws the row, the 40px steps with their 48px
targets, the selected page and the swap to "Page n of m" below 600px
(plan step 36, inputs). It imports button.css for the simple
paginators, now that the button is rewritten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:47:07 +02:00
Andreas Reinhold / reiniandClaude Opus 5 6df034f81a Draw the menu separator without Tailwind
The separator renders data-md-menu-separator and takes its 1px line,
8px block margin and 16px inset from menu-separator.css in
material.components (plan step 36, actions).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:47:07 +02:00
Andreas Reinhold / reini b573cfbcc2 Merge branch 'worktree-agent-a9b4c522a39c6ce62'
# Conflicts:
#	tests/Feature/StylesheetsTest.php
#	workbench/resources/css/app.css
2026-09-14 15:41:37 +02:00
Andreas Reinhold / reiniandClaude Opus 5 c68a1fdbef Draw the sort header without Tailwind
<x-sort-header> renders data-md-sort-header (data-md-active on the
sorted column) with its button and arrow as data-md-* attributes; the
button keeps md-focus-ring and md-touch-target, the arrow takes size 16,
and the hover and hint-arrow states move into components/sort-header.css
(plan step 36). A browser test presses the button at the edge of its
48px target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:07:37 +02:00
Andreas Reinhold / reiniandClaude Opus 5 25e1bb4788 Draw the data table without Tailwind
<x-table> renders data-md-table with data-md-size and data-md-dense,
and table.css moves into material.components on px and spacing tokens,
its cell selectors still inside :where() so a caller's cell rule wins
(plan step 36). The showcase's layout table follows the hook. A browser
test pins 52px rows and 36px dense ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:06:51 +02:00
Andreas Reinhold / reiniandClaude Opus 5 1cf4f16c95 Draw the FAB without Tailwind
Plan step 36. <x-fab> renders data-md-fab with data-md-size,
data-md-color, data-md-variant, data-md-extended and, collapsing on
scroll, data-md-collapse-on-scroll with a bound data-md-collapsed; it
passes its glyph's size to <x-icon>. fab.css draws FabBaseline/Medium/
LargeTokens and ExtendedFab*Tokens per size, the container and filled
colours, elevation 3 and 4 on hover, the state layer and focus ring,
and the collapse morph that leaves actions.css.

data-fab becomes data-md-fab, also in navigation.css (the rail flattens
a nested FAB) and toolbar.css (a docked toolbar's FAB), with their tests.
The actions browser test gains the owed collapse-on-scroll test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:06:45 +02:00
Andreas Reinhold / reiniandClaude Opus 5 4141ebe7b0 Draw the search without Tailwind
<x-search> renders data-md-search with data-md-trigger and binds
data-md-open and data-md-full-screen; its parts become data-md-search-*
and the empty row data-md-search-empty. search.css moves into
material.components on px, spacing and state tokens (plan step 36).
search.js and the showcase layout follow the renamed hooks.

Browser tests cover the polite result count as it changes, the icon
entry point expanding full screen and returning focus, and suggestions
swapping to results on the first key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:04:50 +02:00
Andreas Reinhold / reiniandClaude Opus 5 2a4dcead3d Draw the split button without Tailwind
Plan step 36. <x-split-button> renders data-md-split-button and
data-md-size on the pair and data-md-split on its halves. split-button.css
draws SplitButton*Tokens' shape — full outer corners, inner corners that
grow under the finger, the trailing half round while its menu is open —
the narrower leading padding and 48px trailing half at xs and sm, and the
chevron's own size, nudge and turn on the standard scheme. groups.css is
empty and leaves tailwind.css.

The actions browser test follows data-md-split and data-md-button-group,
and gains the owed tests for a connected segment's 48px edge and a
button group's single-required and multi selection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:03:02 +02:00
Andreas Reinhold / reiniandClaude Opus 5 281c21b0a4 Draw the slider without Tailwind
<x-slider> renders data-md-slider with its size, colour, value label,
orientation and centring as data-md-* attributes and its parts as
data-md-slider-*; every size, colour role, disabled state, the vertical
quarter turn, RTL mirroring and the no-script fallback move into
components/slider.css as custom properties per size and colour (plan
step 36). slider.js reads the props from the root and marks the
renamed handle, tick and icon hooks.

Browser tests pin the handle centred on the track at each size, Space
held with an arrow, and the vertical slider's drag along Y, keys and
value label beside the handle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 15:01:19 +02:00
Andreas Reinhold / reiniandClaude Opus 5 b8c6d411db Draw the connected choice group without Tailwind
Plan step 36. <x-group> renders data-md-group with its size, variant,
shape, multiple and inline, a data-md-button-group row and
data-md-group-segment labels over its radios or checkboxes. group.css
draws the segments as M3's buttons with the toggle button's colours
from :has(:checked), the disabled treatment from :has(:disabled), the
focus ring from :has(:focus-visible) and the 48px target at xs and sm.

The connected shapes move into button-group.css (the corner scale,
square ends, the pressed and selected inner corners), which group.css
imports; <x-button-group> adopts them in its own rewrite. The group's
render tests move to GroupTest; AppBarTest (navigation group) follows
the new legend and row hooks of theme-toggle's rows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:56:59 +02:00
Andreas Reinhold / reiniandClaude Opus 5 1bb5adab0e Draw the choices without Tailwind
<x-choices> renders data-md-choices (data-md-searchable) and its
"Nothing matches" row as data-md-choices-empty, drawn by
components/choices.css, which brings the field, chip set and chip it
renders (plan step 36).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:55:29 +02:00
Andreas Reinhold / reiniandClaude Opus 5 55cf8ceed7 Draw the chip set without Tailwind
<x-chip-set> renders data-md-chip-set (data-md-scroll), its row, label,
hint, errors and scroll buttons as data-md-* attributes, and its row,
fade mask, scroll padding and pointer-fine buttons move into
components/chip-set.css on tokens (plan step 36). chips.js marks the
row data-md-scroll-start and data-md-scroll-end. Browser tests cover the
scroll buttons in LTR and RTL and the arrow keys with a roving tab stop
that scrolls the focused chip clear of the button.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:54:41 +02:00
Andreas Reinhold / reiniandClaude Opus 5 4ad257034e Draw the button without Tailwind
Plan step 36. <x-button> renders data-md-button with its variant, colour,
size, shape, icon-button width, selected state and compact FAB as
data-md-* attributes, and passes the glyph's size to <x-icon>.
button.css draws Button*Tokens' geometry per size, the colour roles
through custom properties that the disabled treatment replaces, the
state layer, focus ring and 48px target, and the compact FAB below
600px. Its corner rules carry no specificity (:where), so a group's
stylesheet reshapes the buttons inside it with any selector; the
split button no longer passes an empty corners prop, which is gone.

data-icon-button becomes data-md-icon-button, also in groups.css,
toolbar.css and theme-toggle's own button (navigation group), and the
AppBarTest assertions follow the new hooks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:50:58 +02:00
Andreas Reinhold / reiniandClaude Opus 5 d8072d878a Draw the chips without Tailwind
<x-chip> renders data-md-chip with its type and its states and parts as
data-md-* attributes (elevated, disabled, selected, actionable, the
icon, check slot, avatar, action and remove button), and every colour,
size, target and transition moves into components/chip.css on tokens
(plan step 36). Icons take size 18; the filter checkbox is
md-visually-hidden. chips.js follows the renamed chip hooks.

A disabled filter chip drawn as a label no longer shows a hover state
layer, which M3 never gives a disabled control. Browser tests cover the
32px chip and the remove button's 48px target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:50:29 +02:00
Andreas Reinhold / reiniandClaude Opus 5 7bdd3ef61c Draw the badge without Tailwind
Plan step 36. <x-badge> renders data-md-badge with data-md-dot,
data-md-variant (solid, tonal or outline, resolved in that order),
data-md-color and data-md-floating; badge.css draws BadgeTokens' dot and
count, the status label, each colour's pair of roles through custom
properties, and M3's anchor geometry when floating. A plain badge sets
no colour, so the caller's CSS paints it.

NavigationBarTest (navigation group) asserts the dot by data-md-dot.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:34:24 +02:00
Andreas Reinhold / reiniandClaude Opus 5 f86afc0542 Draw the checkbox and the selection controls' row without Tailwind
<x-checkbox> renders data-md-checkbox, its box, tick and dash, and its
row, text and errors as data-md-* attributes; the 18px tick takes a size
prop and a label-less box md-touch-target (plan step 36). selection.css
moves into material.components as the row, text and state layer the
three controls share, and each control's drawing goes to its own file:
checkbox.css, radio.css, toggle.css, on the state tokens. The radio and
the switch take the renamed shared hooks now and lose their layout
classes in their own commits. field.js follows data-md-indeterminate.

Renaming the switch's data-handle also stops selection.css matching the
slider's handles, which it drew 24px above the track.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:34:00 +02:00
Andreas Reinhold / reiniandClaude Opus 5 3083fe28b2 Move the file picker's rules out of the field into file.css
<x-file> marks its field root data-md-file, and the tonal
::file-selector-button with its hover and disabled states moves from
field.css to components/file.css on the state tokens (plan step 36). A
browser test pins the field's 56px box and 16px padding and the pill.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:12:40 +02:00
Andreas Reinhold / reiniandClaude Opus 5 23f2bdabf9 Move the select's rules out of the field into select.css
<x-select> marks its field root data-md-select, and what a <select>
changes in the field — covering the whole box, the customizable
select's closed button, the focused look and turned arrow while open —
moves from field.css to components/select.css (plan step 36). The open
list stays in menu.css until the menu leaves Tailwind.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:11:40 +02:00
Andreas Reinhold / reiniandClaude Opus 5 147dbcf041 Draw the plain tooltip without Tailwind
Plan step 36. <x-tooltip> renders data-md-tooltip and data-md-side on
the bubble and data-md-tooltip-anchor on a standalone trigger's wrapper;
tooltip.css draws PlainTooltipTokens' inverse-surface bubble, its anchor
placement and flips per side, and the fade on the fast effects spring
with @starting-style.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:11:37 +02:00
Andreas Reinhold / reiniandClaude Opus 5 c2fe64e00d Move the textarea's rules out of the field into textarea.css
<x-textarea> marks its field root data-md-textarea, and what a
<textarea> changes in the field — the grip in the corner, the label on
the first line, autogrow between rows and max-rows, the filled offsets —
moves from field.css to components/textarea.css (plan step 36).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:11:22 +02:00
Andreas Reinhold / reiniandClaude Opus 5 6c7414d60e Draw the loading indicator without Tailwind
Plan step 36. <x-loading> renders data-md-loading and data-md-contained,
and loading.css in material.components draws the 48px indicator in
primary, the contained circle and the still shape under reduced motion.
The view no longer reads the caller's classes to decide its size and
colour: a caller's utility outranks the package's layer on its own.

ActionStylesheetsTest checks the group's stylesheets for the package's
shape (layer statement, plain imports, material.components, tokens, px
breakpoints, imports of rendered components) and its views for class
lists; tests/Support/ComponentStylesheet reads a rule's declarations.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:10:16 +02:00
Andreas Reinhold / reiniandClaude Opus 5 cfdb4619ad Give the password field its own stylesheet entry
<x-password> marks its field root data-md-password, and
components/password.css brings the field and its icons (plan step 36).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:10:14 +02:00
Andreas Reinhold / reiniandClaude Opus 5 172629face Give the one-line text field its own stylesheet entry
<x-input> marks its field root data-md-input, and components/input.css
brings what it renders, the field and its icons, so an application
imports one file per component (plan step 36).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:09:58 +02:00
Andreas Reinhold / reiniandClaude Opus 5 0341f9d4ca Draw the text field's chrome without Tailwind
<x-field> renders data-md-field with its props and parts as data-md-*
attributes (box, control, label, outline, support, counter, trailing
buttons), and field.css moves into material.components on tokens: px
geometry, spacing and state tokens, the 600px breakpoint (plan step 36).
Its icons take a size prop, 24/20/16 by the field's size.

Every control the field wraps now marks itself data-md-field-control,
so the inputs, the pickers, choices, field.js, menu.css's select and
listbox rules and timepicker.css follow the renamed hooks. Browser tests
cover the error icon, the disabled field's hover, the counter and the
width bound from 600px.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:08:22 +02:00
Andreas Reinhold / reiniandClaude Opus 5 a6e5a593d5 Draw the form without Tailwind
<x-form> renders data-md-form and data-md-form-actions, and its column
and actions row move to components/form.css in material.components, on
the spacing tokens (plan step 36). The actions slot's own attributes
still land on the row.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 13:59:32 +02:00
Andreas Reinhold / reiniandClaude Opus 5 6be9f35c98 Group the stylesheet import lists by component stream
tailwind.css and components.css now hold one block per audit group, and the new
layout.css gathers the layout components, so the parallel rewrites of plan steps
35 and 36 each edit their own lines. .browser-lock is the lock that keeps those
streams to one browser at a time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 13:50:27 +02:00
Andreas Reinhold / reiniandClaude Opus 5 bdbb76a0bd Size icons and shapes with a prop instead of a Tailwind class
<x-icon size> writes --md-icon-size (24px by default) and takes the optical-size-20
cut for 20px or less, as M3 asks; mirror-rtl flips a directional symbol. <x-shape
size> writes --md-shape-size. Both draw from plain-CSS stylesheets in
material.components, gathered in components.css until all.css replaces it; a
caller's size class still wins while the other components are rewritten.
Plan steps 35 and 36, the prop every component rewrite depends on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 13:49:24 +02:00