feat(calendar): Kalenderwahl im Termin mit Farbe statt nur Text
Die Farbe ist das, woran man einen Kalender im Raster wiedererkennt -- im Termindialog stand aber nur der Name in einem Auswahlfeld. Wer "Arbeit" waehlt, soll dabei schon das Blau sehen, in dem der Termin gleich erscheint. Deshalb Plaketten statt <select>: Farbpunkt plus Name, alle nebeneinander sichtbar, kein Aufklappen noetig. Der Punkt spricht dieselbe Sprache wie ueberall sonst im Kalender -- gefuellt heisst gewaehlt, ein leerer Ring heisst nicht gewaehlt, genau wie in der Kalenderliste und bei der Terminfarbe. Die gewaehlte Plakette bekommt nur einen Hauch der Kalenderfarbe als Grund. Acht kraeftig ausgefuellte Toene nebeneinander erschluegen sonst das ganze Formular, in dem die Farbe eigentlich der Nebendarsteller ist. Als CalendarPicker in controls.tsx, wo schon Toggle und ColorSwatches liegen -- damit die naechste Stelle, die eine Kalenderwahl braucht, nicht wieder bei null anfaengt. Selbsttest weiter 36 gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
77bf16b27f
commit
7a1f0837f5
2 files changed
+56
-4
No files matched your search
@@ -5,7 +5,7 @@ import {
|
||||
addDays, allDayISO, dateFromInput, eventDay, nthOfMonth, timedISO,
|
||||
toDateInput, toTimeInput, weekdayCodeOf, weekdayCodes,
|
||||
} from './dates'
|
||||
import { ColorSwatches, Toggle } from './controls'
|
||||
import { CalendarPicker, ColorSwatches, Toggle } from './controls'
|
||||
|
||||
interface Props {
|
||||
/** Fehlt er, entsteht ein neuer Termin. */
|
||||
@@ -215,9 +215,7 @@ export default function EventDialog({ event, defaultStart, calendars, calendarId
|
||||
Speichern die Sammlung, behält aber seine Kennung – für
|
||||
CalDAV-Clients derselbe Termin an neuer Adresse, nicht ein
|
||||
neuer. */}
|
||||
<select value={calId} disabled={readOnly} onChange={e => setCalId(e.target.value)} style={inputStyle}>
|
||||
{calendars.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
|
||||
</select>
|
||||
<CalendarPicker calendars={calendars} value={calId} onChange={setCalId} disabled={readOnly} />
|
||||
{!!event && calId !== calendarId && (
|
||||
<p style={{ margin: '6px 2px 0', fontSize: 12, color: 'var(--color-text-muted)', lineHeight: 1.4 }}>
|
||||
Wird beim Speichern nach „{calendars.find(c => c.id === calId)?.name}" verschoben
|
||||
|
||||
@@ -93,3 +93,57 @@ export function ColorSwatches({ value, onChange, inherit, disabled }: {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Kalenderwahl als farbige Plaketten statt als Auswahlfeld.
|
||||
*
|
||||
* Ein Auswahlfeld zeigt nur den Namen – die Farbe aber ist das, woran man
|
||||
* einen Kalender im Raster wiedererkennt. Wer „Arbeit" wählt, soll dabei
|
||||
* schon das Blau sehen, in dem der Termin gleich erscheint.
|
||||
*
|
||||
* Der Punkt spricht dieselbe Sprache wie überall sonst im Kalender: gefüllt
|
||||
* heißt gewählt, ein leerer Ring heißt nicht gewählt.
|
||||
*/
|
||||
export function CalendarPicker({ calendars, value, onChange, disabled }: {
|
||||
calendars: { id: string; name: string; color: string }[]
|
||||
value: string
|
||||
onChange: (id: string) => void
|
||||
disabled?: boolean
|
||||
}) {
|
||||
return (
|
||||
<div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>
|
||||
{calendars.map(cal => {
|
||||
const on = cal.id === value
|
||||
return (
|
||||
<button
|
||||
key={cal.id} type="button" disabled={disabled}
|
||||
onClick={() => onChange(cal.id)}
|
||||
aria-pressed={on}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: 7, maxWidth: '100%',
|
||||
padding: '7px 12px 7px 10px', borderRadius: 999, fontSize: 13,
|
||||
border: `1.5px solid ${on ? cal.color : 'var(--color-border)'}`,
|
||||
// Nur ein Hauch der Kalenderfarbe: Ausgefüllte Plaketten in acht
|
||||
// kräftigen Tönen nebeneinander erschlagen das ganze Formular.
|
||||
background: on ? cal.color + '22' : 'transparent',
|
||||
color: on ? 'var(--color-text)' : 'var(--color-text-muted)',
|
||||
cursor: disabled ? 'default' : 'pointer',
|
||||
opacity: disabled ? 0.6 : 1,
|
||||
transition: 'background 0.12s, border-color 0.12s, color 0.12s',
|
||||
} as CSSProperties}
|
||||
>
|
||||
<span style={{
|
||||
width: 12, height: 12, borderRadius: '50%', flexShrink: 0,
|
||||
border: `2px solid ${cal.color}`,
|
||||
background: on ? cal.color : 'transparent',
|
||||
transition: 'background 0.12s',
|
||||
}} />
|
||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{cal.name}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user