Desktop: wide tables keep their first column in view while scrolling; compact table density (Settings > Appearance, Ctrl+K)
This commit is contained in:
parent
364b8ec0d4
commit
c0a13b5f87
6 changed files with 23 additions and 2 deletions
|
|
@ -160,10 +160,11 @@ export function App({ onTheme }: { onTheme: () => void }) {
|
|||
c.push({ id: 'act-check', group: G.act, title: t('action.checkConfigs'), icon: 'shield', run: () => { d.refreshPortfolio(false); } });
|
||||
c.push({ id: 'act-add', group: G.act, title: t('action.addFolder'), icon: 'folderPlus', run: () => go({ screen: 'apps' }) });
|
||||
c.push({ id: 'act-account', group: G.act, title: t('action.addAccount'), icon: 'key', run: () => go({ screen: 'accounts' }) });
|
||||
c.push({ id: 'act-density', group: G.act, title: t('action.toggleDensity'), icon: 'grid', keywords: 'dense compact table density rows', run: () => update({ ...prefs, density: prefs.density === 'compact' ? 'comfortable' : 'compact' }) });
|
||||
c.push({ id: 'act-theme', group: G.act, title: t('action.toggleTheme'), icon: 'moon', keywords: 'dark light', run: onTheme });
|
||||
c.push({ id: 'act-welcome', group: G.act, title: t('action.welcome'), icon: 'sparkle', keywords: 'onboarding start guide', run: () => setWelcome(true) });
|
||||
return c;
|
||||
}, [d, visible, app, tabs, route, go, onTheme, exports, runExport, showIgnored, stepApp]);
|
||||
}, [d, visible, app, tabs, route, go, onTheme, exports, runExport, showIgnored, stepApp, prefs, update]);
|
||||
|
||||
const crumbs: { label: string; to?: Route }[] = route.screen === 'portfolio' ? [{ label: t('nav.portfolio') }]
|
||||
: route.screen === 'app' ? [{ label: t('nav.portfolio'), to: { screen: 'portfolio' } }, { label: app?.name ?? '', to: app ? { screen: 'app', appId: app.key, tab: 'releases' } : undefined }, { label: t(TAB_KEY[route.tab]) }]
|
||||
|
|
|
|||
|
|
@ -239,3 +239,9 @@
|
|||
@media (max-width: 1560px) { .ds-tabs .ds-tab { padding: 0 10px; gap: 6px; } .ds-tabs .ds-tab svg { width: 15px; height: 15px; } }
|
||||
.dr-cmd { display: block; margin: 10px 0 8px; padding: 6px 10px; border-radius: var(--ds-r-xs); background: var(--ds-inset); overflow-wrap: anywhere; }
|
||||
.dr-out { max-height: 320px; overflow: auto; margin: 0; padding: 10px 12px; border-radius: var(--ds-r-sm); background: var(--ds-inset); border: 1px solid var(--ds-stroke); font: 12px/1.5 var(--mono, ui-monospace, monospace); white-space: pre-wrap; }
|
||||
/* wide tables: the first column (the row's name) stays in view while the rest scrolls sideways */
|
||||
.table-wrap .table tr > :first-child, .ds-table-wrap .table tr > :first-child { position: sticky; left: 0; z-index: 1; background: var(--ds-surface, var(--surface)); }
|
||||
.table-wrap .table thead tr > :first-child, .ds-table-wrap .table thead tr > :first-child { z-index: 3; }
|
||||
.table-wrap .table tbody tr:hover > :first-child, .ds-table-wrap .table tbody tr:hover > :first-child { background: color-mix(in srgb, var(--tint, var(--accent-solid)) 6%, var(--ds-surface, var(--surface))); }
|
||||
/* Settings > Appearance > Tables: compact */
|
||||
:root[data-density="compact"] .table th, :root[data-density="compact"] .table td { padding-top: 5px; padding-bottom: 5px; padding-left: 8px; padding-right: 8px; font-size: 12.5px; }
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@ export const en = {
|
|||
'preview.lead': "Dry run: nothing is changed yet. Continue opens the confirmation, which runs the dry run once more and then applies it.",
|
||||
'preview.more': "… {count} more lines",
|
||||
'preview.nothing': "The dry run reports no change.",
|
||||
'settings.density': "Tables",
|
||||
'settings.comfortable': "Comfortable",
|
||||
'settings.compact': "Compact",
|
||||
'action.toggleDensity': "Compact / comfortable tables",
|
||||
'palette.gActions': 'Actions',
|
||||
'palette.openApp': 'Open',
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,10 @@ export const tr: Record<keyof typeof en, string> = {
|
|||
'preview.lead': "Deneme çalıştırması: henüz hiçbir şey değişmedi. Devam onay penceresini açar; deneme bir kez daha çalışır, sonra uygulanır.",
|
||||
'preview.more': "… {count} satır daha",
|
||||
'preview.nothing': "Deneme çalıştırması bir değişiklik bildirmiyor.",
|
||||
'settings.density': "Tablolar",
|
||||
'settings.comfortable': "Rahat",
|
||||
'settings.compact': "Sıkı",
|
||||
'action.toggleDensity': "Sıkı / rahat tablolar",
|
||||
'palette.gActions': 'İşlemler',
|
||||
'palette.openApp': 'Aç',
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
export type Theme = 'system' | 'light' | 'dark';
|
||||
export type Motion = 'system' | 'reduce';
|
||||
export type Lang = 'system' | 'en' | 'tr';
|
||||
export interface Prefs { theme: Theme; motion: Motion; lang: Lang; onboarded: boolean }
|
||||
/** Tables: comfortable rows, or compact (smaller padding) for wide data on small windows. */
|
||||
export type Density = 'comfortable' | 'compact';
|
||||
export interface Prefs { theme: Theme; motion: Motion; lang: Lang; onboarded: boolean; density?: Density }
|
||||
|
||||
export const DEFAULT_PREFS: Prefs = { theme: 'system', motion: 'system', lang: 'system', onboarded: false };
|
||||
const KEY = 'storebound.prefs.v1';
|
||||
|
|
@ -16,6 +18,7 @@ export function parsePrefs(raw: string | null): Prefs {
|
|||
motion: v.motion === 'reduce' ? 'reduce' : 'system',
|
||||
lang: v.lang === 'en' || v.lang === 'tr' ? v.lang : 'system',
|
||||
onboarded: v.onboarded === true,
|
||||
...(v.density === 'compact' ? { density: 'compact' as const } : {}),
|
||||
};
|
||||
} catch { return { ...DEFAULT_PREFS }; }
|
||||
}
|
||||
|
|
@ -32,6 +35,7 @@ export function savePrefs(p: Prefs): void {
|
|||
export function applyPrefs(p: Prefs, root: { dataset: DOMStringMap; lang?: string } = document.documentElement, systemLang = 'en'): void {
|
||||
if (p.theme === 'system') delete root.dataset.theme; else root.dataset.theme = p.theme;
|
||||
if (p.motion === 'reduce') root.dataset.motion = 'reduce'; else delete root.dataset.motion;
|
||||
if (p.density === 'compact') root.dataset.density = 'compact'; else delete root.dataset.density;
|
||||
root.lang = resolveLang(p.lang, systemLang);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ export function Settings({ onTheme: _onTheme, section }: { onTheme: () => void;
|
|||
<Seg value={prefs.theme} onChange={theme => update({ ...prefs, theme })} label={t('settings.theme')} options={[['system', t('settings.system'), 'settings'], ['light', t('settings.light'), 'sun'], ['dark', t('settings.dark'), 'moon']]} /></div>
|
||||
<div className="field" role="group" aria-label={t('settings.motion')}><span className="legend">{t('settings.motion')}</span>
|
||||
<Seg value={prefs.motion} onChange={motion => update({ ...prefs, motion })} label={t('settings.motion')} options={[['system', t('settings.followSystem')], ['reduce', t('settings.reduce')]]} /></div>
|
||||
<div className="field" role="group" aria-label={t('settings.density')}><span className="legend">{t('settings.density')}</span>
|
||||
<Seg value={prefs.density ?? 'comfortable'} onChange={density => update({ ...prefs, density })} label={t('settings.density')} options={[['comfortable', t('settings.comfortable'), 'layers'], ['compact', t('settings.compact'), 'grid']]} /></div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue