initial commit

This commit is contained in:
2023-11-15 18:41:25 +01:00
commit 555fd347cc
26 changed files with 10168 additions and 0 deletions

12
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,12 @@
module.exports = {
extends: ['@it-incubator/eslint-config','plugin:storybook/recommended'],
overrides: [
{
files: ['**/*.stories.tsx'],
rules: {
'react-hooks/rules-of-hooks': 'off',
'no-console': 'off',
},
},
],
}

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

4
.prettierrc.cjs Normal file
View File

@@ -0,0 +1,4 @@
module.exports = {
...require('@it-incubator/prettier-config'),
//override settings here
}

28
.storybook/main.ts Normal file
View File

@@ -0,0 +1,28 @@
import { dirname, join } from 'path'
import { StorybookConfig } from '@storybook/react-vite'
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(ts|tsx)'],
addons: [
getAbsolutePath('@storybook/addon-links'),
getAbsolutePath('@storybook/addon-interactions'),
getAbsolutePath('@storybook/addon-essentials'),
],
framework: {
name: getAbsolutePath('@storybook/react-vite'),
options: {},
},
docs: {
autodocs: true,
},
viteFinal: config => {
config.build = config.build || {}
config.build.sourcemap = false
return config
},
}
export default config
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, 'package.json')))
}

15
.storybook/preview.ts Normal file
View File

@@ -0,0 +1,15 @@
import type { Preview } from '@storybook/react'
import '../src/styles/index.scss'
const preview: Preview = {
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
}
export default preview

3
.stylelintrc.cjs Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
extends: '@it-incubator/stylelint-config',
}

22
README.md Normal file
View File

@@ -0,0 +1,22 @@
# Usage:
- Clone template: (replace `my-lib` with your project name)
```bash
npx degit https://github.com/ershisan99/lib-with-storybook-starter my-lib
```
- Change directory: (replace `my-lib` with your project name)
```bash
cd my-lib
```
- Install dependencies:
```bash
pnpm i
```
- Run storybook:
```bash
pnpm dev
```

12
index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.ts"></script>
</body>
</html>

43
package.json Normal file
View File

@@ -0,0 +1,43 @@
{
"name": "lib-with-storybook-starter",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "vite",
"dev": "storybook dev -p 6006",
"build": "vite build && tsc",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix",
"preview": "vite preview",
"build-storybook": "storybook build"
},
"dependencies": {
"@radix-ui/react-slider": "^1.1.2",
"clsx": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@it-incubator/eslint-config": "^1.0.1",
"@it-incubator/prettier-config": "^0.1.2",
"@it-incubator/stylelint-config": "^0.1.5",
"@storybook/addon-essentials": "7.5.3",
"@storybook/addon-interactions": "7.5.3",
"@storybook/addon-links": "7.5.3",
"@storybook/blocks": "7.5.3",
"@storybook/react": "7.5.3",
"@storybook/react-vite": "7.5.3",
"@storybook/testing-library": "0.2.2",
"@types/node": "^20.9.0",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@vitejs/plugin-react": "^4.0.3",
"eslint-plugin-storybook": "^0.6.15",
"sass": "^1.69.5",
"storybook": "7.5.3",
"stylelint": "^15.11.0",
"typescript": "^5.2.2",
"vite": "^4.5.0"
}
}

9647
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
.button {
all: unset;
cursor: pointer;
box-sizing: border-box;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
&:focus-visible {
outline: 2px solid lightcoral;
outline-offset: 2px;
}
}
.fullWidth {
width: 100%;
}
.primary {
color: white;
background-color: blue;
}
.secondary {
color: black;
background-color: lightblue;
}
.tertiary {
color: blue;
border: 1px solid blue;
}
.link {
color: blue;
text-decoration: underline;
}
.icon {
width: 1.5rem;
height: 1.5rem;
}

View File

@@ -0,0 +1,69 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './'
const meta = {
argTypes: {
onClick: { action: 'clicked' },
variant: {
control: { type: 'radio' },
options: ['primary', 'secondary', 'tertiary', 'link'],
},
},
component: Button,
tags: ['autodocs'],
title: 'Components/Button',
} satisfies Meta<typeof Button>
export default meta
type Story = StoryObj<typeof meta>
export const Primary: Story = {
args: {
children: 'Primary Button',
disabled: false,
variant: 'primary',
},
}
export const Secondary: Story = {
args: {
children: 'Secondary Button',
disabled: false,
variant: 'secondary',
},
}
export const Tertiary: Story = {
args: {
children: 'Tertiary Button',
disabled: false,
variant: 'tertiary',
},
}
export const Link: Story = {
args: {
children: 'Button that looks like a link',
disabled: false,
variant: 'link',
},
}
export const FullWidth: Story = {
args: {
children: 'Full Width Button',
disabled: false,
fullWidth: true,
variant: 'primary',
},
}
export const AsLink: Story = {
args: {
as: 'a',
children: 'Link that looks like a button',
href: 'https://google.com',
rel: 'noopener noreferrer',
target: '_blank',
variant: 'primary',
},
}

View File

