Skip to content

Commit 94f52c4

Browse files
Merge pull request matrix-org#4731 from matrix-org/joriks/radio-buttons
Change theme selector to use new styled radio buttons
2 parents 8ebae4c + d44fbda commit 94f52c4

File tree

6 files changed

+124
-26
lines changed

6 files changed

+124
-26
lines changed

res/css/views/elements/_StyledCheckbox.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ limitations under the License.
2525

2626
input[type=checkbox] {
2727
appearance: none;
28+
margin: 0;
29+
padding: 0;
2830

2931
& + label {
3032
display: flex;

res/css/views/settings/tabs/user/_AppearanceUserSettingsTab.scss

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,83 @@ limitations under the License.
4444
padding-right: 5px;
4545
}
4646

47+
.mx_AppearanceUserSettingsTab {
48+
> .mx_SettingsTab_SubHeading {
49+
margin-bottom: 32px;
50+
}
51+
}
52+
53+
.mx_AppearanceUserSettingsTab_themeSection {
54+
$radio-bg-color: $input-darker-bg-color;
55+
color: $primary-fg-color;
56+
57+
> .mx_ThemeSelectors {
58+
display: flex;
59+
flex-direction: row;
60+
flex-wrap: wrap;
61+
62+
margin-top: 4px;
63+
margin-bottom: 30px;
64+
65+
> .mx_RadioButton {
66+
padding: $font-16px;
67+
box-sizing: border-box;
68+
border-radius: 10px;
69+
width: 180px;
70+
71+
background: $radio-bg-color;
72+
opacity: 0.4;
73+
74+
flex-shrink: 1;
75+
flex-grow: 0;
76+
77+
margin-right: 15px;
78+
margin-top: 10px;
79+
80+
font-weight: 600;
81+
color: $muted-fg-color;
82+
83+
> span {
84+
justify-content: center;
85+
}
86+
}
87+
88+
> .mx_RadioButton_enabled {
89+
opacity: 1;
90+
91+
// These colors need to be hardcoded because they don't change with the theme
92+
&.mx_ThemeSelector_light {
93+
background-color: #f3f8fd;
94+
color: #2e2f32;
95+
}
96+
97+
&.mx_ThemeSelector_dark {
98+
background-color: #181b21;
99+
color: #f3f8fd;
100+
101+
> input > div {
102+
border-color: $input-darker-bg-color;
103+
> div {
104+
border-color: $input-darker-bg-color;
105+
}
106+
}
107+
}
108+
109+
&.mx_ThemeSelector_black {
110+
background-color: #000000;
111+
color: #f3f8fd;
112+
113+
> input > div {
114+
border-color: $input-darker-bg-color;
115+
> div {
116+
border-color: $input-darker-bg-color;
117+
}
118+
}
119+
}
120+
}
121+
}
122+
}
123+
47124
.mx_SettingsTab_customFontSizeField {
48125
margin-left: calc($font-16px + 10px);
49126
}

src/components/views/elements/StyledRadioButton.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@ export default class StyledRadioButton extends React.PureComponent<IProps, IStat
2929
}
3030

3131
public render() {
32-
const { children, className, ...otherProps } = this.props;
33-
return <label className={classnames('mx_RadioButton', className)}>
34-
<input type='radio' {...otherProps} />
32+
const { children, className, disabled, ...otherProps } = this.props;
33+
const _className = classnames(
34+
'mx_RadioButton',
35+
className,
36+
{
37+
"mx_RadioButton_disabled": disabled,
38+
"mx_RadioButton_enabled": !disabled,
39+
});
40+
return <label className={_className}>
41+
<input type='radio' disabled={disabled} {...otherProps} />
3542
{/* Used to render the radio button circle */}
3643
<div><div></div></div>
3744
<span>{children}</span>

src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
103103
};
104104
}
105105

