Skip to content

Commit

Permalink
feat: header to app component, link context
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Jun 6, 2020
1 parent 1bed424 commit 24c7476
Show file tree
Hide file tree
Showing 19 changed files with 152 additions and 64 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
# Motivation

- Create a components development environment with testing as a first-class feature.
- Provide out-of-the-box documentation experience with markdown pages for home page, blogging and general project documentation .
- Use smart "super-bundlers" (gatsby, nextjs) to build compact and fast documentation sites.
- Decouple the user interface from loading of the 'stories' = modular design.
- Do not modify the source files (both story and component files) at instrumentation-time as much as possible to avoid random build/run-time errors. Exception only where absolutely necessary, ie instrumenting coverage or performance profiling probes.
Expand All @@ -50,6 +51,8 @@ There are many developments that have contributed to the creation of `component-

- [docz](https://www.docz.site) has a beautiful architecture and introduced non-proprietary [gatsby](https://www.gatsbyjs.org) build engine. This monorepo was also heavily influenced by the `docz` project repository structure.

- [docusaurus](https://docusaurus.io) creates very clean and effective UX for documentation websites. Provides excellent options for project blogging, versioning, translation and algolia-powered search.

- [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) advancements have been greatly responsible for making possible the parsing and analysis features of this library.

- [blocks-ui](https://blocks-ui.com) is taking `AST` to a new level by generating and reversing AST to create [react](https://reactjs.org) applications and has been an inspiraton for pushing the enveloppe on our own `AST` work.
Expand Down
4 changes: 4 additions & 0 deletions core/loader/src/runtimeLoader.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { loadConfiguration, extractStories } from '@component-controls/config';
import { stringifyRequest } from 'loader-utils';
import { replaceSource, StoryPath } from './replaceSource';
import { store } from './store';

module.exports = function(content: string) {
//@ts-ignore
const params = JSON.parse(this.query.slice(1));
//@ts-ignore
const config = loadConfiguration(this.rootContext, params.config);
store.config = config?.optionsFilePath
? require(config?.optionsFilePath)
: undefined;
const stories: StoryPath[] = (config ? extractStories(config) || [] : []).map(
fileName => ({
absPath: fileName,
Expand Down
2 changes: 1 addition & 1 deletion core/specification/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export interface Configuration {
*/
siteImage?: string;
/**
* base url path for API documentation pages. Default is "docs"
* base url path for API documentation pages. Default is "docs/"
*/
basePath?: string;
/**
Expand Down
2 changes: 1 addition & 1 deletion core/store/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ export const defaultConfig: Configuration = {
'Component controls stories. Write your components documentation with MDX and JSX. Design, develop, test and review in a single site.',
siteLanguage: 'en',
author: '@component-controls',
basePath: 'docs',
basePath: 'docs/',
},
};
2 changes: 1 addition & 1 deletion examples/gatsby/.config/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
siteDescription: `Component controls stories. Write your components documentation with MDX and JSX. Design, develop, test and review in a single site.`,
siteLanguage: `en`,
author: `@atanasster`,
basePath: 'docs',
basePath: 'docs/',

storySort: (a, b) => {
const aDoc = a.split('/')[0];
Expand Down
6 changes: 3 additions & 3 deletions integrations/gatsby-theme-stories/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@

# Overview

Accessibility testing plugin using the [axe-core](https://github.com/dequelabs/axe-core) library from [deque](https://www.deque.com/axe/)

Some of the design goals:
Gatsby theme for documenting your projects with component controls

- Gatsby theme quick start.
- Full UI configurability with components shadowing.

Special thanks for the inspiration drawn from [Gatsby themes](https://github.com/LekoArts/gatsby-themes).

# Getting Started

## Install
Expand Down
27 changes: 27 additions & 0 deletions integrations/gatsby-theme-stories/src/components/GatsbyLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/** @jsx jsx */
import { FC } from 'react';
import { jsx, LinkProps, Theme } from 'theme-ui';
import { Link } from 'gatsby';

export const GatsbyLink: FC<LinkProps & { to?: string }> = ({
href,
to,
...props
}) => (
//@ts-ignore
<Link
to={href || to || ''}
{...props}
activeClassName="active"
sx={{
color: 'inherit',
'&.active': {
borderLeft: (t: Theme) => `4px solid ${t?.colors?.accent}`,
color: 'white',
},
':hover': {
backgroundColor: 'shadow',
},
}}
/>
);
23 changes: 14 additions & 9 deletions integrations/gatsby-theme-stories/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { FC } from 'react';
import { jsx, Flex } from 'theme-ui';
import { Global } from '@emotion/core';
import { ThemeProvider } from '@component-controls/components';
import { Page, SEO } from '@component-controls/app';
import { SidebarContextProvider } from '@component-controls/app-components';
import { Page, SEO, Header } from '@component-controls/app';
import {
SidebarContextProvider,
LinkContextProvider,
} from '@component-controls/app-components';
import { BlockContextProvider } from '@component-controls/blocks';
import { Store } from '@component-controls/store';
import { Sidebar } from './Sidebar';
import { Header } from './Header';
import { GatsbyLink } from './GatsbyLink';
import { PagesConfig } from './types';
import { Footer } from './Footer';

Expand Down Expand Up @@ -46,12 +49,14 @@ export const Layout: FC<LayoutProps> = ({
flexDirection: 'column',
}}
>
<Header title={title}></Header>
<Flex sx={{ flexDirection: 'row', flex: 1 }}>
<Sidebar docPath={docTitle} />
<Page pagesFn={pagesFn} />
</Flex>
<Footer />
<LinkContextProvider linkClass={GatsbyLink}>
<Header title={title}></Header>
<Flex sx={{ flexDirection: 'row', flex: 1 }}>
<Sidebar docPath={docTitle} />
<Page pagesFn={pagesFn} />
</Flex>
<Footer />
</LinkContextProvider>
</Flex>
</SidebarContextProvider>
</BlockContextProvider>
Expand Down
22 changes: 2 additions & 20 deletions integrations/gatsby-theme-stories/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
/** @jsx jsx */
import { FC } from 'react';
import { jsx, LinkProps, Theme } from 'theme-ui';
import { Link as GatsbyLink } from 'gatsby';
import { jsx } from 'theme-ui';
import { Sidebar as AppSidebar } from '@component-controls/app';

const Link: FC<LinkProps> = props => (
//@ts-ignore
<GatsbyLink
{...props}
activeClassName="active"
sx={{
color: 'inherit',
'&.active': {
borderLeft: (t: Theme) => `4px solid ${t?.colors?.accent}`,
color: 'white',
},
':hover': {
backgroundColor: 'shadow',
},
}}
/>
);
export interface SidebarProps {
docPath?: string;
}

export const Sidebar: FC<SidebarProps> = ({ docPath }) => {
return <AppSidebar docPath={docPath} buttonClass={Link} />;
return <AppSidebar docPath={docPath} />;
};
8 changes: 5 additions & 3 deletions integrations/gatsby-theme-stories/src/gatsby-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ exports.createPages = async (
? await watch(config)
: await compile(config);
if (store) {
const { basePath = '' } = store.config?.options || {};
console.log('basePath', basePath);
const template = require.resolve(`../src/templates/StoryPage.tsx`);
store.stores.forEach(s => {
const doc = s.doc;
if (doc) {
createPage({
path: doc.route || `/docs/${doc.title.toLowerCase()}`,
path: doc.route || `/${basePath}${doc.title.toLowerCase()}`,
component: template,
context: {
doc: doc.title,
Expand All @@ -44,9 +46,9 @@ exports.createPages = async (
doc: homePage?.doc?.title,
},
});
const docsPage = store.stores.find(s => s.doc?.route === '/docs');
const docsPage = store.stores.find(s => s.doc?.route === `/${basePath}`);
createPage({
path: `/docs/`,
path: `/${basePath}`,
component: template,
context: {
doc: docsPage?.doc?.title,
Expand Down
7 changes: 7 additions & 0 deletions ui/app-components/src/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React, { FC } from 'react';
import { LinkProps } from 'theme-ui';
import { useGetLinkClass } from './LinkContext';
export const Link: FC<LinkProps> = props => {
const LinkClass = useGetLinkClass();
return <LinkClass {...props} />;
};
16 changes: 16 additions & 0 deletions ui/app-components/src/Link/LinkContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { FC, createContext, useContext } from 'react';
import { Link, LinkProps } from 'theme-ui';

export type LinkClassType = React.FC<LinkProps>;
const LinkContext = createContext<LinkClassType>(Link);

export const LinkContextProvider: FC<{
linkClass: LinkClassType;
}> = ({ linkClass: LinkClass, children }) => {
return (
<LinkContext.Provider value={LinkClass}>{children}</LinkContext.Provider>
);
};
export const useGetLinkClass = () => {
return useContext(LinkContext) || Link;
};
2 changes: 2 additions & 0 deletions ui/app-components/src/Link/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Link';
export * from './LinkContext';
18 changes: 5 additions & 13 deletions ui/app-components/src/Navmenu/Navmenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsx jsx */
import React, { FC, useEffect, useState } from 'react';
import { jsx, Box, Flex, Button, ButtonProps, LinkProps, Text } from 'theme-ui';
import { jsx, Box, Flex, Text, Button, ButtonProps } from 'theme-ui';
import Octicon, { ChevronDown, ChevronRight } from '@primer/octicons-react';
import {
Keyboard,
Expand All @@ -9,6 +9,7 @@ import {
RIGHT_ARROW,
DOWN_ARROW,
} from '../Keyboard';
import { Link, LinkClassType } from '../Link';

export interface MenuItem {
/** Unique id */
Expand All @@ -31,19 +32,12 @@ export interface MenuItem {

export type MenuItems = MenuItem[];

export type ButtonClassType =
| React.FunctionComponent<ButtonProps>
| React.FunctionComponent<LinkProps>;

export interface NavMenuProps {
/** Array of menu items */
items: MenuItems;
/** Initially active menu item */
activeItem?: Pick<MenuItem, 'id' | 'label'>;

/** Custom class to use for the button instead of Button */
buttonClass?: ButtonClassType;

/** If specified, will expand all items with chidren */
expandAll?: boolean;

Expand Down Expand Up @@ -210,7 +204,6 @@ export const Navmenu: FC<NavMenuProps> = ({
activeItem,
search,
onSelect,
buttonClass,
}) => {
const [state, setState] = useState<NavMenuState>(
stateFromProps({
Expand Down Expand Up @@ -266,8 +259,7 @@ export const Navmenu: FC<NavMenuProps> = ({
const itemId = id || label;
const isExpanded: boolean =
expandedItems && itemId ? expandedItems.includes(item) : false;
const ButtonClass: ButtonClassType =
(items ? Button : buttonClass) || Button;
const LinkClass: LinkClassType | FC<ButtonProps> = items ? Button : Link;
const itemKey = `item_${itemId}_${level}`;

let background;
Expand All @@ -282,7 +274,7 @@ export const Navmenu: FC<NavMenuProps> = ({
pl: level,
}}
>
<ButtonClass
<LinkClass
sx={{
width: '100%',
px: 3,
Expand Down Expand Up @@ -344,7 +336,7 @@ export const Navmenu: FC<NavMenuProps> = ({
)}
</Flex>
</Flex>
</ButtonClass>
</LinkClass>
</Flex>
);
return (
Expand Down
1 change: 1 addition & 0 deletions ui/app-components/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './ColorMode';
export * from './Header';
export * from './Keyboard';
export * from './Link';
export * from './Navmenu';
export * from './Sidebar';
50 changes: 50 additions & 0 deletions ui/app/src/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/** @jsx jsx */
import { FC, useContext } from 'react';
import { jsx, Flex, Text } from 'theme-ui';
import {
Link,
ColorMode,
SidebarContext,
Header as AppHeader,
} from '@component-controls/app-components';

interface HeaderProps {
title?: string;
}
export const Header: FC<HeaderProps> = () => {
const { SidebarToggle, collapsed, responsive } = useContext(SidebarContext);

return (
<AppHeader position="sticky">
<Flex
sx={{
flexDirection: 'row',
alignItems: 'center',
color: `secondary`,
a: {
color: `secondary`,
':hover': { color: `accent` },
fontWeight: '700',
},
}}
>
{collapsed && <SidebarToggle />}
<Flex
sx={{
flexDirection: 'row',
alignItems: 'center',
py: 3,
}}
>
<Link href="/">
<Text sx={{ px: 2 }}>Home</Text>
</Link>
<Link href="/docs/">
<Text sx={{ px: 2 }}>Docs</Text>
</Link>
</Flex>
</Flex>
{!responsive && <ColorMode />}
</AppHeader>
);
};
1 change: 1 addition & 0 deletions ui/app/src/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Header';
Loading

0 comments on commit 24c7476

Please sign in to comment.