Move hidden media placeholder to shared components (#33404)
* Move hidden media placeholder to shared components * Add Snapshots * Remove legacy hidden media mx class
This commit is contained in:
BIN
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -18,6 +18,7 @@ export * from "./menus/UserMenu";
|
||||
export * from "./room/timeline/ReadMarker";
|
||||
export * from "./room/timeline/EventPresentation";
|
||||
export * from "./room/timeline/event-tile/body/EventContentBodyView";
|
||||
export * from "./room/timeline/event-tile/body/HiddenMediaPlaceholder";
|
||||
export * from "./room/timeline/event-tile/body/RedactedBodyView";
|
||||
export * from "./room/timeline/event-tile/body/MFileBodyView";
|
||||
export * from "./room/timeline/event-tile/body/MImageBodyView";
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.button {
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: var(--cpd-space-0x);
|
||||
inset: var(--cpd-space-0x);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
background-color: var(--cpd-color-bg-subtle-secondary);
|
||||
}
|
||||
|
||||
.button:hover,
|
||||
.button:focus-visible {
|
||||
background-color: var(--cpd-color-bg-canvas-default);
|
||||
}
|
||||
|
||||
.content {
|
||||
color: var(--cpd-color-text-action-accent);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--cpd-space-1x);
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { fn } from "storybook/test";
|
||||
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { withViewDocs } from "../../../../../../.storybook/withViewDocs";
|
||||
import { HiddenMediaPlaceholder } from "./HiddenMediaPlaceholder";
|
||||
|
||||
const HiddenMediaPlaceholderWrapper = withViewDocs(HiddenMediaPlaceholder, HiddenMediaPlaceholder);
|
||||
|
||||
const meta = {
|
||||
title: "Timeline/Timeline Body/HiddenMediaPlaceholder",
|
||||
component: HiddenMediaPlaceholderWrapper,
|
||||
tags: ["autodocs"],
|
||||
args: {
|
||||
children: "Show image",
|
||||
onClick: fn(),
|
||||
className: "",
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ width: 320, height: 180 }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
} satisfies Meta<typeof HiddenMediaPlaceholderWrapper>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {};
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { composeStories } from "@storybook/react-vite";
|
||||
import { render, screen } from "@test-utils";
|
||||
import React from "react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { HiddenMediaPlaceholder } from "./HiddenMediaPlaceholder";
|
||||
import * as stories from "./HiddenMediaPlaceholder.stories";
|
||||
|
||||
const { Default } = composeStories(stories);
|
||||
|
||||
describe("HiddenMediaPlaceholder", () => {
|
||||
it("renders the default story", () => {
|
||||
const { container } = render(<Default />);
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
expect(screen.getByRole("button", { name: "Show image" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("invokes the click handler", async () => {
|
||||
const user = userEvent.setup();
|
||||
const onClick = vi.fn();
|
||||
|
||||
render(<HiddenMediaPlaceholder onClick={onClick}>Show image</HiddenMediaPlaceholder>);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Show image" }));
|
||||
|
||||
expect(onClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("applies a custom className to the root button", () => {
|
||||
render(
|
||||
<HiddenMediaPlaceholder onClick={vi.fn()} className="custom-hidden-media">
|
||||
Show image
|
||||
</HiddenMediaPlaceholder>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole("button", { name: "Show image" })).toHaveClass("custom-hidden-media");
|
||||
});
|
||||
});
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import classNames from "classnames";
|
||||
import React, { type JSX, type MouseEventHandler, type PropsWithChildren } from "react";
|
||||
import { VisibilityOnIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import styles from "./HiddenMediaPlaceholder.module.css";
|
||||
|
||||
export type HiddenMediaPlaceholderProps = PropsWithChildren<{
|
||||
/**
|
||||
* CSS class names applied to the root button.
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Invoked when the user chooses to reveal the hidden media.
|
||||
*/
|
||||
onClick: MouseEventHandler<HTMLButtonElement>;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Renders a full-frame button used to reveal hidden media previews.
|
||||
*/
|
||||
export function HiddenMediaPlaceholder({
|
||||
className,
|
||||
onClick,
|
||||
children,
|
||||
}: Readonly<HiddenMediaPlaceholderProps>): JSX.Element {
|
||||
return (
|
||||
<button type="button" onClick={onClick} className={classNames(styles.button, className)}>
|
||||
<span className={styles.content}>
|
||||
<VisibilityOnIcon className={styles.icon} aria-hidden="true" />
|
||||
<span>{children}</span>
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`HiddenMediaPlaceholder > renders the default story 1`] = `
|
||||
<div>
|
||||
<div
|
||||
style="width: 320px; height: 180px;"
|
||||
>
|
||||
<button
|
||||
class="HiddenMediaPlaceholder-module_button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="HiddenMediaPlaceholder-module_content"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="HiddenMediaPlaceholder-module_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 16q1.875 0 3.188-1.312Q16.5 13.375 16.5 11.5t-1.312-3.187T12 7 8.813 8.313 7.5 11.5t1.313 3.188T12 16m0-1.8q-1.125 0-1.912-.787A2.6 2.6 0 0 1 9.3 11.5q0-1.125.787-1.912A2.6 2.6 0 0 1 12 8.8q1.125 0 1.912.787.788.788.788 1.913t-.787 1.912A2.6 2.6 0 0 1 12 14.2m0 4.8q-3.475 0-6.35-1.837Q2.775 15.324 1.3 12.2a.8.8 0 0 1-.1-.312 3 3 0 0 1 0-.775.8.8 0 0 1 .1-.313q1.475-3.125 4.35-4.962Q8.525 4 12 4t6.35 1.838T22.7 10.8a.8.8 0 0 1 .1.313 3 3 0 0 1 0 .774.8.8 0 0 1-.1.313q-1.475 3.125-4.35 4.963Q15.475 19 12 19m0-2a9.54 9.54 0 0 0 5.188-1.488A9.77 9.77 0 0 0 20.8 11.5a9.77 9.77 0 0 0-3.613-4.012A9.54 9.54 0 0 0 12 6a9.55 9.55 0 0 0-5.187 1.487A9.77 9.77 0 0 0 3.2 11.5a9.77 9.77 0 0 0 3.613 4.012A9.54 9.54 0 0 0 12 17"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
Show image
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { HiddenMediaPlaceholder, type HiddenMediaPlaceholderProps } from "./HiddenMediaPlaceholder";
|
||||
Reference in New Issue
Block a user