add roadtrip warning areas and tidy driving settings

This commit is contained in:
Maurice
2026-09-12 11:23:09 +02:00
parent ec281e5974
commit af45b0ca74
47 changed files with 652 additions and 45 deletions
@@ -3,6 +3,7 @@ import { Sunrise, Sunset } from 'lucide-react'
import { useTranslation } from '../../i18n/TranslationContext'
import { dayWindow } from './dayWindow'
import CustomTimePicker from '../shared/CustomTimePicker'
import SettingsHint from './SettingsHint'
export default function DayWindowFields({ start, end, endMode = 'route', onSave }: {
start?: string
@@ -25,7 +26,7 @@ export default function DayWindowFields({ start, end, endMode = 'route', onSave
}
}
return (
<fieldset className="flex flex-col gap-3">
<fieldset className="flex min-w-0 flex-col gap-3">
<legend className="sr-only">{t('roadtrip.window.title')}</legend>
{(['start', 'end'] as const).map(field => {
const Icon = field === 'start' ? Sunrise : Sunset
@@ -45,10 +46,10 @@ export default function DayWindowFields({ start, end, endMode = 'route', onSave
</div>
)
})}
<p id="roadtrip-window-hint" role={invalid ? 'alert' : undefined} className={`text-caption ${invalid ? 'text-danger' : 'text-content-faint'}`}>
{t(invalid ? 'roadtrip.window.invalid' : 'roadtrip.window.hint')}
</p>
<fieldset className="flex flex-col gap-2 border-t border-edge-faint pt-3">
{invalid
? <p id="roadtrip-window-hint" role="alert" className="text-caption text-danger">{t('roadtrip.window.invalid')}</p>
: <SettingsHint id="roadtrip-window-hint">{t('roadtrip.window.hint')}</SettingsHint>}
<fieldset className="flex min-w-0 flex-col gap-2 border-t border-edge-faint pt-3">
<legend className="sr-only">{t('roadtrip.window.endAt')}</legend>
<span className="text-body text-content-secondary">{t('roadtrip.window.endAt')}</span>
<div className="flex flex-wrap gap-2">
@@ -61,7 +62,7 @@ export default function DayWindowFields({ start, end, endMode = 'route', onSave
</label>
))}
</div>
<p id="roadtrip-end-mode-hint" className="text-caption text-content-faint">{t(`roadtrip.window.${endMode === 'stop' ? 'stopHint' : 'routeHint'}`)}</p>
<SettingsHint id="roadtrip-end-mode-hint">{t(`roadtrip.window.${endMode === 'stop' ? 'stopHint' : 'routeHint'}`)}</SettingsHint>
</fieldset>
</fieldset>
)
@@ -16,6 +16,7 @@ import ToggleSwitch from '../Settings/ToggleSwitch'
import type { DistanceUnit, RouteAvoidClass } from '../../types'
import { FS } from './typeScale'
import DayWindowFields from './DayWindowFields'
import SettingsHint from './SettingsHint'
import { dayWindow } from './dayWindow'
/**
@@ -193,10 +194,10 @@ function Panel({ icon: Icon, title, note, children }: {
children: React.ReactNode
}): React.ReactElement {
return (
<section className="flex flex-col gap-3 rounded-xl border border-edge-faint bg-surface-secondary px-4 py-3.5">
<section className="flex min-w-0 flex-col gap-3 rounded-xl border border-edge-faint bg-surface-secondary px-4 py-3.5">
<SectionTitle icon={Icon}>{title}</SectionTitle>
{children}
{note ? <p className="text-caption leading-snug text-content-faint">{note}</p> : null}
{note ? <SettingsHint>{note}</SettingsHint> : null}
</section>
)
}
@@ -429,7 +430,7 @@ export default function RoadtripLimitsCard({ onSave, onResetDayBoundaries, loadi
{t('roadtrip.limit.title')}
</span>
}>
<div className="flex flex-col gap-4">
<div className="flex min-w-0 flex-col gap-4">
{/* Two columns, kept. One column reads more tidily but turns the dialog into
something that has to be scrolled, and a setting you cannot see while you
change another is worse than a seam down the middle.
@@ -439,7 +440,7 @@ export default function RoadtripLimitsCard({ onSave, onResetDayBoundaries, loadi
ends on the same right edge, and the panels are stacked to one rhythm. The
left column holds trip settings, the right holds the car and route appearance. */}
<div className="grid items-start gap-4 sm:grid-cols-2">
<div className="flex flex-col gap-4">
<div className="flex min-w-0 flex-col gap-4">
<Panel icon={Clock} title={t('roadtrip.limit.sectionDriving')} note={t('roadtrip.limit.hint')}>
<LimitRow
icon={Clock}
@@ -484,7 +485,7 @@ export default function RoadtripLimitsCard({ onSave, onResetDayBoundaries, loadi
</Panel>
</div>
<div className="flex flex-col gap-4">
<div className="flex min-w-0 flex-col gap-4">
<Panel
icon={Car}
title={t('roadtrip.limit.sectionVehicle')}
@@ -641,6 +642,10 @@ export default function RoadtripLimitsCard({ onSave, onResetDayBoundaries, loadi
onToggle={() => onSave?.('roadtrip_day_colors', !settings.roadtrip_day_colors)}
/>
</Panel>
<Panel icon={Signpost} title={t('roadtrip.hazards.current')} note={t('roadtrip.hazards.note')}>
<AvoidRow icon={Signpost} label={t('roadtrip.hazards.show')} on={settings.roadtrip_show_hazards === true} disabled={!onSave}
onToggle={() => onSave?.('roadtrip_show_hazards', !settings.roadtrip_show_hazards)} />
</Panel>
<Panel icon={Signpost} title={t('roadtrip.stops.section')} note={t('roadtrip.stops.daysHint')}>
<AvoidRow icon={Link2} label={t('roadtrip.stops.inDays')}
on={settings.roadtrip_service_stops_in_days !== false}
@@ -0,0 +1,7 @@
import { Tooltip } from '../shared/Tooltip'
export default function SettingsHint({ children, id }: { children: string; id?: string }) {
return <Tooltip label={children} placement="top">
<p id={id} tabIndex={0} className="min-w-0 truncate text-caption leading-snug text-content-faint">{children}</p>
</Tooltip>
}