fix(golf,baseball): calendar mobile clip + retired accent-stripe card#806
Conversation
…/baseball surface - CalendarHeader control bar could not shrink inside the glass container's horizontal header row (flex-shrink-0 on the header root), so at 390px the Today pill clipped at the container's overflow-hidden rounded edge — observed live on baseball player Schedule (shared PremiumCalendarClient, affects golf + baseball coach too). The header now fills and shrinks; the date title truncates as designed. - NotificationCenter unread badge rendered clipped on the mobile mount; the clipping element was the ui Button primitive itself — its baseStyles apply overflow-hidden to contain the tap ripple, cutting off the badge positioned at -top-1/-right-1. The bell trigger now opts into overflow-visible (twMerge lets the instance class win), keeping the ring-2 ring-cream-50 separation intact. - MobileEventCard still used the retired accent-stripe idiom (MOBILE_DOCTRINE rule 11) with off-palette raw colors; replaced with the sanctioned ringed event-type dot sourced from the shared getEventTypeConfig map (event-styles.ts), unifying the two divergent color maps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019WJ1Gzjj9MT3UsxhMoMzSV
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
WalkthroughCalendar event types gain ring styling and two new variants. Mobile event cards use shared ringed dots, while calendar header shrinking and notification badge overflow behavior are adjusted. ChangesCalendar UI updates
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested labels: 🚥 Pre-merge checks | ✅ 11 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (11 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThis PR fixes shared mobile calendar presentation issues across the golf and baseball calendar surfaces. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "fix(calendar): own-key guard in getEvent..." | Re-trigger Greptile |
| } | ||
| }; | ||
| // Cast string type to EventType for styling (fallback to 'other' if not matched) | ||
| const config = getEventTypeConfig(event.event_type as EventType); |
There was a problem hiding this comment.
When baseball calendar rows use known event types like showcase or tryout, this cast sends those strings through the shared golf/baseball styling lookup even though they are not in the shared EventType config. The new dot becomes the only visible event-type marker on mobile, so those events fall back to neutral other styling and become visually indistinguishable from miscellaneous events.
Context Used: Review for Helm Sports Labs (a commercial multi-sp... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/components/golf/calendar/MobileEventCard.tsx
Line: 96
Comment:
**Baseball Types Lose Styling**
When baseball calendar rows use known event types like `showcase` or `tryout`, this cast sends those strings through the shared golf/baseball styling lookup even though they are not in the shared `EventType` config. The new dot becomes the only visible event-type marker on mobile, so those events fall back to neutral `other` styling and become visually indistinguishable from miscellaneous events.
**Context Used:** Review for Helm Sports Labs (a commercial multi-sp... ([source](.greptile))
How can I resolve this? If you propose a fix, please make it concise.…type config Greptile on #806: with the accent stripe gone, the type dot is the only mobile marker, and baseball's recruiting-facing showcase/tryout types (event-ink 'pursuit') fell through to the neutral 'other' styling. Both join the shared EventType union and event-styles config in the violet recruiting family (solid/soft split mirroring their ink variants). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019WJ1Gzjj9MT3UsxhMoMzSV
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/golf/calendar/MobileEventCard.tsx`:
- Around line 25-26: Update the EventType type import in MobileEventCard.tsx to
use the public '`@/lib/types`' barrel instead of the deep '`@/lib/types/calendar`'
path, leaving the formatTime and getEventTypeConfig import unchanged.
- Around line 95-96: Normalize event.event_type before passing it to
getEventTypeConfig in MobileEventCard: accept only recognized own EventType keys
and fall back to "other" for inherited or unknown values such as "__proto__" and
"constructor", ensuring the returned config always has valid styling fields.
In `@src/lib/calendar/event-styles.ts`:
- Line 34: Update the event style definitions in event-styles.ts, including
dotRingColor and the related amber, stone, teal, violet, orange, sky, rose, and
purple entries, to use only canonical primary-*, destructive, warm-*, or cream-*
classes. Preserve each style’s intended semantic role and ensure MobileEventCard
continues consuming valid approved token classes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: eecadda1-7ebe-433e-b2f4-6659e08ed268
📒 Files selected for processing (5)
src/components/golf/calendar/MobileEventCard.tsxsrc/components/golf/calendar/NotificationCenter.tsxsrc/components/ui/page-header.tsxsrc/lib/calendar/event-styles.tssrc/lib/types/calendar.ts
| import { formatTime, getEventTypeConfig } from '@/lib/calendar/event-styles'; | ||
| import type { EventType } from '@/lib/types/calendar'; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Import EventType through the public type barrel.
Use import type { EventType } from '@/lib/types' instead of the deep @/lib/types/calendar import.
As per coding guidelines, import types from @/lib/types for type definitions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/golf/calendar/MobileEventCard.tsx` around lines 25 - 26,
Update the EventType type import in MobileEventCard.tsx to use the public
'`@/lib/types`' barrel instead of the deep '`@/lib/types/calendar`' path, leaving
the formatTime and getEventTypeConfig import unchanged.
Source: Coding guidelines
There was a problem hiding this comment.
Skipped deliberately: @/lib/types/index.ts does not re-export the calendar module, so the barrel import would not compile. The deep @/lib/types/calendar path is the established idiom for these types — the sibling EventCard.tsx (pre-existing) imports EventType the same way. Expanding the barrel is out of scope for this fix (69 existing exports, collision risk with inline calendar-event types already in index.ts).
Generated by Claude Code
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
fd -t f 'index.ts' src/lib/types
echo "---"
cat src/lib/types/index.ts 2>/dev/null | head -50
echo "---"
rg -n "EventType" src/lib/types/index.ts
echo "---"
rg -n "from '`@/lib/types`" src/components/golf/calendar/EventCard.tsxLength of output: 6102
@njrini99-code Confirmed — src/lib/types/index.ts has no re-export of ./calendar, and src/components/golf/calendar/EventCard.tsx:8 already imports EventType the same way (from '@/lib/types/calendar'). The barrel import would indeed fail to compile as-is, and this is the established pattern for these types. Withdrawing this nit.
🧬 Code Graph Analysis Results
Relevant snippets
src/components/golf/calendar/MobileEventCard.tsx
- (No additional snippets provided with line numbers; file contents already show the relevant imports/casts, e.g.,
type { EventType }from@/lib/types/calendarand castingevent.event_type as EventType.)
src/lib/types/calendar.ts (lines 5-20)
export type EventType =
| 'game'
| 'practice'
| 'scrimmage'
| 'recruiting_visit'
| 'camp'
| 'tournament'
| 'meeting'
| 'workout'
| 'class'
| 'blocked_time'
| 'qualifier' // Golf-specific
| 'travel' // Golf-specific
| 'showcase' // Baseball-specific (recruiting-facing — event-ink 'pursuit')
| 'tryout' // Baseball-specific (recruiting-facing — event-ink 'pursuit')
| 'other';src/lib/calendar/event-styles.ts (lines 165-172)
export function getEventTypeConfig(type: EventType): EventTypeConfig {
// Own-key guard: callers pass raw DB strings (cast to EventType), and a
// plain index would resolve inherited keys like '__proto__' to a truthy
// prototype object with no styling fields instead of the 'other' fallback.
return Object.prototype.hasOwnProperty.call(eventTypeConfigs, type)
? eventTypeConfigs[type]
: eventTypeConfigs.other;
}src/lib/calendar/event-styles.ts (lines 177-196)
export function formatTime(timeString: string): string {
// Handle time-only strings (HH:MM:SS or HH:MM)
if (timeString && !timeString.includes('T') && !timeString.includes(' ')) {
const parts = timeString.split(':').map(Number);
const hours = parts[0] ?? 0;
const minutes = parts[1] ?? 0;
const period = hours >= 12 ? 'PM' : 'AM';
const displayHour = hours % 12 || 12;
const displayMinutes = String(minutes).padStart(2, '0');
return `${displayHour}:${displayMinutes} ${period}`;
}
// Handle full datetime strings
const date = new Date(timeString);
return date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true,
});
}src/hooks/useCalendarEvents.ts (lines 6-34)
export interface CalendarEvent {
id: string;
team_id: string;
title: string;
event_type: string; // Accepts any event type string for flexibility across sports
start_date: string; // Mapped from start_time (timestamptz)
end_date: string | null; // Mapped from end_time (timestamptz)
start_time: string | null; // Raw start_time from DB
end_time: string | null; // Raw end_time from DB
location?: string | null;
description?: string | null;
status?: string;
all_day?: boolean;
recurring?: boolean;
created_by?: string | null;
requires_rsvp?: boolean;
rsvp_deadline?: string | null;
max_attendees?: number | null;
rsvp_confirmed_count?: number;
rsvp_maybe_count?: number;
rsvp_declined_count?: number;
rsvp_pending_count?: number;
rsvp_total_count?: number;
// Recurring-series identity. Series root has recurrence_rule populated and
// parent_event_id null; sibling occurrences carry parent_event_id pointing
// back to the root.
parent_event_id?: string | null;
recurrence_rule?: string | null;
}src/components/golf/calendar/MobileRSVPButtons.tsx (line 20)
export type RSVPResponse = 'accepted' | 'tentative' | 'declined';src/lib/utils.ts (lines 5-7)
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}| color: 'amber', | ||
| bgColor: 'bg-amber-50/60', | ||
| dotColor: 'bg-amber-500', | ||
| dotRingColor: 'ring-amber-500/[0.18]', |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Keep the added ring classes on the approved design-token palette.
The new styles introduce amber, stone, teal, violet, orange, sky, rose, and purple families in src/lib/calendar/event-styles.ts:34-156. These are consumed directly by src/components/golf/calendar/MobileEventCard.tsx:146, but repository guidance permits only primary-*, destructive, warm-*, and cream-*. Map these styles to approved tokens or add sanctioned semantic event tokens before merging.
As per coding guidelines, use only canonical color families: primary-*, destructive, warm-*, and cream-*.
Also applies to: 44-44, 54-54, 64-64, 74-74, 84-84, 94-94, 104-104, 114-114, 124-156
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lib/calendar/event-styles.ts` at line 34, Update the event style
definitions in event-styles.ts, including dotRingColor and the related amber,
stone, teal, violet, orange, sky, rose, and purple entries, to use only
canonical primary-*, destructive, warm-*, or cream-* classes. Preserve each
style’s intended semantic role and ensure MobileEventCard continues consuming
valid approved token classes.
Source: Coding guidelines
There was a problem hiding this comment.
Skipped deliberately: the amber/stone/teal/violet/orange/sky/rose/purple families are pre-existing in event-styles.ts — this PR only added a dotRingColor mirroring each entry's existing dotColor family. They are the sanctioned categorical event-type palette that EventCard (desktop) has consumed all along; the canonical-family rule (helm/no-banned-color) bans the legacy green aliases (helm-green-*, sf-green, emerald-*, raw green-*, #DC2626), not data-viz accent families, and ESLint passes on this file. Collapsing 13 event types onto 4 neutral families would destroy type distinguishability — if the palette should be re-tokenized, that's a design-system-wide change, not this bug-fix PR.
Generated by Claude Code
There was a problem hiding this comment.
@njrini99-code Fair point, and I've confirmed it against the file: every one of the flagged families (amber, stone, teal, violet, orange, sky, rose, purple) already exists on the corresponding dotColor/bgColor/textColor keys prior to this PR — this diff only adds dotRingColor mirroring the existing family per entry (e.g., qualifier.dotColor: 'bg-amber-500' → dotRingColor: 'ring-amber-500/[0.18]'). No new color family is introduced. Since these are the established categorical event-type accents already consumed by the desktop EventCard, flagging them under the canonical UI-token rule was out of scope for this fix. Withdrawing the concern.
CodeRabbit on #806: callers index the config with raw DB strings cast to EventType, so an inherited key ('__proto__', 'constructor') would resolve to a truthy prototype object with undefined styling fields instead of the 'other' fallback. Guard with hasOwnProperty so every consumer gets a complete config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019WJ1Gzjj9MT3UsxhMoMzSV
|
@coderabbitai review Generated by Claude Code |
|
✅ Action performedReview finished.
|
PR Summary by QodoFix mobile calendar clipping and unify event card dot styling
AI Description
Diagram
High-Level Assessment
Files changed (5)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
98 rules 1. Bell icon Button lacks tooltip
|
| <Button variant="ghost" | ||
| onClick={handleToggle} | ||
| className="relative p-2.5 rounded-xl bg-cream-100/75 backdrop-blur-sm border border-warm-200/45 shadow-sm text-warm-500 hover:text-warm-800 hover:bg-cream-50/92 hover:shadow-md active:scale-95 transition-all duration-200" | ||
| className="relative overflow-visible p-2.5 rounded-xl bg-cream-100/75 backdrop-blur-sm border border-warm-200/45 shadow-sm text-warm-500 hover:text-warm-800 hover:bg-cream-50/92 hover:shadow-md active:scale-95 transition-all duration-200" | ||
| aria-label={unreadCount > 0 ? `Notifications, ${unreadCount} unread` : 'Notifications'} | ||
| aria-expanded={isOpen} | ||
| > |
There was a problem hiding this comment.
3. Bell icon button lacks tooltip 📜 Skill insight ☑ Accessibility
The icon-only bell Button has an aria-label but is not wrapped in a tooltip component. This fails the requirement that icon-only buttons provide both a screen-reader label and a visible tooltip.
Agent Prompt
## Issue description
The notification bell is an icon-only button without a tooltip.
## Issue Context
Compliance requires icon-only buttons to include both an accessible label and a tooltip for sighted users.
## Fix Focus Areas
- src/components/golf/calendar/NotificationCenter.tsx[149-172]
- src/components/ui/tooltip.tsx[57-80]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| | 'showcase' // Baseball-specific (recruiting-facing — event-ink 'pursuit') | ||
| | 'tryout' // Baseball-specific (recruiting-facing — event-ink 'pursuit') |
There was a problem hiding this comment.
4. Showcase type unstyled 🐞 Bug ≡ Correctness
The PR adds showcase as an EventType and defines its violet styling via getEventTypeConfig, but the premium grid cards render via PremiumEventBlock → premium-utils → calendar-tokens.css, where showcase is not mapped. As a result, showcase events will fall back to event-type-other and the other dot color in week/month/day views, diverging from the new config-based styling used elsewhere (e.g., MobileEventCard).
Agent Prompt
### Issue description
`showcase` was added as a first-class `EventType` with styling in `event-styles.ts`, but the premium grid renderer (Week/Month/Day views) still derives its type ribbon + dot color from `src/lib/calendar/premium-utils.ts` and `src/styles/calendar-tokens.css`. Those legacy maps/tokens do not include `showcase`, so `showcase` falls back to the neutral `other` styling.
### Issue Context
- `PremiumEventBlock` is used in WeekView and MonthView, and it calls `getEventClasses()` and `getEventDotColorVar()` from `premium-utils`.
- `premium-utils` currently only recognizes baseball types up through `tryout`.
- `calendar-tokens.css` defines `--event-*` tokens and `.event-type-*` classes, also only up through `tryout`.
### Fix Focus Areas
- src/lib/calendar/premium-utils.ts[14-38]
- src/lib/calendar/premium-utils.ts[72-79]
- src/styles/calendar-tokens.css[9-27]
- src/styles/calendar-tokens.css[171-180]
### Suggested fix
1. Add `showcase` to `typeMap` in `getEventTypeClass()` (e.g., `showcase: 'event-type-showcase'`).
2. Add `showcase` to the `known` set in `getEventDotColorVar()`.
3. Define `--event-showcase` in `calendar-tokens.css` using a violet consistent with `event-styles.ts` (e.g., `theme(colors.violet.500)`), and add `.event-type-showcase { border-left-color: var(--event-showcase); }`.
4. (Optional but recommended) Update the header comment in `calendar-tokens.css` to include `showcase` in the listed baseball DB types, to keep the “canonical source” documentation accurate.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
Three mobile defects reported from a live phone screenshot of the baseball player Schedule page — all three live in the shared calendar surface (
PremiumCalendarClient), so this heals golf player, golf coach, baseball player, and baseball coach calendars at once:flex-shrink-0, so as a flex child of the calendar's horizontal header row it refused to compress and overflowed into the glass container'soverflow:hiddenrounded edge. Replaced withw-full(+ existingmin-w-0): the date title now truncates as designed (~9 visible chars at 390px) instead of the controls clipping. Verified the calendar header variant's only consumer isPremiumCalendarClient.Buttonprimitive'soverflow-hidden(ripple containment) cutting the-top-1 -right-1unread badge at the button's own bounds. The trigger now setsoverflow-visible(twMerge instance override); badge position and ring untouched.MobileEventCardstill painted an absolute colored left stripe with its own off-palette color switch (bg-sky-500/bg-purple-500/bg-amber-500). Replaced with the sanctioned ringed event-type dot (v3 design language: 3px soft ring at 18% alpha), sourced from the sharedgetEventTypeConfigmap — a newdotRingColorfield was added toEventTypeConfigand all 13 entries inevent-styles.ts, keeping one source of truth and deleting the divergent local color map.Partner-readable summary
On phones, the team calendar had a cut-off "Today" button, a cut-off notification counter, and an outdated event-card style. All three are fixed across both sports' calendars, and event cards now match the premium design language.
Type of change
Area
golf · baseball · dashboard · mobile
Risk level
Buttonoverflow override is instance-scoped; header shrink verified single-consumer)Git Activity Timeline note
Fixes cut-off calendar controls and notification badge on phones and brings event cards in line with the premium design system across golf and baseball.
Checklist
npm run lintandnpm run typecheckpass (tsc clean; eslint --max-warnings 0 on touched files incl. helm/no-banned-color)Screenshots / notes
Reported from live phone use (baseball player Schedule, 390px). Before: Today pill clipped at card edge, bell badge half-cut, blue accent stripe on event card. The fix removes the last divergent copy of the event-type color map.
🤖 Generated with Claude Code
https://claude.ai/code/session_019WJ1Gzjj9MT3UsxhMoMzSV
Generated by Claude Code