feat: recreate collection list/item

This commit is contained in:
Sonny
2024-11-03 18:38:11 +01:00
committed by Sonny
parent d796e4d38a
commit c7c70b1767
6 changed files with 192 additions and 2 deletions

View File

@@ -54,7 +54,7 @@ function LinkItemURL({ url }: { url: Link['url'] }) {
}
return (
<Text className={styles.linkUrl} color="gray" size="xs" lineClamp={1}>
<Text className={styles.linkUrl} c="gray" size="xs" lineClamp={1}>
{origin}
<span className={styles.linkUrlPathname}>{text}</span>
</Text>
@@ -62,7 +62,7 @@ function LinkItemURL({ url }: { url: Link['url'] }) {
} catch (error) {
console.error('error', error);
return (
<Text className={styles.linkUrl} color="gray" size="xs" lineClamp={1}>
<Text className={styles.linkUrl} c="gray" size="xs" lineClamp={1}>
{url}
</Text>
);

View File

@@ -0,0 +1,44 @@
.link {
width: 100%;
max-width: 100%;
display: flex;
align-items: center;
text-decoration: none;
font-size: var(--mantine-font-size-sm);
color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm);
border-radius: var(--mantine-radius-sm);
font-weight: 500;
@mixin hover {
background-color: light-dark(
var(--mantine-color-gray-0),
var(--mantine-color-dark-6)
);
color: light-dark(var(--mantine-color-black), var(--mantine-color-white));
.linkIcon {
color: light-dark(var(--mantine-color-black), var(--mantine-color-white));
}
}
&[data-active] {
&,
&:hover {
background-color: var(--mantine-color-blue-light);
color: var(--mantine-color-blue-light-color);
.linkIcon {
color: var(--mantine-color-blue-light-color);
}
}
}
}
.linkIcon {
color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2));
margin-right: var(--mantine-spacing-sm);
width: rem(25px);
height: rem(25px);
min-width: rem(25px);
}

View File

@@ -0,0 +1,47 @@
import { Link } from '@inertiajs/react';
import { route } from '@izzyjs/route/client';
import { Text } from '@mantine/core';
import { useEffect, useRef } from 'react';
import { AiFillFolderOpen, AiOutlineFolder } from 'react-icons/ai';
import useActiveCollection from '~/hooks/use_active_collection';
import { appendCollectionId } from '~/lib/navigation';
import { CollectionWithLinks } from '~/types/app';
import classes from './collection_item.module.css';
export default function CollectionItem({
collection,
}: {
collection: CollectionWithLinks;
}) {
const itemRef = useRef<HTMLAnchorElement>(null);
const { activeCollection } = useActiveCollection();
const isActiveCollection = collection.id === activeCollection?.id;
const FolderIcon = isActiveCollection ? AiFillFolderOpen : AiOutlineFolder;
useEffect(() => {
if (collection.id === activeCollection?.id) {
itemRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}, [collection.id, activeCollection?.id]);
const linksCount = activeCollection?.links.length ?? 0;
return (
<Link
className={classes.link}
data-active={isActiveCollection || undefined}
href={appendCollectionId(route('dashboard').path, collection.id)}
key={collection.id}
ref={itemRef}
>
<FolderIcon className={classes.linkIcon} />
<Text lineClamp={1} maw="160px">
{collection.name}
</Text>
{linksCount > 0 && (
<Text c="var(--mantine-color-gray-5)" ml="xs">
{linksCount}
</Text>
)}
</Link>
);
}

View File

@@ -0,0 +1,24 @@
.sideMenu {
height: 100%;
width: 100%;
display: flex;
gap: 0.35em;
flex-direction: column;
}
.listContainer {
height: 100%;
min-height: 0;
display: flex;
flex-direction: column;
}
.collectionList {
padding: 1px;
padding-right: 5px;
display: flex;
flex: 1;
gap: 0.35em;
flex-direction: column;
overflow: auto;
}

View File

@@ -0,0 +1,56 @@
import { Box, ScrollArea, Text } from '@mantine/core';
import { useTranslation } from 'react-i18next';
import useActiveCollection from '~/hooks/use_active_collection';
import useCollections from '~/hooks/use_collections';
import useShortcut from '~/hooks/use_shortcut';
import CollectionItem from '~/mantine/components/dashboard/collection/item/collection_item';
import styles from './collection_list.module.css';
export default function CollectionList() {
const { t } = useTranslation('common');
const { collections } = useCollections();
const { activeCollection, setActiveCollection } = useActiveCollection();
const goToPreviousCollection = () => {
const currentCategoryIndex = collections.findIndex(
({ id }) => id === activeCollection?.id
);
if (currentCategoryIndex === -1 || currentCategoryIndex === 0) return;
setActiveCollection(collections[currentCategoryIndex - 1]);
};
const goToNextCollection = () => {
const currentCategoryIndex = collections.findIndex(
({ id }) => id === activeCollection?.id
);
if (
currentCategoryIndex === -1 ||
currentCategoryIndex === collections.length - 1
)
return;
setActiveCollection(collections[currentCategoryIndex + 1]);
};
useShortcut('ARROW_UP', goToPreviousCollection);
useShortcut('ARROW_DOWN', goToNextCollection);
return (
<Box className={styles.sideMenu}>
<Box className={styles.listContainer}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Text c="dimmed" ml="md" mb="sm">
{t('collection.collections', { count: collections.length })} {' '}
{collections.length}
</Text>
<ScrollArea className={styles.collectionList}>
{collections.map((collection) => (
<CollectionItem collection={collection} key={collection.id} />
))}
</ScrollArea>
</div>
</Box>
</Box>
);
}

View File

@@ -0,0 +1,19 @@
import { AppShell, Burger, Group, ScrollArea, Text } from '@mantine/core';
import CollectionList from '~/mantine/components/dashboard/collection/list/collection_list';
interface DashboardAsideProps {
isOpen: boolean;
toggle: () => void;
}
export const DashboardAside = ({ isOpen, toggle }: DashboardAsideProps) => (
<AppShell.Aside p="md">
<Group justify="space-between" hiddenFrom="md" mb="md">
<Text>Collections</Text>
<Burger opened={isOpen} onClick={toggle} hiddenFrom="md" size="md" />
</Group>
<AppShell.Section grow component={ScrollArea}>
<CollectionList />
</AppShell.Section>
</AppShell.Aside>
);