Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/layout/AppFooter.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.app-footer {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 12px;
background: transparent !important;

.footer-copyright {
font-size: 0.85rem;
white-space: nowrap;
}
}
22 changes: 22 additions & 0 deletions src/layout/AppFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Layout } from 'antd'
import cn from 'classnames'
import { useTranslation } from 'react-i18next'
import { useTheme } from './ThemeContext'
import './AppFooter.scss'

const { Footer } = Layout

const AppFooter = () => {
const { isDarkTheme } = useTheme()
const { t } = useTranslation()

return (
<Footer className={cn('app-footer', { dark: isDarkTheme })}>
<span className="hideOnMobile footer-copyright">
{`${t('homepage.copyright')} ${new Date().getFullYear()}`}
</span>
</Footer>
)
}

export default AppFooter
11 changes: 4 additions & 7 deletions src/layout/header/DonationButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DollarOutlined } from '@ant-design/icons'
import IconButton from '@mui/material/IconButton'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import DonateModal from 'src/pages/DonateModal/DonateModal'
Expand All @@ -13,13 +14,9 @@ export const DonationButton = () => {
const onClose = () => setOpen(false)
return (
<>
<button
className="theme-icon"
onClick={onOpen}
aria-label={tooltip_title}
title={tooltip_title}>
<DollarOutlined style={{ fontSize: '1.5em' }} />
</button>
<IconButton size="small" onClick={onOpen} aria-label={tooltip_title} title={tooltip_title}>
<DollarOutlined />
</IconButton>
<DonateModal isVisible={open} onClose={onClose} />
</>
)
Expand Down
45 changes: 0 additions & 45 deletions src/layout/header/Header.css

This file was deleted.

32 changes: 0 additions & 32 deletions src/layout/header/Header.tsx

This file was deleted.

20 changes: 0 additions & 20 deletions src/layout/header/HeaderLinks/HeaderLinks.scss

This file was deleted.

28 changes: 14 additions & 14 deletions src/layout/header/HeaderLinks/HeaderLinks.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Box from '@mui/material/Box'
import IconButton from '@mui/material/IconButton'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router'
import { HEADER_LINKS } from 'src/routes'
import './HeaderLinks.scss'

type LinkType = Omit<(typeof HEADER_LINKS)[number], 'element'>

Expand All @@ -12,7 +13,7 @@ type HeaderLinksProps = {

const HeaderLinks: FC<HeaderLinksProps> = ({ children }) => {
return (
<div className="header-links">
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
{children}
{HEADER_LINKS.map((item) => {
if (item.element === null) {
Expand All @@ -25,35 +26,34 @@ const HeaderLinks: FC<HeaderLinksProps> = ({ children }) => {
)
}
})}
</div>
</Box>
)
}

const ExternalLink = ({ label, path, icon }: LinkType) => {
const { t } = useTranslation()
function handleClick() {
window.open(path, '_blank')
}
return (
<div className="header-link" aria-label={t(label)} title={t(label)} onClick={handleClick}>
<IconButton
size="small"
aria-label={t(label)}
title={t(label)}
onClick={() => void window.open(path, '_blank')}>
{icon}
</div>
</IconButton>
)
}

const InternalLink = ({ label, path, icon }: LinkType) => {
const navigate = useNavigate()
const { t } = useTranslation()
return (
<div
<IconButton
size="small"
aria-label={t(label)}
title={t(label)}
className="header-link"
onClick={() => {
navigate(path)
}}>
onClick={() => void navigate(path)}>
{icon}
</div>
</IconButton>
)
}

Expand Down
9 changes: 3 additions & 6 deletions src/layout/header/LanguageToggleButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GlobalOutlined } from '@ant-design/icons'
import IconButton from '@mui/material/IconButton'
import { Dropdown, type MenuProps } from 'antd'
import { useTranslation } from 'react-i18next'
import { useTheme } from '../ThemeContext'
Expand Down Expand Up @@ -38,13 +39,9 @@ export const LanguageToggleButton = () => {
}}
trigger={['click']}
placement="bottomRight">
<button
className="header-link"
aria-label={t('change_language')}
title={t('change_language')}
style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
<IconButton size="small" aria-label={t('change_language')} title={t('change_language')}>
<GlobalOutlined />
</button>
</IconButton>
</Dropdown>
)
}
10 changes: 5 additions & 5 deletions src/layout/header/ShareButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CheckOutlined, LinkOutlined } from '@ant-design/icons'
import IconButton from '@mui/material/IconButton'
import { Tooltip } from 'antd'
import { useCallback, useContext, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
Expand Down Expand Up @@ -43,13 +44,12 @@ export const ShareButton = () => {

return (
<Tooltip title={tooltipTitle} open={copied || undefined} placement="bottomRight">
<div
className="header-link"
<IconButton
size="small"
onClick={handleShare}
aria-label={copied ? t('link_copied') : t('share_link')}
style={{ cursor: 'pointer' }}>
aria-label={copied ? t('link_copied') : t('share_link')}>
{copied ? <CheckOutlined /> : <LinkOutlined />}
</div>
</IconButton>
</Tooltip>
)
}
15 changes: 5 additions & 10 deletions src/layout/header/ToggleThemeButton.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import DarkModeIcon from '@mui/icons-material/DarkMode'
import LightModeIcon from '@mui/icons-material/LightMode'
import React from 'react'
import IconButton from '@mui/material/IconButton'
import { useTranslation } from 'react-i18next'

interface ToggleThemeButtonProps {
toggleTheme: () => void
isDarkTheme?: boolean
}

const ToggleThemeButton: React.FC<ToggleThemeButtonProps> = ({ toggleTheme, isDarkTheme }) => {
const ToggleThemeButton = ({ toggleTheme, isDarkTheme }: ToggleThemeButtonProps) => {
const { t } = useTranslation()

const tooltip_title = isDarkTheme ? t('light_mode_tooltip') : t('dark_mode_tooltip')

return (
<button
className="header-link"
onClick={toggleTheme}
aria-label={tooltip_title}
title={tooltip_title}
style={{ border: 'none', background: 'transparent', cursor: 'pointer' }}>
{isDarkTheme ? <LightModeIcon className="theme-icon-dark" /> : <DarkModeIcon />}
</button>
<IconButton size="small" onClick={toggleTheme} aria-label={tooltip_title} title={tooltip_title}>
{isDarkTheme ? <LightModeIcon fontSize="inherit" /> : <DarkModeIcon fontSize="inherit" />}
</IconButton>
)
}

Expand Down
31 changes: 27 additions & 4 deletions src/layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { MenuOutlined } from '@ant-design/icons'
import IconButton from '@mui/material/IconButton'
import { Layout } from 'antd'
import { Suspense } from 'react'
import { Suspense, useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { Link, Outlet } from 'react-router'
import styled from 'styled-components'
import { EasterEgg } from 'src/pages/components/EasterEgg/EasterEgg'
import { Envelope } from 'src/pages/components/EasterEgg/Envelope'
import Preloader from 'src/shared/Preloader'
import MainHeader from './header/Header'
import LayoutContext from './LayoutContext'
import AppFooter from './AppFooter'
import LayoutContext, { LayoutContextInterface, LayoutCtx } from './LayoutContext'
import SideBar from './sidebar/SideBar'
import { useTheme } from './ThemeContext'

const { Content } = Layout

Expand All @@ -24,13 +28,31 @@ const StyledBody = styled.div`
min-height: 360px;
`

const MobileMenuButton = () => {
const { setDrawerOpen } = useContext<LayoutContextInterface>(LayoutCtx)
const { i18n } = useTranslation()
const { currentLanguage } = useTheme()
const direction = i18n.dir(currentLanguage)

return (
<IconButton
className="hideOnDesktop"
dir={direction}
onClick={() => setDrawerOpen(true)}
sx={{ position: 'fixed', top: 8, insetInlineStart: 8, insetInlineEnd: 'auto', zIndex: 1000 }}
size="small">
<MenuOutlined />
</IconButton>
)
}

export function MainLayout() {
return (
<StyledLayout className="main">
<LayoutContext>
<MobileMenuButton />
<SideBar />
<Layout>
<MainHeader />
<StyledContent id="main-content">
<StyledBody>
<Suspense fallback={<Preloader />}>
Expand All @@ -53,6 +75,7 @@ export function MainLayout() {
</Suspense>
</StyledBody>
</StyledContent>
<AppFooter />
</Layout>
</LayoutContext>
</StyledLayout>
Expand Down
Loading
Loading