Files
TREK/client/tests/unit/mobile/shellChrome.test.tsx
T
Maurice 5346182807 fix(mobile): the rail, the docks and the top-level screens on a large screen
From the large-screen review (visual findings of the shell and the top-level
screens):

- Rail: 80px wide, one caption size for every name (no shrinking per item),
  balanced two-line names with every entry as tall as the tallest, short rail
  names where a language's word is too long (mobileNav.rail*, all locales),
  and near-opaque glass so a map's colours no longer smear through it.
- Rail head: always one 56px circle, so the entries never jump between pages:
  the create action, the screen's own action (the vacation calendar's
  year/editor switch moves there instead of floating over the days) or the
  quiet logo on settings and administration. It stays put while a short rail
  scrolls.
- Vacation calendar: weekday letters over each month on a wide window; the
  editor's mode switch sits at the foot with room kept for it.
- Docks: More is marked with a ring rather than the centre button's fill, the
  dock glass is denser, and lists fade out under the dock instead of showing
  in the gap below it.
- Dashboard: trip names get the card's width with the dates under them, the
  hero's facts wrap as whole chips, the filter chips scroll with a fade, the
  hero ends above the dock on a phone on its side and its buttons sit on a
  dark ground; the header bar stands in the content's column.
- Journeys: on a wide window the header is the same glass bar, in the column
  of the cards, and the other journeys' label starts with them.
- Notifications: the round chevron back button, in the list's column.
- Settings and administration share one frame and width. Admin's new-user
  action sits under the section list's title, the users card header wraps
  inside the card, stat labels ellipsize, role badges read in dark mode.
- Collections: one card per place with the status inside it, worded in a
  readable mix of its colour.
- Atlas and the journey map frame clear of the rail and the header; the
  journey's day bar sits on a glass plate, and a phone on its side gets
  smaller cards.
- Rail label tests rewritten for the new rule; FE-MOB-PANES-016 duplicate
  renumbered to 017.
2026-11-07 23:25:15 +01:00

51 lines
2.2 KiB
TypeScript

import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { describe, expect, it } from 'vitest';
import MGlassBar from '../../../src/mobile/components/MGlassBar';
import { render, screen } from '../../helpers/render';
// FE-MOB-CHROME-001 onwards: the touch shell's own chrome against what the
// desktop pages bring along.
const root = resolve(__dirname, '../../..');
describe('desktop chrome inside the touch shell', () => {
it('FE-MOB-CHROME-001: a page without a phone screen shows no desktop navbar over the rail, and keeps no room for it', () => {
// /plugins/:id, /help and a trip's files still render through PageShell. jsdom
// applies no stylesheet, so the rule and the mark it needs are read from source.
const css = readFileSync(resolve(root, 'src/mobile/mobile.css'), 'utf8');
expect(css).toMatch(/html:has\(\.m-shell\) \{\s*--nav-h: 0px;\s*\}/);
expect(css).toMatch(/html:has\(\.m-shell\) \[data-desktop-navbar\] \{\s*display: none;\s*\}/);
const navbar = readFileSync(resolve(root, 'src/components/Layout/Navbar.tsx'), 'utf8');
expect(navbar).toContain('data-desktop-navbar=""');
});
});
describe('MGlassBar', () => {
it('FE-MOB-CHROME-002: a floating bar stands in the content column, padded and capped like it', () => {
render(
<MGlassBar column="wide:max-w-[1280px]">
<span>bar</span>
</MGlassBar>
);
const bar = screen.getByText('bar').parentElement as HTMLElement;
const column = bar.parentElement as HTMLElement;
expect(column.className).toContain('px-4');
expect(column.className).toContain('wide:px-6');
expect(column.className).toContain('wide:max-w-[1280px]');
expect(column.parentElement?.className).toContain('m-span-x');
// The strip around the bar lets taps through to the page.
expect(column.parentElement?.className).toContain('pointer-events-none');
expect(bar.className).toContain('pointer-events-auto');
});
it('FE-MOB-CHROME-003: in flow it is the bar alone', () => {
const { container } = render(
<MGlassBar floating={false}>
<span>bar</span>
</MGlassBar>
);
expect(container.firstElementChild).toBe(screen.getByText('bar').parentElement);
});
});