vojo/src/app/components/mobile-tabs-pager/style.css.ts

100 lines
4.2 KiB
TypeScript

import { style } from '@vanilla-extract/css';
import { color } from 'folds';
// Pager root. Sits inside the authed shell's row-flex slot
// (ClientLayout → Box grow=Yes), so `flex: 1 1 0` fills the slot
// horizontally; `align-items: stretch` on the parent fills vertically.
//
// `touch-action: pan-y` lets the browser keep doing native vertical
// scroll (DM list virtualizer, curtain peek pull-down) without us
// having to call preventDefault on every move — only the pager's own
// listener calls preventDefault, and only after axis-resolve commits
// to "horizontal".
//
// `SurfaceVariant.Container` backdrop intentionally shows through
// (a) the inter-pane gap during a swipe — the gap colour the user
// asked for is "light blue same as the header", which IS this
// SurfaceVariant tone — and (b) any sub-pixel rounding seam at rest.
//
// `color: Background.OnContainer` mirrors what the route-level
// `<PageRoot>` would have set via its `ContainerColor({ variant:
// 'Background' })` wrapper. We mount Direct/Channels/Bots directly
// here, bypassing PageRoot for the swipe-pager experience, so without
// this declaration the form labels rendered inside the per-pane
// StreamHeader curtain (`<Text size="L400">` for Username/Server/
// Options) had `color: inherit` cascading all the way up to `body`,
// which sets no color → browser default black. The labels became
// invisible against the dark form background only on native (where the
// pager activates). Desktop / web go through PageRoot and inherit the
// expected light tone for free.
export const pagerRoot = style({
position: 'relative',
flex: '1 1 0',
minWidth: 0,
minHeight: 0,
height: '100%',
overflow: 'hidden',
touchAction: 'pan-y',
backgroundColor: color.SurfaceVariant.Container,
color: color.Background.OnContainer,
});
// Shared static tabs row painted ABOVE the strip. Reserves the
// status-bar safe-area inset via padding-top so the segments + icons
// sit just below the system status bar, and so the backdrop colour
// extends through the inset zone (matching the per-pane PageNav's
// own `paddingTop: var(--vojo-safe-top)` so there's no visible band
// boundary at the inset edge).
//
// `z-index: 10` keeps this above the strip and any in-pane curtain
// (curtain is `z-index: 2` within its pane's stacking context, which
// in turn lives inside the strip with z-index auto = 0 in pagerRoot's
// context — so 10 reliably wins).
export const pagerStaticHeader = style({
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 10,
paddingTop: 'var(--vojo-safe-top, 0px)',
// The wrapped tabsRow has its own height of TABS_ROW_PX via the
// stream-header recipe; we don't set a fixed height here so the
// status-bar inset adds on top naturally.
backgroundColor: color.SurfaceVariant.Container,
});
// Horizontal strip carrying all three panes side-by-side. Width &
// transform are computed inline in the JSX (they depend on tabs.length
// and visualIdx + visualDragPx, and the gap math couples to them).
//
// `gap: PANE_GAP_PX` is what makes the inter-pane void visible during
// a swipe — the pagerRoot's SurfaceVariant.Container colour shows
// through the gap, matching the static header tone exactly.
export const strip = style({
display: 'flex',
flexDirection: 'row',
height: '100%',
willChange: 'transform',
});
// Each pane is exactly one viewport wide. CRITICALLY `display: flex;
// flex-direction: row` so the nested Folds PageNav (which is a flex
// child with `flex-grow: 1` on mobile to override its 256px recipe
// width) expands to fill the pane. A column-flex parent here would
// leave PageNav at 256px — the bug that ate the previous attempt.
//
// No paddingTop here: the per-pane StreamHeader still renders its
// own tabs row (kept for the curtain's TABS_ROW_PX snap math, just
// painted invisible via visibility:hidden), and PageNav's inner
// column reserves the status-bar safe-area inset via its own
// `paddingTop: var(--vojo-safe-top)`. The static header overlay at
// the pager root simply paints OVER the same screen zone, so the
// underlying geometry stays identical to non-pager mode.
export const pane = style({
display: 'flex',
flexDirection: 'row',
flexShrink: 0,
width: '100vw',
height: '100%',
minWidth: 0,
});