Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Co-authored-by: Kamil Piwko <[email protected]>
Co-authored-by: Katrin Fritz <[email protected]>
  • Loading branch information
iz-podpolja and katrinundfritz authored Sep 27, 2022
1 parent 71e0208 commit 9ab35c2
Show file tree
Hide file tree
Showing 48 changed files with 3,358 additions and 1,572 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ node_modules
style-dictionary/config.js
storybook-static
dist
coverage
**/*.mdx
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ dist-ssr
.history
.eslintcache
.env
coverage
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ app/javascript/gql/generated.ts
app/javascript/shared/i18n.ts
*.ejs
build
coverage
5 changes: 4 additions & 1 deletion .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StorybookConfig, Options } from '@storybook/core-common'
import { UserConfig } from 'vite'
import postcss from 'postcss'
interface ExtendedConfig extends StorybookConfig {
viteFinal?: (config: UserConfig, options: Options) => Promise<UserConfig>
}
Expand All @@ -17,10 +18,12 @@ const config: ExtendedConfig = {
core: {
builder: '@storybook/builder-vite',
},
typescript: {
reactDocgen: 'react-docgen-typescript',
},
async viteFinal(config) {
console.log('env', process.env.BASE_URL, process.env.STORYBOOK_FIGMA_ACCESS_TOKEN)
config.base = process.env.BASE_URL || config.base

// return the customized config
return config
},
Expand Down
1 change: 1 addition & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import order from './order.json'
export const parameters: Parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
expanded: true,
matchers: {
color: /(background|color)$/i,
date: /Date$/,
Expand Down
11 changes: 7 additions & 4 deletions figma/lib/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// eslint-disable @typescript-eslint/no-explicit-any
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Node } from 'figma-api'
export function rgbToHex(r: number, g: number, b: number) {
const color = '#' + ((1 << 24) + ((r * 255) << 16) + ((g * 255) << 8) + b * 255).toString(16).slice(1)
Expand All @@ -21,16 +21,19 @@ export function camelize(str: string, capitalizeInitial?: boolean): string {
if (p2) return p2.toUpperCase()
return p1.toLowerCase()
})
if (res.length && capitalizeInitial) res = res.charAt(0).toUpperCase() + res.slice(1)
const capitalize = capitalizeInitial || (res.length >= 2 && res.charAt(1) === res.charAt(1).toUpperCase())
if (res.length && capitalize) res = res.charAt(0).toUpperCase() + res.slice(1)
return res
}

export function kebabCase(str: string) {
return str.replace(/([\W_])/g, '-').toLowerCase()
const result = str.replace(/([\W])/g, ' $1').replace(/\s+/g, ' ')
return result.split(' ').join('-').toLowerCase()
}

export function snakeify(str: string) {
return str.replace(/([\W_])/g, '_').toLowerCase()
const result = str.replace(/([\W])/g, ' $1').replace(/\s+/g, ' ')
return result.split(' ').join('_').toLowerCase()
}

export type DataTuple<T, K extends string = string> = readonly [string, K, T]
Expand Down
36 changes: 20 additions & 16 deletions generator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class StorybookGenerator extends Generator<GeneratorOpts> {
this.option('figma', { type: Boolean, description: 'Link with Figma component' })
this.options = { ...opts, props: opts.props ?? {} }
this.options.camelizedName = camelize(this.options.name)
this.options.snakifiedName = snakeify(this.options.camelizedName)
this.options.snakifiedName = snakeify(this.options.name)
console.log(this.options.snakifiedName, this.options.camelizedName)
if (!this.options.root) {
this.log.error('Component root was not provided!')
process.exit(1)
Expand Down Expand Up @@ -197,21 +198,23 @@ class StorybookGenerator extends Generator<GeneratorOpts> {
}
)
if (this.options.story) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const fileInfo = this.fileInfo!
const specUrl = getComponentSpecUrl(fileInfo, this.options)
this.fs.copyTpl(
this.templatePath('figma.lock.ts.ejs'),
this.destinationPath(`${this.componentPath}/figma.lock.ts`),
{
url: specUrl,
id: this.options.id,
themes: objToArr(this.options.themes ?? {}).map((theme) => ({
...theme,
url: getComponentSpecUrl(fileInfo, this.options, theme.theme),
})),
}
)
if (this.options.figma) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const fileInfo = this.fileInfo!
const specUrl = getComponentSpecUrl(fileInfo, this.options)
this.fs.copyTpl(
this.templatePath('figma.lock.ts.ejs'),
this.destinationPath(`${this.componentPath}/figma.lock.ts`),
{
url: specUrl,
id: this.options.id,
themes: objToArr(this.options.themes ?? {}).map((theme) => ({
...theme,
url: getComponentSpecUrl(fileInfo, this.options, theme.theme),
})),
}
)
}
this.fs.copyTpl(
this.templatePath('component.stories.tsx.ejs'),
this.destinationPath(`${this.componentPath}/${this.options.snakifiedName}.stories.tsx`),
Expand All @@ -220,6 +223,7 @@ class StorybookGenerator extends Generator<GeneratorOpts> {
compFileName: this.options.snakifiedName,
title: storyTitle,
variants,
figma: this.options.figma,
}
)
}
Expand Down
4 changes: 4 additions & 0 deletions generator/templates/component.stories.tsx.ejs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
<% if (figma) { %>
import FigmaCfg from './figma.lock'
<% } %>
import <%=compName%> from './<%=compFileName%>'

// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
Expand All @@ -9,9 +11,11 @@ export default {
component: <%=compName%>,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
// argTypes: {},
<% if (figma) { %>
parameters: {
design: FigmaCfg.themes.length ? FigmaCfg.themes.map(({url, name}) => ({url, name, type: 'figspec', accessToken: process.env.STORYBOOK_FIGMA_ACCESS_TOKEN,})) : { type: 'figspec', accessToken: process.env.STORYBOOK_FIGMA_ACCESS_TOKEN, url: FigmaCfg.url,},
},
<% } %>
} as ComponentMeta<typeof <%=compName%>>

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
Expand Down
43 changes: 24 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"resolutions": {
"@types/react": "^17.0.10"
"@types/react": "^17.0.10",
"postcss": "^8.4.16"
},
"name": "betterplace-design-system",
"author": "betterplace <[email protected]>",
Expand All @@ -25,10 +26,12 @@
"dev": "vite",
"build": "yarn build-tokens && tsc -p tsconfig.base.json && vite build && cp -r ./build/* ./dist/",
"preview": "vite preview",
"prestorybook": "yarn build-tokens",
"storybook": "start-storybook -p 6006",
"figma::tokens": "ts-node -r dotenv/config --project ./tsconfig.tsnode.json figma/fetch_tokens.ts PJ7OUutWRrSHW6qgaPNW1l",
"figma::components": "ts-node -r dotenv/config --project ./tsconfig.tsnode.json figma/fetch_components.ts PJ7OUutWRrSHW6qgaPNW1l",
"component::add::main": "ts-node --project ./tsconfig.tsnode.json node_modules/.bin/yo ./generator --figma --test --story --root src/lib",
"component::add::figma": "ts-node --project ./tsconfig.tsnode.json node_modules/.bin/yo ./generator --figma --test --story --root src/lib",
"component::add::lib": "ts-node --project ./tsconfig.tsnode.json node_modules/.bin/yo ./generator --test --story --root src/lib",
"component::add::local": "ts-node --project ./tsconfig.tsnode.json node_modules/.bin/yo ./generator --root",
"build-storybook": "export BASE_URL='/betterplace-design-system/'; build-storybook",
"build-tokens": "style-dictionary build --config config/style-dictionary/config.js",
Expand All @@ -40,22 +43,22 @@
},
"peerDependencies": {
"react": "^17.0.2",
"rxjs": "^7.5.5",
"react-dom": "^17.0.2",
"remotedev": "^0.2.9"
"remotedev": "^0.2.9",
"rxjs": "^7.5.5"
},
"devDependencies": {
"remotedev": "^0.2.9",
"@babel/core": "^7.17.9",
"@storybook/addon-a11y": "^6.4.22",
"@storybook/addon-actions": "^6.4.21",
"@storybook/addon-essentials": "^6.4.21",
"@storybook/addon-interactions": "^6.4.21",
"@storybook/addon-jest": "^6.4.22",
"@storybook/addon-links": "^6.4.21",
"@storybook/builder-vite": "^0.1.28",
"@storybook/react": "^6.4.21",
"@storybook/testing-library": "^0.0.9",
"@storybook/addon-a11y": "^6.5.12",
"@storybook/addon-actions": "^6.5.12",
"@storybook/addon-docs": "^6.5.12",
"@storybook/addon-essentials": "^6.5.12",
"@storybook/addon-interactions": "^6.5.12",
"@storybook/addon-jest": "^6.5.12",
"@storybook/addon-links": "^6.5.12",
"@storybook/builder-vite": "^0.2.2",
"@storybook/react": "^6.5.12",
"@storybook/testing-library": "^0.0.13",
"@swc/core": "^1.2.189",
"@swc/jest": "^0.2.21",
"@testing-library/jest-dom": "^5.16.4",
Expand All @@ -69,7 +72,6 @@
"@types/yeoman-generator": "^5.2.10",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@vitejs/plugin-react": "^1.0.7",
"babel-loader": "^8.2.4",
"dotenv": "^16.0.0",
"eslint": "^8.13.0",
Expand All @@ -89,12 +91,15 @@
"jest-css-modules": "^2.1.0",
"jest-environment-jsdom": "^28.1.0",
"lint-staged": ">=10",
"postcss": "^8.4.16",
"postcss-apply": "^0.12.0",
"postcss-nested": "^5.0.6",
"postcss-nesting": "^10.1.7",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"remotedev": "^0.2.9",
"rxjs": "^7.5.5",
"storybook-addon-designs": "^6.2.1",
"storybook-addon-designs": "^6.3.1",
"style-dictionary": "^3.7.0",
"stylelint": "^14.8.1",
"stylelint-config-prettier": "^9.0.3",
Expand All @@ -105,10 +110,10 @@
"ts-node": "^10.7.0",
"ts-node-register": "^1.0.0",
"typescript": "^4.5.4",
"vite": "^2.9.13",
"vite-plugin-dts": "^1.0.5",
"vite": "^3.1.3",
"vite-plugin-dts": "^1.5.0",
"vite-plugin-dynamic-import": "^0.9.3",
"vite-plugin-eslint": "^1.6.0",
"vite-plugin-eslint": "^1.8.1",
"yeoman-generator": "^5.6.1",
"yo": "^4.3.0"
},
Expand Down
30 changes: 30 additions & 0 deletions src/helpers/hook_render_helper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { PropsWithChildren, useState } from 'react'
import { JSONPrettyPrint } from '../lib/components/json_pretty_print'

export const HookRenderHelper = ({ children }: PropsWithChildren<Record<string, unknown>>) => {
const [key, setKey] = useState(1)
const [_, setRerender] = useState(1)

return (
<div key={key}>
{children}
<hr />
<div>
<button onClick={() => setRerender((x) => x + 1)}>Rerender Hook</button>
<button onClick={() => setKey((x) => x + 1)}>Remount Hook</button>
</div>
</div>
)
}

export const RenderHook = <T extends (...args: any[]) => any>(hook: T) => {
const name = `${hook.name}[0].toUpperCase()}${hook.name.slice(1)}`

const Component = (props: Parameters<typeof hook>[0]) => {
const result = hook(props)
return <JSONPrettyPrint json={result} />
}
Component.displayName = `${name}Demo`
return Component
}
1 change: 1 addition & 0 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './theme_provider'
export * from './hook_render_helper'
28 changes: 19 additions & 9 deletions src/helpers/theme_provider.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { ReactFramework, StoryContext } from '@storybook/react'
import React, { ReactNode, useState } from 'react'
import React, { ReactNode, useEffect, useState } from 'react'
import '../../build/css/globals.css'
import tokens from '../../config/tokens.json'
import AVAILABLE_THEMES from '../lib/shared/themes'
const ThemeKeys = AVAILABLE_THEMES.map((theme) => theme.key)
import AVAILABLE_THEMES from '../lib/shared/themes.json'

const ThemeKeys = AVAILABLE_THEMES.map((theme) => theme.key) as Exclude<
keyof typeof tokens,
'global' | '$themes' | '$metadata'
>[]
type Theme = typeof ThemeKeys[number]

type ThemeProviderProps = {
Expand All @@ -15,21 +19,27 @@ export type ThemeProviderContext = {
theme?: Theme
tokens?: {
global: Tokens['global']
theme: Tokens[Exclude<keyof Tokens, 'global'>]
theme: Tokens[Theme]
}
}

export const ThemeContext = React.createContext<ThemeProviderContext>({})

export const ThemeProvider = ({ theme, children }: ThemeProviderProps) => {
const [themeVars, setThemeVars] = useState('')

import(`../../build/css/themes/${theme}.css`).then((styles) => {
setThemeVars(styles.default)
})
useEffect(() => {
import(`../../build/css/themes/${theme}.css`).then((styles) => {
setThemeVars(styles.default)
})
}, [theme])

return (
<ThemeContext.Provider value={{ theme, tokens: { global: tokens.global, theme: tokens[theme] } }}>
<ThemeContext.Provider
value={{
theme,
tokens: { global: tokens.global, theme: tokens[theme] },
}}
>
<style id="theme-vars">{themeVars}</style>
{children}
</ThemeContext.Provider>
Expand Down
1 change: 1 addition & 0 deletions src/lib/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './rectangle'
export * from './json_pretty_print'
3 changes: 3 additions & 0 deletions src/lib/components/json_pretty_print/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import JSONPrettyPrint from './json_pretty_print'
export * from './types'
export { JSONPrettyPrint }
19 changes: 19 additions & 0 deletions src/lib/components/json_pretty_print/json_pretty_print.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.JSONPrettyPrintMain {
padding: 5px;
}

.string {
color: green;
}
.number {
color: darkorange;
}
.boolean {
color: blue;
}
.null {
color: magenta;
}
.key {
color: red;
}
21 changes: 21 additions & 0 deletions src/lib/components/json_pretty_print/json_pretty_print.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'

import JSONPrettyPrint from './json_pretty_print'

// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
title: 'Components/JSON Pretty Print',
component: JSONPrettyPrint,
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
// argTypes: {},
} as ComponentMeta<typeof JSONPrettyPrint>

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof JSONPrettyPrint> = (args) => <JSONPrettyPrint {...args} />

export const Default = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Default.args = {
json: { bar: 'Lorem ipsum sic dolor', baz: ['it is a string', { foo: false, sus: null }], bub: 123 },
}
16 changes: 16 additions & 0 deletions src/lib/components/json_pretty_print/json_pretty_print.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @jest-environment jsdom
*/
import React from 'react'
import { render } from '@testing-library/react'
import JSONPrettyPrint from './json_pretty_print'
import '@testing-library/jest-dom'

describe('JSON Pretty Print', () => {
it('should correctly render the component', () => {
const test = { a: 1, b: 2, c: [true, { e: 'var' }] }
const { container } = render(<JSONPrettyPrint json={test} />)
const element = container.querySelector('.JSONPrettyPrintMain')
expect(element).toBeTruthy()
})
})
Loading

0 comments on commit 9ab35c2

Please sign in to comment.