Files
TREK/client/tailwind.config.js
T
Maurice 6906f80ff8 feat(native): Android tablets get the shortcuts, two panes meet at a foldable's fold
The Android shell now reports keyCommands and windowLayout, so the large
screen layout no longer assumes an iPad:

- The keyboard host hands the shortcuts to the app whenever the shell has
  the keyCommands feature, whatever the platform. Before it also required
  iOS, so an Android tablet with a keyboard answered the keys in the page
  and never listed them in the system's shortcuts.
- useWindowFold follows the layout the Android shell reports (feature
  windowLayout). When a vertical fold separates the window, a foldable half
  open like a book, MobileShell marks it with data-fold and its place, and
  the leading pane (the trip's plan, a tab's summary, a list beside its
  detail) ends at the fold while the trailing one starts there, on either
  reading direction. A flat fold that does not separate stays one screen.
- The split size class starts at 840pt, Android's expanded width, instead
  of 900pt, so a foldable unfolded on its side (about 841dp) gets two panes
  like an iPad does. An 11" iPad upright (834pt) stays a single pane. The
  address screen of the native shell follows the same width.
- TrekShell exports NativeWindowLayout for it.

Also: the sheet's width and anchor types and the collab board type stay
private to their modules, which nothing else imports (knip).
2026-11-07 23:25:13 +01:00

134 lines
5.2 KiB
JavaScript

/** @type {import('tailwindcss').Config} */
export default {
darkMode: 'class',
content: [
"./index.html",
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
primary: {
50: '#eef2ff',
100: '#e0e7ff',
200: '#c7d2fe',
300: '#a5b4fc',
400: '#818cf8',
500: '#6366f1',
600: '#4f46e5',
700: '#4338ca',
800: '#3730a3',
900: '#312e81',
950: '#1e1b4b',
},
planner: {
day: '#f8fafc',
dayBorder: '#e2e8f0',
dayHeader: '#1e293b',
sidebar: '#ffffff',
sidebarBorder: '#f1f5f9',
overlay: 'rgba(15, 23, 42, 0.4)',
dragActive: '#eef2ff',
dragOver: '#c7d2fe',
},
// Semantic theme tokens — resolve to the CSS variables in src/index.css
// (:root light / .dark dark). Use these utilities (bg-surface, text-content,
// border-edge, bg-accent) instead of inline `style={{ ... 'var(--...)' }}`.
surface: {
DEFAULT: 'var(--bg-primary)',
secondary: 'var(--bg-secondary)',
tertiary: 'var(--bg-tertiary)',
elevated: 'var(--bg-elevated)',
card: 'var(--bg-card)',
input: 'var(--bg-input)',
hover: 'var(--bg-hover)',
selected: 'var(--bg-selected)',
},
content: {
DEFAULT: 'var(--text-primary)',
secondary: 'var(--text-secondary)',
muted: 'var(--text-muted)',
faint: 'var(--text-faint)',
},
edge: {
DEFAULT: 'var(--border-primary)',
secondary: 'var(--border-secondary)',
faint: 'var(--border-faint)',
},
accent: {
DEFAULT: 'var(--accent)',
text: 'var(--accent-text)',
on: 'var(--accent-on)',
hover: 'var(--accent-hover)',
subtle: 'var(--accent-subtle)',
},
// Semantic status colors (+ soft tinted background variant).
success: { DEFAULT: 'var(--success)', soft: 'var(--success-soft)' },
danger: { DEFAULT: 'var(--danger)', soft: 'var(--danger-soft)' },
warning: { DEFAULT: 'var(--warning)', soft: 'var(--warning-soft)' },
info: { DEFAULT: 'var(--info)', soft: 'var(--info-soft)' },
// Inverse surface (the near-black/near-white "pill" header pattern).
inverse: { DEFAULT: 'var(--bg-inverse)', text: 'var(--text-inverse)' },
// Mobile rewrite tokens — resolve to the --m-* variables scoped to
// .m-root in src/mobile/mobile.css. Only meaningful inside MobileShell.
'm-ink': 'var(--m-ink)',
'm-muted': 'var(--m-muted)',
'm-faint': 'var(--m-faint)',
'm-act': 'var(--m-act)',
'm-actfg': 'var(--m-actfg)',
'm-card': 'var(--m-card)',
'm-cbr': 'var(--m-cbr)',
'm-inner': 'var(--m-inner)',
'm-inbr': 'var(--m-inbr)',
'm-glass': 'var(--m-glass)',
'm-gbr': 'var(--m-gbr)',
'm-sheet': 'var(--m-sheet)',
'm-sheetop': 'var(--m-sheetop)',
'm-shbr': 'var(--m-shbr)',
'm-ic': 'var(--m-ic)',
'm-avbr': 'var(--m-avbr)',
'm-rowbr': 'var(--m-rowbr)',
'm-dim': 'var(--m-dim)',
'm-conn': 'var(--m-conn)',
'm-trackoff': 'var(--m-trackoff)',
},
fontFamily: {
// Secondary "subtext" face of the mobile design (numbers, eyebrows).
geist: ['Geist Sans', 'Poppins', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'system-ui', 'sans-serif'],
},
boxShadow: {
'day-column': '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
'place-card': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
'drag-overlay': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
// Token-backed elevation (scheme/dark aware) — for migrating inline rgba shadows.
'card': 'var(--shadow-card)',
'elevated': 'var(--shadow-elevated)',
'modal': 'var(--shadow-modal)',
'dropdown': 'var(--shadow-dropdown)',
'popover': 'var(--shadow-popover)',
},
// Semantic type tiers — each scales with its own user multiplier (defaults
// to 1). Use text-title/subtitle/body/caption for headings/labels so the
// appearance "text size" control reaches them; the global fontScale (root
// font-size) additionally scales all rem-based text.
fontSize: {
title: ['calc(24px * var(--fs-scale-title, 1))', '1.2'],
subtitle: ['calc(18px * var(--fs-scale-subtitle, 1))', '1.35'],
body: ['calc(14px * var(--fs-scale-body, 1))', '1.5'],
caption: ['calc(12px * var(--fs-scale-caption, 1))', '1.4'],
},
},
},
plugins: [
// The touch shell's size classes (src/hooks/sizeClass.ts) as the `wide:` and
// `split:` variants. Variants of their own rather than entries in `screens`:
// both need a height bound (a phone on its side stays compact), and a raw
// screen among the min-width ones reorders how Tailwind sorts every
// responsive class.
({ addVariant }) => {
addVariant('wide', '@media (min-width: 600px) and (min-height: 501px)')
addVariant('split', '@media (min-width: 840px) and (min-height: 501px)')
},
],
}