1import { css } from '@emotion/react'; 2import { 3 ArrowRightIcon, 4 ArrowUpRightIcon, 5 borderRadius, 6 breakpoints, 7 iconSize, 8 palette, 9 shadows, 10 spacing, 11 theme, 12 typography, 13} from '@expo/styleguide'; 14import { PropsWithChildren } from 'react'; 15import { Col, ColProps } from 'react-grid-system'; 16 17import { A, P } from '~/ui/components/Text'; 18 19const CustomCol = ({ children, sm, md, lg, xl, xxl }: PropsWithChildren<ColProps>) => ( 20 <> 21 <Col css={cellWrapperStyle} sm={sm} md={md} lg={lg} xl={xl} xxl={xxl}> 22 {children} 23 </Col> 24 <div css={mobileCellWrapperStyle}>{children}</div> 25 </> 26); 27 28export const GridCell = ({ 29 children, 30 sm, 31 md, 32 lg, 33 xl, 34 xxl, 35 className, 36}: PropsWithChildren<ColProps>) => ( 37 <CustomCol css={cellWrapperStyle} sm={sm} md={md} lg={lg} xl={xl} xxl={xxl}> 38 <div css={cellStyle} className={className}> 39 {children} 40 </div> 41 </CustomCol> 42); 43 44type APIGridCellProps = ColProps & { 45 icon?: string | JSX.Element; 46 title?: string; 47 link?: string; 48}; 49 50export const APIGridCell = ({ 51 icon, 52 title, 53 link, 54 className, 55 sm = 6, 56 md = 6, 57 lg = 6, 58 xl = 3, 59}: APIGridCellProps) => ( 60 <CustomCol css={cellWrapperStyle} md={md} sm={sm} lg={lg} xl={xl}> 61 <A href={link} css={[cellStyle, cellAPIStyle, cellHoverStyle]} className={className}> 62 <div css={cellIconWrapperStyle}>{icon}</div> 63 <div css={cellTitleWrapperStyle}> 64 {title} 65 <ArrowRightIcon color={theme.icon.secondary} /> 66 </div> 67 </A> 68 </CustomCol> 69); 70 71type CommunityGridCellProps = APIGridCellProps & { 72 description?: string; 73 iconBackground?: string; 74}; 75 76export const CommunityGridCell = ({ 77 icon, 78 iconBackground = palette.light.gray['800'], 79 title, 80 link, 81 description, 82 className, 83 md = 6, 84}: CommunityGridCellProps) => ( 85 <CustomCol css={cellWrapperStyle} md={md}> 86 <a 87 href={link} 88 css={[cellStyle, cellCommunityStyle, cellCommunityHoverStyle]} 89 className={className}> 90 <div css={[cellCommunityIconWrapperStyle, css({ backgroundColor: iconBackground })]}> 91 {icon} 92 </div> 93 <div css={cellCommunityContentStyle}> 94 <span css={cellCommunityTitleStyle}>{title}</span> 95 <P css={cellCommunityDescriptionStyle}>{description}</P> 96 </div> 97 <ArrowUpRightIcon color={theme.icon.secondary} css={cellCommunityLinkIconStyle} /> 98 </a> 99 </CustomCol> 100); 101 102const cellWrapperStyle = css` 103 padding-left: 0 !important; 104 padding-right: 0 !important; 105 106 @media screen and (max-width: ${breakpoints.medium}px) { 107 display: none; 108 } 109`; 110 111const mobileCellWrapperStyle = css({ 112 width: '100%', 113 114 [`@media screen and (min-width: ${breakpoints.medium}px)`]: { 115 display: 'none', 116 }, 117}); 118 119const cellHoverStyle = css` 120 & { 121 transition: box-shadow 200ms; 122 123 svg { 124 transition: transform 200ms; 125 } 126 } 127 128 &:hover { 129 box-shadow: ${shadows.tiny}; 130 131 svg { 132 transform: scale(1.05); 133 } 134 135 svg[role='img'] { 136 transform: none; 137 } 138 } 139`; 140 141const cellStyle = css({ 142 margin: spacing[4], 143 padding: spacing[8], 144 minHeight: 200, 145 overflow: 'hidden', 146 position: 'relative', 147 borderWidth: 1, 148 borderStyle: 'solid', 149 borderColor: theme.border.default, 150 borderRadius: borderRadius.large, 151}); 152 153const cellAPIStyle = css({ 154 display: 'block', 155 backgroundColor: theme.background.secondary, 156 padding: 0, 157 overflow: 'hidden', 158 textDecoration: 'none', 159}); 160 161const cellIconWrapperStyle = css({ 162 display: 'flex', 163 minHeight: 136, 164 justifyContent: 'space-around', 165 alignItems: 'center', 166}); 167 168const cellTitleWrapperStyle = css({ 169 ...typography.fontSizes[15], 170 display: 'flex', 171 justifyContent: 'space-between', 172 backgroundColor: theme.background.default, 173 padding: spacing[4], 174 textDecoration: 'none', 175 fontFamily: typography.fontStacks.medium, 176 lineHeight: '30px', 177 color: theme.text.default, 178 alignItems: 'center', 179}); 180 181const cellCommunityStyle = css({ 182 display: 'flex', 183 minHeight: `calc(100% - (2 * ${spacing[3]}px}))`, 184 padding: spacing[4], 185 margin: `${spacing[3]}px ${spacing[4]}px`, 186 flexDirection: 'row', 187 textDecoration: 'none', 188}); 189 190const cellCommunityIconWrapperStyle = css({ 191 height: 48, 192 width: 48, 193 minWidth: 48, 194 display: 'flex', 195 justifyContent: 'center', 196 alignItems: 'center', 197 borderRadius: borderRadius.large, 198 marginRight: spacing[3], 199}); 200 201const cellCommunityContentStyle = css({ 202 flexGrow: 1, 203}); 204 205const cellCommunityTitleStyle = css({ 206 ...typography.fontSizes[16], 207 fontFamily: typography.fontStacks.medium, 208 color: theme.text.default, 209 textDecoration: 'none', 210 marginBottom: spacing[2], 211}); 212 213const cellCommunityDescriptionStyle = css({ 214 ...typography.fontSizes[14], 215 color: theme.text.secondary, 216}); 217 218const cellCommunityLinkIconStyle = css({ 219 marginLeft: spacing[1.5], 220 alignSelf: 'center', 221 minWidth: iconSize.regular, 222}); 223 224const cellCommunityHoverStyle = css` 225 & { 226 transition: box-shadow 200ms; 227 228 svg { 229 transition: transform 200ms; 230 } 231 } 232 233 &:hover { 234 box-shadow: ${shadows.tiny}; 235 236 svg { 237 transform: scale(1.075); 238 } 239 } 240`; 241