Remove global h2 css rule in favour of heading styles/components (#32969)

* Remove global h2 css rule in favour of heading styles/components

* Use Compound Heading in shared-components

and forbid hX elements

* Use Compound Heading in settings

add back margin to some legacy headings

* Tweak some headings

* Update screenshots

* Update screenshots

* Update snapshots

* Tweak .gitignore

* Update snapshots

* Iterate

* Update screenshots

* Update screenshots

* Update screenshot
This commit is contained in:
Michael Telatynski 2026-04-02 17:13:17 +01:00 committed by GitHub
parent 7bbd86ca10
commit 2d3e2fcb70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
89 changed files with 65 additions and 30 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 981 KiB

After

Width:  |  Height:  |  Size: 982 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -163,14 +163,6 @@ b {
font-weight: bold;
}
h2 {
color: $primary-content;
font: var(--cpd-font-heading-lg-regular);
letter-spacing: var(--cpd-font-letter-spacing-heading-lg);
margin-top: 16px;
margin-bottom: 16px;
}
a:hover,
a:link,
a:visited {

View File

@ -335,6 +335,7 @@
@import "./views/settings/_SpellCheckLanguages.pcss";
@import "./views/settings/_ThemeChoicePanel.pcss";
@import "./views/settings/_UpdateCheckButton.pcss";
@import "./views/settings/_UserPersonalInfoSettings.pcss";
@import "./views/settings/_UserProfileSettings.pcss";
@import "./views/settings/encryption/_AdvancedPanel.pcss";
@import "./views/settings/encryption/_ChangeRecoveryKey.pcss";

View File

@ -30,8 +30,7 @@ Please see LICENSE files in the repository root for full details.
.mx_DevTools_toolHeading {
color: var(--cpd-color-text-secondary);
font-weight: var(--cpd-font-weight-semibold);
font-size: var(--cpd-font-size-heading-sm);
font: var(--cpd-font-heading-sm-semibold);
}
.mx_DevTools_content {

View File

@ -118,6 +118,7 @@ Please see LICENSE files in the repository root for full details.
.mx_EmojiPicker_category_label {
width: 304px;
font: var(--cpd-font-heading-sm-semibold);
}
.mx_EmojiPicker_list {

View File

@ -37,9 +37,8 @@ Please see LICENSE files in the repository root for full details.
}
> h2 {
margin-top: 24px;
font-size: $font-24px;
font-weight: var(--cpd-font-weight-semibold);
margin: var(--cpd-space-6x) 0 var(--cpd-space-4x);
font: var(--cpd-font-heading-md-semibold);
}
> p {

View File

@ -0,0 +1,12 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
.mx_UserPersonalInfoSettings {
h2 {
margin: var(--cpd-space-4x) 0;
}
}

View File

@ -9,6 +9,10 @@ Please see LICENSE files in the repository root for full details.
.mx_UserProfileSettings {
border-bottom: 1px solid $quinary-content;
h2 {
margin: var(--cpd-space-4x) 0;
}
.mx_UserProfileSettings_profile {
display: flex;
margin-top: var(--cpd-space-6x);

View File

@ -23,7 +23,7 @@ Please see LICENSE files in the repository root for full details.
> div {
> h2 {
font-weight: var(--cpd-font-weight-semibold);
font: var(--cpd-font-heading-sm-semibold);
font-size: $font-18px;
margin-top: 4px;
}

View File

@ -12,6 +12,7 @@ Please see LICENSE files in the repository root for full details.
.mx_Heading_h4 {
margin-inline: unset;
margin-block: unset;
color: $primary-content;
}
.mx_Heading_h1 {

View File

@ -18,6 +18,7 @@ import { type ThirdPartyIdentifier } from "../../../AddThreepid";
import SettingsStore from "../../../settings/SettingsStore";
import { UIFeature } from "../../../settings/UIFeature";
import { AddRemoveThreepids } from "./AddRemoveThreepids";
import Heading from "../typography/Heading.tsx";
type LoadingState = "loading" | "loaded" | "error";
@ -81,8 +82,8 @@ export const UserPersonalInfoSettings: React.FC<UserPersonalInfoSettingsProps> =
if (!SettingsStore.getValue(UIFeature.ThirdPartyID)) return null;
return (
<div>
<h2>{_t("settings|general|personal_info")}</h2>
<div className="mx_UserPersonalInfoSettings">
<Heading size="2">{_t("settings|general|personal_info")}</Heading>
<SettingsSubsection
heading={_t("settings|general|emails_heading")}
stretchContent

View File

@ -27,6 +27,7 @@ import AccessibleButton from "../elements/AccessibleButton";
import LogoutDialog, { shouldShowLogoutDialog } from "../dialogs/LogoutDialog";
import Modal from "../../../Modal";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import Heading from "../typography/Heading.tsx";
const SpinnerToast: React.FC<{ children?: ReactNode }> = ({ children }) => (
<>
@ -194,7 +195,7 @@ const UserProfileSettings: React.FC<UserProfileSettingsProps> = ({
return (
<div className="mx_UserProfileSettings">
<h2>{_t("common|profile")}</h2>
<Heading size="2">{_t("common|profile")}</Heading>
<div>
{someFieldsDisabled
? _t("settings|general|profile_subtitle_oidc")

View File

@ -47,11 +47,12 @@ exports[`MessagePanel should handle lots of membership events quickly 1`] = `
role="none"
/>
<div
class="_flex_4dswl_9 _content_5dcky_8"
class="_flex_4dswl_9 _content_u6fft_8"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Thu, Jan 1, 1970
</h2>

View File

@ -49,11 +49,12 @@ exports[`<MessageEditHistory /> should match the snapshot 1`] = `
role="none"
/>
<div
class="_flex_4dswl_9 _content_5dcky_8"
class="_flex_4dswl_9 _content_u6fft_8"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Thu, Jan 1, 1970
</h2>
@ -188,11 +189,12 @@ exports[`<MessageEditHistory /> should support events with 1`] = `
role="none"
/>
<div
class="_flex_4dswl_9 _content_5dcky_8"
class="_flex_4dswl_9 _content_u6fft_8"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Thu, Jan 1, 1970
</h2>

File diff suppressed because one or more lines are too long

View File

@ -66,13 +66,28 @@ module.exports = {
},
],
"storybook/meta-satisfies-type": "error",
"react/forbid-elements": [
"error",
{
forbid: [
{ element: "h1", message: "Use Compound <Heading> instead" },
{ element: "h2", message: "Use Compound <Heading> instead" },
{ element: "h3", message: "Use Compound <Heading> instead" },
{ element: "h4", message: "Use Compound <Heading> instead" },
{ element: "h5", message: "Use Compound <Heading> instead" },
{ element: "h6", message: "Use Compound <Heading> instead" },
],
},
],
},
overrides: [
{
files: ["src/**/*.test.{ts,tsx}"],
files: ["src/**/*.test.{ts,tsx}", "src/**/*.stories.tsx"],
rules: {
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/no-explicit-any": "off",
"react/forbid-elements": "off",
},
},
],

View File

@ -2,9 +2,8 @@
/src/**/__screenshots__/
# Ignore vis diffs & local baseline
/__vis__/**/__diffs__
/__vis__/**/__results__
/__vis__/local
/__vis__/**
!/__vis__/linux/__baselines__
# Ignore coverage report
/coverage/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -6,7 +6,7 @@
*/
import React from "react";
import { Tooltip } from "@vector-im/compound-web";
import { Heading, Tooltip } from "@vector-im/compound-web";
import ChevronDownIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-down";
import { Flex } from "../../../core/utils/Flex";
@ -53,7 +53,9 @@ export function DateSeparatorButton({
tabIndex={0}
{...props}
>
<h2 aria-hidden="true">{label}</h2>
<Heading as="h2" size="lg" aria-hidden="true">
{label}
</Heading>
<ChevronDownIcon />
</Flex>
</Tooltip>

View File

@ -13,8 +13,6 @@
flex: 0 0 auto;
margin: 0;
font-size: inherit;
font-weight: inherit;
color: inherit;
text-transform: capitalize;
}

View File

@ -7,6 +7,7 @@
import classNames from "classnames";
import React, { type JSX, useState } from "react";
import { Heading } from "@vector-im/compound-web";
import { type ViewModel } from "../../../core/viewmodel/ViewModel";
import { useViewModel } from "../../../core/viewmodel/useViewModel";
@ -107,7 +108,9 @@ export function DateSeparatorView({ vm, className }: Readonly<DateSeparatorViewP
return (
<TimelineSeparator label={label} className={classNames(className)}>
<Flex className={styles.content}>
<h2 aria-hidden="true">{label}</h2>
<Heading as="h2" size="lg" aria-hidden="true">
{label}
</Heading>
</Flex>
</TimelineSeparator>
);

View File

@ -17,6 +17,7 @@ exports[`DateSeparatorView > renders default story 1`] = `
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Today
</h2>
@ -45,6 +46,7 @@ exports[`DateSeparatorView > renders long localized label story 1`] = `
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Wednesday, December 17, 2025 at 11:59 PM Coordinated Universal Time
</h2>
@ -73,6 +75,7 @@ exports[`DateSeparatorView > renders with extra class names 1`] = `
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Today
</h2>
@ -113,6 +116,7 @@ exports[`DateSeparatorView > renders with jump to date picker story 1`] = `
>
<h2
aria-hidden="true"
class="_typography_6v6n8_153 _font-heading-lg-regular_6v6n8_121"
>
Today
</h2>