106-
private onThemeChange = (e: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>): void => {
106+
private onThemeChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
107107
const newTheme = e.target.value;
108108
if (this.state.theme === newTheme) return;
109109

110110
// doing getValue in the .catch will still return the value we failed to set,
111111
// so remember what the value was before we tried to set it so we can revert
112112
const oldTheme: string = SettingsStore.getValue('theme');
113-
SettingsStore.setValue("theme", null, SettingLevel.ACCOUNT, newTheme).catch(() => {
113+
SettingsStore.setValue("theme", null, SettingLevel.DEVICE, newTheme).catch(() => {
114114
dis.dispatch<RecheckThemePayload>({action: Action.RecheckTheme});
115115
this.setState({theme: oldTheme});
116116
});
@@ -199,17 +199,19 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
199199

200200
private renderThemeSection() {
201201
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
202-
const LabelledToggleSwitch = sdk.getComponent("views.elements.LabelledToggleSwitch");
202+
const StyledCheckbox = sdk.getComponent("views.elements.StyledCheckbox");
203+
const StyledRadioButton = sdk.getComponent("views.elements.StyledRadioButton");
203204

204205
const themeWatcher = new ThemeWatcher();
205206
let systemThemeSection: JSX.Element;
206207
if (themeWatcher.isSystemThemeSupported()) {
207208
systemThemeSection = <div>
208-
<LabelledToggleSwitch
209-
value={this.state.useSystemTheme}
210-
label={SettingsStore.getDisplayName("use_system_theme")}
211-
onChange={this.onUseSystemThemeChanged}
212-
/>
209+
<StyledCheckbox
210+
checked={this.state.useSystemTheme}
211+
onChange={(e) => this.onUseSystemThemeChanged(e.target.checked)}
212+
>
213+
{SettingsStore.getDisplayName("use_system_theme")}
214+
</StyledCheckbox>
213215
</div>;
214216
}
215217

@@ -256,17 +258,22 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
256258
<div className="mx_SettingsTab_section mx_AppearanceUserSettingsTab_themeSection">
257259
<span className="mx_SettingsTab_subheading">{_t("Theme")}</span>
258260
{systemThemeSection}
259-
<Field
260-
id="theme" label={_t("Theme")} element="select"
261-
value={this.state.theme} onChange={this.onThemeChange}
262-
disabled={this.state.useSystemTheme}
263-
>
261+
<div className="mx_ThemeSelectors" onChange={this.onThemeChange}>
264262
{orderedThemes.map(theme => {
265-
return <option key={theme.id} value={theme.id}>{theme.name}</option>;
263+
return <StyledRadioButton
264+
key={theme.id}
265+
value={theme.id}
266+
name={"theme"}
267+
disabled={this.state.useSystemTheme}
268+
checked={!this.state.useSystemTheme && theme.id === this.state.theme}
269+
className={"mx_ThemeSelector_" + theme.id}
270+
>
271+
{theme.name}
272+
</StyledRadioButton>;
266273
})}
267-
</Field>
274+
</div>
268275
{customThemeForm}
269-
<SettingsFlag name="useCompactLayout" level={SettingLevel.ACCOUNT} />
276+
<SettingsFlag name="useCompactLayout" level={SettingLevel.ACCOUNT} useCheckbox={true} />
270277
</div>
271278
);
272279
}
@@ -309,8 +316,11 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
309316

310317
render() {
311318
return (
312-
<div className="mx_SettingsTab">
313-
<div className="mx_SettingsTab_heading">{_t("Appearance")}</div>
319+
<div className="mx_SettingsTab mx_AppearanceUserSettingsTab">
320+
<div className="mx_SettingsTab_heading">{_t("Customise your appearance")}</div>
321+
<div className="mx_SettingsTab_SubHeading">
322+
{_t("Appearance Settings only affect this Riot session.")}
323+
</div>
314324
{this.renderThemeSection()}
315325
{SettingsStore.isFeatureEnabled("feature_font_scaling") ? this.renderFontSection() : null}
316326
</div>

src/i18n/strings/en_EN.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@
298298
"%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
299299
"%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
300300
"%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s",
301-
"Light theme": "Light theme",
302-
"Dark theme": "Dark theme",
301+
"Light": "Light",
302+
"Dark": "Dark",
303303
"You signed in to a new session without verifying it:": "You signed in to a new session without verifying it:",
304304
"Verify your other session using one of the options below.": "Verify your other session using one of the options below.",
305305
"%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:",
@@ -779,7 +779,8 @@
779779
"Custom theme URL": "Custom theme URL",
780780
"Add theme": "Add theme",
781781
"Theme": "Theme",
782-
"Appearance": "Appearance",
782+
"Customise your appearance": "Customise your appearance",
783+
"Appearance Settings only affect this Riot session.": "Appearance Settings only affect this Riot session.",
783784
"Flair": "Flair",
784785
"Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
785786
"Success": "Success",
@@ -1769,6 +1770,7 @@
17691770
"Upload %(count)s other files|one": "Upload %(count)s other file",
17701771
"Cancel All": "Cancel All",
17711772
"Upload Error": "Upload Error",
1773+
"Appearance": "Appearance",
17721774
"Verify other session": "Verify other session",
17731775
"Verification Request": "Verification Request",
17741776
"A widget would like to verify your identity": "A widget would like to verify your identity",

src/theme.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import ThemeWatcher from "./settings/watchers/ThemeWatcher";
2424

2525
export function enumerateThemes() {
2626
const BUILTIN_THEMES = {
27-
"light": _t("Light theme"),
28-
"dark": _t("Dark theme"),
27+
"light": _t("Light"),
28+
"dark": _t("Dark"),
2929
};
3030
const customThemes = SettingsStore.getValue("custom_themes");
3131
const customThemeNames = {};

0 commit comments

Comments
 (0)