Use semantic headings in user settings - Notifications (#10948)
* use semantic headings in user notif settings * unset margin for subsection content when no heading * remove debug
This commit is contained in:
parent
f491f2f951
commit
9211da20f4
6 changed files with 81 additions and 85 deletions
|
@ -52,4 +52,8 @@ limitations under the License.
|
||||||
&.mx_SettingsSubsection_contentStretch {
|
&.mx_SettingsSubsection_contentStretch {
|
||||||
justify-items: stretch;
|
justify-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.mx_SettingsSubsection_noHeading {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ limitations under the License.
|
||||||
grid-template-columns: auto repeat(3, 62px);
|
grid-template-columns: auto repeat(3, 62px);
|
||||||
place-items: center center;
|
place-items: center center;
|
||||||
grid-gap: 8px;
|
grid-gap: 8px;
|
||||||
margin-top: $spacing-40;
|
|
||||||
|
|
||||||
/* Override StyledRadioButton default styles */
|
/* Override StyledRadioButton default styles */
|
||||||
.mx_StyledRadioButton {
|
.mx_StyledRadioButton {
|
||||||
|
@ -34,6 +33,11 @@ limitations under the License.
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// left align section heading
|
||||||
|
.mx_SettingsSubsectionHeading {
|
||||||
|
justify-self: start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_UserNotifSettings_gridRowContainer {
|
.mx_UserNotifSettings_gridRowContainer {
|
||||||
|
@ -51,10 +55,6 @@ limitations under the License.
|
||||||
/* force it inline using float */
|
/* force it inline using float */
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
.mx_UserNotifSettings_gridRowHeading {
|
|
||||||
font-size: $font-18px;
|
|
||||||
font-weight: var(--font-semi-bold);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_UserNotifSettings_gridColumnLabel {
|
.mx_UserNotifSettings_gridColumnLabel {
|
||||||
color: $secondary-content;
|
color: $secondary-content;
|
||||||
|
@ -70,39 +70,35 @@ limitations under the License.
|
||||||
margin-top: -$spacing-4;
|
margin-top: -$spacing-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_UserNotifSettings {
|
.mx_UserNotifSettings_floatingSection {
|
||||||
color: $primary-content; /* override from default settings page styles */
|
margin-top: 40px;
|
||||||
|
|
||||||
.mx_UserNotifSettings_floatingSection {
|
& > div:first-child {
|
||||||
margin-top: 40px;
|
/* section header */
|
||||||
|
font-size: $font-18px;
|
||||||
& > div:first-child {
|
font-weight: var(--font-semi-bold);
|
||||||
/* section header */
|
|
||||||
font-size: $font-18px;
|
|
||||||
font-weight: var(--font-semi-bold);
|
|
||||||
}
|
|
||||||
|
|
||||||
> table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
margin-top: 8px;
|
|
||||||
|
|
||||||
tr > td:first-child {
|
|
||||||
/* Just for a bit of spacing */
|
|
||||||
padding-right: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_UserNotifSettings_clearNotifsButton {
|
> table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
|
||||||
|
|
||||||
.mx_TagComposer {
|
tr > td:first-child {
|
||||||
margin-top: 35px; /* lots of distance from the last line of the table */
|
/* Just for a bit of spacing */
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_UserNotifSettings_clearNotifsButton {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_TagComposer {
|
||||||
|
margin-top: 35px; /* lots of distance from the last line of the table */
|
||||||
|
}
|
||||||
|
|
||||||
.mx_AccessibleButton.mx_NotificationSound_browse {
|
.mx_AccessibleButton.mx_NotificationSound_browse {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ import {
|
||||||
updatePushRuleActions,
|
updatePushRuleActions,
|
||||||
} from "../../../utils/pushRules/updatePushRuleActions";
|
} from "../../../utils/pushRules/updatePushRuleActions";
|
||||||
import { Caption } from "../typography/Caption";
|
import { Caption } from "../typography/Caption";
|
||||||
|
import { SettingsSubsectionHeading } from "./shared/SettingsSubsectionHeading";
|
||||||
|
import SettingsSubsection from "./shared/SettingsSubsection";
|
||||||
|
|
||||||
// TODO: this "view" component still has far too much application logic in it,
|
// TODO: this "view" component still has far too much application logic in it,
|
||||||
// which should be factored out to other files.
|
// which should be factored out to other files.
|
||||||
|
@ -649,16 +651,14 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
|
|
||||||
private renderTopSection(): JSX.Element {
|
private renderTopSection(): JSX.Element {
|
||||||
const masterSwitch = (
|
const masterSwitch = (
|
||||||
<>
|
<LabelledToggleSwitch
|
||||||
<LabelledToggleSwitch
|
data-testid="notif-master-switch"
|
||||||
data-testid="notif-master-switch"
|
value={!this.isInhibited}
|
||||||
value={!this.isInhibited}
|
label={_t("Enable notifications for this account")}
|
||||||
label={_t("Enable notifications for this account")}
|
caption={_t("Turn off to disable notifications on all your devices and sessions")}
|
||||||
caption={_t("Turn off to disable notifications on all your devices and sessions")}
|
onChange={this.onMasterRuleChanged}
|
||||||
onChange={this.onMasterRuleChanged}
|
disabled={this.state.phase === Phase.Persisting}
|
||||||
disabled={this.state.phase === Phase.Persisting}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// If all the rules are inhibited, don't show anything.
|
// If all the rules are inhibited, don't show anything.
|
||||||
|
@ -680,7 +680,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<SettingsSubsection>
|
||||||
{masterSwitch}
|
{masterSwitch}
|
||||||
|
|
||||||
<LabelledToggleSwitch
|
<LabelledToggleSwitch
|
||||||
|
@ -718,7 +718,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{emailSwitches}
|
{emailSwitches}
|
||||||
</>
|
</SettingsSubsection>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,7 +814,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
</fieldset>
|
</fieldset>
|
||||||
));
|
));
|
||||||
|
|
||||||
let sectionName: TranslatedString;
|
let sectionName: string;
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case RuleClass.VectorGlobal:
|
case RuleClass.VectorGlobal:
|
||||||
sectionName = _t("Global");
|
sectionName = _t("Global");
|
||||||
|
@ -830,11 +830,9 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<div data-testid={`notif-section-${category}`} className="mx_UserNotifSettings_grid">
|
<div data-testid={`notif-section-${category}`} className="mx_UserNotifSettings_grid">
|
||||||
<span className="mx_UserNotifSettings_gridRowLabel mx_UserNotifSettings_gridRowHeading">
|
<SettingsSubsectionHeading heading={sectionName} />
|
||||||
{sectionName}
|
|
||||||
</span>
|
|
||||||
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.Off]}</span>
|
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.Off]}</span>
|
||||||
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.On]}</span>
|
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.On]}</span>
|
||||||
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.Loud]}</span>
|
<span className="mx_UserNotifSettings_gridColumnLabel">{VectorStateToLabel[VectorState.Loud]}</span>
|
||||||
|
@ -842,7 +840,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
</div>
|
</div>
|
||||||
{clearNotifsButton}
|
{clearNotifsButton}
|
||||||
{keywordComposer}
|
{keywordComposer}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,13 +875,13 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_UserNotifSettings">
|
<>
|
||||||
{this.renderTopSection()}
|
{this.renderTopSection()}
|
||||||
{this.renderCategory(RuleClass.VectorGlobal)}
|
{this.renderCategory(RuleClass.VectorGlobal)}
|
||||||
{this.renderCategory(RuleClass.VectorMentions)}
|
{this.renderCategory(RuleClass.VectorMentions)}
|
||||||
{this.renderCategory(RuleClass.VectorOther)}
|
{this.renderCategory(RuleClass.VectorOther)}
|
||||||
{this.renderTargets()}
|
{this.renderTargets()}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import React, { HTMLAttributes } from "react";
|
||||||
import { SettingsSubsectionHeading } from "./SettingsSubsectionHeading";
|
import { SettingsSubsectionHeading } from "./SettingsSubsectionHeading";
|
||||||
|
|
||||||
export interface SettingsSubsectionProps extends HTMLAttributes<HTMLDivElement> {
|
export interface SettingsSubsectionProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
heading: string | React.ReactNode;
|
heading?: string | React.ReactNode;
|
||||||
description?: string | React.ReactNode;
|
description?: string | React.ReactNode;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
// when true content will be justify-items: stretch, which will make items within the section stretch to full width.
|
// when true content will be justify-items: stretch, which will make items within the section stretch to full width.
|
||||||
|
@ -50,6 +50,7 @@ export const SettingsSubsection: React.FC<SettingsSubsectionProps> = ({
|
||||||
<div
|
<div
|
||||||
className={classNames("mx_SettingsSubsection_content", {
|
className={classNames("mx_SettingsSubsection_content", {
|
||||||
mx_SettingsSubsection_contentStretch: !!stretchContent,
|
mx_SettingsSubsection_contentStretch: !!stretchContent,
|
||||||
|
mx_SettingsSubsection_noHeading: !heading && !description,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -18,16 +18,17 @@ import React from "react";
|
||||||
|
|
||||||
import { _t } from "../../../../../languageHandler";
|
import { _t } from "../../../../../languageHandler";
|
||||||
import Notifications from "../../Notifications";
|
import Notifications from "../../Notifications";
|
||||||
|
import { SettingsSection } from "../../shared/SettingsSection";
|
||||||
|
import SettingsTab from "../SettingsTab";
|
||||||
|
|
||||||
export default class NotificationUserSettingsTab extends React.Component {
|
export default class NotificationUserSettingsTab extends React.Component {
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsTab">
|
<SettingsTab>
|
||||||
<div className="mx_SettingsTab_heading">{_t("Notifications")}</div>
|
<SettingsSection heading={_t("Notifications")}>
|
||||||
<div className="mx_SettingsTab_section mx_SettingsTab_subsectionText">
|
|
||||||
<Notifications />
|
<Notifications />
|
||||||
</div>
|
</SettingsSection>
|
||||||
</div>
|
</SettingsTab>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,40 +3,36 @@
|
||||||
exports[`<Notifications /> main notification switches renders only enable notifications switch when notifications are disabled 1`] = `
|
exports[`<Notifications /> main notification switches renders only enable notifications switch when notifications are disabled 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_UserNotifSettings"
|
class="mx_SettingsFlag"
|
||||||
|
data-testid="notif-master-switch"
|
||||||
>
|
>
|
||||||
<div
|
<span
|
||||||
class="mx_SettingsFlag"
|
class="mx_SettingsFlag_label"
|
||||||
data-testid="notif-master-switch"
|
|
||||||
>
|
>
|
||||||
<span
|
|
||||||
class="mx_SettingsFlag_label"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
id="mx_LabelledToggleSwitch_testid_0"
|
|
||||||
>
|
|
||||||
Enable notifications for this account
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
class="mx_Caption"
|
|
||||||
id="mx_LabelledToggleSwitch_testid_0_caption"
|
|
||||||
>
|
|
||||||
Turn off to disable notifications on all your devices and sessions
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<div
|
<div
|
||||||
aria-checked="false"
|
id="mx_LabelledToggleSwitch_testid_0"
|
||||||
aria-describedby="mx_LabelledToggleSwitch_testid_0_caption"
|
|
||||||
aria-disabled="false"
|
|
||||||
aria-labelledby="mx_LabelledToggleSwitch_testid_0"
|
|
||||||
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
|
|
||||||
role="switch"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
Enable notifications for this account
|
||||||
class="mx_ToggleSwitch_ball"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span
|
||||||
|
class="mx_Caption"
|
||||||
|
id="mx_LabelledToggleSwitch_testid_0_caption"
|
||||||
|
>
|
||||||
|
Turn off to disable notifications on all your devices and sessions
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
aria-checked="false"
|
||||||
|
aria-describedby="mx_LabelledToggleSwitch_testid_0_caption"
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-labelledby="mx_LabelledToggleSwitch_testid_0"
|
||||||
|
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_enabled"
|
||||||
|
role="switch"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_ToggleSwitch_ball"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue