Skip to content

Commit

Permalink
Replace legacy Tooltips with Compound tooltips (#28231)
Browse files Browse the repository at this point in the history
* Ditch legacy Tooltips in favour of Compound

Signed-off-by: Michael Telatynski <[email protected]>

* Remove dead code

Signed-off-by: Michael Telatynski <[email protected]>

* Extract markdown CodeBlock into React component

Signed-off-by: Michael Telatynski <[email protected]>

* Upgrade compound

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

---------

Signed-off-by: Michael Telatynski <[email protected]>
  • Loading branch information
t3chguy authored Oct 18, 2024
1 parent fad4573 commit 26430a3
Show file tree
Hide file tree
Showing 29 changed files with 410 additions and 670 deletions.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@
"@types/seedrandom": "3.0.8",
"oidc-client-ts": "3.1.0",
"jwt-decode": "4.0.0",
"@vector-im/compound-design-tokens": "1.8.0",
"@vector-im/compound-web": "7.0.0",
"@floating-ui/react": "0.26.11",
"@radix-ui/react-id": "1.1.0",
"caniuse-lite": "1.0.30001668",
Expand All @@ -98,7 +96,7 @@
"@sentry/browser": "^8.0.0",
"@testing-library/react-hooks": "^8.0.1",
"@vector-im/compound-design-tokens": "^1.8.0",
"@vector-im/compound-web": "^7.0.0",
"@vector-im/compound-web": "^7.1.0",
"@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.4",
"@zxcvbn-ts/language-en": "^3.0.2",
Expand Down
1 change: 0 additions & 1 deletion playwright/e2e/editing/editing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ test.describe("Editing", () => {
checkA11y,
}) => {
axe.disableRules("color-contrast"); // XXX: We have some known contrast issues here
axe.exclude(".mx_Tooltip_visible"); // XXX: this is fine but would be good to fix

await page.goto(`#/room/${room.roomId}`);

Expand Down
6 changes: 3 additions & 3 deletions playwright/e2e/register/register.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ test.describe("Registration", () => {
});
});
await page.getByRole("textbox", { name: "Username", exact: true }).fill("_alice");
await expect(page.getByRole("alert").filter({ hasText: "Some characters not allowed" })).toBeVisible();
await expect(page.getByRole("tooltip").filter({ hasText: "Some characters not allowed" })).toBeVisible();

await page.route("**/_matrix/client/*/register/available?username=bob", async (route) => {
await route.fulfill({
Expand All @@ -108,9 +108,9 @@ test.describe("Registration", () => {
});
});
await page.getByRole("textbox", { name: "Username", exact: true }).fill("bob");
await expect(page.getByRole("alert").filter({ hasText: "Someone already has that username" })).toBeVisible();
await expect(page.getByRole("tooltip").filter({ hasText: "Someone already has that username" })).toBeVisible();

await page.getByRole("textbox", { name: "Username", exact: true }).fill("foobar");
await expect(page.getByRole("alert")).not.toBeVisible();
await expect(page.getByRole("tooltip")).not.toBeVisible();
});
});
3 changes: 1 addition & 2 deletions playwright/element-web-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,7 @@ export const expect = baseExpect.extend({

if (!options?.showTooltips) {
css += `
[role="tooltip"],
.mx_Tooltip_visible {
[role="tooltip"] {
visibility: hidden !important;
}
`;
Expand Down
1 change: 0 additions & 1 deletion res/css/_components.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@
@import "./views/elements/_TagComposer.pcss";
@import "./views/elements/_TextWithTooltip.pcss";
@import "./views/elements/_ToggleSwitch.pcss";
@import "./views/elements/_Tooltip.pcss";
@import "./views/elements/_UseCaseSelection.pcss";
@import "./views/elements/_UseCaseSelectionButton.pcss";
@import "./views/elements/_Validation.pcss";
Expand Down
3 changes: 2 additions & 1 deletion res/css/views/auth/_PassphraseField.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ progress.mx_PassphraseField_progress {
border: 0;
height: 4px;
position: absolute;
top: -12px;
top: -10px;
left: 0;

@mixin ProgressBarBorderRadius "2px";
@mixin ProgressBarColour $PassphraseStrengthLow;
Expand Down
8 changes: 0 additions & 8 deletions res/css/views/elements/_Field.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,6 @@ Please see LICENSE files in the repository root for full details.
}
}

.mx_Field_tooltip {
width: 200px;
}

.mx_Field_tooltip.mx_Field_valid {
animation: mx_fadeout 1s 2s forwards;
}

/* Customise other components when placed inside a Field */

.mx_Field .mx_Dropdown_input {
Expand Down
12 changes: 0 additions & 12 deletions res/css/views/elements/_MiniAvatarUploader.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@ Please see LICENSE files in the repository root for full details.
position: relative;
width: min-content;

/* this isn't a floating tooltip so override some things to not need to bother with z-index and floating */
.mx_Tooltip {
display: inline-block;
position: absolute;
z-index: unset;
width: max-content;
left: 72px;
/* top edge starting at 50 % of parent - 50 % of itself -> centered vertically */
top: 50%;
transform: translateY(-50%);
}

.mx_MiniAvatarUploader_indicator {
position: absolute;

Expand Down
107 changes: 0 additions & 107 deletions res/css/views/elements/_Tooltip.pcss

This file was deleted.

1 change: 1 addition & 0 deletions res/css/views/elements/_Validation.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.

.mx_Validation {
position: relative;
max-width: 200px;
}

.mx_Validation_details {
Expand Down
30 changes: 0 additions & 30 deletions src/components/structures/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import React, { CSSProperties, RefObject, SyntheticEvent, useRef, useState } fro
import ReactDOM from "react-dom";
import classNames from "classnames";
import FocusLock from "react-focus-lock";
import { TooltipProvider } from "@vector-im/compound-web";

import { Writeable } from "../../@types/common";
import UIStore from "../../stores/UIStore";
Expand Down Expand Up @@ -611,35 +610,6 @@ export const useContextMenu = <T extends any = HTMLElement>(inputRef?: RefObject
return [button.current ? isOpen : false, button, open, close, setIsOpen];
};

// XXX: Deprecated, used only for dynamic Tooltips. Avoid using at all costs.
export function createMenu(
ElementClass: typeof React.Component,
props: Record<string, any>,
): { close: (...args: any[]) => void } {
const onFinished = function (...args: any[]): void {
ReactDOM.unmountComponentAtNode(getOrCreateContainer());
props?.onFinished?.apply(null, args);
};

const menu = (
<TooltipProvider>
<ContextMenu
{...props}
mountAsChild={true}
hasBackground={false}
onFinished={onFinished} // eslint-disable-line react/jsx-no-bind
windowResize={onFinished} // eslint-disable-line react/jsx-no-bind
>
<ElementClass {...props} onFinished={onFinished} />
</ContextMenu>
</TooltipProvider>
);

ReactDOM.render(menu, getOrCreateContainer());

return { close: onFinished };
}

// re-export the semantic helper components for simplicity
export { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton";
export { ContextMenuTooltipButton } from "../../accessibility/context_menu/ContextMenuTooltipButton";
Expand Down
6 changes: 3 additions & 3 deletions src/components/structures/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useContext, useState } from "react";

import AutoHideScrollbar from "./AutoHideScrollbar";
import { getHomePageUrl } from "../../utils/pages";
import { _tDom } from "../../languageHandler";
import { _t, _tDom } from "../../languageHandler";
import SdkConfig from "../../SdkConfig";
import dis from "../../dispatcher/dispatcher";
import { Action } from "../../dispatcher/actions";
Expand Down Expand Up @@ -66,8 +66,8 @@ const UserWelcomeTop: React.FC = () => {
<div>
<MiniAvatarUploader
hasAvatar={!!ownProfile.avatarUrl}
hasAvatarLabel={_tDom("onboarding|has_avatar_label")}
noAvatarLabel={_tDom("onboarding|no_avatar_label")}
hasAvatarLabel={_t("onboarding|has_avatar_label")}
noAvatarLabel={_t("onboarding|no_avatar_label")}
setAvatarUrl={(url) => cli.setAvatarUrl(url)}
isUserAvatar
onClick={(ev) => PosthogTrackers.trackInteraction("WebHomeMiniAvatarUploadButton", ev)}
Expand Down
5 changes: 2 additions & 3 deletions src/components/views/auth/EmailField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import React, { PureComponent, RefCallback, RefObject } from "react";
import React, { ComponentProps, PureComponent, RefCallback, RefObject } from "react";

import Field, { IInputProps } from "../elements/Field";
import { _t, _td, TranslationKey } from "../../../languageHandler";
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
import * as Email from "../../../email";
import { Alignment } from "../elements/Tooltip";

interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
id?: string;
Expand All @@ -23,7 +22,7 @@ interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
label: TranslationKey;
labelRequired: TranslationKey;
labelInvalid: TranslationKey;
tooltipAlignment?: Alignment;
tooltipAlignment?: ComponentProps<typeof Field>["tooltipAlignment"];

// When present, completely overrides the default validation rules.
validationRules?: (fieldState: IFieldState) => Promise<IValidationResult>;
Expand Down
5 changes: 2 additions & 3 deletions src/components/views/auth/PassphraseConfirmField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import React, { PureComponent, RefCallback, RefObject } from "react";
import React, { ComponentProps, PureComponent, RefCallback, RefObject } from "react";

import Field, { IInputProps } from "../elements/Field";
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
import { _t, _td, TranslationKey } from "../../../languageHandler";
import { Alignment } from "../elements/Tooltip";

interface IProps extends Omit<IInputProps, "onValidate" | "label" | "element"> {
id?: string;
Expand All @@ -23,7 +22,7 @@ interface IProps extends Omit<IInputProps, "onValidate" | "label" | "element"> {
label: TranslationKey;
labelRequired: TranslationKey;
labelInvalid: TranslationKey;
tooltipAlignment?: Alignment;
tooltipAlignment?: ComponentProps<typeof Field>["tooltipAlignment"];
onChange(ev: React.FormEvent<HTMLElement>): void;
onValidate?(result: IValidationResult): void;
}
Expand Down
5 changes: 2 additions & 3 deletions src/components/views/auth/PassphraseField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import React, { PureComponent, RefCallback, RefObject } from "react";
import React, { ComponentProps, PureComponent, RefCallback, RefObject } from "react";
import classNames from "classnames";

import type { ZxcvbnResult } from "@zxcvbn-ts/core";
Expand All @@ -15,7 +15,6 @@ import withValidation, { IFieldState, IValidationResult } from "../elements/Vali
import { _t, _td, TranslationKey } from "../../../languageHandler";
import Field, { IInputProps } from "../elements/Field";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { Alignment } from "../elements/Tooltip";

interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
autoFocus?: boolean;
Expand All @@ -31,7 +30,7 @@ interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
labelEnterPassword: TranslationKey;
labelStrongPassword: TranslationKey;
labelAllowedButUnsafe: TranslationKey;
tooltipAlignment?: Alignment;
tooltipAlignment?: ComponentProps<typeof Field>["tooltipAlignment"];

onChange(ev: React.FormEvent<HTMLElement>): void;
onValidate?(result: IValidationResult): void;
Expand Down
7 changes: 3 additions & 4 deletions src/components/views/auth/RegistrationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import React, { BaseSyntheticEvent, ReactNode } from "react";
import React, { BaseSyntheticEvent, ComponentProps, ReactNode } from "react";
import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";

Expand All @@ -26,7 +26,6 @@ import RegistrationEmailPromptDialog from "../dialogs/RegistrationEmailPromptDia
import CountryDropdown from "./CountryDropdown";
import PassphraseConfirmField from "./PassphraseConfirmField";
import { PosthogAnalytics } from "../../../PosthogAnalytics";
import { Alignment } from "../elements/Tooltip";

enum RegistrationField {
Email = "field_email",
Expand Down Expand Up @@ -441,9 +440,9 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
return true;
}

private tooltipAlignment(): Alignment | undefined {
private tooltipAlignment(): ComponentProps<typeof EmailField>["tooltipAlignment"] | undefined {
if (this.props.mobileRegister) {
return Alignment.Bottom;
return "bottom";
}
return undefined;
}
Expand Down
Loading

0 comments on commit 26430a3

Please sign in to comment.