1import { css } from '@emotion/react';
2import { shadows, theme } from '@expo/styleguide';
3import { borderRadius, breakpoints, spacing } from '@expo/styleguide-base';
4
5import { Icon } from './Icon';
6
7import { A, CALLOUT, RawH4 } from '~/ui/components/Text';
8
9type GridItemProps = React.PropsWithChildren<{
10  title: string;
11  image?: string;
12  href?: string;
13  protocol: string[];
14}>;
15
16export const GridItem = ({
17  title,
18  image,
19  protocol = [],
20  href = `#${title.toLowerCase().replaceAll(' ', '-')}`,
21}: GridItemProps) => (
22  <A href={href} css={itemStyle} isStyled>
23    <Icon title={title} image={image} />
24    <RawH4 css={titleStyle}>{title}</RawH4>
25    {(protocol || []).length && (
26      <CALLOUT theme="secondary" css={protocolStyle}>
27        {protocol.join(' | ')}
28      </CALLOUT>
29    )}
30  </A>
31);
32
33const protocolStyle = css({
34  opacity: 0,
35  transform: `translateY(4px)`,
36  transitionProperty: 'all',
37  transitionDuration: '0.15s',
38  textAlign: 'center',
39});
40
41const titleStyle = css({
42  marginTop: spacing[2],
43  textAlign: 'center',
44});
45
46const itemStyle = css({
47  display: 'flex',
48  flexDirection: 'column',
49  justifyContent: 'center',
50  alignItems: 'center',
51  padding: spacing[6],
52  gap: spacing[2],
53  textDecoration: 'none',
54  borderRadius: borderRadius.sm,
55  transition: 'box-shadow 0.15s ease 0s, transform 0.15s ease 0s',
56  boxShadow: shadows.xs,
57  border: `1px solid ${theme.border.default}`,
58
59  ':hover': {
60    boxShadow: shadows.md,
61    transform: 'scale(1.05)',
62
63    p: {
64      opacity: 0.75,
65      transform: 'translateY(0)',
66    },
67  },
68
69  [`@media screen and (max-width: ${(breakpoints.medium + breakpoints.large) / 2}px)`]: {
70    p: {
71      opacity: 0.75,
72    },
73  },
74});
75