Skip to content

feat(theme): optional per-feature color accents#693

Open
ericgriffin wants to merge 16 commits into
mainfrom
worktree-color-accents
Open

feat(theme): optional per-feature color accents#693
ericgriffin wants to merge 16 commits into
mainfrom
worktree-color-accents

Conversation

@ericgriffin

Copy link
Copy Markdown
Member

Summary

Adds an optional per-feature-area color accent system. Each feature area gets a
curated identity color that can tint main-menu icons, page-header icons, and
list/settings icons. Three independent toggles live in Settings > Appearance and
all default off, so the app looks exactly as it does today until a toggle is
switched on.

Design spec and implementation plan are committed under
docs/superpowers/ (2026-07-23-color-accents-*).

Changes

Palette

  • New FeatureAccentColors ThemeExtension (lib/core/theme/feature_accent_colors.dart)
    holding curated light and dark maps keyed by the stable NavDestination.id
    strings, plus settings-<sectionId> entries. Registered on all five theme
    presets, so accents resolve per brightness and lerp smoothly across theme
    changes.
  • A missing key returns null and the icon keeps its default color: every failure
    mode degrades to the app's current appearance rather than throwing.
  • Orange and amber are deepened past their Material 700 shades so every feature
    accent clears the 3:1 WCAG ratio for graphical objects in light mode; a test
    enforces this for any accent added later.

Settings, persistence, sync

  • Three per-diver booleans accentNavIcons / accentSectionHeaders /
    accentListIcons, schema v135 on diver_settings (idempotent
    _assertAccentColorSettingsColumns called from both onUpgrade and the
    beforeOpen backstop).
  • Sync needed only import defaults; export already carries new columns because
    _exportDiverSettings serializes whole rows via the generated toJson().
  • Toggles are surfaced in both appearance UIs — the phone AppearancePage and
    the desktop master-detail _AppearanceSectionContent.
  • 7 new strings translated across all 10 non-English locales.

Surfaces

  • Navigation: bottom bar, desktop rail, and the More overflow sheet. The More
    sentinel is never tinted (it has no palette entry by design).
  • Page headers: feature pages had no app-bar icon at all, so the toggle adds
    the feature's icon, accent-tinted, beside the title. Applied to both the
    standard AppBar and the compact app bars used in master-detail layouts.
  • List icons: existing leading avatars on equipment, equipment sets, trips, and
    dive centers. Tiles with no leading icon today are untouched — the toggle
    never adds icons to list rows.
  • Settings root: its section colors were already hardcoded Colors.*. Those
    exact values moved into the shared palette under settings-* keys, so there
    is now one source of truth. The root stays always-colored and visually
    unchanged.

Refactor (behavior-preserving)

  • main_scaffold.dart's NavigationRail hardcoded all 14 destinations plus two
    index/route switch statements. It now iterates the shared kNavDestinations
    list like the mobile bar already did (-129 lines, +19). A new
    rail_destination_order_test.dart locks the previous index-to-route contract
    so the refactor cannot silently reorder navigation.

Test Plan

  • flutter test passes — 13,719 passed, 14 skipped, 0 failed
  • flutter analyze passes — no issues
  • dart format . — 0 files changed
  • Manual testing on: macOS (pending)

New coverage includes palette completeness and contrast guards, theme-preset
registration, the v135 migration on both the upgrade and fresh-database paths,
sync hydration of pre-v135 payloads, per-column persistence independence, the
FeatureAccentIcon on/off/unknown-id/dark-mode matrix, nav accents on bar, rail
and overflow sheet, and a test asserting that an overdue equipment service
keeps its error color even with accents on
— a cosmetic preference must not be
able to hide a maintenance warning.

Note: four inherited settings-row colors (Data, Notifications, Shared data,
Debug) sit below 3:1 contrast in light mode. They reproduce what the settings
screen renders today and were deliberately left unchanged; raising them is worth
doing as its own change.

The desktop master-detail pane renders _AppearanceSectionContent, a
separate widget from AppearancePage, so the toggles were phone-only.
Same duplication hid header accents behind the eight list-content
compact app bars, which render their own styled title instead of an
AppBar; FeatureAppBarTitle now takes an optional style so those can
adopt it without changing their typography.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in “feature accent colors” system that tints icons across navigation, page headers, and selected list/settings surfaces, controlled by three per-diver toggles persisted in Drift (v135) and synced across devices.

Changes:

  • Introduces FeatureAccentColors ThemeExtension (light/dark palettes) and registers it across all theme presets, with contrast/completeness tests.
  • Adds three diver settings toggles (accentNavIcons, accentSectionHeaders, accentListIcons) with schema v135 migration + sync-default hydration for legacy payloads.
  • Applies accent-driven icon tinting to navigation (bar/rail/overflow), feature page AppBar titles, and selected list/settings leading icons; refactors rail destinations to iterate kNavDestinations with a regression test for ordering.

Reviewed changes

Copilot reviewed 72 out of 72 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/shared/widgets/nav/rail_destination_order_test.dart Locks canonical rail destination ordering/route mapping after rail refactor.
test/shared/widgets/main_scaffold_test.dart Extends scaffold tests to cover nav accent behavior.
test/shared/widgets/feature_accent_test.dart Widget tests for FeatureAccentIcon / FeatureAppBarTitle behavior and fallbacks.
test/helpers/mock_providers.dart Adds accent-toggle setters to MockSettingsNotifier.
test/features/statistics/presentation/pages/records_page_test.dart Updates mock SettingsNotifier to implement new accent setters.
test/features/settings/presentation/providers/settings_notifier_real_test.dart Adds real-notifier tests for accent toggle independence/providers.
test/features/settings/presentation/pages/settings_page_test.dart Adds tests for settings section palette resolution + appearance hub accent toggles.
test/features/settings/presentation/pages/settings_page_shared_data_test.dart Updates mock SettingsNotifier to implement new accent setters.
test/features/settings/presentation/pages/appearance_page_test.dart Adds tests asserting the three accent toggles appear and behave independently.
test/features/settings/data/repositories/diver_settings_repository_accents_test.dart DB-backed persistence tests for the three new accent columns.
test/features/equipment/presentation/widgets/equipment_tile_service_badge_test.dart Stubs settings provider for tiles that now read accent toggles.
test/features/equipment/presentation/widgets/equipment_tile_accent_test.dart Tests list-icon accents and ensures overdue-service colors win over accents.
test/features/equipment/presentation/widgets/equipment_list_content_test.dart Stubs settings provider for equipment list content tests (accent reads).
test/core/theme/theme_preset_accents_test.dart Verifies all theme presets register FeatureAccentColors in both modes.
test/core/theme/feature_accent_colors_test.dart Validates palette completeness, lerp/copyWith, and WCAG-ish contrast guards.
test/core/services/sync/sync_diver_settings_fallback_test.dart Ensures pre-v135 sync payloads hydrate new non-nullable accent fields safely.
test/core/database/migration_v135_accent_columns_test.dart Migration coverage for v135 accent toggle columns + schema tripwire.
test/core/database/media_compressed_columns_migration_test.dart Relaxes previous “latest schema” tripwire now that v135 exists.
lib/shared/widgets/main_scaffold.dart Refactors rail to iterate kNavDestinations and applies nav icon accents (bar/rail/overflow).
lib/shared/widgets/feature_accent.dart Adds shared accent resolution helper + FeatureAccentIcon/FeatureAppBarTitle.
lib/features/trips/presentation/widgets/trip_list_content.dart Applies header accents and list-avatar accent tinting for trips.
lib/features/transfer/presentation/pages/transfer_page.dart Applies header accents to Transfer page AppBar.
lib/features/statistics/presentation/pages/statistics_page.dart Applies header accents to Statistics page AppBar.
lib/features/settings/presentation/widgets/settings_list_content.dart Moves settings section colors to palette lookup (removes per-section hardcoded colors).
lib/features/settings/presentation/providers/settings_providers.dart Adds accent fields to AppSettings, setters on SettingsNotifier, and narrow gate providers.
lib/features/settings/presentation/pages/settings_page.dart Adds desktop appearance-pane toggles + uses accent icons; settings tile colors now resolve from palette.
lib/features/settings/presentation/pages/appearance_page.dart Adds “Color accents” toggle group and tints appearance-page leading icons via FeatureAccentIcon.
lib/features/settings/data/repositories/diver_settings_repository.dart Maps new accent fields to/from Drift diver_settings rows.
lib/features/planning/presentation/pages/planning_page.dart Applies header accents to Planning page AppBar.
lib/features/gps_log/presentation/pages/gps_logger_page.dart Applies header accents to GPS Logger page AppBar.
lib/features/equipment/presentation/widgets/equipment_set_list_content.dart Applies list-icon accents to equipment set avatar.
lib/features/equipment/presentation/widgets/equipment_list_content.dart Applies header accents + list avatar accents; preserves overdue error colors.
lib/features/equipment/presentation/pages/equipment_list_page.dart Applies header accents to equipment list page AppBar.
lib/features/dive_sites/presentation/widgets/site_list_content.dart Applies header accents to sites list AppBars (regular + compact).
lib/features/dive_log/presentation/widgets/dive_list_content.dart Applies header accents to dive list AppBars (regular + compact).
lib/features/dive_centers/presentation/widgets/dive_center_list_content.dart Applies header accents + list-icon accents to dive center search/list leading icon container.
lib/features/courses/presentation/widgets/course_list_content.dart Applies header accents to courses list AppBars (regular + compact).
lib/features/certifications/presentation/widgets/certification_list_content.dart Applies header accents to certifications list AppBars (regular + compact).
lib/features/buddies/presentation/widgets/buddy_list_content.dart Applies header accents to buddies list AppBars (regular + compact).
lib/core/theme/full_themes/tropical_theme.dart Registers FeatureAccentColors extension on tropical themes.
lib/core/theme/full_themes/submersion_theme.dart Registers FeatureAccentColors extension on default themes.
lib/core/theme/full_themes/minimalist_theme.dart Registers FeatureAccentColors extension on minimalist themes.
lib/core/theme/full_themes/deep_theme.dart Registers FeatureAccentColors extension on deep themes.
lib/core/theme/full_themes/console_theme.dart Registers FeatureAccentColors extension on console themes.
lib/core/theme/feature_accent_colors.dart Implements curated accent palettes as a ThemeExtension with lerp/copyWith.
lib/core/services/sync/sync_data_serializer.dart Seeds sync defaults for new accent fields to handle legacy payloads.
lib/core/database/database.dart Adds v135 accent columns + idempotent migration/backstop and bumps schema version.
lib/l10n/arb/app_zh.arb Adds 7 new localized strings for color accents (ZH).
lib/l10n/arb/app_pt.arb Adds 7 new localized strings for color accents (PT).
lib/l10n/arb/app_nl.arb Adds 7 new localized strings for color accents (NL).
lib/l10n/arb/app_localizations.dart Adds generated getters for accent toggle strings.
lib/l10n/arb/app_localizations_zh.dart Adds generated ZH implementations for new strings.
lib/l10n/arb/app_localizations_pt.dart Adds generated PT implementations for new strings.
lib/l10n/arb/app_localizations_nl.dart Adds generated NL implementations for new strings.
lib/l10n/arb/app_localizations_it.dart Adds generated IT implementations for new strings.
lib/l10n/arb/app_localizations_hu.dart Adds generated HU implementations for new strings.
lib/l10n/arb/app_localizations_he.dart Adds generated HE implementations for new strings.
lib/l10n/arb/app_localizations_fr.dart Adds generated FR implementations for new strings.
lib/l10n/arb/app_localizations_es.dart Adds generated ES implementations for new strings.
lib/l10n/arb/app_localizations_en.dart Adds generated EN implementations for new strings.
lib/l10n/arb/app_localizations_de.dart Adds generated DE implementations for new strings.
lib/l10n/arb/app_localizations_ar.dart Adds generated AR implementations for new strings.
lib/l10n/arb/app_it.arb Adds 7 new localized strings for color accents (IT).
lib/l10n/arb/app_hu.arb Adds 7 new localized strings for color accents (HU).
lib/l10n/arb/app_he.arb Adds 7 new localized strings for color accents (HE).
lib/l10n/arb/app_fr.arb Adds 7 new localized strings for color accents (FR).
lib/l10n/arb/app_es.arb Adds 7 new localized strings for color accents (ES).
lib/l10n/arb/app_en.arb Adds 7 new English strings for color accents.
lib/l10n/arb/app_de.arb Adds 7 new localized strings for color accents (DE).
lib/l10n/arb/app_ar.arb Adds 7 new localized strings for color accents (AR).
docs/superpowers/specs/2026-07-23-color-accents-design.md Adds design spec for the feature accent system.
docs/superpowers/plans/2026-07-23-color-accents.md Adds detailed implementation plan and task breakdown.
Comments suppressed due to low confidence (1)

test/features/settings/presentation/pages/settings_page_test.dart:830

  • The wide-screen Appearance hub tests below assert English labels ('Color accents', 'Dives', etc.), but buildAppearanceWidget's MaterialApp.router doesn't pin locale, so these can fail under a non-English platform locale. Repo convention is to pin locale: const Locale('en') for deterministic string finders (test/helpers/test_app.dart:17-19).

Comment on lines 82 to 86
child: MaterialApp.router(
routerConfig: router,
theme: theme,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
Comment on lines 500 to +504
child: ProviderScope(
overrides: getOverrides(),
child: MaterialApp(
locale: locale,
theme: theme,
Comment on lines +139 to +145
group('AppearancePage color accents', () {
testWidgets('shows the three accent toggles, all off by default', (
tester,
) async {
await tester.binding.setSurfaceSize(const Size(400, 2000));
addTearDown(() => tester.binding.setSurfaceSize(null));

@github-actions

Copy link
Copy Markdown
Contributor

📦 Build artifacts for this PR · commit 89a4bfa

Platform Download
Android (APK) android-apk
macOS macos-build
Windows windows-build
Linux linux-build

Artifacts expire in 7 days. Downloading requires being signed in to GitHub. The macOS build is ad-hoc signed — right-click → Open on first launch.

Updated automatically on each push.

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

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants