Skip to content

Commit

Permalink
✨ feat(header): Add className and style prop support for logo, nav, a…
Browse files Browse the repository at this point in the history
…nd actions

This commit adds support for the `className` and `style` props to customize the styling of the `logo`, `nav`, and `actions` components in the `Header` component. This is achieved by adding new optional props `logoClassName`, `logoStyle`, `navClassName`, `navStyle`, `actionsClassName`, and `actionsStyle` to the `HeaderProps` interface. The implementation involves using the `classnames` library to merge the custom class names with the existing ones and applying the custom styles using the `style` prop.
  • Loading branch information
canisminor1990 committed Jun 18, 2023
1 parent 2fd696f commit e0e604e
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 87 deletions.
111 changes: 74 additions & 37 deletions src/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useResponsive } from 'antd-style';
import { ReactNode, memo } from 'react';
import { CSSProperties, ReactNode, memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import { DivProps } from '@/types';
Expand All @@ -8,48 +8,85 @@ import { useStyles } from './style';

export interface HeaderProps extends DivProps {
actions?: ReactNode;
actionsClassName?: string;
actionsStyle?: CSSProperties;
logo?: ReactNode;
logoClassName?: string;
logoStyle?: CSSProperties;
nav?: ReactNode;
navClassName?: string;
navStyle?: CSSProperties;
}

const Header = memo<HeaderProps>(({ nav, logo, actions }) => {
const { mobile } = useResponsive();
const { styles } = useStyles();
const Header = memo<HeaderProps>(
({
actionsClassName,
navClassName,
logoClassName,
nav,
logo,
actions,
actionsStyle,
logoStyle,
navStyle,
className,
...props
}) => {
const { mobile } = useResponsive();
const { cx, styles } = useStyles();

return (
<section className={styles.header}>
<Flexbox
align={'center'}
className={styles.content}
distribution={'space-between'}
horizontal
width={'auto'}
>
{mobile ? (
<>
<Flexbox>{nav}</Flexbox>
<Flexbox className={styles.left} horizontal>
{logo}
</Flexbox>
<Flexbox>{actions}</Flexbox>
</>
) : (
<>
<Flexbox className={styles.left} horizontal>
{logo}
</Flexbox>
<Flexbox style={{ alignSelf: 'end', marginLeft: 48 }}>{nav}</Flexbox>
<section className={styles.right}>
<div />
<Flexbox align={'center'} gap={8} horizontal>
return (
<section className={cx(styles.header, className)} {...props}>
<Flexbox
align={'center'}
className={styles.content}
distribution={'space-between'}
horizontal
width={'auto'}
>
{mobile ? (
<>
<Flexbox className={actionsClassName} style={{ flex: 0, ...navStyle }}>
{nav}
</Flexbox>
<Flexbox
className={cx(styles.left, logoClassName)}
horizontal
style={{ flex: 1, overflow: 'hidden', ...logoStyle }}
>
{logo}
</Flexbox>
<Flexbox className={actionsClassName} style={{ flex: 0, ...actionsStyle }}>
{actions}
</Flexbox>
</section>
</>
)}
</Flexbox>
</section>
);
});
</>
) : (
<>
<Flexbox
className={cx(styles.left, logoClassName)}
horizontal
style={{ flex: 0, ...logoStyle }}
>
{logo}
</Flexbox>
<Flexbox
className={navClassName}
style={{ flex: 1, marginLeft: 48, overflow: 'hidden', ...navStyle }}
>
{nav}
</Flexbox>
<section className={cx(styles.right, actionsClassName)} style={actionsStyle}>
<div />
<Flexbox align={'center'} gap={8} horizontal>
{actions}
</Flexbox>
</section>
</>
)}
</Flexbox>
</section>
);
},
);

export default Header;
109 changes: 88 additions & 21 deletions src/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,87 @@ import { useResponsive } from 'antd-style';
import { ReactNode, memo, useEffect, useState } from 'react';

import DraggablePanel from '@/DraggablePanel';
import { DivProps } from '@/types';

import { useStyles } from './style';

export interface LayoutHeaderProps extends DivProps {
headerHeight?: number;
}
export const LayoutHeader = memo<LayoutHeaderProps>(({ headerHeight, children, ...props }) => {
const { styles } = useStyles(headerHeight);
return (
<header
className={styles.header}
style={{
height: headerHeight,
}}
{...props}
>
<div className={styles.glass} />
{children}
</header>
);
});

export type LayoutMainProps = DivProps;
export const LayoutMain = memo<LayoutMainProps>(({ children, ...props }) => {
const { styles } = useStyles();
return (
<main className={styles.main} {...props}>
{children}
</main>
);
});

export interface LayoutSidebarProps extends DivProps {
headerHeight?: number;
}
export const LayoutSidebar = memo<LayoutSidebarProps>(({ headerHeight, children, ...props }) => {
const { styles } = useStyles(headerHeight);
return (
<aside className={styles.aside} style={{ top: headerHeight }} {...props}>
{children}
</aside>
);
});

export interface LayoutSidebarInnerProps extends DivProps {
headerHeight?: number;
}
export const LayoutSidebarInner = memo<LayoutSidebarInnerProps>(
({ headerHeight, children, ...props }) => {
const { styles } = useStyles(headerHeight);
return (
<div className={styles.asideInner} {...props}>
{children}
</div>
);
},
);

export interface LayoutTocProps extends DivProps {
tocWidth?: number;
}
export const LayoutToc = memo<LayoutTocProps>(({ tocWidth, children, ...props }) => {
const { styles } = useStyles();
return (
<nav className={styles.toc} style={{ width: tocWidth }} {...props}>
{children}
</nav>
);
});

export type LayoutFooterProps = DivProps;
export const LayoutFooter = memo<LayoutFooterProps>(({ children, ...props }) => {
const { styles } = useStyles();
return (
<footer className={styles.footer} {...props}>
{children}
</footer>
);
});

export interface LayoutProps {
asideWidth?: number;
children?: ReactNode;
Expand All @@ -31,40 +109,29 @@ const Layout = memo<LayoutProps>(
<>
{helmet}
{header && (
<header
className={styles.header}
style={{
height: headerHeight,
}}
>
<div className={styles.glass} />
<LayoutHeader headerHeight={headerHeight}>
{header}
{mobile && toc && <nav className={styles.toc}>{toc}</nav>}
</header>
{mobile && toc && <LayoutToc tocWidth={tocWidth}>{toc}</LayoutToc>}
</LayoutHeader>
)}

<main className={styles.main}>
<LayoutMain>
{!mobile && !sidebar && <nav style={{ width: tocWidth }} />}
{!mobile && sidebar && (
<aside className={styles.aside} style={{ top: headerHeight }}>
<LayoutSidebar headerHeight={headerHeight}>
<DraggablePanel
expand={expand}
maxWidth={asideWidth}
onExpandChange={setExpand}
placement="left"
>
<div className={styles.asideInner}>{sidebar}</div>
<LayoutSidebarInner headerHeight={headerHeight}>{sidebar}</LayoutSidebarInner>
</DraggablePanel>
</aside>
</LayoutSidebar>
)}
<section className={styles.content}>{children}</section>
{!mobile && toc && (
<nav className={styles.toc} style={{ width: tocWidth }}>
{toc}
</nav>
)}
</main>
{footer && <footer className={styles.footer}>{footer}</footer>}
{!mobile && toc && <LayoutToc tocWidth={tocWidth}>{toc}</LayoutToc>}
</LayoutMain>
{footer && <LayoutFooter>{footer}</LayoutFooter>}
</>
);
},
Expand Down
2 changes: 1 addition & 1 deletion src/Layout/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const useStyles = createStyles(({ css, stylish, responsive }, headerHeigh
overflow-x: hidden;
overflow-y: auto;
width: 100%;
height: calc(100vh - 64px);
height: calc(100vh - ${headerHeight}px);
`,
content: css`
position: relative;
Expand Down
55 changes: 28 additions & 27 deletions src/ThemeProvider/GlobalStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const GlobalStyle = createGlobalStyle`
body {
overflow-x: hidden;
overflow-y: auto;
height: 100vh;
}
Expand All @@ -59,37 +58,39 @@ const GlobalStyle = createGlobalStyle`
background: ${({ theme }) => theme.yellow9};
}
* {
box-sizing: border-box;
vertical-align: baseline;
::-webkit-scrollbar {
cursor: pointer;
width: 4px;
height: 4px;
background-color: transparent;
}
@media only screen and (min-width: 574px) {
* {
box-sizing: border-box;
vertical-align: baseline;
::-webkit-scrollbar-thumb {
cursor: pointer;
background-color: transparent;
border-radius: 2px;
transition: background-color 500ms ${({ theme }) => theme.motionEaseOut};
::-webkit-scrollbar {
cursor: pointer;
width: 4px;
height: 4px;
background-color: transparent;
}
&:hover {
background-color: ${({ theme }) => theme.colorText};
::-webkit-scrollbar-thumb {
cursor: pointer;
background-color: transparent;
border-radius: 2px;
transition: background-color 500ms ${({ theme }) => theme.motionEaseOut};
&:hover {
background-color: ${({ theme }) => theme.colorText};
}
}
}
::-webkit-scrollbar-corner {
display: none;
width: 0;
height: 0;
}
::-webkit-scrollbar-corner {
display: none;
width: 0;
height: 0;
}
&:hover {
::-webkit-scrollbar-thumb {
background-color: ${({ theme }) => theme.colorFill};
&:hover {
::-webkit-scrollbar-thumb {
background-color: ${({ theme }) => theme.colorFill};
}
}
}
}
Expand Down
17 changes: 16 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,22 @@ export {
} from './Highlighter';
export { default as Icon, type IconProps, type IconSize } from './Icon';
export { Input, type InputProps, TextArea, type TextAreaProps } from './Input';
export { default as Layout, type LayoutProps } from './Layout';
export {
default as Layout,
LayoutFooter,
type LayoutFooterProps,
LayoutHeader,
type LayoutHeaderProps,
LayoutMain,
type LayoutMainProps,
type LayoutProps,
LayoutSidebar,
LayoutSidebarInner,
type LayoutSidebarInnerProps,
type LayoutSidebarProps,
LayoutToc,
type LayoutTocProps,
} from './Layout';
export { default as List } from './List';
export { default as Logo, type LogoProps } from './Logo';
export { default as Markdown, type MarkdownProps } from './Markdown';
Expand Down

1 comment on commit e0e604e

@vercel
Copy link

@vercel vercel bot commented on e0e604e Jun 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

lobe-ui – ./

lobe-ui-git-master-lobehub.vercel.app
lobe-ui.vercel.app
lobe-ui-lobehub.vercel.app
ui.lobehub.com

Please sign in to comment.