My personal website
1import React, { createContext, useContext } from 'react';
2import * as styles from './Layout.styles';
3import { DEFAULT_THEME } from './Layout.constants';
4import { AsideProps, LayoutProps, PageTheme, MainProps } from './Layout.types';
5import { Divider } from '@/components/Divider/Divider';
6
7// Context to share page theme with child components
8const PageThemeContext = createContext<PageTheme>(DEFAULT_THEME);
9
10export const usePageTheme = () => useContext(PageThemeContext);
11
12export const Layout: React.FC<LayoutProps> = ({ children, theme = DEFAULT_THEME }) => {
13 // Split children into Main and Aside
14 const childArray = React.Children.toArray(children);
15 const mainComponent = childArray.find(
16 (child) => React.isValidElement(child) && child.type === Main
17 );
18 const asideComponent = childArray.find(
19 (child) => React.isValidElement(child) && child.type === Aside
20 );
21
22 return (
23 <PageThemeContext.Provider value={theme}>
24 <div className={styles.getLayoutStyles(theme)}>
25 {mainComponent}
26 {asideComponent && <Divider orientation="vertical" className="hidden md:block" />}
27 {asideComponent}
28 </div>
29 </PageThemeContext.Provider>
30 );
31};
32
33export const Main: React.FC<MainProps> = ({ children }) => {
34 return <main className={styles.main}>{children}</main>;
35};
36
37export const Aside: React.FC<AsideProps> = ({ children }) => {
38 const theme = usePageTheme();
39 return <aside className={styles.getAsideStyles(theme)}>{children}</aside>;
40};