fix(ui): dark-mode skeleton shimmer and border parity#49
Conversation
Replace hardcoded hex CSS with light-dark() for 8 components: skeleton loading shimmer, border colors, scrollbar tracks. Ensures proper dark-mode rendering when consumed by host apps.
Greptile SummaryThis PR converts hardcoded light-mode CSS variable references to Confidence Score: 5/5Safe to merge — the only finding is a P2 progressively-enhanced fallback suggestion with no functional regression on supported browsers. All changes are CSS-only and internally consistent. The sole concern is the absence of a plain-gradient fallback before the light-dark() declarations, which is a best-practice suggestion rather than a blocking defect. No browser that already supports light-dark() (the intended target) is broken. No files require special attention; the fallback suggestion applies equally to all six skeleton-shimmer components. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Host App sets color-scheme] --> B{Browser supports light-dark}
B -- Yes - modern --> C[light-dark resolves correctly]
C --> D[Light mode - surface-200/300 gradient shimmer]
C --> E[Dark mode - surface-700/800 gradient shimmer]
B -- No - older browser --> F[Declaration silently ignored]
F --> G[Skeleton background = transparent - no shimmer visible]
Reviews (1): Last reviewed commit: "fix(ui): dark-mode skeleton shimmer and ..." | Re-trigger Greptile |
| .skeleton-slot { | ||
| background: linear-gradient(90deg, var(--color-surface-200) 25%, var(--color-surface-300) 50%, var(--color-surface-200) 75%); | ||
| background: light-dark( | ||
| linear-gradient(90deg, var(--color-surface-200) 25%, var(--color-surface-300) 50%, var(--color-surface-200) 75%), | ||
| linear-gradient(90deg, var(--color-surface-800) 25%, var(--color-surface-700) 50%, var(--color-surface-800) 75%) | ||
| ); | ||
| background-size: 200% 100%; | ||
| animation: shimmer 1.5s infinite; |
There was a problem hiding this comment.
Missing fallback for unsupported browsers
light-dark() with linear-gradient() arguments is only supported in Chrome 123+, Firefox 120+, and Safari 17.5+. In browsers without support the entire background declaration is silently dropped, leaving skeleton shimmer elements with a transparent background — the loading placeholder becomes invisible. Adding a plain gradient before the light-dark() declaration lets unsupported browsers degrade gracefully to the light-mode shimmer.
| .skeleton-slot { | |
| background: linear-gradient(90deg, var(--color-surface-200) 25%, var(--color-surface-300) 50%, var(--color-surface-200) 75%); | |
| background: light-dark( | |
| linear-gradient(90deg, var(--color-surface-200) 25%, var(--color-surface-300) 50%, var(--color-surface-200) 75%), | |
| linear-gradient(90deg, var(--color-surface-800) 25%, var(--color-surface-700) 50%, var(--color-surface-800) 75%) | |
| ); | |
| background-size: 200% 100%; | |
| animation: shimmer 1.5s infinite; | |
| background: linear-gradient(90deg, var(--color-surface-200) 25%, var(--color-surface-300) 50%, var(--color-surface-200) 75%); | |
| background: light-dark( | |
| linear-gradient(90deg, var(--color-surface-200) 25%, var(--color-surface-300) 50%, var(--color-surface-200) 75%), | |
| linear-gradient(90deg, var(--color-surface-800) 25%, var(--color-surface-700) 50%, var(--color-surface-800) 75%) | |
| ); |
The same pattern applies to the .skeleton-* rules in PaymentSelector, ProviderPicker, ServicePicker, StripeCheckout, VenmoButton, and VenmoCheckout.
* refactor!: remove middleware code (belongs in acuity-middleware) (#10) Removed: src/middleware/ (33 files), modal-app.py, Dockerfile, live tests, playwright deps. Version 0.3.1 to 0.4.0. * chore: bump version to 0.5.0 * refactor!: remove acuity-scraper adapter Scraper belongs in acuity-middleware, not the scheduling library. Deprecated since extract-business.ts + middleware wizard steps replaced all scraper functionality. BREAKING: AcuityScraper, createScraperAdapter, scrapeServicesOnce, scrapeAvailabilityOnce removed from @tummycrypt/scheduling-kit/adapters. * build: add Bazel 8 configuration with subpackage targets - MODULE.bazel: bzlmod config with rules_js 2.9.1, rules_ts 3.8.4, SWC, pnpm 9 - BUILD.bazel: svelte-package build, npm_package, 6 subpackage ts_project targets (core, adapters, payments, reconciliation, lib, testing), vitest, svelte-check typecheck - .bazelrc: build/CI/debug/release configs with disk cache - .bazelversion: pin to 8.1.1 - .npmrc: hoist=false (required by rules_js) * feat: v0.5.0 - remove acuity-scraper, add Bazel 8 config (#11) * chore: bump version to 0.5.0 * refactor!: remove acuity-scraper adapter Scraper belongs in acuity-middleware, not the scheduling library. Deprecated since extract-business.ts + middleware wizard steps replaced all scraper functionality. BREAKING: AcuityScraper, createScraperAdapter, scrapeServicesOnce, scrapeAvailabilityOnce removed from @tummycrypt/scheduling-kit/adapters. * build: add Bazel 8 configuration with subpackage targets - MODULE.bazel: bzlmod config with rules_js 2.9.1, rules_ts 3.8.4, SWC, pnpm 9 - BUILD.bazel: svelte-package build, npm_package, 6 subpackage ts_project targets (core, adapters, payments, reconciliation, lib, testing), vitest, svelte-check typecheck - .bazelrc: build/CI/debug/release configs with disk cache - .bazelversion: pin to 8.1.1 - .npmrc: hoist=false (required by rules_js) * feat(venmo): add payeeEmail option to route payments to practitioner When payeeEmail is set in VenmoAdapterConfig, the PayPal order creation includes payee.email_address in purchase_units. This routes payments directly to the practitioner's PayPal account without requiring their API credentials. Ref: PayPal "Pay another account" docs * chore: bump version to 0.5.1 (payee-email support) * fix(ci): use @Jesssullivan scope for GitHub Packages mirror (Jesssullivan#18) * feat(venmo): add returnUrl/cancelUrl to experience_context (Jesssullivan#19) * fix(ci): use @Jesssullivan scope for GitHub Packages mirror * feat(venmo): add returnUrl/cancelUrl to experience_context PayPal requires return_url and cancel_url in the Venmo payment source experience_context for proper popup handling. Without them, PayPal may force additional buyer verification loops or block the popup flow. New optional fields on VenmoAdapterConfig: returnUrl, cancelUrl. * chore: bump to 0.5.2 (PayPal return URLs) (Jesssullivan#20) * fix(ci): use @Jesssullivan scope for GitHub Packages mirror * feat(venmo): add returnUrl/cancelUrl to experience_context PayPal requires return_url and cancel_url in the Venmo payment source experience_context for proper popup handling. Without them, PayPal may force additional buyer verification loops or block the popup flow. New optional fields on VenmoAdapterConfig: returnUrl, cancelUrl. * chore: bump to 0.5.2 (PayPal return URLs) * feat: onboarding subpackage — provider credential management (Jesssullivan#21-Jesssullivan#27) (Jesssullivan#28) New @tummycrypt/scheduling-kit/onboarding subpackage: Interfaces: - CredentialStore: app-provided key-value storage (PG, Redis, etc.) - EncryptionProvider: app-provided encryption (AES, Vault, etc.) - StripeConnectConfig, StripeAccountStatus, WebhookSetupResult types Stripe: - buildStripeAuthorizeUrl() + exchangeStripeCode() — Connect OAuth - getStripeAccountStatus() — account onboarding status - validateStripeKeys() — key validation against Stripe API - createStripeWebhook() + deleteStripeWebhooks() — webhook CRUD PayPal: - validatePayPalCredentials() — OAuth token validation - createPayPalWebhook() — webhook creation Build: - Bazel //src/onboarding target (deps: :core, :payments, effect) - Package.json ./onboarding export Pattern: library defines interfaces + helpers, application provides CredentialStore implementation. Same pattern as HomegrownAdapter's getDb callback — scheduling-kit doesn't know about databases. Closes Jesssullivan#21, Jesssullivan#22, Jesssullivan#23, Jesssullivan#24, Jesssullivan#27. Partial Jesssullivan#25, Jesssullivan#26. * chore: bump to 0.6.0 (onboarding subpackage) (Jesssullivan#29) * feat: adapter factory pattern + 21 onboarding tests (Jesssullivan#25, Jesssullivan#26) (Jesssullivan#30) - createAdapterFactory(): settings-driven singleton with cache, promise dedup, reset, and disable lifecycle - 21 tests: Stripe OAuth URL, key validation, account status, PayPal credential validation, factory lifecycle (cache, reset, disable, store passthrough) - Updated vitest.config.ts to include onboarding test glob Closes Jesssullivan#25, Jesssullivan#26. * chore: strip sourcemaps from npm package (Jesssullivan#31) * feat: adapter factory pattern + 21 onboarding tests (Jesssullivan#25, Jesssullivan#26) - createAdapterFactory(): settings-driven singleton with cache, promise dedup, reset, and disable lifecycle - 21 tests: Stripe OAuth URL, key validation, account status, PayPal credential validation, factory lifecycle (cache, reset, disable, store passthrough) - Updated vitest.config.ts to include onboarding test glob Closes Jesssullivan#25, Jesssullivan#26. * chore: strip sourcemaps from npm package (2,711 .map files excluded) * feat: provider status helpers + SetupStep type (Jesssullivan#32) (Jesssullivan#33) * chore: bump to 0.6.1 (status helpers) (Jesssullivan#34) * align build truth and package boundaries (Jesssullivan#39) * ci: enforce Bazel release metadata truth (Jesssullivan#40) * docs: add agent and llm operating brief (Jesssullivan#42) * feat(payments)!: converge PaymentCapabilities contract from tinyland-inc (Jesssullivan#45) * feat(payments)!: converge PaymentCapabilities contract from tinyland-inc Cherry-pick tinyland-inc/main squash (v0.7.0) onto Jesssullivan/main. Keeps Jess's CI/publish workflows and Bazel structure. Bumps all version references to 0.7.0. - PaymentCapabilities, StripeCapability, VenmoCapability types - getDefaultCapabilities() factory - HybridCheckoutDrawer: capabilities prop replaces individual payment props - Cash at Visit structurally removed (cash: false) * fix(ci): skip prepublish scripts in gh packages mirror * docs(release): clarify scheduling-kit authority (Jesssullivan#46) * ci(publish): validate bazel package artifact (Jesssullivan#47) * build(bazel): publish scheduling-kit from bazel artifact * fix(ui): dark-mode skeleton shimmer and border parity (Jesssullivan#49) Replace hardcoded hex CSS with light-dark() for 8 components: skeleton loading shimmer, border colors, scrollbar tracks. Ensures proper dark-mode rendering when consumed by host apps. * ci: support honey self-hosted runner stopgap (Jesssullivan#50) * ci: isolate pnpm store on self-hosted runners (Jesssullivan#51) * fix: make publish workflow self-hosted-safe (Jesssullivan#52) * fix(ci): make github package artifact writable (Jesssullivan#53) * perf(components): drop zod from browser client form (Jesssullivan#54) * fix(ci): ignore npm scripts when publishing bazel pkg (Jesssullivan#55) * fix(ci): ignore npm scripts when publishing bazel pkg * fix(ci): clean stale bazel publish artifacts on runners * fix(ci): partition pnpm caches by runner (Jesssullivan#56)
Summary
light-dark()in 8 componentslight-dark(var(--color-surface-300), var(--color-surface-700))Components
ClientForm, DateTimePicker, PaymentSelector, ProviderPicker, ServicePicker, StripeCheckout, VenmoButton, VenmoCheckout
Test plan
pnpm test— 583/583 pass