Skip to content

Commit

Permalink
Next.js PR 4: Implement the component overview page in Next.js (#873)
Browse files Browse the repository at this point in the history
  • Loading branch information
danoc authored Jan 11, 2023
1 parent 61bb6fa commit ccd3a34
Show file tree
Hide file tree
Showing 9 changed files with 495 additions and 4 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,13 @@ module.exports = {
],
},
},
{
files: ['next/pages/**/*.tsx'],
rules: {
// We can use Next.js's `InferGetStaticPropsType` rather than specifying the return
// type manually.
'@typescript-eslint/explicit-function-return-type': 'off',
},
},
],
};
6 changes: 6 additions & 0 deletions next/components/alert/alert.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@import '~@thumbtack/thumbprint-tokens/dist/scss/_index';

.children a {
color: $tp-color__black-300;
border-bottom: 1px solid $tp-color__gray;
}
50 changes: 50 additions & 0 deletions next/components/alert/alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import classNames from 'classnames';
import { Text } from '@thumbtack/thumbprint-react';
import {
NotificationAlertsInfoFilledSmall,
NotificationAlertsWarningFilledSmall,
} from '@thumbtack/thumbprint-icons';
import styles from './alert.module.scss';

const alertStyles = {
boxShadow: '0 2px 4px rgba(0,0,0,.1)',
maxWidth: '580px',
};

const iconStyles = 'db relative -top-2';

interface PropTypes {
title: React.ReactNode;
children: React.ReactNode;
type: 'warning' | 'note';
}

export default function Alert({ type, title, children }: PropTypes): JSX.Element {
return (
<div
className={classNames(`pv3 ph4 pr2 bt bw-3 br1 br--bottom relative mb5 `, {
'b-green': type === 'note',
'b-yellow': type === 'warning',
})}
style={alertStyles}
>
<div className="flex items-center">
<div className="mr2">
{type === 'note' && (
<NotificationAlertsInfoFilledSmall className={`green ${iconStyles}`} />
)}
{type === 'warning' && (
<NotificationAlertsWarningFilledSmall className={`yellow ${iconStyles}`} />
)}
</div>
<Text size={1} className="b black mb1">
{title}
</Text>
</div>
<Text size={2} className={`black-300 ${styles.children}`}>
{children}
</Text>
</div>
);
}
21 changes: 17 additions & 4 deletions next/components/mdx/mdx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,25 +255,38 @@ export function getStaticProps(): { props: { layoutProps: LayoutProps } } {
};
}

interface MdxPropTypes {
interface ContentPageProps {
children: React.ReactNode;
title: string;
description?: string;
layoutProps: LayoutProps;
}

export default function MDX({
export const ContentPage = ({
children,
title,
description,
layoutProps,
}: MdxPropTypes): JSX.Element {
}: ContentPageProps): JSX.Element => {
return (
<Layout {...layoutProps}>
<Wrap>
<PageHeader pageTitle={title} metaTitle={title} description={description} />
<MDXRenderer>{children}</MDXRenderer>
{children}
</Wrap>
</Layout>
);
};

export default function MDX({
children,
title,
description,
layoutProps,
}: ContentPageProps): JSX.Element {
return (
<ContentPage title={title} description={description} layoutProps={layoutProps}>
<MDXRenderer>{children}</MDXRenderer>
</ContentPage>
);
}
197 changes: 197 additions & 0 deletions next/components/thumbprint-components/overview/overview.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/* eslint-disable import/prefer-default-export */
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Text } from '@thumbtack/thumbprint-react';
import { tpColorGray300 } from '@thumbtack/thumbprint-tokens';
import styles from './overview.module.scss';

const documentationStatuses = ['Unknown', 'To-do', 'In progress', 'Done', "Done / Won't do"];
const documentationStatusPropTypes = PropTypes.oneOf(documentationStatuses);

const developmentStatuses = [
'Unknown',
'To-do',
'In progress',
'Done',
'Done / Uses OS component',
"Done / Won't build",
'Done / Deprecated',
];
const developmentStatusPropTypes = PropTypes.oneOf(developmentStatuses);

const designStatuses = ['Unknown', 'To-do', 'In progress', 'Done', "Done / Won't do"];
const designStatusPropTypes = PropTypes.oneOf(designStatuses);

export const Dot = ({ status }) => (
<div
aria-label={status}
className={classNames({
[styles.dot]: true,
[styles.dotToDo]: ['To-do', 'Unknown'].includes(status),
[styles.dotInProgress]: status === 'In progress',
[styles.dotDeprecated]: status === 'Done / Deprecated',
[styles.dotNotApplicable]: ["Done / Won't build", "Done / Won't do"].includes(status),
[styles.dotDone]: ['Done', 'Done / Uses OS component'].includes(status),
})}
/>
);

Dot.propTypes = {
status: PropTypes.oneOf([...designStatuses, ...developmentStatuses, ...documentationStatuses])
.isRequired,
};

export const ComponentRow = ({ name, react, scss, ios, android }) => (
<>
<tr className="tl bb b-gray-300">
<th rowSpan={4} className="pr2 pv2 v-top bb b-gray-300 bw-2">
{name}
</th>
<th className="normal ph2 pv1">
<Text size={2}>React</Text>
</th>
<td className="pa2 tc">
<Dot status={react.design} />
</td>
<td className="pa2 tc">
<Dot status={react.development} />
</td>
<td className="pa2 tc">
<Dot status={react.documentation} />
</td>
</tr>
<tr className="bb b-gray-300 tl">
<th className="normal ph2 pv1">
<Text size={2}>SCSS</Text>
</th>
<td className="pa2 tc">
<Dot status={scss.design} />
</td>
<td className="pa2 tc">
<Dot status={scss.development} />
</td>
<td className="pa2 tc">
<Dot status={scss.documentation} />
</td>
</tr>
<tr className="bb b-gray-300 tl">
<th className="normal ph2 pv1">
<Text size={2}>iOS</Text>
</th>
<td className="pa2 tc">
<Dot status={ios.design} />
</td>
<td className="pa2 tc">
<Dot status={ios.development} />
</td>
<td className="pa2 tc">
<Dot status={ios.documentation} />
</td>
</tr>
<tr className="bb b-gray-300 bw-2 tl">
<th className="normal ph2 pv1">
<Text size={2}>Android</Text>
</th>
<td className="pa2 tc">
<Dot status={android.design} />
</td>
<td className="pa2 tc">
<Dot status={android.development} />
</td>
<td className="pa2 tc">
<Dot status={android.documentation} />
</td>
</tr>
</>
);

ComponentRow.propTypes = {
name: PropTypes.string.isRequired,
react: PropTypes.shape({
design: designStatusPropTypes.isRequired,
development: developmentStatusPropTypes.isRequired,
documentation: documentationStatusPropTypes.isRequired,
}).isRequired,
scss: PropTypes.shape({
design: designStatusPropTypes.isRequired,
development: developmentStatusPropTypes.isRequired,
documentation: documentationStatusPropTypes.isRequired,
}).isRequired,
ios: PropTypes.shape({
design: designStatusPropTypes.isRequired,
development: developmentStatusPropTypes.isRequired,
documentation: documentationStatusPropTypes.isRequired,
}).isRequired,
android: PropTypes.shape({
design: designStatusPropTypes.isRequired,
development: developmentStatusPropTypes.isRequired,
documentation: documentationStatusPropTypes.isRequired,
}).isRequired,
};

export const ComponentTable = ({ children }) => (
<table className="w-100">
<thead className="tl">
<tr>
{/*
The `boxShadow` is used instead of `border` because of:
https://stackoverflow.com/q/41882616/316602
*/}
<th
className="pt3 pr2 pb2 v-top top0 bg-white"
style={{
position: 'sticky',
boxShadow: `0px 2px 0px 0px ${tpColorGray300}`,
}}
>
<Text size={2}>Component</Text>
</th>
<th
className="pt3 ph2 pb2 v-top top0 bg-white"
style={{
position: 'sticky',
boxShadow: `0px 2px 0px 0px ${tpColorGray300}`,
}}
>
<Text size={2}>Platforms</Text>
</th>
<th
className="pt3 ph3 pb2 v-top top0 bg-white"
style={{
width: '1%',
position: 'sticky',
boxShadow: `0px 2px 0px 0px ${tpColorGray300}`,
}}
>
<Text size={2}>Design</Text>
</th>
<th
className="pt3 ph3 pb2 v-top top0 bg-white"
style={{
width: '1%',
position: 'sticky',
boxShadow: `0px 2px 0px 0px ${tpColorGray300}`,
}}
>
<Text size={2}>Development</Text>
</th>
<th
className="pt3 ph3 pb2 v-top top0 bg-white"
style={{
width: '1%',
position: 'sticky',
boxShadow: `0px 2px 0px 0px ${tpColorGray300}`,
}}
>
<Text size={2}>Documentation</Text>
</th>
</tr>
</thead>
<tbody>{children}</tbody>
</table>
);

ComponentTable.propTypes = {
children: PropTypes.node.isRequired,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@import '~@thumbtack/thumbprint-tokens/dist/scss/_index';

.dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
}

.dotDone {
background: $tp-color__green;
}

.dotInProgress {
border: 2px solid $tp-color__yellow;
}

.dotToDo {
border: 2px solid $tp-color__blue;
}

.dotNotApplicable {
background: $tp-color__gray;
}

.dotDeprecated {
background: $tp-color__red-300;
}
4 changes: 4 additions & 0 deletions next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@types/react-dom": "18.0.10",
"clickable-box": "^1.1.10",
"gonzales-pe": "^4.3.0",
"lodash-es": "^4.17.21",
"mousetrap": "^1.6.5",
"next": "13.1.1",
"prism-react-renderer": "0.1.7",
Expand All @@ -32,5 +33,8 @@
},
"installConfig": {
"hoistingLimits": "workspaces"
},
"devDependencies": {
"@types/lodash-es": "^4.17.6"
}
}
Loading

0 comments on commit ccd3a34

Please sign in to comment.