1import { css } from '@emotion/react';
2import { StatusFailedIcon, StatusSuccessIcon, StatusWaitingIcon, theme } from '@expo/styleguide';
3import * as React from 'react';
4
5import { H4 } from '~/components/base/headings';
6import { ElementType } from '~/types/common';
7import { Cell, HeaderCell, Row, Table, TableHead, TableLayout } from '~/ui/components/Table';
8
9const STYLES_TITLE = css`
10  margin-bottom: 1rem;
11`;
12
13const STYLES_LINK = css`
14  text-decoration: none;
15  display: grid;
16  grid-template-columns: 20px auto;
17  text-align: left;
18  grid-gap: 8px;
19  color: ${theme.link.default};
20`;
21
22const platforms = [
23  { title: 'Android Device', propName: 'android' },
24  { title: 'Android Emulator', propName: 'emulator' },
25  { title: 'iOS Device', propName: 'ios' },
26  { title: 'iOS Simulator', propName: 'simulator' },
27  { title: 'Web', propName: 'web' },
28];
29
30type Platform = ElementType<typeof platforms>;
31type IsSupported = boolean | undefined | { pending: string };
32
33function getInfo(isSupported: IsSupported, { title }: Platform) {
34  if (isSupported === true) {
35    return {
36      children: <StatusSuccessIcon color={theme.status.success} />,
37      title: `${title} is supported`,
38    };
39  } else if (typeof isSupported === 'object') {
40    return {
41      children: (
42        <a css={STYLES_LINK} target="_blank" href={isSupported.pending}>
43          <StatusWaitingIcon color={theme.status.info} /> Pending
44        </a>
45      ),
46      title: `${title} support is pending`,
47    };
48  }
49
50  return {
51    children: <StatusFailedIcon color={theme.status.error} />,
52    title: `${title} is not supported`,
53  };
54}
55
56type Props = {
57  title?: string;
58  ios?: boolean;
59  android?: boolean;
60  web?: boolean;
61  simulator?: boolean;
62  emulator?: boolean;
63};
64
65type PlatformProps = Omit<Props, 'title'>;
66
67const PlatformsSection = (props: Props) => (
68  <>
69    <H4 css={STYLES_TITLE}>{props.title || 'Platform Compatibility'}</H4>
70    <Table layout={TableLayout.Fixed}>
71      <TableHead>
72        <Row>
73          {platforms.map(({ title }) => (
74            <HeaderCell key={title}>{title}</HeaderCell>
75          ))}
76        </Row>
77      </TableHead>
78      <tbody>
79        <Row>
80          {platforms.map(platform => (
81            <Cell
82              key={platform.title}
83              {...getInfo(props[platform.propName as keyof PlatformProps], platform)}
84            />
85          ))}
86        </Row>
87      </tbody>
88    </Table>
89  </>
90);
91
92export default PlatformsSection;
93