Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 373a34c

Browse files
author
Germain
authored
Create flexbox layout helper (#11411)
1 parent ad73b0c commit 373a34c

File tree

7 files changed

+232
-7
lines changed

7 files changed

+232
-7
lines changed

res/css/_components.pcss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
@import "./components/views/settings/shared/_SettingsSubsectionHeading.pcss";
5353
@import "./components/views/spaces/_QuickThemeSwitcher.pcss";
5454
@import "./components/views/typography/_Caption.pcss";
55+
@import "./components/views/utils/_Box.pcss";
56+
@import "./components/views/utils/_Flex.pcss";
5557
@import "./compound/_Icon.pcss";
5658
@import "./compound/_SuccessDialog.pcss";
5759
@import "./structures/_AutoHideScrollbar.pcss";
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
.mx_Box {
18+
flex: var(--mx-box-flex, initial);
19+
flex-shrink: var(--mx-box-shrink, initial);
20+
flex-grow: var(--mx-box-grow, initial);
21+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
.mx_Flex {
18+
display: var(--mx-flex-display, initial);
19+
flex-direction: var(--mx-flex-direction, initial);
20+
align-items: var(--mx-flex-align, initial);
21+
justify-content: var(--mx-flex-justify, initial);
22+
gap: var(--mx-flex-gap, initial);
23+
}

res/css/views/rooms/_RoomHeader.pcss

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ limitations under the License.
1515
*/
1616

1717
.mx_RoomHeader {
18-
display: flex;
19-
align-items: center;
2018
height: 64px;
21-
gap: var(--cpd-space-3x);
2219
padding: 0 var(--cpd-space-3x);
2320
border-bottom: 1px solid $separator;
2421
background-color: $background;

src/components/utils/Box.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import classNames from "classnames";
18+
import React, { useEffect, useRef } from "react";
19+
20+
type FlexProps = {
21+
/**
22+
* The type of the HTML element
23+
* @default div
24+
*/
25+
as?: string;
26+
/**
27+
* The CSS class name.
28+
*/
29+
className?: string;
30+
/**
31+
* the on click event callback
32+
*/
33+
onClick?: (e: React.MouseEvent) => void;
34+
/**
35+
* The flex space to use
36+
* @default null
37+
*/
38+
flex?: string | null;
39+
/**
40+
* The flex shrink factor
41+
* @default null
42+
*/
43+
shrink?: string | null;
44+
/**
45+
* The flex grow factor
46+
* @default null
47+
*/
48+
grow?: string | null;
49+
};
50+
51+
/**
52+
* Set or remove a CSS property
53+
* @param ref the reference
54+
* @param name the CSS property name
55+
* @param value the CSS property value
56+
*/
57+
function addOrRemoveProperty(
58+
ref: React.MutableRefObject<HTMLElement | undefined>,
59+
name: string,
60+
value?: string | null,
61+
): void {
62+
const style = ref.current!.style;
63+
if (value) {
64+
style.setProperty(name, value);
65+
} else {
66+
style.removeProperty(name);
67+
}
68+
}
69+
70+
/**
71+
* A flex child helper
72+
*/
73+
export function Box({
74+
as = "div",
75+
flex = null,
76+
shrink = null,
77+
grow = null,
78+
className,
79+
children,
80+
...props
81+
}: React.PropsWithChildren<FlexProps>): JSX.Element {
82+
const ref = useRef<HTMLElement>();
83+
84+
useEffect(() => {
85+
addOrRemoveProperty(ref, `--mx-box-flex`, flex);
86+
addOrRemoveProperty(ref, `--mx-box-shrink`, shrink);
87+
addOrRemoveProperty(ref, `--mx-box-grow`, grow);
88+
}, [flex, grow, shrink]);
89+
90+
return React.createElement(as, { ...props, className: classNames("mx_Box", className), ref }, children);
91+
}

src/components/utils/Flex.tsx

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import classNames from "classnames";
18+
import React, { useEffect, useRef } from "react";
19+
20+
type FlexProps = {
21+
/**
22+
* The type of the HTML element
23+
* @default div
24+
*/
25+
as?: string;
26+
/**
27+
* The CSS class name.
28+
*/
29+
className?: string;
30+
/**
31+
* The type of flex container
32+
* @default flex
33+
*/
34+
display?: "flex" | "inline-flex";
35+
/**
36+
* The flow direction of the flex children
37+
* @default row
38+
*/
39+
direction?: "row" | "column" | "row-reverse" | "column-reverse";
40+
/**
41+
* The alingment of the flex children
42+
* @default start
43+
*/
44+
align?: "start" | "center" | "end" | "baseline" | "stretch";
45+
/**
46+
* The justification of the flex children
47+
* @default start
48+
*/
49+
justify?: "start" | "center" | "end" | "between";
50+
/**
51+
* The spacing between the flex children, expressed with the CSS unit
52+
* @default 0
53+
*/
54+
gap?: string;
55+
/**
56+
* the on click event callback
57+
*/
58+
onClick?: (e: React.MouseEvent) => void;
59+
};
60+
61+
/**
62+
* A flexbox container helper
63+
*/
64+
export function Flex({
65+
as = "div",
66+
display = "flex",
67+
direction = "row",
68+
align = "start",
69+
justify = "start",
70+
gap = "0",
71+
className,
72+
children,
73+
...props
74+
}: React.PropsWithChildren<FlexProps>): JSX.Element {
75+
const ref = useRef<HTMLElement>();
76+
77+
useEffect(() => {
78+
ref.current!.style.setProperty(`--mx-flex-display`, display);
79+
ref.current!.style.setProperty(`--mx-flex-direction`, direction);
80+
ref.current!.style.setProperty(`--mx-flex-align`, align);
81+
ref.current!.style.setProperty(`--mx-flex-justify`, justify);
82+
ref.current!.style.setProperty(`--mx-flex-gap`, gap);
83+
}, [align, direction, display, gap, justify]);
84+
85+
return React.createElement(as, { ...props, className: classNames("mx_Flex", className), ref }, children);
86+
}

src/components/views/rooms/RoomHeader.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,18 @@ import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
2323
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
2424
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
2525
import { useTopic } from "../../../hooks/room/useTopic";
26+
import { Flex } from "../../utils/Flex";
27+
import { Box } from "../../utils/Box";
2628

2729
export default function RoomHeader({ room }: { room: Room }): JSX.Element {
2830
const roomName = useRoomName(room);
2931
const roomTopic = useTopic(room);
3032

3133
return (
32-
<header
34+
<Flex
35+
as="header"
36+
align="center"
37+
gap="var(--cpd-space-3x)"
3338
className="mx_RoomHeader light-panel"
3439
onClick={() => {
3540
const rightPanel = RightPanelStore.instance;
@@ -39,7 +44,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
3944
}}
4045
>
4146
<DecoratedRoomAvatar room={room} avatarSize={40} displayBadge={false} />
42-
<div className="mx_RoomHeader_info">
47+
<Box flex="1" className="mx_RoomHeader_info">
4348
<BodyText
4449
as="div"
4550
size="lg"
@@ -56,7 +61,7 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
5661
{roomTopic.text}
5762
</BodyText>
5863
)}
59-
</div>
60-
</header>
64+
</Box>
65+
</Flex>
6166
);
6267
}

0 commit comments

Comments
 (0)