Skip to content

sam-datepicker-v2 renders unstyled: .datepicker__* CSS was lost in the 2019 fork #681

Description

@fpigeonjr

sam-datepicker-v2 renders with no styling at all. Its template asks for a full set of bespoke .datepicker__* classes that are not defined in any stylesheet — not in this repo, not in sam-styles/, not in @gsa-sam/sam-styles, and not in any node_modules of either workspace.

Measured on the /datepicker gallery route added in #666 (Chromium, real browser):

popup:      684 x 2081 px
.datepicker__calendar        position: static   (needs absolute)
.datepicker__calendar__month__day  display: block, width: 684px

Day cells stack vertically down the page instead of forming a 7-column grid, and the popup is not positioned over the input.

Root cause

sam-datepicker-v2 is a fork of angular2-material-datepicker (MIT). The animation trigger is byte-identical, keyframe offsets and all:

// upstream and SAM, identical
trigger('calendarAnimation', [
  transition('* => left', [ animate(180, keyframes([
    style({ transform: 'translateX(105%)',  offset: 0.5  }),
    style({ transform: 'translateX(-130%)', offset: 0.51 }),
    style({ transform: 'translateX(0)',     offset: 1    }) ]))]),

Upstream carried its CSS inline in styles: [...] — 25 .datepicker__* rules, including the structural ones:

.datepicker { position: relative; display: inline-block; }
.datepicker__calendar { position: absolute; overflow: hidden; z-index: 1000;
  top: 1.9em; left: 0; height: 24.25em; width: 20.5em;
  background-color: #fff; box-shadow: 0 3px 6px rgba(0,0,0,.16), 0 3px 6px rgba(0,0,0,.23); }

SAM's fork (3ba95ec0, Feb 2019, "PR for adding date range component related to IAE-14621" #263) moved the inline template out to picker.template.html and dropped the styles: block entirely, without re-adding it to either the component or sam-styles/. The class names came along, so the markup still requests CSS that has never existed in this repo. date-range-v2.component.scss has been 0 bytes since that same commit and picker.component.ts has no styleUrls.

Why this went unnoticed for ~7 years

Nothing rendered it. test-app could not render any library component until #665, and the sole tracked consumer does not use this component:

  • scripts/consumer-deep-imports.json tracks 3 consumers, all the same app (iae-sam-front-end, -front-end3, -front-end-uat).
  • Zero occurrences of sam-datepicker-v2 or sam-date-range-v2 in that app's source. It uses the stable control instead: 32x <sam-date>, 8x <sam-date-range>.
  • SamUIKitModule -> SamExperimentalModule does register SamDateRangeV2Module, so it is compiled into the consumer bundle and available in templates — just never used.
  • Five other SAM frontends checked (-search, -admin, -integrity, -systemaccounts, -role-management-service) do not depend on sam-ui-elements at all.

Contrast with the stable sam-date, which also has no styleUrls but whose markup uses USWDS classes (usa-form-group, usa-form-control) that every consumer already loads globally. That is why sam-date renders fine with no CSS from this library and sam-datepicker-v2 does not.

Decision needed first

Given zero known consumers, "write calendar CSS" may not be the right answer. Pick one:

  1. Restore the lost upstream CSS as component styleUrls (matches experimental/tabs, which does self-style; Angular's _ngcontent scoping avoids any global-namespace collision). Upstream is MIT — attribute it.
  2. Add it to sam-styles/themes/sam-gov, matching the library's dominant global-CSS model (that is how iae-sam-front-end styles the kit: @import '@gsa-sam/sam-ui-elements/sam-styles/themes/sam-gov'). Riskier — global namespace.
  3. Deprecate date-range-v2. It is experimental/, forked, unstyled, and unused. Removal is a breaking change for the deep-import contract, so check scripts/consumer-deep-imports.json first (it currently lists no date-range-v2 paths).

Two smaller, separable gaps

These are legitimately the consumer's responsibility, but the harness needs them for manual testing either way:

  • .fa fa-calendar — a SAM addition (upstream had no icon; it clicked the input). @fortawesome/fontawesome-free is a root peerDependency, so consumers load the webfont CSS. test-app has only fontawesome-svg-core (JS/SVG API), so no glyph renders.
  • .sr-only — Bootstrap-era class. @gsa-sam/sam-styles ships only USWDS .usa-sr-only, so nothing defines it and the screen-reader label renders as the visible text "Calendar" next to the input.

Acceptance criteria

  • A decision is recorded on options 1/2/3 above
  • If styling: .datepicker, .datepicker__calendar, nav/arrow/chevron, __labels/__label, __month/__month__day, and __cancel all render as a positioned 7-column calendar overlay
  • If styling: upstream MIT attribution is included alongside the restored rules
  • test-app loads FontAwesome webfont CSS and an .sr-only rule so /datepicker is manually testable without DevTools injection
  • Playwright assertions cover the cascade-level properties jsdom cannot see (position: absolute on the popup, popup width, day-cell width ~14.28%) — per AGENTS.md's Vitest/Playwright boundary
  • The existing open-click guard in test-app/e2e/datepicker.spec.ts still fails when the contains() fix in picker.component.ts is reverted. It clicks the .sr-only child explicitly for exactly this reason; adding an .sr-only rule collapses that span to 1x1, and a centre click on .fa-calendar would pass even with the defect reintroduced. Verify by reverting the fix locally.

Context

Found while manually testing #666, which added the /datepicker gallery route — the first time this component had ever been rendered in a browser in CI or locally. Deliberately kept out of #666 to hold that PR to its two event-handling fixes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions