mirror of https://github.com/lukechilds/docs.git
Thomas Osmonson
5 years ago
16 changed files with 1025 additions and 290 deletions
@ -1,54 +0,0 @@ |
|||
name: Deploy preview |
|||
on: pull_request |
|||
|
|||
jobs: |
|||
vercel-deployment: |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- uses: actions/checkout@v2 |
|||
- name: Vercel action |
|||
uses: amondnet/vercel-action@master |
|||
id: vercel-deployment-preview |
|||
with: |
|||
vercel-token: ${{ secrets.VERCEL_TOKEN }} |
|||
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} |
|||
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} |
|||
scope: ${{ secrets.VERCEL_SCOPE }} |
|||
- name: Comment on PR |
|||
uses: actions/github-script@v2 |
|||
id: comment |
|||
with: |
|||
github-token: ${{ secrets.GITHUB_TOKEN }} |
|||
script: | |
|||
const firstLine = `The Blockstack docs have been deployed with Vercel using the code from this PR!`; |
|||
const { data } = await github.issues.listComments({ |
|||
...context.repo, |
|||
issue_number: context.issue.number, |
|||
}); |
|||
const vercelPreviewURLComment = data.find((comment) => |
|||
comment.body.includes(firstLine) |
|||
); |
|||
const commentId = vercelPreviewURLComment && vercelPreviewURLComment.id || undefined; |
|||
const commentBody = ` |
|||
#### Deploy previews |
|||
${firstLine} |
|||
|
|||
- [Blockstack docs](${{ steps.vercel-deployment-preview.outputs.preview-url }}) |
|||
|
|||
Built with commit ${context.sha}. |
|||
`; |
|||
if(context.issue.number){ |
|||
if (commentId) { |
|||
await github.issues.updateComment({ |
|||
...context.repo, |
|||
comment_id: commentId, |
|||
body: commentBody, |
|||
}); |
|||
} else { |
|||
await github.issues.createComment({ |
|||
...context.repo, |
|||
issue_number: context.issue.number, |
|||
body: commentBody, |
|||
}); |
|||
} |
|||
} |
@ -0,0 +1,37 @@ |
|||
name: Code quality |
|||
on: [push] |
|||
|
|||
jobs: |
|||
code_quality: |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout |
|||
uses: actions/checkout@v2 |
|||
|
|||
- name: Set Node Version |
|||
uses: actions/setup-node@v1.4.2 |
|||
with: |
|||
node-version: 14 |
|||
|
|||
- name: Get yarn cache directory path |
|||
id: yarn-cache-dir-path |
|||
run: echo "::set-output name=dir::$(yarn cache dir)" |
|||
|
|||
- name: Check Cache |
|||
uses: actions/cache@v2 |
|||
id: yarn-cache |
|||
with: |
|||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }} |
|||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} |
|||
restore-keys: | |
|||
${{ runner.os }}-yarn- |
|||
|
|||
- name: Install deps |
|||
run: yarn --frozen-lockfile |
|||
if: steps.yarn-cache.outputs.cache-hit != 'true' |
|||
|
|||
- name: Lint |
|||
run: yarn lint |
|||
|
|||
- name: Typecheck |
|||
run: yarn typecheck |
@ -0,0 +1,28 @@ |
|||
import React from 'react'; |
|||
import { Box, BoxProps, color, Flex, space, Stack, themeColor } from '@blockstack/ui'; |
|||
import { MDXComponents } from '@components/mdx'; |
|||
import { SadIcon, NeutralIcon, HappyIcon } from '@components/icons/feedback'; |
|||
import { useHover } from 'use-events'; |
|||
import { border } from '@common/utils'; |
|||
|
|||
const Icon: React.FC<BoxProps & { icon: React.FC<any> }> = ({ icon: IconComponent, ...props }) => { |
|||
const [isHovered, bind] = useHover(); |
|||
return ( |
|||
<Box _hover={{ color: color('accent'), cursor: 'pointer' }} size="42px" {...props} {...bind}> |
|||
<IconComponent bg={isHovered ? themeColor('blue.200') : themeColor('ink.200')} /> |
|||
</Box> |
|||
); |
|||
}; |
|||
|
|||
export const FeedbackSection: React.FC<BoxProps> = props => { |
|||
return ( |
|||
<Box borderTop={border()} py={space('extra-loose')} mt={space('extra-loose')}> |
|||
<MDXComponents.h3>Was this page helpful?</MDXComponents.h3> |
|||
<Stack isInline spacing={space('base-loose')} mt={space('base-loose')}> |
|||
<Icon icon={SadIcon} /> |
|||
<Icon icon={NeutralIcon} /> |
|||
<Icon icon={HappyIcon} /> |
|||
</Stack> |
|||
</Box> |
|||
); |
|||
}; |
@ -0,0 +1,120 @@ |
|||
import React from 'react'; |
|||
import { Box, BoxProps, transition } from '@blockstack/ui'; |
|||
import { SVGProps } from 'react'; |
|||
|
|||
export type SvgProps = React.FC<BoxProps & SVGProps<any>>; |
|||
|
|||
export const SadIcon: SvgProps = ({ bg = '#E1E3E8', ...props }) => ( |
|||
<Box |
|||
as="svg" |
|||
width="28" |
|||
height="28" |
|||
viewBox="0 0 28 28" |
|||
fill="none" |
|||
strokeLinecap="round" |
|||
strokeLinejoin="round" |
|||
{...props} |
|||
> |
|||
<Box |
|||
as="circle" |
|||
transition={transition} |
|||
// @ts-ignore
|
|||
cx="14" |
|||
cy="14" |
|||
r="14" |
|||
fill={bg as string} |
|||
/> |
|||
<path |
|||
d="M5.83334 8.75V8.75C6.94335 10.415 9.39 10.415 10.5 8.75V8.75" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
<path |
|||
d="M17.5 8.75V8.75C18.61 10.415 21.0567 10.415 22.1667 8.75V8.75" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
<path |
|||
d="M7 17.5001V17.5001C11.055 14.1209 16.945 14.1209 21 17.5001V17.5001" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
</Box> |
|||
); |
|||
|
|||
export const NeutralIcon: SvgProps = ({ bg = '#E1E3E8', ...props }) => ( |
|||
<Box |
|||
as="svg" |
|||
width="28" |
|||
height="28" |
|||
viewBox="0 0 28 28" |
|||
fill="none" |
|||
strokeLinecap="round" |
|||
strokeLinejoin="round" |
|||
{...props} |
|||
> |
|||
<Box |
|||
as="circle" |
|||
transition={transition} |
|||
// @ts-ignore
|
|||
cx="14" |
|||
cy="14" |
|||
r="14" |
|||
fill={bg as string} |
|||
/> |
|||
<path |
|||
d="M5.83331 9.91659V9.91659C7.38689 10.0276 8.9464 10.0276 10.5 9.91659V9.91659" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
<path |
|||
d="M17.5 9.91659V9.91659C19.0536 10.0276 20.6131 10.0276 22.1667 9.91659V9.91659" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
<path d="M7 17.5H14H21" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" /> |
|||
</Box> |
|||
); |
|||
|
|||
export const HappyIcon: SvgProps = ({ bg = '#E1E3E8', ...props }) => ( |
|||
<Box |
|||
as="svg" |
|||
width="28" |
|||
height="28" |
|||
viewBox="0 0 28 28" |
|||
fill="none" |
|||
strokeLinecap="round" |
|||
strokeLinejoin="round" |
|||
{...props} |
|||
> |
|||
<Box |
|||
as="circle" |
|||
transition={transition} // @ts-ignore
|
|||
cx="14" |
|||
cy="14" |
|||
r="14" |
|||
fill={bg as string} |
|||
/> |
|||
<path |
|||
d="M5.83331 10.5V10.5C6.94332 8.83498 9.38997 8.83498 10.5 10.5V10.5" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
<path |
|||
d="M17.5 10.5V10.5C18.61 8.83498 21.0567 8.83498 22.1667 10.5V10.5" |
|||
stroke="currentColor" |
|||
strokeWidth="1.5" |
|||
strokeLinecap="round" |
|||
/> |
|||
<path |
|||
d="M21 14C21 15.8565 20.2625 17.637 18.9497 18.9497C17.637 20.2625 15.8565 21 14 21C12.1435 21 10.363 20.2625 9.05025 18.9497C7.7375 17.637 7 15.8565 7 14L14 14H21Z" |
|||
fill="currentColor" |
|||
/> |
|||
</Box> |
|||
); |
@ -1,167 +1,113 @@ |
|||
import { Box, Flex, FlexProps, color, space, BoxProps } from '@blockstack/ui'; |
|||
import { Caption, Text } from '@components/typography'; |
|||
import { useRouter } from 'next/router'; |
|||
import React from 'react'; |
|||
import { slugify } from '@common/utils'; |
|||
import Link from 'next/link'; |
|||
import { useHover } from 'use-events'; |
|||
import { ContentWrapper } from '@components/content-wrapper'; |
|||
import { Box, BoxProps, Flex, Grid, color, space } from '@blockstack/ui'; |
|||
import routes from '@common/routes'; |
|||
import { useRouter } from 'next/router'; |
|||
import { MDXComponents } from '@components/mdx'; |
|||
import { border } from '@common/utils'; |
|||
import NextLink from 'next/link'; |
|||
import { Link } from '@components/typography'; |
|||
const usePaginateRoutes = () => { |
|||
const router = useRouter(); |
|||
|
|||
const getRoute = route => router.pathname.includes(route.path); |
|||
const getSection = _section => _section.routes.find(getRoute); |
|||
const findSectionByTitle = item => item.title === section.title; |
|||
|
|||
const section = routes.find(getSection); |
|||
|
|||
if (!section) |
|||
return { |
|||
next: undefined, |
|||
prev: undefined, |
|||
}; |
|||
|
|||
const { routes: sectionRoutes } = section; |
|||
const sectionIndex: number = routes.findIndex(findSectionByTitle); |
|||
|
|||
const nextSection = routes[sectionIndex + 1]; |
|||
const prevSection = routes[sectionIndex - 1]; |
|||
|
|||
const isFirstSection = sectionIndex === 0; |
|||
const isLastSection = sectionIndex === routes.length - 1; |
|||
|
|||
const route = sectionRoutes.find(getRoute); |
|||
const routeIndex: number = sectionRoutes.findIndex(getRoute); |
|||
|
|||
const isFirstRouteInSection = routeIndex === 0; |
|||
const isLastRouteInSection = routeIndex === sectionRoutes.length - 1; |
|||
|
|||
let next; |
|||
let prev; |
|||
|
|||
if (!isLastRouteInSection) { |
|||
next = sectionRoutes[routeIndex + 1]; |
|||
} |
|||
if (isLastRouteInSection && !isLastSection) { |
|||
next = nextSection?.routes?.length && nextSection?.routes[0]; |
|||
} |
|||
if (!isFirstRouteInSection) { |
|||
prev = sectionRoutes[routeIndex - 1]; |
|||
} |
|||
if (isFirstRouteInSection && !isFirstSection) { |
|||
prev = prevSection?.routes?.length && prevSection?.routes[0]; |
|||
} |
|||
|
|||
return { next, prev }; |
|||
}; |
|||
|
|||
// const transition = 'all 0.2s cubic-bezier(0.23, 1, 0.32, 1)';
|
|||
//
|
|||
// const Previous = ({ isHovered }: { isHovered: boolean }) => {
|
|||
// return (
|
|||
// <Flex>
|
|||
// <Box
|
|||
// mr="extra-tight"
|
|||
// transition={transition}
|
|||
// transform={isHovered ? 'translateX(-2px)' : 'none'}
|
|||
// >
|
|||
// ←
|
|||
// </Box>
|
|||
// <Box>
|
|||
// <Caption>Previous</Caption>
|
|||
// </Box>
|
|||
// </Flex>
|
|||
// );
|
|||
// };
|
|||
// const Next = ({ isHovered }: { isHovered: boolean }) => {
|
|||
// return (
|
|||
// <Flex justifyContent="flex-end">
|
|||
// <Box>
|
|||
// <Caption>Next</Caption>
|
|||
// </Box>
|
|||
// <Box
|
|||
// ml="extra-tight"
|
|||
// transition={transition}
|
|||
// transform={isHovered ? 'translateX(2px)' : 'none'}
|
|||
// >
|
|||
// →
|
|||
// </Box>
|
|||
// </Flex>
|
|||
// );
|
|||
// };
|
|||
//
|
|||
// interface PaginationLinkProps extends BoxProps {
|
|||
// slug: string;
|
|||
// label: string;
|
|||
// prev?: boolean;
|
|||
// }
|
|||
//
|
|||
// const PaginationLink = ({ slug, label, prev, ...rest }: PaginationLinkProps) => {
|
|||
// const [isHovered, bindHover] = useHover();
|
|||
// return (
|
|||
// <Link href={`/${slug}`} passHref>
|
|||
// <Box
|
|||
// color="var(--colors-text-body)"
|
|||
// _hover={{
|
|||
// color: 'var(--colors-accent)',
|
|||
// }}
|
|||
// as="a"
|
|||
// py={space('extra-loose')}
|
|||
// display="block"
|
|||
// flexGrow={1}
|
|||
// {...bindHover}
|
|||
// {...rest}
|
|||
// >
|
|||
// <Caption textAlign={prev ? 'left' : 'right'} display="block">
|
|||
// {prev ? <Previous isHovered={isHovered} /> : <Next isHovered={isHovered} />}
|
|||
// </Caption>
|
|||
// <Text
|
|||
// textAlign={prev ? 'left' : 'right'}
|
|||
// display="block"
|
|||
// textStyle="display.large"
|
|||
// color="currentColor"
|
|||
// >
|
|||
// {label}
|
|||
// </Text>
|
|||
// </Box>
|
|||
// </Link>
|
|||
// );
|
|||
// };
|
|||
//
|
|||
// const getRouteWithSection = (route: string) => {
|
|||
// let section = '';
|
|||
// const keys = Object.keys(paginationRoutes);
|
|||
// keys.forEach(key => {
|
|||
// const routes = paginationRoutes[key].map(r => slugify(r));
|
|||
// if (routes.length && routes.find(r => r === route) && key !== 'top' && key !== 'bottom') {
|
|||
// section = key + '/';
|
|||
// }
|
|||
// });
|
|||
// return section + route;
|
|||
// };
|
|||
//
|
|||
// const usePagination = () => {
|
|||
// const router = useRouter();
|
|||
// const [state, setState] = React.useState({
|
|||
// previous: undefined,
|
|||
// previousSlug: undefined,
|
|||
// next: undefined,
|
|||
// nextSlug: undefined,
|
|||
// });
|
|||
// React.useEffect(() => {
|
|||
// const routesAsSlugs = routes.map(r => slugify(r));
|
|||
// const _route = router.asPath.replace('/', '');
|
|||
// const __route = _route.includes('/') ? _route.split('/')[1] : _route;
|
|||
// const route = __route === '' ? 'getting-started' : __route;
|
|||
// const index = routesAsSlugs.indexOf(route);
|
|||
// const previous = routes[index - 1];
|
|||
// const previousSlug = getRouteWithSection(routesAsSlugs[index - 1]);
|
|||
// const next = routes[index + 1];
|
|||
// const nextSlug = getRouteWithSection(routesAsSlugs[index + 1]);
|
|||
//
|
|||
// setState({
|
|||
// previous,
|
|||
// previousSlug,
|
|||
// next,
|
|||
// nextSlug,
|
|||
// });
|
|||
// }, [router.asPath]);
|
|||
//
|
|||
// const { previous, previousSlug, next, nextSlug } = state;
|
|||
//
|
|||
// return [
|
|||
// { label: previous, path: previousSlug, condition: !!previous },
|
|||
// {
|
|||
// label: next,
|
|||
// path: nextSlug,
|
|||
// condition: !!next,
|
|||
// },
|
|||
// ];
|
|||
// };
|
|||
//
|
|||
// export const Pagination: React.FC<FlexProps> = props => {
|
|||
// const buttons = usePagination();
|
|||
// return (
|
|||
// <Box maxWidth="100%" {...props}>
|
|||
// <ContentWrapper
|
|||
// borderTop="1px solid"
|
|||
// borderColor={color('border')}
|
|||
// flexDirection="row"
|
|||
// alignItems="baseline"
|
|||
// justify="space-between"
|
|||
// pt="unset"
|
|||
// pb="unset"
|
|||
// width="100%"
|
|||
// maxWidth="98ch"
|
|||
// mx="auto"
|
|||
// px={space('extra-loose')}
|
|||
// >
|
|||
// {buttons.map((button, index) =>
|
|||
// button.condition ? (
|
|||
// <PaginationLink
|
|||
// textAlign={index === 0 ? 'left' : 'right'}
|
|||
// slug={button.path}
|
|||
// label={button.label}
|
|||
// prev={index === 0}
|
|||
// key={index}
|
|||
// />
|
|||
// ) : null
|
|||
// )}
|
|||
// </ContentWrapper>
|
|||
// </Box>
|
|||
// );
|
|||
// };
|
|||
const Description: React.FC<BoxProps> = props => ( |
|||
<Box maxWidth="32ch" mt={space('extra-tight')}> |
|||
<MDXComponents.p {...props} /> |
|||
</Box> |
|||
); |
|||
|
|||
export const Pagination: React.FC<FlexProps> = props => <></>; |
|||
export const Pagination = ({ hidePagination, ...rest }: any) => { |
|||
const { next, prev } = usePaginateRoutes(); |
|||
return ( |
|||
<Grid |
|||
pt={space('extra-loose')} |
|||
borderTop={border()} |
|||
gridColumnGap={space('base-loose')} |
|||
gridRowGap={space('extra-loose')} |
|||
gridTemplateColumns={['repeat(1, 1fr)', 'repeat(1, 1fr)', 'repeat(2, 1fr)', 'repeat(2, 1fr)']} |
|||
> |
|||
{prev ? ( |
|||
<Box _hover={{ cursor: 'pointer' }} width="100%" position="relative"> |
|||
<NextLink href={`/${prev.path}`} passHref> |
|||
<Link position="absolute" size="100%" zIndex={2} as="a" /> |
|||
</NextLink> |
|||
<MDXComponents.h5 color={color('text-caption')}>Previous</MDXComponents.h5> |
|||
<Box maxWidth="38ch"> |
|||
<MDXComponents.h3 my={0}>{prev.title || prev.headings[0]}</MDXComponents.h3> |
|||
</Box> |
|||
{prev.description && <Description>{prev.description}</Description>} |
|||
</Box> |
|||
) : ( |
|||
<Box /> |
|||
)} |
|||
{next ? ( |
|||
<Flex |
|||
_hover={{ cursor: 'pointer' }} |
|||
width="100%" |
|||
textAlign="right" |
|||
direction="column" |
|||
align="flex-end" |
|||
position="relative" |
|||
> |
|||
<NextLink href={`/${next.path}`} passHref> |
|||
<Link position="absolute" size="100%" zIndex={2} as="a" /> |
|||
</NextLink> |
|||
<MDXComponents.h5 color={color('text-caption')} width="100%" display="block"> |
|||
Next |
|||
</MDXComponents.h5> |
|||
<Box maxWidth="38ch"> |
|||
<MDXComponents.h3 my={0}>{next.title || next.headings[0]}</MDXComponents.h3> |
|||
</Box> |
|||
{next.description && <Description>{next.description}</Description>} |
|||
</Flex> |
|||
) : ( |
|||
<Box /> |
|||
)} |
|||
</Grid> |
|||
); |
|||
}; |
|||
|
File diff suppressed because it is too large
Loading…
Reference in new issue