Move the navigation into a floating toolbar at the bottom
The top app bar repeated the site's name, which already heads the upload and download pages, and spread its actions to the window's far edge. A floating toolbar centred above the bottom edge, as wide as its buttons, now holds them: Upload and the admin pages with the current one filled, and the account menu; guests get Upload, the theme toggle and Log in, without tooltips. On a phone the sign-in card no longer stretches to the full height, and the admin dashboard's empty state sits outside the scrolling table. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
This commit is contained in:
co-authored by
Claude Opus 5
parent
2a363defd1
commit
accbc17c1c
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* The page's main navigation, the floating toolbar at the bottom.
|
||||
*/
|
||||
function toolbar(string $html): string
|
||||
{
|
||||
preg_match('/<nav aria-label="Main">.*?<\/nav>/s', $html, $matches);
|
||||
|
||||
return $matches[0] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* The opening tag of the toolbar's link to a URL.
|
||||
*/
|
||||
function toolbarLink(string $html, string $url): string
|
||||
{
|
||||
preg_match('/<a\s[^>]*href="'.preg_quote($url, '/').'"[^>]*>/', toolbar($html), $matches);
|
||||
|
||||
return $matches[0] ?? '';
|
||||
}
|
||||
|
||||
test('pages have a floating toolbar at the bottom instead of a top app bar', function () {
|
||||
$html = $this->get(route('upload'))->assertOk()->getContent();
|
||||
|
||||
expect($html)->not->toContain('data-app-bar')
|
||||
->and(toolbar($html))->toContain('role="toolbar"')->toContain('data-toolbar-place="bottom"');
|
||||
});
|
||||
|
||||
test('a guest gets the upload page, the theme toggle and a way to log in, without tooltips', function () {
|
||||
$html = $this->get(route('upload'))->getContent();
|
||||
|
||||
expect(toolbarLink($html, route('upload')))->toContain('aria-current="page"')->toContain('aria-label="Upload"')
|
||||
->and(toolbarLink($html, route('login')))->not->toBe('')
|
||||
->and(toolbar($html))->toContain('Log in')->toContain('data-theme-toggle')->not->toContain('popover')->not->toContain('data-account-menu');
|
||||
|
||||
expect(toolbar($this->get(route('login'))->getContent()))->not->toContain(route('login').'"');
|
||||
});
|
||||
|
||||
test('an admin gets the admin pages and the account menu, the current page marked', function () {
|
||||
$admin = User::query()->where('is_admin', true)->first();
|
||||
|
||||
$html = $this->actingAs($admin)->get(route('admin.dashboard'))->assertOk()->getContent();
|
||||
|
||||
expect(toolbarLink($html, route('admin.dashboard')))->toContain('aria-current="page"')
|
||||
->and(toolbarLink($html, route('upload')))->not->toContain('aria-current')
|
||||
->and(toolbarLink($html, route('admin.settings')))->not->toContain('aria-current')
|
||||
->and(toolbar($html))->toContain('data-account-menu')->toContain('data-test="logout-button"')->not->toContain('Log in');
|
||||
});
|
||||
|
||||
test('a user who is not an admin gets no admin pages', function () {
|
||||
$html = $this->actingAs(User::factory()->create(['is_admin' => false]))->get(route('profile.edit'))->assertOk()->getContent();
|
||||
|
||||
expect(toolbarLink($html, route('upload')))->not->toBe('')
|
||||
->and(toolbar($html))->not->toContain(route('admin.dashboard'))->not->toContain(route('admin.settings'));
|
||||
});
|
||||
Reference in New Issue
Block a user