The calendar surface that hosts the Day/Month/Year picker grids.
DatePicker(.graphical)) and Material 3 (DatePicker/DatePickerDialog) render the calendar surface with full locale, keyboard, and a11y support built in. The DS should ship a tokenized wrapper, not a from-scratch Figma redraw. Current component has raster chevrons (C6), no cell state coverage (C5), day-of-week layer names (C1), misleading Type axis (C2), a fake drawn scrollbar (C4), and asymmetric Month navigation (C4).The group appears immediately below the Date Picker trigger when it enters State=Active. The three Type variants swap when the user taps the header (Date → Year → Month).
Scrollbar rectangle instead of using a scrollable container.Type = Date | Year | Month is misleading — "Date" means day-grid view. Native convention is mode: day | month | year. Month variant has only a Next chevron (no Prev), asymmetric from Date and Year. Day cells use day-of-week layer names (Sunday...Saturday) as semantic roles.DatePicker and Compose DatePickerDialog render their own calendar surface internally — this Figma component has no 1:1 native primitive. It also is currently nested inline inside the trigger (see Date Picker), not exposed as a standalone overlay.| State | iOS | Android | Figma Property | Notes |
|---|---|---|---|---|
| Day grid | Yes | Yes | Type=Date | 6 rows × 7 cols. Weekday header (Su/M/T/W/Th/F/Sa). Today shown with 1.5px blue ring. Prev/next month days dimmed. |
| Year grid | Yes | Yes | Type=Year | 3-col grid with overflow-clip and a drawn "Scrollbar" decoration. Selected year shown with 1px blue ring + blue label. |
| Month grid | Yes | Yes | Type=Month | 3-col grid with all 12 months. Missing Prev chevron — only Next is drawn. Selected month shown with 1px blue ring. |
| Cell: Today / Selected | Yes | Yes | Date Picker - Item state | 1.5px blue ring on day cells; 1px blue ring on year/month cells. Native pickers fill the cell with tint instead of ringing it. |
| Cell: Pressed / Hover / Focus | No | No | — | Missing. Native pickers provide these automatically; a DS wrapper only needs to tint them. |
| In-range / Range start / Range end | No | No | — | Not defined. Both platforms support date-range selection; the DS has no tokens or visuals for it. |
| Disabled cell | No | No | — | No business-rule disabled state (e.g. minDate/maxDate). Only the "prev/next month" greyed variant exists. |
| Keyboard navigation / focus ring | No | No | — | No focus styling. Native pickers handle keyboard+TalkBack/VoiceOver by default; the DS needs to preserve that. |
- Day cells are named by weekday, not by index or role. The day rows contain layers literally named
Sunday,Monday...Saturdayinstead ofday-cell[0]...day-cell[6]or a single repeated instance. Weekday is runtime data, not a layer identity. This leaks through to Dev Mode handoff as nonsense layer names. C1 · Layer Structure & Naming - Weekday header rows are instance-swapped
Date Picker - Item, not a dedicated weekday cell. The header row uses the same Date Picker - Item component as the day grid but with a.base/date-iteminner naming. Handoff can't distinguish "day label" from "weekday label" from property alone. C1 · Layer Structure & Naming -
Type = Date | Year | Monthis misleading. "Date" means the day grid, not a date value. Native convention and consumer mental model ismode: day | month | year. Rename the axis so code-connect params readmode = .dayinstead oftype = "Date". C2 · Variant & Property Naming - No 1:1 native primitive for the whole calendar surface. SwiftUI
DatePicker(selection:).datePickerStyle(.graphical)and Material 3DatePicker(state:)both render the full calendar internally. Keeping this as a drawn Figma component means the developer either ignores it (using native) or redraws it from scratch (defeating the purpose of a DS). C4 · Native Mappability - Year variant has a drawn fake
Scrollbarrectangle. Node18414:6277is aScrollbarlayer with a 4px × 80px blue-tinted pill absolutely positioned over the grid. Scroll state can't be represented in static geometry — native pickers render the scroll indicator automatically. Remove, and use a scrollable container instead. C4 · Native Mappability - Month variant is missing the Prev chevron. Node
18431:2826's header has only a Chevron Right — the left slot is an empty 24×24 box (Chevron Leftremoved). Date and Year variants both have bidirectional navigation; Month is asymmetric. C4 · Native Mappability - Cell interaction states not defined on the grid. Only Default, Today (day), Selected (year/month), and Prev/Next (day-only, disabled-looking) exist. Missing: Pressed, Hover/Focus, In-range, Range-start, Range-end, Business-rule disabled (outside minDate/maxDate). C5 · Interaction State Coverage
- Chevrons are raster
shape_fullassets. Both Prev and Next chevrons in every variant referencehttps://www.figma.com/api/mcp/asset/...image URLs rather than a vector icon instance. Won't scale, won't inherit token colors, can't be swapped. Reuse the DS chevron icon component. C6 · Asset & Icon Quality - No dedicated picker surface token scope. The panel bg and border reuse
main/date-picker/month-header/color/bg/...borderas a stand-in — but the month-header is a sub-region, not the surface. Without a distinctmain/date-picker/group/*scope, changing one visually mutates the other. C6 · Asset & Icon Quality - Code Connect mappings not registered. Blocked by C1/C2/C4/C5/C6 and by the recommendation to wrap native pickers instead of mapping this drawn surface directly. C7 · Code Connect Linkability
- Composition — Wrap the native date pickers, don't redraw them. iOS:
DatePicker(selection:, displayedComponents:).datePickerStyle(.graphical)renders the calendar surface with full locale, leap-year, keyboard, VoiceOver, and Dynamic Type support. Material 3:DatePicker(state:)+DatePickerDialogdoes the same. The DS should shipEBDatePickerPanelas a token-styled overlay of the native picker — not a from-scratch Figma surface. Documentation lives as a reference spec here; production code calls the native API. Composition - Family — Unify Date Picker - Item and Month/Year Picker - Item into one
Picker Cell. Day, month, and year cells inside this Group are all selectable cells with the same state semantics. Replace the two sibling components with onePicker Cellwithkind: day | month | yearandstate: default | today | selected | in-range | disabled. Collapses 10 variants across 2 components into one component with two clean axes. Family - Property — Rename
Typetomodeand use native terminology. ChangeType = Date | Year | Monthtomode = day | month | year. Matches SwiftUIdisplayedComponentsand ComposeDisplayMode. Eliminates the ambiguity of "Date" meaning "day grid". Rename - Rename day cells by index/role, not by weekday. Replace the
Sunday...Saturdaylayer names with a single repeatedday-cellinstance indexed by position, or with semantic roles (header-cell,day-cell,spacer-cell). Weekday is data, not layer identity. Rename - Replace chevron raster glyphs with vector icon instances. Swap the two
shape_fullimage references per variant (×3 = 6 assets) for the DS chevron icon component. Color-bind tomain/date-picker/month-header/color/iconso hover/disabled states propagate. Asset - Add Prev chevron to the Month variant. Navigate between year clusters (2015-2024, 2025-2034...) so Month behaves symmetrically with Date and Year. State
- Remove the drawn Scrollbar on the Year variant. Delete node
18414:6277and its child rectangle. Mark the Grid frame as scrollable in the component spec (overflow-clip already applied) and document that native pickers render the scroll indicator automatically. Property - Add cell state coverage via Picker Cell axes. Expose Pressed, Hover/Focus, In-range, Range-start, Range-end, and business-rule Disabled on the unified Picker Cell component. Link to Figma tokens in a dedicated
main/date-picker/cell/*scope. State - Introduce a
main/date-picker/group/*token scope for the surface. Separate the panel-level bg/border/shadow tokens from the month-header tokens so the two can be themed independently. Token - Document as a reference spec, not a production component. Given the native-pickers-own-this direction, this Figma component should be annotated as a visual reference for designers reviewing what the native picker will look like in GCash theme — not as a component developers are expected to rebuild. Add a description banner in Figma and mark it
_reference. Docs
Calendar surface. Flip the Type control between Date / Year / Month grids.
Panel-level colors are shared across all three variants. Cell-level colors belong to Date Picker - Item and Month/Year Picker - Item — shown here for cross-reference.
| Role | Token | DEFAULT | SELECTED / TODAY | DISABLED |
|---|---|---|---|---|
| Panel bg | main/date-picker/month-header/color/bg | #FFFFFF | – | – |
| Panel border | main/date-picker/month-header/color/border | #E5EBF4 (1px) | – | – |
| Panel shadow | elevation/app/shadow | 0 6px 12px -8 rgba(2,14,34,.16) | – | – |
| Header label | main/date-picker/month-header/color/label | #0A2757 | – | – |
| Header chevron | main/date-picker/month-header/color/icon | #005CE5 | – | – |
| Weekday bg | main/date-picker/week-header/color/bg | #FFFFFF | – | – |
| Weekday label | main/date-picker/week-header/color/label | #0A2757 | – | – |
| Day cell bg | main/date-picker/day/color/unselected/bg | #FFFFFF | #FFFFFF (ring) | #FFFFFF |
| Day cell label | main/date-picker/day/color/unselected/label | #0A2757 | #005CE5 | #C2CFE5 |
| Today ring (day) | border/color-border-primary | – | #005CE5 (1.5px) | – |
| Selected ring (month/year) | border/color-border-primary | – | #005CE5 (1px) | – |
| Prev/next-month day label | text/color-text-disabled | – | – | #C2CFE5 |
| Scrollbar overlay (Year) | bg/color-bg-inverse (10% opacity) | #0A2757 @ 10% | – | – |
| Figma Property | SwiftUI | Compose |
|---|---|---|
| Type = Date | displayedComponents: .date (graphical style, default view) | DisplayMode.Picker |
| Type = Year | (tap header label in .graphical style) | DisplayMode.Input / year header tap |
| Type = Month | (tap month header in .graphical style) | (year-cluster header tap) |
| Header label "Month / Year" | header automatically rendered | headline slot |
| Prev / Next chevrons | automatic on .graphical | automatic on DatePicker |
| Day cell | cell styling via tint / accentColor | colors.dayContentColor, selectedDayContainerColor |
| Year / Month cell | styled via tint | colors.yearContentColor, selectedYearContainerColor |
| Scrollbar overlay (Year) | — | — |
| Requirement | iOS | Android |
|---|---|---|
| Calendar role / traits | Automatic via DatePicker (.isDatePicker trait) | Automatic via Material 3 DatePicker (Role.DatePicker) |
| Keyboard navigation | Arrow keys move between day cells on iPad / hw keyboard | D-Pad + hw keyboard navigation by default |
| Focus ring | System focus ring on focused cell | System focus indicator on focused cell |
| Screen reader label | VoiceOver announces day-of-week, date, month, and Selected / Today | TalkBack announces full date + state |
| Dynamic Type / font scaling | Automatic | Automatic |
| Locale / first-day-of-week | Calendar.current.firstWeekday | Locale.getDefault().firstDayOfWeek |
| minDate / maxDate | in: Date...Date range parameter | selectableDates / yearRange |
Do
Render the panel through SwiftUI's DatePicker(.graphical) or Compose's Material 3 DatePicker. Apply DS tokens via .tint / colors = ....
Don't
Don't hand-draw the calendar grid, chevrons, or month/year pickers. You'll reimplement leap-year logic, locale handling, VoiceOver/TalkBack, and keyboard support that the native pickers provide for free.
Do
Use the Figma spec as a visual target for the tokenized wrapper — colors, corner radius, shadow, and ring thickness.
Don't
Don't treat the Figma layout as a 1:1 blueprint — the native picker's internal spacing and cell sizes may not match exactly, and that's fine.
Do
Pass an explicit in: Date... range to enforce minDate/maxDate and rely on the platform's disabled styling.
Don't
Don't style disabled cells manually in consumer code — let the native picker dim them consistently with OS conventions.
| ID | Criterion | Status | Notes |
|---|---|---|---|
| C1 | Layer Structure & Naming | Requires Rework | Day cells named by weekday (Sunday, Monday...). Weekday header rows re-use Date Picker - Item rather than a dedicated weekday cell. Scrollbar drawn as a geometry layer. |
| C2 | Variant & Property Naming | Requires Rework | Type = Date | Year | Month is misleading ("Date" means day-grid). Rename to mode = day | month | year. |
| C3 | Token Coverage | Needs Refinement | Most colors, spacing, radius, and shadow values are token-bound. Missing a dedicated main/date-picker/group/* scope — panel reuses month-header tokens as a proxy. |
| C4 | Native Mappability | Requires Rework | Both platforms own the full calendar surface. Scrollbar drawn as geometry, Month missing Prev chevron — neither expressible natively. Recommend wrapping native pickers. |
| C5 | Interaction State Coverage | Requires Rework | Only Today (day) and Selected (year/month) exist. Missing Pressed, Hover/Focus, In-range, Range-start, Range-end, Business-rule Disabled. |
| C6 | Asset & Icon Quality | Requires Rework | Chevrons are raster shape_full image references across all 3 variants. Replace with vector icon instances. |
| C7 | Code Connect Linkability | Not Mapped | Blocked by C1/C2/C4/C5/C6 and by the native-wrapper direction. Map only once the Picker Cell family is unified and the surface is confirmed as a wrapper, not a redraw. |
| Aspect | Status | Notes |
|---|---|---|
| Property naming | Requires Rework | Rename Type to mode with values day | month | year to match native conventions. |
| Cell primitive unification | Requires Rework | Day / Month / Year cells should become one Picker Cell with kind + state axes before mapping. |
| Native component file | Not Mapped | EBDatePickerPanel wrapper to be created around SwiftUI DatePicker(.graphical) / Compose DatePicker. |
| Raster chevrons | Requires Rework | Replace with vector icon instances before mapping — raster URLs are not representable in native code. |
| Recommendation | Consolidate | Don't ship as a drawn component. Wrap native pickers and tokenize colors. |
Single axis. 3 variants on Type. All share the 360×296 card frame.
| Type | Dimensions | Header | Grid | Node ID |
|---|---|---|---|---|
| Date | 360 × 296 | Prev · "Month / Year" · Next | 7 × 7 (weekdays + 6 day rows) | 12879:49310 |
| Year | 360 × 296 | Prev · "Year" · Next | 3 × 7 visible + Scrollbar overlay | 18431:2825 |
| Month | 360 × 296 | (empty) · "Year" · Next | 3 × 4 (12 months) | 18431:2826 |
Sunday, Monday...Saturday instead of index/role. Weekday is data, not layer identity.
OpenType axis misleading — "Date" means day-grid view. Rename to mode = day | month | year to match SwiftUI / Material 3 terminology.
Open18414:6277 is a 4×80 pill absolutely positioned over the Year grid. Native pickers render the scroll indicator automatically; this decoration misrepresents scroll state.
OpenDatePicker(.graphical) and Material 3 DatePicker own the full calendar. Recommend wrapping and tokenizing, not redrawing.
Openshape_full image URLs. Replace with vector icon instances.
Openmain/date-picker/month-header/*. Add a main/date-picker/group/* scope.
Open