Make shared components aware of layout and density settings (#33368)

* Add shared event presentation context

* Add app-web event presentation mapper

* Wire event presentation provider into app timelines

* Add Storybook controls for event layout and density

* Wire compact density through app/web event presentation provider

* Use event presentation density for URL previews

* Move TileErrorView layout to event presentation context

* Minor fix and updated snapshot

* Updated snapshots for url preview group

* Prettier fix

* Restore removed story to fix missing playwright test

* Updates after review comments

* Fix prettier issue
This commit is contained in:
rbondesson
2026-05-06 07:30:46 +02:00
committed by GitHub
parent 7e26c2d144
commit 1f71a3a3fe
23 changed files with 379 additions and 209 deletions
@@ -0,0 +1,50 @@
/*
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, { type JSX, type PropsWithChildren, useMemo } from "react";
import { EventPresentationProvider, type EventLayout, type EventPresentation } from "@element-hq/web-shared-components";
import { Layout } from "../settings/enums/Layout";
import { useSettingValue } from "../hooks/useSettings";
const EVENT_LAYOUT_BY_APP_LAYOUT: Record<Layout, EventLayout> = {
[Layout.Bubble]: "bubble",
[Layout.Group]: "group",
[Layout.IRC]: "irc",
};
function getEventDensity(layout: Layout, useCompactLayout: boolean): EventPresentation["density"] {
return useCompactLayout && layout === Layout.Group ? "compact" : "default";
}
/** Converts app/web layout settings into shared event presentation settings. */
export function getEventPresentation(layout: Layout, useCompactLayout: boolean): EventPresentation {
return {
layout: EVENT_LAYOUT_BY_APP_LAYOUT[layout],
density: getEventDensity(layout, useCompactLayout),
};
}
/** Props for the app/web event presentation context provider. */
export interface EventPresentationContextProviderProps {
/** Layout selected by the app/web surface rendering the timeline. */
layout: Layout;
}
/** Provides shared event presentation using app/web-owned layout settings. */
export function EventPresentationContextProvider({
layout,
children,
}: Readonly<PropsWithChildren<EventPresentationContextProviderProps>>): JSX.Element {
// Compact density is still owned by app/web; this exposes it as shared event presentation.
const useCompactLayout = useSettingValue("useCompactLayout");
const eventLayout = EVENT_LAYOUT_BY_APP_LAYOUT[layout];
const density = getEventDensity(layout, useCompactLayout);
const value = useMemo<EventPresentation>(() => ({ layout: eventLayout, density }), [eventLayout, density]);
return <EventPresentationProvider value={value}>{children}</EventPresentationProvider>;
}