Skip to content

Commit

Permalink
Merge pull request #98 from subquery/feat/change-bem
Browse files Browse the repository at this point in the history
feat: update Header & Markdown
  • Loading branch information
HuberTRoy authored Dec 13, 2023
2 parents dca3cad + d3de5b9 commit 9a56ec4
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 116 deletions.
1 change: 0 additions & 1 deletion components/app/header/Header.less
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@

.subql-header-navlink {
text-decoration: none;
margin-right: 24px;
display: flex;
color: var(--sq-gray700);
width: fit-content;
Expand Down
215 changes: 111 additions & 104 deletions components/app/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import { AiOutlineMenu } from 'react-icons/ai';
import { IoCloseSharp } from 'react-icons/io5';
import { Dropdown, MenuWithDesc, Typography } from '../../common';
import { Context } from 'components/common/provider';
import { createBEM } from 'components/utilities/createBem';
import { useBem } from 'components/utilities/useBem';
import './Header.less';
import { useMemo } from 'react';
import { createBEM } from 'components/utilities/createBem';

const logo = 'https://static.subquery.network/design/images/logo.svg';
const logoDark = 'https://static.subquery.network/design/images/logo-light.svg';
Expand Down Expand Up @@ -65,7 +67,7 @@ export interface LeftHeaderProps {
isMobile?: boolean;
}
const LeftHeader = ({ leftElement, dropdownLinks, isMobile }: LeftHeaderProps) => {
const bem = createBEM('subql-left-header');
const bem = useBem('subql-left-header');
const { theme } = React.useContext(Context);
const sortedDropdownLinks = !leftElement && dropdownLinks && (
<div className={clsx(bem(), theme === 'dark' ? bem({ dark: 'dark' }) : '')} id="leftHeader">
Expand Down Expand Up @@ -120,63 +122,66 @@ const MiddleHeader = ({
),
}: MiddleHeaderProps) => {
const { theme } = React.useContext(Context);
const bem = createBEM('subql-middle-header');
const sortedAppNavigation = !middleElement && appNavigation && (
<Space className={clsx(bem({ wrapper: 'wrapper' }))} direction={isMobile ? 'vertical' : 'horizontal'}>
{appNavigation.map((nav, index) => {
if (nav.dropdown) {
const dropdownMenu = nav.dropdown.map((menu) => ({
key: menu.link,
label: <Typography>{menu.label}</Typography>,
className: clsx(bem('menu-item'), theme === 'dark' && bem('menu-item', { dark: 'dark' })), // should refoctor
}));
return (
<div key={nav.link} className={clsx(bem('item'), `middle-item-${index}`)}>
<Dropdown
rootClassName={clsx(bem('menu-wrapper'))}
menuClassName={clsx(bem('menu', { dark: theme === 'dark' ? 'dark' : null }))}
menuitem={dropdownMenu}
label={nav.label}
trigger={[isMobile ? 'click' : 'hover']}
onMenuItemClick={({ key }) => {
if (nav.onClick) {
nav.onClick(key);
} else if (isExternalLink(key)) {
window.open(key, '_blank');
} else {
navigate(key);
}
}}
getPopupContainer={() => {
return document.querySelector(`.middle-item-${index}`) as HTMLElement;
}}
/>
</div>
);
}
return (
<div
className={clsx(bem('item'))}
key={nav.link}
onClickCapture={(e) => {
if (!isExternalLink(nav.link ?? '/')) {
navigate(nav.link ?? '/');
e.stopPropagation();
e.preventDefault();
}
}}
>
{renderLink(nav.link ?? '/', nav.label, nav.active || active)}
</div>
);
})}
</Space>
);
const bem = useBem('subql-middle-header');

return (
<>
<>{middleElement}</>
<>{sortedAppNavigation}</>
{!middleElement && appNavigation && (
<Space className={clsx(bem({ wrapper: 'wrapper' }))} direction={isMobile ? 'vertical' : 'horizontal'} size={24}>
{appNavigation.map((nav, index) => {
if (nav.dropdown) {
return (
<div key={nav.link || index} className={clsx(bem('item'), `middle-item-${index}`)}>
<Dropdown
rootClassName={clsx(bem('menu-wrapper'))}
menuClassName={clsx(bem('menu', { dark: theme === 'dark' ? 'dark' : null }))}
menuitem={nav.dropdown.map((menu) => ({
key: menu.link,
label: <Typography>{menu.label}</Typography>,
className: clsx(bem('menu-item'), theme === 'dark' && bem('menu-item', { dark: 'dark' })), // should refoctor
}))}
label={nav.label}
trigger={[isMobile ? 'click' : 'hover']}
onMenuItemClick={({ key }) => {
if (nav.onClick) {
nav.onClick(key);
} else if (isExternalLink(key)) {
window.open(key, '_blank');
} else {
navigate(key);
}
}}
onLableClick={() => {
if (nav.link) {
navigate(nav.link);
}
}}
getPopupContainer={() => {
return document.querySelector(`.middle-item-${index}`) as HTMLElement;
}}
/>
</div>
);
}
return (
<div
className={clsx(bem('item'))}
key={nav.link || index}
onClickCapture={(e) => {
if (!isExternalLink(nav.link ?? '/')) {
navigate(nav.link ?? '/');
e.stopPropagation();
e.preventDefault();
}
}}
>
{renderLink(nav.link ?? '/', nav.label, nav.active || active)}
</div>
);
})}
</Space>
)}
</>
);
};
Expand All @@ -201,68 +206,70 @@ export const Header: React.FC<React.PropsWithChildren<HeaderProps>> = ({
navigate,
active,
}) => {
const { screenWidth } = useScreen();
const isMobile = screenWidth < 768;
const { theme } = React.useContext(Context);
const bem = createBEM('subql-header');
const FullHeader = () => (
<div className={clsx(bem(), theme === 'dark' ? bem({ dark: 'dark' }) : '', className)}>
<div className={clsx(bem('inner'))}>
<div>
<a href={logoLink ?? '/'}>
<img src={theme === 'light' ? logo : logoDark} alt="SubQuery Logo" width={140} />
</a>
</div>

<LeftHeader leftElement={leftElement} dropdownLinks={dropdownLinks} showDivider />
<MiddleHeader middleElement={middleElement} appNavigation={appNavigation} navigate={navigate} active={active} />
</div>

<>{rightElement}</>
</div>
);

const MenuHeader = () => {
const [showMenu, setShowMenu] = React.useState<boolean>(false);
const bem = createBEM('subql-mobile-header');
const { theme } = React.useContext(Context);
const handleMenuClick = () => {
setShowMenu(!showMenu);
};
const bem = useBem('subql-header');
const mobileHeaderBem = useBem('subql-mobile-header');
const { screenWidth } = useScreen();
const [showMenu, setShowMenu] = React.useState<boolean>(false);
const MenuIcon = useMemo(() => (showMenu ? IoCloseSharp : AiOutlineMenu), [showMenu]);
const isMobile = useMemo(() => screenWidth < 768, [screenWidth]);

const MenuIcon = showMenu ? IoCloseSharp : AiOutlineMenu;
return (
<>
{isMobile ? (
<div>
<div
className={clsx(mobileHeaderBem(), theme === 'dark' ? mobileHeaderBem({ dark: 'dark' }) : '', className)}
>
<div>
<a href={logoLink ?? '/'}>
<img src={logoMobile} alt="SubQuery Logo" width={48} />
</a>
</div>

return (
<div>
<div className={clsx(bem(), theme === 'dark' ? bem({ dark: 'dark' }) : '', className)}>
<div>
<a href={logoLink ?? '/'}>
<img src={logoMobile} alt="SubQuery Logo" width={48} />
</a>
<MenuIcon
onClick={() => {
setShowMenu(!showMenu);
}}
size={20}
style={{ cursor: 'pointer' }}
/>
</div>

<MenuIcon onClick={handleMenuClick} size={20} style={{ cursor: 'pointer' }} />
{showMenu && (
<div className={clsx(mobileHeaderBem('menu', { dark: theme === 'dark' ? 'dark' : null }))}>
<LeftHeader leftElement={leftElement} dropdownLinks={dropdownLinks} showDivider isMobile />
<MiddleHeader
middleElement={middleElement}
appNavigation={appNavigation}
isMobile
navigate={navigate}
active={active}
/>
<>{rightElement}</>
</div>
)}
</div>
{showMenu && (
<div className={clsx(bem('menu', { dark: theme === 'dark' ? 'dark' : null }))}>
<LeftHeader leftElement={leftElement} dropdownLinks={dropdownLinks} showDivider isMobile />
) : (
<div className={clsx(bem(), theme === 'dark' ? bem({ dark: 'dark' }) : '', className)}>
<div className={clsx(bem('inner'))}>
<div>
<a href={logoLink ?? '/'}>
<img src={theme === 'light' ? logo : logoDark} alt="SubQuery Logo" width={140} />
</a>
</div>

<LeftHeader leftElement={leftElement} dropdownLinks={dropdownLinks} showDivider />
<MiddleHeader
middleElement={middleElement}
appNavigation={appNavigation}
isMobile
navigate={navigate}
active={active}
/>
<>{rightElement}</>
</div>
)}
</div>
);
};

return (
<>
{isMobile ? <MenuHeader /> : <FullHeader />}
<>{rightElement}</>
</div>
)}
{children}
</>
);
Expand Down
25 changes: 23 additions & 2 deletions components/common/dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import DownOutlined from '@ant-design/icons/DownOutlined';
import { ItemType, MenuClickEventHandler } from 'rc-menu/lib/interface';
import styles from './Dropdown.module.css';
import { Typography } from '../typography';
import { Context } from '../provider';

export interface DropdownProps extends Partial<AntdDropdownProps> {
label?: string;
menuitem: ItemType[];
menuClassName?: string;
onMenuItemClick?: MenuClickEventHandler;
onLableClick?: () => void;
LeftLabelIcon?: React.ReactElement;
RightLabelIcon?: React.ReactElement;
active?: boolean;
Expand All @@ -27,14 +29,33 @@ export const Dropdown: React.FC<DropdownProps> = ({
menuClassName,
active,
onMenuItemClick,
onLableClick,
...props
}) => {
const { theme } = React.useContext(Context);
const [isOpen, setIsOpen] = React.useState<boolean>(false);
const sortedLabel = (
<Space className={clsx(styles.dropdownLabel, styles.pointer, (isOpen || active) && styles.isOnHover)}>
{LeftLabelIcon}
<Typography>{label ?? 'Dropdown'}</Typography>
<Typography>{LeftLabelIcon ? undefined : RightLabelIcon ? RightLabelIcon : <DownOutlined />}</Typography>
<Typography
onClick={() => {
onLableClick?.();
}}
>
{label ?? 'Dropdown'}
</Typography>
<Typography>
{LeftLabelIcon ? undefined : RightLabelIcon ? (
RightLabelIcon
) : (
<DownOutlined
style={{
fontSize: 12,
color: theme === 'dark' ? '#fff' : 'var(--sq-gray600)',
}}
/>
)}
</Typography>
</Space>
);

Expand Down
16 changes: 12 additions & 4 deletions components/common/markdown/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const previewBem = createBEM('subql-markdown-preview');
export interface SubqlMarkdown {
value?: string | undefined;
onChange?: (val: string | undefined) => void;
inputProps: TextAreaProps;
previewProps: Options;
inputProps?: TextAreaProps;
previewProps?: Options;
}

const MarkdownPreview: FC<Options> = (props) => {
Expand Down Expand Up @@ -52,9 +52,9 @@ const Markdown: FC<SubqlMarkdown> = (props) => {
<Radio value={'preview'}>Preview</Radio>
</Radio.Group>
<span style={{ flex: 1 }}></span>
<Typography type="secondary">
<Typography type="secondary" variant="small">
This entry supports{' '}
<Typography.Link href="https://commonmark.org/help/" active>
<Typography.Link href="https://commonmark.org/help/" active variant="small">
&#32;basic markdown
</Typography.Link>
</Typography>
Expand All @@ -64,6 +64,14 @@ const Markdown: FC<SubqlMarkdown> = (props) => {
{tabVal === 'edit' && (
<Input.TextArea
rows={20}
placeholder={`You can provide a detailed description of your SubQuery project.
# hello world
- you can use lists
- *Italics*
- *bold*
- [Links](http://subquery.network)
`}
{...props.inputProps}
value={markdownVal}
onChange={(val) => {
Expand Down
1 change: 1 addition & 0 deletions components/common/markdown/markdown.less
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
}

&-preview {
color: var(--sq-gray700);
p {
margin: 1em 0;
}
Expand Down
1 change: 1 addition & 0 deletions components/common/typography/Typography.less
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
}

&-link {
cursor: pointer;
.subql-typography {
transition: .1s all linear;
color: var(--sq-gray600);
Expand Down
Loading

0 comments on commit 9a56ec4

Please sign in to comment.