Plan step 37: all.css replaces the two interim import lists with one entry for an application that wants everything — the foundation, every layout stylesheet and every component stylesheet, grouped under the same block comments components.css used, plus a Layout block. It also directly imports the three files nothing imported by name before (layout/spacing.css, layout/visibility.css, components/selection.css), so every file under components/ and layout/ is now one @import away. Every test that read a block of components.css or layout.css now reads the matching block of all.css through one shared helper (allCssBlock(), in tests/Pest.php so it loads for any test run) instead of repeating the same substr() search in each file. StylesheetsTest.php's shape, Tailwind-free and breakpoint checks, previously run twice (once for the foundation, once for the layout tree), now run once over the whole tree all.css reaches, since every component and layout stylesheet is plain CSS after step 36; a new test asserts all.css imports everything under components/ and layout/ exactly once. The Workbench imports all.css in place of layout.css and components.css. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
92 lines
4.8 KiB
PHP
92 lines
4.8 KiB
PHP
<?php
|
|
|
|
it('draws a content region with a body and no app bar when it has no title', function () {
|
|
$html = (string) $this->blade('<x-pane>The page</x-pane>');
|
|
|
|
expect(layoutRoot($html))->toMatchArray(['<' => 'div', 'data-md-pane' => 'data-md-pane'])
|
|
->not->toHaveKeys(['data-md-width', 'data-md-hide-below', 'data-md-hide-from'])
|
|
->and($html)->toMatch('/<div data-md-pane-body>The page<\/div>/')
|
|
->not->toContain('data-md-app-bar')
|
|
->not->toContain('data-md-pane-navigation');
|
|
});
|
|
|
|
it('gives the pane its own app bar, a direct child spanning it, with the title, subtitle and actions', function () {
|
|
$html = (string) $this->blade(<<<'BLADE'
|
|
<x-pane title="Settings" subtitle="Your account" heading="h2">
|
|
<x-slot:actions><span>ACTIONS</span></x-slot:actions>
|
|
BODY
|
|
</x-pane>
|
|
BLADE);
|
|
|
|
expect($html)
|
|
->toMatch('/^\s*<div data-md-pane[^>]*>\s*<header\b[^>]*data-md-app-bar[^>]*data-md-pane-bar/s')
|
|
->toContain('<h2 data-md-app-bar-title>Settings</h2>')
|
|
->toContain('<p data-md-app-bar-subtitle>Your account</p>')
|
|
->toMatch('/<div data-md-app-bar-trailing><span>ACTIONS<\/span><\/div>/')
|
|
->toContain('data-md-sticky')
|
|
->toMatch('/<\/header>\s*<div data-md-pane-body>\s*BODY\s*<\/div>/s')
|
|
->and((string) $this->blade('<x-pane title="Settings" :sticky="false" />'))->not->toContain('data-md-sticky');
|
|
});
|
|
|
|
it('draws a bar for actions alone, and names the heading h1 by default', function () {
|
|
expect((string) $this->blade('<x-pane><x-slot:actions><span>ACTIONS</span></x-slot:actions></x-pane>'))->toContain('data-md-pane-bar')
|
|
->and((string) $this->blade('<x-pane title="Inbox" />'))->toContain('<h1 data-md-app-bar-title>Inbox</h1>');
|
|
});
|
|
|
|
it('puts the section navigation under the bar and above the body', function () {
|
|
$html = (string) $this->blade(<<<'BLADE'
|
|
<x-pane title="Settings">
|
|
<x-slot:navigation><nav>SECTIONS</nav></x-slot:navigation>
|
|
BODY
|
|
</x-pane>
|
|
BLADE);
|
|
|
|
expect($html)->toMatch('/<\/header>\s*<div data-md-pane-navigation><nav>SECTIONS<\/nav><\/div>\s*<div data-md-pane-body>\s*BODY/s')
|
|
// It is the pane's section navigation, not the bar's leading button.
|
|
->not->toContain('data-md-app-bar-leading');
|
|
});
|
|
|
|
it('leads the bar with a back link, a back action for a list-detail, or the leading slot', function () {
|
|
$link = (string) $this->blade('<x-pane title="Recipients" back="/shares" />');
|
|
$action = (string) $this->blade('<x-pane title="Message" back />');
|
|
$leading = (string) $this->blade('<x-pane title="Inbox" back><x-slot:leading><button>MENU</button></x-slot:leading></x-pane>');
|
|
|
|
expect($link)->toMatch('/data-md-app-bar-leading><span data-md-pane-back\s*>/')
|
|
->toMatch('/<a[^>]*href="\/shares"[^>]*aria-label="Back"/s')
|
|
->not->toContain('data-md-list-detail-back')
|
|
->and($action)->toMatch('/<span data-md-pane-back\s+data-md-list-detail-back\s*>/')
|
|
->toMatch('/<button[^>]*aria-label="Back"[^>]*x-on:click="back\(\)"/s')
|
|
->and($leading)->toContain('<div data-md-app-bar-leading><button>MENU</button></div>')
|
|
->not->toContain('data-md-pane-back');
|
|
});
|
|
|
|
it('caps its width with M3\'s narrow measure or the wider steps', function () {
|
|
foreach (['full', 'narrow', 'medium', 'wide'] as $width) {
|
|
expect(layoutRoot((string) $this->blade('<x-pane :width="$width" />', ['width' => $width]))['data-md-width'])->toBe($width);
|
|
}
|
|
|
|
expect(layoutRoot((string) $this->blade('<x-pane width="40rem" />')))->not->toHaveKey('data-md-width');
|
|
});
|
|
|
|
it('takes the element, the visibility props and the caller\'s class and style', function () {
|
|
expect(layoutRoot((string) $this->blade('<x-pane as="section" hide-below="expanded" class="checkout" style="max-width: 50rem" aria-labelledby="checkout-title" />')))
|
|
->toMatchArray([
|
|
'<' => 'section',
|
|
'data-md-hide-below' => 'expanded',
|
|
'class' => 'checkout',
|
|
'style' => 'max-width: 50rem;',
|
|
'aria-labelledby' => 'checkout-title',
|
|
]);
|
|
});
|
|
|
|
it('keeps M3\'s margin on the body, once, in the layout layer', function () {
|
|
$css = (string) file_get_contents(__DIR__.'/../../../resources/css/layout/pane.css');
|
|
|
|
expect($css)->toContain('@layer material.layout')
|
|
->toContain('padding-inline: var(--md-layout-margin, var(--md-sys-measurement-space200));')
|
|
->toContain("@media (width >= 600px) {\n padding-inline: var(--md-layout-margin, var(--md-sys-measurement-space300));")
|
|
->toContain("[data-md-pane-body] > * {\n --md-layout-margin: 0px;")
|
|
->toContain("[data-md-pane][data-md-width='narrow'] {\n max-inline-size: 40rem;")
|
|
->and((string) file_get_contents(__DIR__.'/../../../resources/css/all.css'))->toContain("@import './layout/pane.css';");
|
|
});
|