Desktop: custom context menus everywhere, never the browser's menu
One ContextMenu in the design system (keyboard, type-ahead, submenus, check items, disabled reasons, Shift+F10 / Menu key, viewport placement, light and dark). The native menu is prevented globally; text fields keep Cut / Copy / Paste / Select all. Menus on sidebar and portfolio apps, app hero, releases, store art, live art, reviews, checks, editor fields, catalog, prices, accounts, app folders, ignored.
This commit is contained in:
parent
944b24fe59
commit
dece83c3e8
23 changed files with 839 additions and 28 deletions
|
|
@ -17,6 +17,8 @@ import { RolloutBar } from '../../ui/charts';
|
|||
import { Card, Empty, Notice, PhaseChip, phaseLabel, Skeleton, storeName } from '../../ui/kit';
|
||||
import { EmptyState, Section, StatusPill, tintStyle, useTint } from '../../ui/ds';
|
||||
import { AppleSubmitCard, PlayProductionCard } from './Submit';
|
||||
import { useContextMenu } from '../../ui/ContextMenu';
|
||||
import { releaseMenu } from '../../ui/app-menu';
|
||||
import '../../styles/releases.css';
|
||||
|
||||
const STAGE_KEY: Record<(typeof STAGES)[number], Key> = { build: 'stage.build', testing: 'stage.testing', review: 'stage.review', live: 'stage.live', rollout: 'stage.rollout' };
|
||||
|
|
@ -49,8 +51,10 @@ function LaneRow({ lane, version, st, app }: { lane: Lane; version: string; st:
|
|||
const ph = r ? phaseLabel(r) : null;
|
||||
const rolling = lane.at === STAGES.length - 1 && lane.share !== null;
|
||||
const ringTone = lane.tone === 'bad' ? 'bad' : (lane.share ?? 0) >= 1 ? 'ok' : 'accent';
|
||||
const d = useData();
|
||||
const menu = useContextMenu();
|
||||
return (
|
||||
<article className="tl-lane rel-store" data-store={lane.store} data-tone={lane.tone} aria-label={storeName(lane.store)}>
|
||||
<article {...menu(() => releaseMenu(d, app, lane.store, r?.version ?? version, r?.build))} className="tl-lane rel-store" data-store={lane.store} data-tone={lane.tone} aria-label={storeName(lane.store)}>
|
||||
<header className="rel-store-h">
|
||||
<span className="rel-mark"><StoreGlyph store={lane.store} /></span>
|
||||
<div className="rel-who">
|
||||
|
|
@ -168,6 +172,7 @@ function Train({ title, train, tf, tone, app, st }: { title: string; train: Rele
|
|||
|
||||
export function ReleasesTab({ app }: { app: UnifiedApp }) {
|
||||
const d = useData();
|
||||
const menu = useContextMenu();
|
||||
const l = d.liveFor(app);
|
||||
const project = app.project;
|
||||
const hue = useTint(d.iconFor(app), app.name);
|
||||
|
|
@ -221,7 +226,10 @@ export function ReleasesTab({ app }: { app: UnifiedApp }) {
|
|||
<thead><tr><th>{t('col.version')}</th><th>App Store</th><th>{t('col.build')}</th><th>Google Play</th><th>{t('col.versionCode')}</th><th>{t('col.track')}</th></tr></thead>
|
||||
<tbody>
|
||||
{history.map(h => (
|
||||
<tr key={h.version}>
|
||||
<tr key={h.version} {...menu(() => [
|
||||
...(h.ios ? [{ label: 'App Store', icon: 'phone' as const, submenu: releaseMenu(d, app, 'ios', h.ios.version, h.ios.build) }] : []),
|
||||
...(h.android ? [{ label: 'Google Play', icon: 'phone' as const, submenu: releaseMenu(d, app, 'android', h.android.version, h.android.build) }] : []),
|
||||
])}>
|
||||
<td className="strong num rel-hv">{[...new Set([h.version, h.ios?.version, h.android?.version].filter(Boolean))].join(' / ')}</td>
|
||||
<td>{h.ios ? <PhaseChip r={h.ios} /> : <span className="muted small">–</span>}</td>
|
||||
<td className="num muted">{h.ios?.build ?? '–'}</td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue