Skip to content

feat(android): support themeVariant on the default date and time dialogs - #1075

Open
zarek-marshall wants to merge 1 commit into
react-native-datetimepicker:masterfrom
zarek-marshall:feat/android-theme-variant
Open

zarek-marshall wants to merge 1 commit into
react-native-datetimepicker:masterfrom
zarek-marshall:feat/android-theme-variant

Conversation

@zarek-marshall

Copy link
Copy Markdown

Summary

themeVariant is currently iOS-only. On Android, the default (non-material) DatePickerDialog and TimePickerDialog always take their light or dark look from the Activity's night mode. Apps with an in-app theme switch that differs from the system theme get a dark picker on a light screen, or the reverse. The only workaround is changing the Activity's night mode at runtime (AppCompatDelegate.setDefaultNightMode). That triggers a configuration change or recreate, which some apps avoid because it can orphan open dialogs.

This PR makes Android honour themeVariant per dialog:

  • JS: themeVariant is forwarded from datetimepicker.android.js and DateTimePickerAndroid.open through androidUtils.getOpenPicker, which rebuilds the params from a fixed field list, to RNCDatePicker.open and RNCTimePicker.open. The field is added to both TurboModule specs, index.d.ts and types.js.
  • Native: Common.applyThemeVariant(activity, args) returns a ContextWrapper around the Activity with resources from createConfigurationContext (uiMode night bit forced) and a fresh Theme built from the Activity's theme resource on those resources. The Activity's live Theme isn't copied, because it can hold attributes resolved under the other night mode. Window and system services still come from the Activity, so the dialog keeps its window token. Both dialog fragments build their dialog on this context.
  • Unchanged: without themeVariant, behaviour is the same as before. Material pickers (design="material") are not touched.
  • README: themeVariant is no longer marked iOS only, and the Android behaviour is described.

Test Plan

  • New Jest test in test/index.test.js runs DateTimePickerAndroid.open → getOpenPicker against a mocked picker module and asserts themeVariant reaches the date and time pickers. It fails without the androidUtils.js change. yarn test: 32 passed. ESLint shows no new warnings. I couldn't run flow check locally (flow-bin version mismatch with .flowconfig).
  • Shipped as a patch-package patch in a production app (React Native 0.87, new architecture), with device testing on Android:
    • system Dark and app Light → both dialogs light
    • app Dark → both dialogs dark
    • app following the system → dialogs follow the system
    • no app restart needed

What's required for testing (prerequisites)?

An Android device or emulator with the system theme set to Dark.

What are the steps to reproduce (after prerequisites)?

Render <DateTimePicker value={new Date()} themeVariant="light" /> (default design) and open it. Before this change the dialog is dark; with it, it's light. For the time picker, use mode="time".

Compatibility

OS Implemented
iOS ✅
Android ✅

Checklist

  • I have tested this on a device (Android phone, not an emulator)
  • I added the documentation in README.md
  • I updated the typed files (TS and Flow)
  • I added a sample use of the API in the example project (example/App.js)
  • I have added automated tests, either in JS or e2e tests, as applicable

🤖 Generated with Claude Code

themeVariant was iOS-only. On Android the default (non-material) dialogs
always followed the Activity's night mode, so apps with an in-app theme
that differs from the system theme got a mismatched picker unless they
changed the Activity's night mode at runtime.

Forward themeVariant from the component and DateTimePickerAndroid.open
through androidUtils.getOpenPicker to both native modules, and build each
dialog on a context whose resources have the uiMode night bit forced and
whose theme is created fresh from the Activity's theme resource (not copied
from the Activity's live Theme). The Activity is not changed. Without
themeVariant, behaviour is unchanged; material pickers are untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019NZ2QVLavesbwzc7npEiDM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants