Move Flex & Box component into shared component folder (#30357)

* refactor: move Flex component in shared components

* refactor: update imports

* refactor: remove Flex pcss file

* fix: Flex component css override

* test: update snapshots

* fix: html export

* chore: add css module support to jest

* chore: keep old copyright

* refactor: change `mx_Flex` in `ErrorView` to `mx_ErrorView_flexContainer`

* test: update snapshots

* refactor: move Box component in shared components

* refactor: update import and css override

* test: update snapshots
This commit is contained in:
Florian Duros
2025-07-22 18:25:45 +02:00
committed by GitHub
parent 16ab7ffbc7
commit 1e689ac098
61 changed files with 218 additions and 190 deletions

View File

@@ -0,0 +1,19 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
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.
*/
.box-flex {
flex: var(--mx-box-flex, unset);
}
.box-shrink {
flex-shrink: var(--mx-box-shrink, unset);
}
.box-grow {
flex-grow: var(--mx-box-grow, unset);
}

View File

@@ -0,0 +1,78 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
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, useMemo } from "react";
import styles from "./Box.module.css";
type BoxProps = {
/**
* The type of the HTML element
* @default div
*/
as?: string;
/**
* The CSS class name.
*/
className?: string;
/**
* the on click event callback
*/
onClick?: (e: React.MouseEvent) => void;
/**
* The flex space to use
* @default null
*/
flex?: string | null;
/**
* The flex shrink factor
* @default null
*/
shrink?: string | null;
/**
* The flex grow factor
* @default null
*/
grow?: string | null;
};
/**
* A flex child helper
*/
export function Box({
as = "div",
flex = null,
shrink = null,
grow = null,
className,
children,
...props
}: React.PropsWithChildren<BoxProps>): JSX.Element {
const style = useMemo(() => {
const style: Record<string, any> = {};
if (flex) style["--mx-box-flex"] = flex;
if (shrink) style["--mx-box-shrink"] = shrink;
if (grow) style["--mx-box-grow"] = grow;
return style;
}, [flex, grow, shrink]);
return React.createElement(
as,
{
...props,
className: classNames(className, {
[styles["box-flex"]]: !!flex,
[styles["box-shrink"]]: !!shrink,
[styles["box-grow"]]: !!grow,
}),
style,
},
children,
);
}

View File

@@ -0,0 +1,8 @@
/*
* Copyright 2025 New Vector 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 { Box } from "./Box";

View File

@@ -0,0 +1,16 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
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.
*/
.flex {
display: var(--mx-flex-display, unset);
flex-direction: var(--mx-flex-direction, unset);
align-items: var(--mx-flex-align, unset);
justify-content: var(--mx-flex-justify, unset);
gap: var(--mx-flex-gap, unset);
flex-wrap: var(--mx-flex-wrap, unset);
}

View File

@@ -0,0 +1,88 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
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 ComponentProps, type JSXElementConstructor, useMemo } from "react";
import styles from "./Flex.module.css";
type FlexProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = {
/**
* The type of the HTML element
* @default div
*/
as?: T;
/**
* The CSS class name.
*/
className?: string;
/**
* The type of flex container
* @default flex
*/
display?: "flex" | "inline-flex";
/**
* The flow direction of the flex children
* @default row
*/
direction?: "row" | "column" | "row-reverse" | "column-reverse";
/**
* The alignment of the flex children
* @default start
*/
align?: "start" | "center" | "end" | "baseline" | "stretch" | "normal";
/**
* The justification of the flex children
* @default start
*/
justify?: "start" | "center" | "end" | "space-between";
/**
* The wrapping of the flex children
* @default nowrap
*/
wrap?: "wrap" | "nowrap" | "wrap-reverse";
/**
* The spacing between the flex children, expressed with the CSS unit
* @default 0
*/
gap?: string;
/**
* the on click event callback
*/
onClick?: (e: React.MouseEvent) => void;
} & ComponentProps<T>;
/**
* A flexbox container helper
*/
export function Flex<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any> = "div">({
as = "div",
display = "flex",
direction = "row",
align = "start",
justify = "start",
gap = "0",
wrap = "nowrap",
className,
children,
...props
}: React.PropsWithChildren<FlexProps<T>>): JSX.Element {
const style = useMemo(
() => ({
"--mx-flex-display": display,
"--mx-flex-direction": direction,
"--mx-flex-align": align,
"--mx-flex-justify": justify,
"--mx-flex-gap": gap,
"--mx-flex-wrap": wrap,
}),
[align, direction, display, gap, justify, wrap],
);
return React.createElement(as, { ...props, className: classNames(styles.flex, className), style }, children);
}

View File

@@ -0,0 +1,8 @@
/*
* Copyright 2025 New Vector 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 { Flex } from "./Flex";