feishin/src/renderer/features/sidebar/components/collapsed-sidebar-item.tsx

107 lines
2.8 KiB
TypeScript
Raw Normal View History

import { createPolymorphicComponent, Flex } from '@mantine/core';
import { motion } from 'framer-motion';
2023-09-15 20:42:38 -07:00
import { forwardRef, ReactNode } from 'react';
2023-06-01 20:08:43 -07:00
import { useMatch } from 'react-router';
import styled from 'styled-components';
import { Text } from '/@/renderer/components';
const Container = styled(Flex)<{ $active?: boolean; $disabled?: boolean }>`
2023-07-01 19:10:05 -07:00
position: relative;
width: 100%;
padding: 0.9rem 0.3rem;
2023-09-15 20:42:38 -07:00
pointer-events: ${(props) => (props.$disabled ? 'none' : 'all')};
2023-07-01 19:10:05 -07:00
cursor: ${(props) => (props.$disabled ? 'default' : 'pointer')};
user-select: ${(props) => (props.$disabled ? 'none' : 'initial')};
2023-09-15 20:42:38 -07:00
border-right: var(--sidebar-border);
opacity: ${(props) => props.$disabled && 0.6};
2023-07-01 19:10:05 -07:00
svg {
fill: ${(props) => (props.$active ? 'var(--primary-color)' : 'var(--sidebar-fg)')};
}
2023-07-01 19:10:05 -07:00
&:focus-visible {
background-color: var(--sidebar-bg-hover);
outline: none;
}
2023-07-01 19:10:05 -07:00
${(props) =>
!props.$disabled &&
`
&:hover {
background-color: var(--sidebar-bg-hover);
div {
color: var(--main-fg) !important;
}
svg {
fill: var(--primary-color);
}
}
`}
`;
const TextWrapper = styled.div`
2023-07-01 19:10:05 -07:00
width: 100%;
overflow: hidden;
text-align: center;
text-overflow: ellipsis;
2023-09-15 20:42:38 -07:00
white-space: nowrap;
`;
const ActiveTabIndicator = styled(motion.div)`
2023-07-01 19:10:05 -07:00
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 3px;
width: 2px;
height: 80%;
margin-top: auto;
margin-bottom: auto;
background: var(--primary-color);
`;
interface CollapsedSidebarItemProps {
2023-09-15 20:42:38 -07:00
activeIcon: ReactNode;
2023-07-01 19:10:05 -07:00
disabled?: boolean;
2023-09-15 20:42:38 -07:00
icon: ReactNode;
2023-07-01 19:10:05 -07:00
label: string;
route?: string;
}
const _CollapsedSidebarItem = forwardRef<HTMLDivElement, CollapsedSidebarItemProps>(
2023-07-01 19:10:05 -07:00
({ route, activeIcon, icon, label, disabled, ...props }: CollapsedSidebarItemProps, ref) => {
const match = useMatch(route || '/null');
const isMatch = Boolean(match);
2023-06-01 20:08:43 -07:00
2023-07-01 19:10:05 -07:00
return (
<Container
ref={ref}
$active={Boolean(match)}
$disabled={disabled}
align="center"
direction="column"
{...props}
>
{isMatch ? <ActiveTabIndicator /> : null}
{isMatch ? activeIcon : icon}
<TextWrapper>
<Text
$secondary={!isMatch}
fw="600"
overflow="hidden"
size="xs"
>
{label}
</Text>
</TextWrapper>
</Container>
);
},
);
export const CollapsedSidebarItem = createPolymorphicComponent<'button', CollapsedSidebarItemProps>(
2023-07-01 19:10:05 -07:00
_CollapsedSidebarItem,
);