mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-25 01:37:05 +00:00
feat(security): reflow the node Security page for mobile (#1372)
* feat(security): reflow the node Security page for mobile Below the md breakpoint the Security page now reads as a phone surface instead of a squeezed desktop, with no change to the desktop layout. - Masthead stat cluster moves into a full-width 3-cell strip (critical / high / last scan) below the tab strip, since the masthead hides its inline cluster on a phone. - The eight-section tab strip becomes a horizontally scrollable mono row with an edge mask-fade and a cyan underline on the active tab; every section stays reachable by scroll. - The six totals render as a 3x2 hairline-divided grid instead of the 640px-wide rail that forced a horizontal scroll. - The Images tab becomes a filterable, scrollable list (severity dot, truncated ref, freshness, critical/high count tags) with a chip row, in place of the desktop table. - A freshness footer band states scan recency and scanner version. All mobile treatment is gated by useIsMobile() or max-md: utilities, so the desktop view is byte-identical. Charts are reused full-width. * feat(security): make the mobile Security page a bespoke masthead-led screen On a phone the Security page now drops the global top bar and leads with its masthead (the notifications + more-menu cluster moves into the masthead's right slot), matching Home and Fleet so the mobile shell is continuous across pages. The view is reclassified bespoke and rendered through the masthead-led path; the desktop layout is unchanged. The mobile "more" menu now lists every destination instead of omitting the bottom-tab views, so the same menu opens the same set on every screen rather than changing contents from page to page.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { Home, Radar, Boxes, ShieldCheck } from 'lucide-react';
|
||||
import { MobileMoreMenu } from './MobileMoreMenu';
|
||||
import type { NavItem } from './EditorLayout/hooks/useViewNavigationState';
|
||||
|
||||
// Includes a bottom-tab primary (dashboard) and secondary destinations; the
|
||||
// menu must list every one so navigation is identical on every screen.
|
||||
const navItems: NavItem[] = [
|
||||
{ value: 'dashboard', label: 'Home', icon: Home },
|
||||
{ value: 'fleet', label: 'Fleet', icon: Radar },
|
||||
{ value: 'resources', label: 'Resources', icon: Boxes },
|
||||
{ value: 'security', label: 'Security', icon: ShieldCheck },
|
||||
];
|
||||
|
||||
function open(over: Partial<React.ComponentProps<typeof MobileMoreMenu>> = {}) {
|
||||
const props: React.ComponentProps<typeof MobileMoreMenu> = {
|
||||
navItems,
|
||||
activeView: 'security',
|
||||
onNavigate: vi.fn(),
|
||||
...over,
|
||||
};
|
||||
render(<MobileMoreMenu {...props} />);
|
||||
// The destination list lives inside a Sheet that is closed until the trigger
|
||||
// is clicked, so open it before querying the nav buttons.
|
||||
fireEvent.click(screen.getByRole('button', { name: 'More destinations' }));
|
||||
return props;
|
||||
}
|
||||
|
||||
describe('MobileMoreMenu', () => {
|
||||
it('lists every nav item, including the bottom-tab primaries', () => {
|
||||
open();
|
||||
for (const item of navItems) {
|
||||
expect(screen.getByRole('button', { name: item.label })).toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
|
||||
it('navigates to the chosen destination on click', () => {
|
||||
const { onNavigate } = open();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Resources' }));
|
||||
expect(onNavigate).toHaveBeenCalledWith('resources');
|
||||
});
|
||||
|
||||
it('marks the active destination', () => {
|
||||
open({ activeView: 'security' });
|
||||
expect(screen.getByRole('button', { name: 'Security' }).className).toContain('bg-glass-highlight');
|
||||
expect(screen.getByRole('button', { name: 'Resources' }).className).not.toContain('font-medium');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user