@@ -0,0 +1,23 @@
import { ComponentPropsWithoutRef, ElementType } from 'react'
import { clsx } from 'clsx'
import s from './button.module.scss'
export const buttonVariant = ['icon', 'link', 'primary', 'secondary', 'tertiary'] as const
export type ButtonVariant = (typeof buttonVariant)[number]
export type ButtonProps<T extends ElementType = 'button'> = {
as?: T
fullWidth?: boolean
variant?: ButtonVariant
} & ComponentPropsWithoutRef<T>
export const Button = <T extends ElementType = 'button'>(props: ButtonProps<T>) => {
const { as: Component = 'button', className, fullWidth, variant = 'primary', ...rest } = props
const classNames = clsx(s.button, s[variant], fullWidth && s.fullWidth, className)
return <Component className={classNames} {...rest} />
}

View File

@@ -0,0 +1 @@
export * from './button'

2
src/components/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from './button'
export * from './slider'

View File

@@ -0,0 +1 @@
export * from './slider'

View File

@@ -0,0 +1,52 @@
.container {
display: flex;
gap: 10px;
align-items: center;
justify-content: center;
width: 100%;
}
.root {
touch-action: none;
user-select: none;
position: relative;
display: flex;
align-items: center;
width: 100%;
}
.track {
position: relative;
width: 100%;
height: 4px;
opacity: 0.5;
background-color: var(--color-accent-500);
border-radius: 2px;
}
.range {
position: absolute;
height: 100%;
background-color: var(--color-accent-500);
}
.thumb {
touch-action: pan-x;
cursor: pointer;
display: block;
width: 16px;
height: 16px;
background-color: var(--color-light-100);
border-radius: 9999px;
transition: transform 0.2s ease-in-out;
}

View File

@@ -0,0 +1,43 @@
import { ComponentPropsWithoutRef, ElementRef, forwardRef, useEffect } from 'react'
import * as SliderPrimitive from '@radix-ui/react-slider'
import { clsx } from 'clsx'
import s from './slider.module.scss'
const Slider = forwardRef<
ElementRef<typeof SliderPrimitive.Root>,
Omit<ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, 'value'> & {
value?: (number | undefined)[]
}
>(({ className, max, onValueChange, value, ...props }, ref) => {
useEffect(() => {
if (value?.[1] === undefined || value?.[1] === null) {
onValueChange?.([value?.[0] ?? 0, max ?? 0])
}
}, [max, value, onValueChange])
return (
<div className={s.container}>
<span>{value?.[0]}</span>
<SliderPrimitive.Root
className={clsx(s.root, className)}
max={max}
onValueChange={onValueChange}
ref={ref}
{...props}
value={[value?.[0] ?? 0, value?.[1] ?? max ?? 0]}
>
<SliderPrimitive.Track className={s.track}>
<SliderPrimitive.Range className={'absolute h-full bg-primary'} />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className={s.thumb} />
<SliderPrimitive.Thumb className={s.thumb} />
</SliderPrimitive.Root>
<span>{value?.[1]}</span>
</div>
)
})
Slider.displayName = SliderPrimitive.Root.displayName
export { Slider }

4
src/index.ts Normal file
View File

@@ -0,0 +1,4 @@
import './styles/index.scss'
export * from './components'
export { clsx } from 'clsx'

View File

@@ -0,0 +1,30 @@
html {
box-sizing: border-box;
font-size: 100%;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
input,
button,
select,
textarea,
optgroup,
option {
font-family: inherit;
font-size: inherit;
font-weight: inherit;
font-style: inherit;
color: inherit;
}
body {
margin: 0;
padding: 0;
font-family: var(--font-family);
line-height: var(--line-height-m);
}

View File

@@ -0,0 +1,22 @@
:root {
/* globals */
--font-family: system-ui, sans-serif;
/* font-sizes */
--font-size-xs: 12px;
--font-size-s: 14px;
--font-size-m: 16px;
--font-size-l: 18px;
--font-size-xl: 20px;
--font-size-xxl: 22px;
/* line-heights */
--line-height-m: 24px;
--line-height-xl: 36px;
/* font-weights */
--font-weight-regular: 400;
--font-weight-medium: 500;
--font-weight-semi-bold: 600;
--font-weight-bold: 700;
}

2
src/styles/index.scss Normal file
View File

@@ -0,0 +1,2 @@
@forward 'typography';
@forward 'boilerplate';

1
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

27
tsconfig.json Normal file
View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": false,
"resolveJsonModule": true,
"isolatedModules": true,
"outDir": "dist",
"emitDeclarationOnly": true,
"declaration": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

10
tsconfig.node.json Normal file
View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts", "package.json"]
}

27
vite.config.ts Normal file
View File

@@ -0,0 +1,27 @@
import { resolve } from 'path'
import { defineConfig } from 'vite'
import { dependencies, devDependencies } from './package.json'
// https://vitejs.dev/config/
export default defineConfig({
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(__dirname, 'src/index.ts'),
// the proper extensions will be added
fileName: 'index',
formats: ['es'],
name: 'live-bundlers',
},
rollupOptions: {
external: [
'react/jsx-runtime',
...Object.keys(dependencies),
...Object.keys(devDependencies),
],
},
sourcemap: true,
target: 'esnext',
},
})