feat(ui): animate sidebar icons on hover
This commit is contained in:
@@ -13,6 +13,83 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navIcon {
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.drawStroke {
|
||||
stroke-dasharray: 1;
|
||||
}
|
||||
|
||||
.topSlider {
|
||||
--slider-offset: -3px;
|
||||
}
|
||||
|
||||
.bottomSlider {
|
||||
--slider-offset: 3px;
|
||||
}
|
||||
|
||||
.navLink:focus-visible {
|
||||
.portfolioIcon {
|
||||
animation: portfolio-sway 650ms ease-in-out;
|
||||
}
|
||||
.drawStroke {
|
||||
animation: stroke-draw 650ms ease-in-out;
|
||||
}
|
||||
:is(.topSlider, .bottomSlider) {
|
||||
animation: slider-slide 650ms ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.navLink:hover {
|
||||
.portfolioIcon {
|
||||
animation: portfolio-sway 650ms ease-in-out;
|
||||
}
|
||||
.drawStroke {
|
||||
animation: stroke-draw 650ms ease-in-out;
|
||||
}
|
||||
:is(.topSlider, .bottomSlider) {
|
||||
animation: slider-slide 650ms ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes portfolio-sway {
|
||||
0%,
|
||||
100% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
30% {
|
||||
transform: translateY(-1px) rotate(-10deg);
|
||||
}
|
||||
65% {
|
||||
transform: rotate(7deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes stroke-draw {
|
||||
0% {
|
||||
stroke-dashoffset: 1;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slider-slide {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(var(--slider-offset));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 47.99375em) {
|
||||
.bottomNav {
|
||||
background: var(--mantine-color-white);
|
||||
|
||||
+46
-16
@@ -16,6 +16,7 @@ const AppShell: FC<AppShellProps> = (props) => {
|
||||
{
|
||||
to: "/accounts",
|
||||
label: t("navigation.accounts"),
|
||||
iconClassName: classes.portfolioIcon,
|
||||
icon: (
|
||||
<path d="M8 6V4h8v2M3 10h18M9 10v3h6v-3M5 6h14a2 2 0 0 1 2 2v11H3V8a2 2 0 0 1 2-2Z" />
|
||||
),
|
||||
@@ -23,18 +24,42 @@ const AppShell: FC<AppShellProps> = (props) => {
|
||||
{
|
||||
to: "/stocks",
|
||||
label: t("navigation.stocks"),
|
||||
icon: <path d="M3 3v18h18M7 14l5-5 4 3 5-7M16 5h5v5" />,
|
||||
icon: (
|
||||
<>
|
||||
<path d="M3 3v18h18" />
|
||||
<path
|
||||
className={classes.drawStroke}
|
||||
pathLength={1}
|
||||
d="M7 14l5-5 4 3 5-7M16 5h5v5"
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
to: "/bonds",
|
||||
label: t("navigation.bonds"),
|
||||
icon: <path d="M6 3h12v18l-3-2-3 2-3-2-3 2V3ZM9 7h6M9 11h6M9 15h3" />,
|
||||
icon: (
|
||||
<>
|
||||
<path d="M6 3h12v18l-3-2-3 2-3-2-3 2V3Z" />
|
||||
<path
|
||||
className={classes.drawStroke}
|
||||
pathLength={1}
|
||||
d="M9 7h6M9 11h6M9 15h3"
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
to: "/settings",
|
||||
label: t("navigation.settings"),
|
||||
icon: (
|
||||
<path d="M4 7h9m4 0h3M4 17h3m4 0h9M13 4v6h4V4h-4ZM7 14v6h4v-6H7Z" />
|
||||
<>
|
||||
<path className={classes.topSlider} d="M4 7h9m4 0h3M13 4v6h4V4h-4Z" />
|
||||
<path
|
||||
className={classes.bottomSlider}
|
||||
d="M4 17h3m4 0h9M7 14v6h4v-6H7Z"
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
@@ -52,24 +77,29 @@ const AppShell: FC<AppShellProps> = (props) => {
|
||||
{items.map((item) => (
|
||||
<NavLink
|
||||
component={RouterNavLink}
|
||||
className={classes.navLink}
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
label={item.label}
|
||||
leftSection={
|
||||
<svg
|
||||
width={20}
|
||||
height={20}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
<span
|
||||
className={`${classes.navIcon} ${item.iconClassName ?? ""}`}
|
||||
>
|
||||
{item.icon}
|
||||
</svg>
|
||||
<svg
|
||||
width={20}
|
||||
height={20}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
{item.icon}
|
||||
</svg>
|
||||
</span>
|
||||
}
|
||||
active={pathname.startsWith(item.to)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user