Import the foundation before Tailwind in the Workbench

Plan step 33. The Workbench imports foundation.css ahead of
@import 'tailwindcss', so the material layers are declared first and
sit below Tailwind's, then tailwind.css: the theme, the token utilities
and the component stylesheets still written for Tailwind, with no
tokens, so nothing is declared twice. material.css keeps working for
1.x-style imports after Tailwind by bringing the tokens, the hiding
rules and tailwind.css, and never the reset, which would outrank
Tailwind's utilities from there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 13:43:23 +02:00
co-authored by Claude Opus 5
parent 0ab3bd861d
commit 1075305a9c
4 changed files with 49 additions and 24 deletions
+8 -20
View File
@@ -1,6 +1,6 @@
/* /*
* Livewire Material — the one stylesheet an application imports, after Tailwind, followed by * Livewire Material on 1.x-style imports — the one stylesheet an application imports, after
* the scheme `php artisan material:scheme` wrote for it: * Tailwind, followed by the scheme `php artisan material:scheme` wrote for it:
* *
* @import 'tailwindcss'; * @import 'tailwindcss';
* @import '../../vendor/nonameweb/livewire-material/resources/css/material.css'; * @import '../../vendor/nonameweb/livewire-material/resources/css/material.css';
@@ -11,6 +11,11 @@
* tokens/scheme.css is the package's own default (M3's baseline purple), so an application * tokens/scheme.css is the package's own default (M3's baseline purple), so an application
* renders before it has a scheme; the application's file declares the same roles, unlayered, and * renders before it has a scheme; the application's file declares the same roles, unlayered, and
* wins over the default in `material.tokens`. * wins over the default in `material.tokens`.
*
* It brings the tokens, the two hiding rules and tailwind.css, but not foundation.css: imported
* after Tailwind, the foundation's reset would land in a layer above Tailwind's utilities and
* undo them. An application moving to 2.0.0's vocabulary imports foundation.css before
* `@import 'tailwindcss'` and tailwind.css after it, instead of this file.
*/ */
@import './tokens/scheme.css'; @import './tokens/scheme.css';
@@ -19,26 +24,9 @@
@import './tokens/motion.css'; @import './tokens/motion.css';
@import './tokens/type.css'; @import './tokens/type.css';
@import './tokens/font.css'; @import './tokens/font.css';
@import './tokens/theme.css';
@import './tokens/state.css'; @import './tokens/state.css';
@import './tokens/utilities.css';
@import './foundation/hidden.css'; @import './foundation/hidden.css';
@import './components/actions.css'; @import './tailwind.css';
@import './components/groups.css';
@import './components/list.css';
@import './components/collapse.css';
@import './components/dialog.css';
@import './components/field.css';
@import './components/menu.css';
@import './components/selection.css';
@import './components/search.css';
@import './components/datepicker.css';
@import './components/timepicker.css';
@import './components/tabs.css';
@import './components/app-bar.css';
@import './components/navigation.css';
@import './components/toolbar.css';
@import './components/table.css';
@layer base { @layer base {
html { html {
+34
View File
@@ -0,0 +1,34 @@
/*
* Livewire Material's Tailwind half: the theme that turns the tokens into utilities, the token
* utilities, and the component stylesheets still written for Tailwind (`@utility`, `@variant`,
* `@layer components`). It goes when the last component leaves Tailwind.
*
* It carries no tokens, so it can sit behind the foundation without declaring them twice — the
* Workbench imports it that way, after Tailwind:
*
* @import '../../../resources/css/foundation.css';
* @import 'tailwindcss' source(none);
* @import '../../../resources/css/tailwind.css';
*
* An application on 1.x-style imports keeps importing material.css, which brings the tokens and
* this file together.
*/
@import './tokens/theme.css';
@import './tokens/utilities.css';
@import './components/actions.css';
@import './components/groups.css';
@import './components/list.css';
@import './components/collapse.css';
@import './components/dialog.css';
@import './components/field.css';
@import './components/menu.css';
@import './components/selection.css';
@import './components/search.css';
@import './components/datepicker.css';
@import './components/timepicker.css';
@import './components/tabs.css';
@import './components/app-bar.css';
@import './components/navigation.css';
@import './components/toolbar.css';
@import './components/table.css';
+1 -1
View File
@@ -88,7 +88,7 @@ it('divides a scrolling body from its header and actions only while content is h
->toContain('position: absolute;') ->toContain('position: absolute;')
// A token that reduced motion sets to zero, so then the rule appears without a fade. // A token that reduced motion sets to zero, so then the rule appears without a fade.
->toContain('transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);') ->toContain('transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);')
->and(File::get(__DIR__.'/../../../resources/css/material.css'))->toContain("@import './components/dialog.css';") ->and(File::get(__DIR__.'/../../../resources/css/tailwind.css'))->toContain("@import './components/dialog.css';")
->and(File::get(__DIR__.'/../../../resources/js/material.js'))->toContain("import './dialog.js'") ->and(File::get(__DIR__.'/../../../resources/js/material.js'))->toContain("import './dialog.js'")
->and(File::get(__DIR__.'/../../../resources/js/dialog.js')) ->and(File::get(__DIR__.'/../../../resources/js/dialog.js'))
->toContain("directive('dialog-dividers'") ->toContain("directive('dialog-dividers'")
+6 -3
View File
@@ -1,7 +1,10 @@
/* The Workbench builds the package exactly as an application would, with explicit /* The Workbench builds the package as an application would, with explicit sources so the plans
sources so the plans in docs/ are not scanned for class names. */ in docs/ are not scanned for class names. The foundation comes before Tailwind, so the
`material` layers are declared first and sit below Tailwind's; tailwind.css brings the
components still written for Tailwind, without declaring the tokens a second time. */
@import '../../../resources/css/foundation.css';
@import 'tailwindcss' source(none); @import 'tailwindcss' source(none);
@import '../../../resources/css/material.css'; @import '../../../resources/css/tailwind.css';
@import './material-scheme.css'; @import './material-scheme.css';
@source '../../../resources/views'; @source '../../../resources/views';