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