mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-14 08:11:03 +00:00
5346182807
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.
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
import type { LucideIcon } from 'lucide-react';
|
|
import { useEffect, useLayoutEffect, useRef } from 'react';
|
|
import { create } from 'zustand';
|
|
|
|
/**
|
|
* A screen's own action at the head of the navigation rail, in the place the
|
|
* "+" holds elsewhere: the vacation calendar's switch between the year and the
|
|
* editor. On the phone the same screen draws it into the dock's centre slot.
|
|
*/
|
|
export interface RailAction {
|
|
label: string;
|
|
icon: LucideIcon;
|
|
/** On: drawn as a ring rather than filled (the editor is open). */
|
|
pressed?: boolean;
|
|
run: () => void;
|
|
}
|
|
|
|
const useRailActionStore = create<{ action: RailAction | null }>(() => ({ action: null }));
|
|
|
|
/** The action the screen on show has put at the head of the rail, if any. */
|
|
export function useRailAction(): RailAction | null {
|
|
return useRailActionStore((s) => s.action);
|
|
}
|
|
|
|
/**
|
|
* Puts the screen's action at the head of the rail while it is mounted; null
|
|
* takes it away. Pressing it always runs the newest handler, and the rail only
|
|
* redraws when what it shows changes.
|
|
*/
|
|
export function useScreenRailAction(action: RailAction | null): void {
|
|
const run = useRef(action?.run);
|
|
useLayoutEffect(() => {
|
|
run.current = action?.run;
|
|
});
|
|
const shown = action !== null;
|
|
const label = action?.label ?? '';
|
|
const icon = action?.icon;
|
|
const pressed = action?.pressed ?? false;
|
|
useEffect(() => {
|
|
if (!shown || !icon) return;
|
|
useRailActionStore.setState({ action: { label, icon, pressed, run: () => run.current?.() } });
|
|
return () => useRailActionStore.setState({ action: null });
|
|
}, [shown, label, icon, pressed]);
|
|
}
|