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} isStyled> 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.gray11, 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 isStyled> 91 <div css={[cellCommunityIconWrapperStyle, css({ backgroundColor: iconBackground })]}> 92 {icon} 93 </div> 94 <div css={cellCommunityContentStyle}> 95 <span css={cellCommunityTitleStyle}>{title}</span> 96 <P css={cellCommunityDescriptionStyle}>{description}</P> 97 </div> 98 <ArrowUpRightIcon color={theme.icon.secondary} css={cellCommunityLinkIconStyle} /> 99 </A> 100 </CustomCol> 101); 102 103const cellWrapperStyle = css` 104 padding-left: 0 !important; 105 padding-right: 0 !important; 106 107 @media screen and (max-width: ${breakpoints.medium}px) { 108 display: none; 109 } 110`; 111 112const mobileCellWrapperStyle = css({ 113 width: '100%', 114 115 [`@media screen and (min-width: ${breakpoints.medium}px)`]: { 116 display: 'none', 117 }, 118}); 119 120const cellHoverStyle = css` 121 & { 122 transition: box-shadow 200ms; 123 124 svg { 125 transition: transform 200ms; 126 } 127 } 128 129 &:hover { 130 box-shadow: ${shadows.sm}; 131 132 svg { 133 transform: scale(1.05); 134 } 135 136 svg[role='img'] { 137 transform: none; 138 } 139 } 140`; 141 142const cellStyle = css({ 143 margin: spacing[4], 144 padding: spacing[8], 145 minHeight: 200, 146 overflow: 'hidden', 147 position: 'relative', 148 borderWidth: 1, 149 borderStyle: 'solid', 150 borderColor: theme.border.default, 151 borderRadius: borderRadius.lg, 152 153 h2: { 154 marginTop: 0, 155 marginBottom: 0, 156 }, 157 158 h3: { 159 marginTop: 0, 160 }, 161}); 162 163const cellAPIStyle = css({ 164 display: 'block', 165 backgroundColor: theme.background.subtle, 166 padding: 0, 167 overflow: 'hidden', 168 textDecoration: 'none', 169}); 170 171const cellIconWrapperStyle = css({ 172 display: 'flex', 173 minHeight: 136, 174 justifyContent: 'space-around', 175 alignItems: 'center', 176}); 177 178const cellTitleWrapperStyle = css({ 179 ...typography.fontSizes[15], 180 display: 'flex', 181 justifyContent: 'space-between', 182 backgroundColor: theme.background.default, 183 padding: spacing[4], 184 textDecoration: 'none', 185 fontWeight: 500, 186 lineHeight: '30px', 187 color: theme.text.default, 188 alignItems: 'center', 189}); 190 191const cellCommunityStyle = css({ 192 display: 'flex', 193 minHeight: `calc(100% - (2 * ${spacing[3]}px}))`, 194 padding: spacing[4], 195 margin: `${spacing[3]}px ${spacing[4]}px`, 196 flexDirection: 'row', 197 textDecoration: 'none', 198}); 199 200const cellCommunityIconWrapperStyle = css({ 201 height: 48, 202 width: 48, 203 minWidth: 48, 204 display: 'flex', 205 justifyContent: 'center', 206 alignItems: 'center', 207 borderRadius: borderRadius.lg, 208 marginRight: spacing[3], 209}); 210 211const cellCommunityContentStyle = css({ 212 flexGrow: 1, 213}); 214 215const cellCommunityTitleStyle = css({ 216 ...typography.fontSizes[16], 217 fontWeight: 500, 218 color: theme.text.default, 219 textDecoration: 'none', 220 marginBottom: spacing[2], 221}); 222 223const cellCommunityDescriptionStyle = css({ 224 ...typography.fontSizes[14], 225 color: theme.text.secondary, 226}); 227 228const cellCommunityLinkIconStyle = css({ 229 marginLeft: spacing[1.5], 230 alignSelf: 'center', 231 minWidth: iconSize.md, 232}); 233 234const cellCommunityHoverStyle = css` 235 & { 236 transition: box-shadow 200ms; 237 238 svg { 239 transition: transform 200ms; 240 } 241 } 242 243 &:hover { 244 box-shadow: ${shadows.sm}; 245 246 svg { 247 transform: scale(1.075); 248 } 249 } 250`; 251