chore: a11y and animation for the theme toggle
This commit is contained in:
parent
21653c4156
commit
03a249c032
2 changed files with 77 additions and 27 deletions
|
@ -1,19 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import {
|
import { Command, Activity, Globe, Link2, Settings, File } from 'react-feather';
|
||||||
Moon,
|
|
||||||
Command,
|
|
||||||
Activity,
|
|
||||||
Globe,
|
|
||||||
Link2,
|
|
||||||
Settings,
|
|
||||||
File
|
|
||||||
} from 'react-feather';
|
|
||||||
|
|
||||||
import { connect } from './StateProvider';
|
import { connect } from './StateProvider';
|
||||||
import { switchTheme } from '../store/app';
|
import { getTheme, switchTheme } from '../store/app';
|
||||||
|
|
||||||
import SvgYacd from './SvgYacd';
|
import SvgYacd from './SvgYacd';
|
||||||
import s from './SideBar.module.css';
|
import s from './SideBar.module.css';
|
||||||
|
@ -68,7 +61,6 @@ const pages = [
|
||||||
iconId: 'command',
|
iconId: 'command',
|
||||||
labelText: 'Rules'
|
labelText: 'Rules'
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
to: '/connections',
|
to: '/connections',
|
||||||
iconId: 'link',
|
iconId: 'link',
|
||||||
|
@ -86,7 +78,7 @@ const pages = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function SideBar({ dispatch }) {
|
function SideBar({ dispatch, theme }) {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const switchThemeHooked = useCallback(() => {
|
const switchThemeHooked = useCallback(() => {
|
||||||
dispatch(switchTheme());
|
dispatch(switchTheme());
|
||||||
|
@ -115,18 +107,67 @@ function SideBar({ dispatch }) {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className={s.themeSwitchContainer} onClick={switchThemeHooked}>
|
<button className={s.themeSwitchContainer} onClick={switchThemeHooked}>
|
||||||
<Moon size={20} />
|
{theme === 'light' ? <MoonA /> : <Sun />}
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SideBar.propTypes = {
|
function MoonA() {
|
||||||
// location: PropTypes.shape({
|
return (
|
||||||
// pathname: PropTypes.string
|
<svg
|
||||||
// }).isRequired
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
// };
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<motion.path
|
||||||
|
d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
|
||||||
|
initial={{ rotate: -30 }}
|
||||||
|
animate={{ rotate: 0 }}
|
||||||
|
transition={{ duration: 0.7 }}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const mapState = () => null;
|
function Sun() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="5"></circle>
|
||||||
|
<motion.g
|
||||||
|
initial={{ scale: 0.8 }}
|
||||||
|
animate={{ scale: 1 }}
|
||||||
|
transition={{ duration: 0.7 }}
|
||||||
|
>
|
||||||
|
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||||||
|
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||||||
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||||||
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||||||
|
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||||||
|
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||||||
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||||||
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||||||
|
</motion.g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapState = s => ({ theme: getTheme(s) });
|
||||||
export default connect(mapState)(SideBar);
|
export default connect(mapState)(SideBar);
|
||||||
|
|
|
@ -96,24 +96,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.themeSwitchContainer {
|
.themeSwitchContainer {
|
||||||
--sz: 50px;
|
--sz: 40px;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 10px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: var(--sz);
|
width: var(--sz);
|
||||||
height: var(--sz);
|
height: var(--sz);
|
||||||
padding: 20px 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
svg {
|
|
||||||
display: block;
|
color: var(--color-text);
|
||||||
color: var(--color-icon);
|
|
||||||
|
padding: 5px;
|
||||||
|
appearance: none;
|
||||||
|
outline: none;
|
||||||
|
user-select: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 100%;
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--color-focus-blue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue