I would like to add a toggle for my Ionic project that controls the theme of the entire application. The toggle can force a light mode/dark mode irrespective of what the system mode is (ie. stays dark mode even if the system turns from dark → light) and also an option to toggle back to automatic.
Currently what I have done is follow the Ionic Conference App https://github.com/ionic-team/ionic-conference-app and what I’ve done to my base project is:
- Remove
@media (prefers-color-scheme: dark)
fromvariables.scss
and add.dark-theme
class to the media queries, ie.body
→.dark-theme
,.ios body
→.dark-theme.ios
- Add an
ion-segment
to my settings page:
<ion-label position="fixed">Mode</ion-label>
<ion-segment
[(ngModel)]="modeService.mode"
(ionChange)="modeService.setMode()"
>
<ion-segment-button value="light">
<ion-label>Light</ion-label>
</ion-segment-button>
<ion-segment-button value="dark">
<ion-label>Dark</ion-label>
</ion-segment-button>
<ion-segment-button value="auto">
<ion-label>Auto</ion-label>
</ion-segment-button>
</ion-segment>
- in my
modeService.ts
file (which is the service I use to save the mode to the storage and handle the mode change:
dark: boolean;
mode = 'auto';
prefDark = window.matchMedia('(prefers-color-scheme: dark)');
constructor() { }
setMode = async (): Promise<void> => {
const storeMode = this.mode;
await Storage.set({
key: 'mode',
value: storeMode
});
if (this.mode !== 'auto') {
this.dark = (this.mode === 'dark') ? true : false;
} else {
this.dark = this.prefDark.matches;
this.prefDark.addEventListener('change', e => {
this.dark = e.matches;
});
}
};
checkMode = async (): Promise<void> => {
const { value } = await Storage.get({ key: 'mode' });
if (value) {
this.mode = value;
}
};
}
- In
app.component.html
I added[class.dark-theme]="modeService.dark"
to<ion-app>
- In
app.component.ts
:
export class AppComponent implements OnInit{
prefDark = window.matchMedia('(prefers-color-scheme: dark)');
constructor(
private themeService: ThemesService,
public teamService: TeamService,
private helpService: HelpService,
public modeService: ModeService,
private router: Router,
public modalController: ModalController,
private menuController: MenuController,
) { }
async ngOnInit() {
await ... /// some other theme change
if (this.modeService.mode === 'auto') {
this.modeService.dark = this.prefDark.matches;
this.prefDark.addEventListener('change', e => {
this.modeService.dark = e.matches;
});
}
}
The problem is, the toggle work but say when I have the segment to dark
and the OS theme is changed to dark
, then I toggle the OS theme to light
the app turns back to the light theme and does not keep the dark theme.
1 post - 1 participant