Phase 4: mobile polish and touch fallbacks
4a. Touch fallbacks for group-hover actions:
- 9 occurrences across 5 files changed from opacity-0 group-hover:opacity-100
to opacity-100 md:opacity-0 md:group-hover:opacity-100
- CalendarSidebar (3), SharedCalendarSection (2), TaskDetailPanel (2),
NotificationsPage (1), CopyableField (1)
- Action buttons now always visible on touch, hover-revealed on desktop
4b. FullCalendar mobile touch:
- Wheel navigation disabled on touch devices (ontouchstart check)
- Prevents scroll hijacking on mobile, allows native scroll
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b05adf7f12
commit
f7ec04241b
@ -189,6 +189,8 @@ export default function CalendarPage() {
|
||||
if (!el) return;
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
const handleWheel = (e: WheelEvent) => {
|
||||
// Skip wheel navigation on touch devices (let them scroll normally)
|
||||
if ('ontouchstart' in window) return;
|
||||
const api = calendarRef.current?.getApi();
|
||||
if (!api || api.view.type !== 'dayGridMonth') return;
|
||||
e.preventDefault();
|
||||
|
||||
@ -131,7 +131,7 @@ const CalendarSidebar = forwardRef<HTMLDivElement, CalendarSidebarProps>(functio
|
||||
<span className="text-sm text-foreground truncate flex-1">{cal.name}</span>
|
||||
<button
|
||||
onClick={() => handleEdit(cal)}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
@ -184,7 +184,7 @@ const CalendarSidebar = forwardRef<HTMLDivElement, CalendarSidebarProps>(functio
|
||||
setEditingTemplate(tmpl);
|
||||
setShowTemplateForm(true);
|
||||
}}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Pencil className="h-3 w-3" />
|
||||
</button>
|
||||
@ -194,7 +194,7 @@ const CalendarSidebar = forwardRef<HTMLDivElement, CalendarSidebarProps>(functio
|
||||
if (!window.confirm(`Delete template "${tmpl.name}"?`)) return;
|
||||
deleteTemplateMutation.mutate(tmpl.id);
|
||||
}}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-destructive"
|
||||
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
</button>
|
||||
|
||||
@ -73,7 +73,7 @@ export default function SharedCalendarSection({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onEditCalendar?.(cal)}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
@ -104,7 +104,7 @@ export default function SharedCalendarSection({
|
||||
<span className="text-sm text-foreground truncate flex-1">{m.calendar_name}</span>
|
||||
<button
|
||||
onClick={() => setSettingsFor(m)}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<Pencil className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
|
||||
@ -316,7 +316,7 @@ export default function NotificationsPage() {
|
||||
<span className="text-[11px] text-muted-foreground tabular-nums">
|
||||
{formatDistanceToNow(new Date(notification.created_at), { addSuffix: true })}
|
||||
</span>
|
||||
<div className="flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<div className="flex items-center gap-0.5 opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity">
|
||||
{!notification.is_read && (
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); handleMarkRead(notification.id); }}
|
||||
|
||||
@ -484,7 +484,7 @@ export default function TaskDetailPanel({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-5 w-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive shrink-0"
|
||||
className="h-5 w-5 opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive shrink-0"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDeleteSubtask(subtask.id, subtask.title);
|
||||
@ -527,7 +527,7 @@ export default function TaskDetailPanel({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-5 w-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive"
|
||||
className="h-5 w-5 opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity text-muted-foreground hover:text-destructive"
|
||||
onClick={() => {
|
||||
if (!window.confirm('Delete this comment?')) return;
|
||||
deleteCommentMutation.mutate(comment.id);
|
||||
|
||||
@ -27,7 +27,7 @@ export default function CopyableField({ value, icon: Icon, label }: CopyableFiel
|
||||
type="button"
|
||||
onClick={handleCopy}
|
||||
aria-label={`Copy ${label || value}`}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 p-0.5 rounded text-muted-foreground hover:text-foreground shrink-0"
|
||||
className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 p-0.5 rounded text-muted-foreground hover:text-foreground shrink-0"
|
||||
>
|
||||
{copied ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />}
|
||||
</button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user