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