[Glitch] Enable theming via new HTML element attributes

Port bc2f8a358f96a9540e6f39bb1c58273deb4545de to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
diondiondion 2026-01-15 17:04:27 +01:00 committed by Claire
parent 4694013f86
commit 73d29e16b5
6 changed files with 24 additions and 51 deletions

View File

@ -1,7 +1,5 @@
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import type { ApiAnnualReportState } from '@/flavours/glitch/api/annual_report'; import type { ApiAnnualReportState } from '@/flavours/glitch/api/annual_report';
import { Button } from '@/flavours/glitch/components/button'; import { Button } from '@/flavours/glitch/components/button';
@ -19,7 +17,7 @@ export const AnnualReportAnnouncement: React.FC<
AnnualReportAnnouncementProps AnnualReportAnnouncementProps
> = ({ year, state, onRequestBuild, onOpen, onDismiss }) => { > = ({ year, state, onRequestBuild, onOpen, onDismiss }) => {
return ( return (
<div className={classNames('theme-dark', styles.wrapper)}> <div className={styles.wrapper} data-color-scheme='dark'>
<FormattedMessage <FormattedMessage
id='annual_report.announcement.title' id='annual_report.announcement.title'
defaultMessage='Wrapstodon {year} has arrived' defaultMessage='Wrapstodon {year} has arrived'

View File

@ -81,7 +81,7 @@ export const AnnualReport: FC<{ context?: 'modal' | 'standalone' }> = ({
const topHashtag = report.data.top_hashtags[0]; const topHashtag = report.data.top_hashtags[0];
return ( return (
<div className={moduleClassNames(styles.wrapper, 'theme-dark')}> <div className={styles.wrapper} data-color-scheme='dark'>
<div className={styles.header}> <div className={styles.header}>
<h1>Wrapstodon {report.year}</h1> <h1>Wrapstodon {report.year}</h1>
{account && <p>@{account.acct}</p>} {account && <p>@{account.acct}</p>}

View File

@ -60,11 +60,8 @@ const AnnualReportModal: React.FC<{
// default modal backdrop, preventing clicks to pass through. // default modal backdrop, preventing clicks to pass through.
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div <div
className={classNames( className={classNames('modal-root__modal', styles.modalWrapper)}
'modal-root__modal', data-color-scheme='dark'
styles.modalWrapper,
'theme-dark',
)}
onClick={handleCloseModal} onClick={handleCloseModal}
> >
{!showAnnouncement ? ( {!showAnnouncement ? (

View File

@ -1,6 +1,6 @@
import Trie from 'substring-trie'; import Trie from 'substring-trie';
import { getUserTheme, isDarkMode } from '@/flavours/glitch/utils/theme'; import { getIsSystemTheme, isDarkMode } from '@/flavours/glitch/utils/theme';
import { assetHost } from 'flavours/glitch/utils/config'; import { assetHost } from 'flavours/glitch/utils/config';
import { autoPlayGif } from '../../initial_state'; import { autoPlayGif } from '../../initial_state';
@ -98,7 +98,7 @@ const emojifyTextNode = (node, customEmojis) => {
const { filename, shortCode } = unicodeMapping[unicode_emoji]; const { filename, shortCode } = unicodeMapping[unicode_emoji];
const title = shortCode ? `:${shortCode}:` : ''; const title = shortCode ? `:${shortCode}:` : '';
const isSystemTheme = getUserTheme() === 'system'; const isSystemTheme = getIsSystemTheme();
const theme = (isSystemTheme || !isDarkMode()) ? 'light' : 'dark'; const theme = (isSystemTheme || !isDarkMode()) ? 'light' : 'dark';

View File

@ -5,49 +5,29 @@
html { html {
@include base.palette; @include base.palette;
&:where([data-user-theme='system']) {
color-scheme: dark light;
@media (prefers-color-scheme: dark) {
@include dark.tokens;
@include utils.invert-on-dark;
@media (prefers-contrast: more) {
@include dark.contrast-overrides;
}
}
@media (prefers-color-scheme: light) {
@include light.tokens;
@include utils.invert-on-light;
@media (prefers-contrast: more) {
@include light.contrast-overrides;
}
}
}
} }
.theme-dark, [data-color-scheme='dark'],
html:where( html:not([data-color-scheme]) {
:not([data-user-theme='mastodon-light'], [data-user-theme='system'])
) {
color-scheme: dark; color-scheme: dark;
@include dark.tokens; @include dark.tokens;
@include utils.invert-on-dark; @include utils.invert-on-dark;
&[data-contrast='high'],
[data-contrast='high'] & {
@include dark.contrast-overrides;
}
} }
html[data-user-theme='contrast'], [data-color-scheme='light'] {
html[data-user-theme='contrast'] .theme-dark {
@include dark.contrast-overrides;
}
.theme-light,
html:where([data-user-theme='mastodon-light']) {
color-scheme: light; color-scheme: light;
@include light.tokens; @include light.tokens;
@include utils.invert-on-light; @include utils.invert-on-light;
&[data-contrast='high'],
[data-contrast='high'] & {
@include light.contrast-overrides;
}
} }

View File

@ -1,11 +1,9 @@
export function getUserTheme() { export function getIsSystemTheme() {
const { userTheme } = document.documentElement.dataset; const { systemTheme } = document.documentElement.dataset;
return userTheme; return systemTheme === 'true';
} }
export function isDarkMode() { export function isDarkMode() {
const { userTheme } = document.documentElement.dataset; const { colorScheme } = document.documentElement.dataset;
return userTheme === 'system' return colorScheme === 'dark';
? window.matchMedia('(prefers-color-scheme: dark)').matches
: userTheme !== 'mastodon-light';
} }