Files
Homarr/src/components/AppShelf/AppShelf.tsx

107 lines
2.9 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
2022-04-25 23:33:32 +02:00
import { motion } from 'framer-motion';
import { Text, AspectRatio, Card, Image, Center, Grid, createStyles } from '@mantine/core';
import { useConfig } from '../../tools/state';
import { serviceItem } from '../../tools/types';
2022-05-10 19:02:16 +02:00
import AppShelfMenu from './AppShelfMenu';
import PingComponent from '../modules/ping/PingModule';
2022-04-25 00:11:32 +02:00
2022-05-17 01:43:40 +02:00
const useStyles = createStyles((theme) => ({
item: {
transition: 'box-shadow 150ms ease, transform 100ms ease',
'&:hover': {
boxShadow: `${theme.shadows.md} !important`,
transform: 'scale(1.05)',
},
},
}));
2022-05-16 15:55:22 +02:00
const AppShelf = (props: any) => {
const { config } = useConfig();
2022-04-25 00:11:32 +02:00
return (
<Grid gutter="xl" align="center">
{config.services.map((service) => (
2022-05-19 22:29:35 +02:00
<Grid.Col key={service.id} span={6} xl={2} xs={4} sm={3} md={3}>
<AppShelfItem key={service.id} service={service} />
</Grid.Col>
2022-05-04 07:12:22 +02:00
))}
</Grid>
2022-05-04 07:12:22 +02:00
);
};
export function AppShelfItem(props: any) {
const { service }: { service: serviceItem } = props;
const [hovering, setHovering] = useState(false);
2022-05-17 01:43:40 +02:00
const { classes, theme } = useStyles();
2022-05-04 07:12:22 +02:00
return (
<motion.div
animate={{
scale: [0.9, 1.06, 1],
rotate: [0, 5, 0],
}}
2022-05-18 23:12:34 +02:00
transition={{ duration: 0.6, type: 'spring', damping: 10, mass: 0.75, stiffness: 100 }}
2022-05-04 07:49:29 +02:00
key={service.name}
onHoverStart={() => {
2022-05-04 07:12:22 +02:00
setHovering(true);
}}
onHoverEnd={() => {
2022-05-04 07:12:22 +02:00
setHovering(false);
}}
>
2022-05-17 01:43:40 +02:00
<Card withBorder radius="lg" shadow="md" className={classes.item}>
2022-05-04 07:12:22 +02:00
<Card.Section>
2022-05-16 22:48:29 +02:00
<Text mt="sm" align="center" lineClamp={1} weight={550}>
2022-05-14 11:40:05 +02:00
{service.name}
</Text>
<motion.div
style={{
position: 'absolute',
top: 15,
right: 15,
alignSelf: 'flex-end',
}}
animate={{
opacity: hovering ? 1 : 0,
}}
>
<AppShelfMenu service={service} />
</motion.div>
2022-05-04 07:12:22 +02:00
</Card.Section>
<Center>
<Card.Section>
<AspectRatio
ratio={3 / 5}
m="xl"
style={{
width: 150,
height: 90,
2022-05-04 07:12:22 +02:00
}}
>
<motion.i
whileHover={{
cursor: 'pointer',
scale: 1.1,
2022-05-04 07:12:22 +02:00
}}
>
<Image
width={80}
height={80}
src={service.icon}
fit="contain"
onClick={() => {
window.open(service.url);
}}
/>
</motion.i>
</AspectRatio>
<PingComponent url={service.url} />
</Card.Section>
</Center>
</Card>
2022-05-04 07:12:22 +02:00
</motion.div>
2022-04-25 00:11:32 +02:00
);
2022-05-04 07:12:22 +02:00
}
2022-04-25 00:11:32 +02:00
2022-04-27 03:11:35 +02:00
export default AppShelf;