mirror of
https://github.com/umami-software/umami.git
synced 2026-02-09 23:27:12 +01:00
More refactoring, cleaned up icons, nav buttons, add messages.
This commit is contained in:
parent
4b1013c8c6
commit
5f15ad0807
68 changed files with 391 additions and 790 deletions
|
|
@ -1,30 +1,51 @@
|
|||
import { Icon, Button, PopupTrigger, Popup, Tooltip, Icons, Text } from 'react-basics';
|
||||
import { useIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { languages } from 'lib/lang';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import MenuButton from 'components/common/MenuButton';
|
||||
import Globe from 'assets/globe.svg';
|
||||
import { Globe } from 'components/icons';
|
||||
import { labels } from 'components/messages';
|
||||
import styles from './LanguageButton.module.css';
|
||||
import { Icon } from 'react-basics';
|
||||
|
||||
export default function LanguageButton() {
|
||||
export default function LanguageButton({ tooltipPosition = 'top' }) {
|
||||
const { formatMessage } = useIntl();
|
||||
const { locale, saveLocale } = useLocale();
|
||||
const menuOptions = Object.keys(languages).map(key => ({ ...languages[key], value: key }));
|
||||
const items = Object.keys(languages).map(key => ({ ...languages[key], value: key }));
|
||||
|
||||
function handleSelect(value) {
|
||||
saveLocale(value);
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuButton
|
||||
options={menuOptions}
|
||||
value={locale}
|
||||
menuClassName={styles.menu}
|
||||
buttonVariant="light"
|
||||
onSelect={handleSelect}
|
||||
hideLabel
|
||||
>
|
||||
<Icon>
|
||||
<Globe />
|
||||
</Icon>
|
||||
</MenuButton>
|
||||
<PopupTrigger>
|
||||
<PopupTrigger action="hover">
|
||||
<Button variant="quiet">
|
||||
<Icon>
|
||||
<Globe />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Tooltip position={tooltipPosition}>{formatMessage(labels.language)}</Tooltip>
|
||||
</PopupTrigger>
|
||||
<Popup position="right" alignment="end">
|
||||
<div className={styles.menu}>
|
||||
{items.map(({ value, label }) => {
|
||||
return (
|
||||
<div
|
||||
key={value}
|
||||
className={classNames(styles.item, { [styles.selected]: value === locale })}
|
||||
onClick={handleSelect.bind(null, value)}
|
||||
>
|
||||
<Text>{label}</Text>
|
||||
{value === locale && (
|
||||
<Icon className={styles.icon}>
|
||||
<Icons.Check />
|
||||
</Icon>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,35 @@
|
|||
.menu {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
min-width: 560px;
|
||||
min-width: 600px;
|
||||
max-width: 100vw;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.menu div {
|
||||
background: var(--base50);
|
||||
z-index: var(--z-index100);
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-width: calc(100% / 3);
|
||||
border-radius: 5px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
.menu {
|
||||
min-width: 90vw;
|
||||
transform: translateX(calc(40vw));
|
||||
}
|
||||
.item:hover {
|
||||
background: var(--base75);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
.menu div {
|
||||
min-width: 50%;
|
||||
}
|
||||
.selected {
|
||||
font-weight: 700;
|
||||
background: var(--blue100);
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: var(--primary400);
|
||||
}
|
||||
|
|
|
|||
22
components/buttons/LogoutButton.js
Normal file
22
components/buttons/LogoutButton.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { Button, Icon, Icons, PopupTrigger, Tooltip } from 'react-basics';
|
||||
import Link from 'next/link';
|
||||
import { labels } from 'components/messages';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
export default function LogoutButton({ tooltipPosition = 'top' }) {
|
||||
const { formatMessage } = useIntl();
|
||||
return (
|
||||
<Link href="/logout">
|
||||
<a>
|
||||
<PopupTrigger action="hover">
|
||||
<Button variant="quiet">
|
||||
<Icon>
|
||||
<Icons.Logout />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Tooltip position={tooltipPosition}>{formatMessage(labels.logout)}</Tooltip>
|
||||
</PopupTrigger>
|
||||
</a>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
import { useTransition, animated } from 'react-spring';
|
||||
import { Button, Icon, PopupTrigger, Tooltip } from 'react-basics';
|
||||
import { useIntl } from 'react-intl';
|
||||
import useTheme from 'hooks/useTheme';
|
||||
import Sun from 'assets/sun.svg';
|
||||
import Moon from 'assets/moon.svg';
|
||||
import { Sun, Moon } from 'components/icons';
|
||||
import { labels } from 'components/messages';
|
||||
import styles from './ThemeButton.module.css';
|
||||
import { Icon } from 'react-basics';
|
||||
|
||||
export default function ThemeButton() {
|
||||
export default function ThemeButton({ tooltipPosition = 'top' }) {
|
||||
const [theme, setTheme] = useTheme();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const transitions = useTransition(theme, {
|
||||
initial: { opacity: 1 },
|
||||
|
|
@ -14,7 +16,7 @@ export default function ThemeButton() {
|
|||
opacity: 0,
|
||||
transform: `translateY(${theme === 'light' ? '20px' : '-20px'}) scale(0.5)`,
|
||||
},
|
||||
enter: { opacity: 1, transform: 'translateY(0px) scale(1)' },
|
||||
enter: { opacity: 1, transform: 'translateY(0px) scale(1.0)' },
|
||||
leave: {
|
||||
opacity: 0,
|
||||
transform: `translateY(${theme === 'light' ? '-20px' : '20px'}) scale(0.5)`,
|
||||
|
|
@ -26,12 +28,15 @@ export default function ThemeButton() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={styles.button} onClick={handleClick}>
|
||||
{transitions((styles, item) => (
|
||||
<animated.div key={item} style={styles}>
|
||||
<Icon>{item === 'light' ? <Sun /> : <Moon />}</Icon>
|
||||
</animated.div>
|
||||
))}
|
||||
</div>
|
||||
<PopupTrigger action="hover" popupProps={{ position: 'top' }}>
|
||||
<Button variant="quiet" className={styles.button} onClick={handleClick}>
|
||||
{transitions((style, item) => (
|
||||
<animated.div key={item} style={style}>
|
||||
<Icon className={styles.icon}>{item === 'light' ? <Sun /> : <Moon />}</Icon>
|
||||
</animated.div>
|
||||
))}
|
||||
</Button>
|
||||
<Tooltip position={tooltipPosition}>{formatMessage(labels.theme)}</Tooltip>
|
||||
</PopupTrigger>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.button svg {
|
||||
.button > div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
import { Button, Icon } from 'react-basics';
|
||||
import useTheme from 'hooks/useTheme';
|
||||
import Sun from 'assets/sun.svg';
|
||||
import Moon from 'assets/moon.svg';
|
||||
import styles from './ThemeSetting.module.css';
|
||||
|
||||
export default function ThemeSetting() {
|
||||
const [theme, setTheme] = useTheme();
|
||||
|
||||
return (
|
||||
<div className={styles.buttons}>
|
||||
<Button
|
||||
className={classNames({ [styles.active]: theme === 'light' })}
|
||||
onClick={() => setTheme('light')}
|
||||
>
|
||||
<Icon>
|
||||
<Sun />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Button
|
||||
className={classNames({ [styles.active]: theme === 'dark' })}
|
||||
onClick={() => setTheme('dark')}
|
||||
>
|
||||
<Icon>
|
||||
<Moon />
|
||||
</Icon>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 2px solid var(--primary400);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue