@mohammadsalman/storybook-custom-ui 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,189 +1,146 @@
1
- # Storybook Component Library
1
+ # @mohammadsalman/storybook-custom-ui
2
2
 
3
- A minimal React TypeScript component library with Storybook, featuring a flexible theming system.
3
+ A minimal React TypeScript component library with Storybook, featuring reusable UI components built with React 19 and TypeScript.
4
4
 
5
- ## Features
5
+ ## Installation
6
6
 
7
- - Button component with multiple variants, colors, and sizes
8
- - ✅ Custom `useFormInput` hook for form input management
9
- - ✅ TypeScript support with full type safety
10
- - ✅ Theming system that can be adapted to any project
11
- - ✅ Storybook with interactive controls
12
- - ✅ Zero external UI library dependencies
13
-
14
- ## Getting Started
15
-
16
- ### Installation
7
+ ### Install via npm
17
8
 
18
9
  ```bash
19
- npm install
10
+ npm install @mohammadsalman/storybook-custom-ui
20
11
  ```
21
12
 
22
- ### Running Storybook
13
+ ### Install via yarn
23
14
 
24
15
  ```bash
25
- npm run storybook
16
+ yarn add @mohammadsalman/storybook-custom-ui
26
17
  ```
27
18
 
28
- This will start Storybook on `http://localhost:6006`
29
-
30
- ### Building Storybook
19
+ ### Install via pnpm
31
20
 
32
21
  ```bash
33
- npm run build-storybook
22
+ pnpm add @mohammadsalman/storybook-custom-ui
34
23
  ```
35
24
 
36
- ## Theming System
25
+ ## Peer Dependencies
37
26
 
38
- The theming system is designed to be easily adaptable to any project. All components use the theme through the `useTheme` hook.
27
+ This package requires React 19.2.0 or higher. Make sure you have the following installed in your project:
39
28
 
40
- ### Default Theme
29
+ ```bash
30
+ npm install react@^19.2.0 react-dom@^19.2.0
31
+ ```
41
32
 
42
- The default theme is located in `src/theme/defaultTheme.ts`. It includes:
33
+ ## Usage
43
34
 
44
- - **Palette**: Colors for primary, secondary, success, error, warning, info, and grey scales
45
- - **Typography**: Font families, sizes, weights, and line heights for all text variants
46
- - **Spacing**: Consistent spacing unit (default: 8px)
47
- - **Shadows**: Elevation shadows (0-24)
48
- - **Shape**: Border radius values
49
- - **Z-Index**: Layering system
35
+ ### Import Components
50
36
 
51
- ### Using the Theme
37
+ ```tsx
38
+ import { Button } from '@mohammadsalman/storybook-custom-ui';
39
+ ```
52
40
 
53
- Wrap your application with the `ThemeProvider`:
41
+ ### Example
54
42
 
55
43
  ```tsx
56
- import { ThemeProvider, defaultTheme } from './theme';
44
+ import React from 'react';
45
+ import { Button } from '@mohammadsalman/storybook-custom-ui';
57
46
 
58
47
  function App() {
59
48
  return (
60
- <ThemeProvider theme={defaultTheme}>
61
- <YourComponents />
62
- </ThemeProvider>
49
+ <div>
50
+ <Button
51
+ primary={true}
52
+ size="large"
53
+ label="Click me"
54
+ onClick={() => console.log('Button clicked!')}
55
+ />
56
+ </div>
63
57
  );
64
58
  }
59
+
60
+ export default App;
65
61
  ```
66
62
 
67
- ## Available Components
63
+ ## Development
68
64
 
69
- ### Button
65
+ ### Prerequisites
70
66
 
71
- A versatile button component with multiple variants, colors, and sizes.
67
+ - Node.js 18+
68
+ - npm, yarn, or pnpm
72
69
 
73
- ```tsx
74
- import { Button } from './components';
70
+ ### Setup
75
71
 
76
- <Button variant="contained" color="primary" size="medium">
77
- Click Me
78
- </Button>
72
+ 1. Clone the repository:
73
+ ```bash
74
+ git clone https://github.com/MohSalman/creative-ui-react-ui-library.git
75
+ cd creative-ui-react-ui-library
79
76
  ```
80
77
 
81
- **Props:**
82
- - `variant`: 'contained' | 'outlined' | 'text'
83
- - `color`: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info'
84
- - `size`: 'small' | 'medium' | 'large'
85
- - `fullWidth`: boolean
86
- - `disabled`: boolean
87
-
88
- ## Available Hooks
78
+ 2. Install dependencies:
79
+ ```bash
80
+ npm install
81
+ ```
89
82
 
90
- ### useFormInput
83
+ 3. Start Storybook to view components:
84
+ ```bash
85
+ npm run storybook
86
+ ```
91
87
 
92
- A custom hook for managing form input state, validation, and error handling.
88
+ This will start Storybook on `http://localhost:6006`
93
89
 
94
- ```tsx
95
- import { useFormInput } from './hooks';
96
-
97
- const MyForm = () => {
98
- const emailInput = useFormInput({
99
- initialValue: '',
100
- validate: (value) => {
101
- if (!value) return 'Email is required';
102
- if (!/\S+@\S+\.\S+/.test(value)) return 'Invalid email format';
103
- return null;
104
- }
105
- });
90
+ ### Build
106
91
 
107
- return (
108
- <div>
109
- <input
110
- value={emailInput.value}
111
- onChange={emailInput.onChange}
112
- onBlur={emailInput.onBlur}
113
- />
114
- {emailInput.error && <span>{emailInput.error}</span>}
115
- <button onClick={emailInput.reset}>Reset</button>
116
- </div>
117
- );
118
- };
92
+ Build the library:
93
+ ```bash
94
+ npm run build
119
95
  ```
120
96
 
121
- **Options:**
122
- - `initialValue`: string (default: '')
123
- - `validate`: (value: string) => string | null
124
- - `onChange`: (value: string) => void (optional callback)
125
-
126
- **Returns:**
127
- - `value`: string
128
- - `error`: string | null
129
- - `onChange`: (e: ChangeEvent) => void
130
- - `onBlur`: () => void
131
- - `setValue`: (value: string) => void
132
- - `setError`: (error: string | null) => void
133
- - `reset`: () => void
134
- - `isValid`: boolean
97
+ This will create the `dist/` folder with the compiled files.
135
98
 
136
- ## Project Structure
99
+ ### Preview
137
100
 
101
+ Preview the built application:
102
+ ```bash
103
+ npm run preview
138
104
  ```
139
- src/
140
- ├── components/ # UI components
141
- │ └── Button/
142
- │ ├── Button.tsx
143
- │ ├── Button.stories.tsx
144
- │ └── index.ts
145
- ├── hooks/ # Custom hooks
146
- │ ├── useFormInput.ts
147
- │ ├── useFormInput.stories.tsx
148
- │ └── index.ts
149
- ├── theme/ # Theming system
150
- │ ├── types.ts
151
- │ ├── defaultTheme.ts
152
- │ ├── ThemeProvider.tsx
153
- │ └── index.ts
154
- └── utils/ # Utility functions
155
- └── styles.ts
156
- .storybook/ # Storybook configuration
157
- ├── main.ts
158
- ├── preview.tsx
159
- └── global.css
105
+
106
+ ### Lint
107
+
108
+ Run ESLint:
109
+ ```bash
110
+ npm run lint
160
111
  ```
161
112
 
162
- ## Adding New Components
113
+ ## Available Scripts
163
114
 
164
- To add a new component:
115
+ - `npm run dev` - Start Vite development server
116
+ - `npm run build` - Build the library for production
117
+ - `npm run lint` - Run ESLint
118
+ - `npm run preview` - Preview the built application
119
+ - `npm run storybook` - Start Storybook development server
120
+ - `npm run build-storybook` - Build Storybook for static hosting
165
121
 
166
- 1. Create a new directory in `src/components/`
167
- 2. Add your component file (e.g., `MyComponent.tsx`)
168
- 3. Create an `index.ts` file that exports your component
169
- 4. Create a `MyComponent.stories.tsx` file for Storybook
170
- 5. Export from `src/components/index.ts`
122
+ ## Project Structure
171
123
 
172
- ## Adding New Hooks
124
+ ```
125
+ src/
126
+ ├── stories/ # Storybook stories and components
127
+ │ ├── Button/
128
+ │ ├── Header/
129
+ │ └── Page/
130
+ ├── index.ts # Main entry point
131
+ └── ...
132
+ .storybook/ # Storybook configuration
133
+ dist/ # Built files (generated)
134
+ ```
173
135
 
174
- To add a new hook:
136
+ ## License
175
137
 
176
- 1. Create a new file in `src/hooks/` (e.g., `useMyHook.ts`)
177
- 2. Export from `src/hooks/index.ts`
178
- 3. Optionally create a `useMyHook.stories.tsx` file for Storybook
138
+ MIT
179
139
 
180
- ## Adapting to Your Project
140
+ ## Author
181
141
 
182
- To use these components and hooks in your project:
142
+ Mohammad Salman <mohammadsalman71993@gmail.com>
183
143
 
184
- 1. Copy the `src/components`, `src/hooks`, `src/theme`, and `src/utils` directories to your project
185
- 2. Create your custom theme based on your design system
186
- 3. Wrap your app with `ThemeProvider` using your custom theme
187
- 4. Import and use components and hooks as needed
144
+ ## Repository
188
145
 
189
- The theme system is designed to be flexible - you can override any part of it to match your brand colors, typography, spacing, and more.
146
+ [https://github.com/MohSalman/creative-ui-react-ui-library](https://github.com/MohSalman/creative-ui-react-ui-library)
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+
package/dist/vite.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/package.json CHANGED
@@ -1,56 +1,64 @@
1
1
  {
2
2
  "name": "@mohammadsalman/storybook-custom-ui",
3
- "version": "1.0.1",
4
3
  "description": "A minimal React TypeScript component library with Button component and useFormInput hook",
5
- "main":"src/index.ts",
6
- "module": "src/index.ts",
7
- "types": "src/index.ts",
8
- "files": [
9
- "src"
10
- ],
11
- "keywords": [
12
- "react",
13
- "typescript",
14
- "components",
15
- "hooks",
16
- "storybook",
17
- "button",
18
- "form-input"
19
- ],
4
+
5
+ "version": "1.0.3",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.esm.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": ["dist"],
10
+
11
+ "keywords": ["react", "typescript", "components", "storybook"],
20
12
  "author": "Mohammad Salman <mohammadsalman71993@gmail.com>",
21
13
  "license": "MIT",
22
14
  "repository": {
23
15
  "type": "git",
24
16
  "url": "https://github.com/MohSalman/creative-ui-react-ui-library.git"
25
17
  },
26
- "runkit": {
27
- "exampleFilename": "./src/index.ts"
18
+ "type": "module",
19
+ "scripts": {
20
+ "dev": "vite",
21
+ "build": "tsc -b && vite build",
22
+ "lint": "eslint .",
23
+ "preview": "vite preview",
24
+ "storybook": "storybook dev -p 6006",
25
+ "build-storybook": "storybook build"
28
26
  },
27
+
29
28
  "peerDependencies": {
30
- "react": "^18.2.0",
31
- "react-dom": "^18.2.0"
29
+ "react": "^19.2.0",
30
+ "react-dom": "^19.2.0"
32
31
  },
33
- "scripts": {
34
- "storybook": "storybook dev -p 6006",
35
- "build-storybook": "storybook build",
36
- "prepublishOnly": "npm run build-storybook"
32
+
33
+ "dependencies": {
34
+ "react": "^19.2.0",
35
+ "react-dom": "^19.2.0"
37
36
  },
38
- "dependencies": {},
37
+
39
38
  "devDependencies": {
40
- "react": "^18.2.0",
41
- "react-dom": "^18.2.0",
42
- "@babel/preset-react": "^7.28.5",
43
- "@babel/preset-typescript": "^7.28.5",
44
- "@storybook/addon-essentials": "^7.6.5",
45
- "@storybook/addon-interactions": "^7.6.5",
46
- "@storybook/addon-links": "^7.6.5",
47
- "@storybook/blocks": "^7.6.5",
48
- "@storybook/react": "^7.6.5",
49
- "@storybook/react-webpack5": "^7.6.5",
50
- "@storybook/test": "^7.6.5",
51
- "@types/react": "^18.2.43",
52
- "@types/react-dom": "^18.2.17",
53
- "storybook": "^7.6.5",
54
- "typescript": "^5.3.3"
39
+ "@eslint/js": "^9.39.1",
40
+ "@types/node": "^24.10.1",
41
+ "@types/react": "^19.2.5",
42
+ "@types/react-dom": "^19.2.3",
43
+ "@vitejs/plugin-react": "^5.1.1",
44
+ "eslint": "^9.39.1",
45
+ "eslint-plugin-react-hooks": "^7.0.1",
46
+ "eslint-plugin-react-refresh": "^0.4.24",
47
+ "globals": "^16.5.0",
48
+ "typescript": "~5.9.3",
49
+ "typescript-eslint": "^8.46.4",
50
+ "vite": "^7.2.4",
51
+ "storybook": "^10.1.11",
52
+ "@storybook/react-vite": "^10.1.11",
53
+ "@chromatic-com/storybook": "^5.0.0",
54
+ "@storybook/addon-vitest": "^10.1.11",
55
+ "@storybook/addon-a11y": "^10.1.11",
56
+ "@storybook/addon-docs": "^10.1.11",
57
+ "@storybook/addon-onboarding": "^10.1.11",
58
+ "eslint-plugin-storybook": "^10.1.11",
59
+ "vitest": "^4.0.17",
60
+ "playwright": "^1.57.0",
61
+ "@vitest/browser-playwright": "^4.0.17",
62
+ "@vitest/coverage-v8": "^4.0.17"
55
63
  }
56
64
  }
@@ -1,109 +0,0 @@
1
- import { Meta, StoryObj } from '@storybook/react';
2
- import { Button } from './Button';
3
-
4
- const meta: Meta<typeof Button> = {
5
- title: 'Components/Button',
6
- component: Button,
7
- tags: ['autodocs'],
8
- argTypes: {
9
- variant: {
10
- control: { type: 'select' },
11
- options: ['contained', 'outlined', 'text'],
12
- },
13
- color: {
14
- control: { type: 'select' },
15
- options: ['primary', 'secondary', 'success', 'error', 'warning', 'info'],
16
- },
17
- size: {
18
- control: { type: 'select' },
19
- options: ['small', 'medium', 'large'],
20
- },
21
- fullWidth: {
22
- control: { type: 'boolean' },
23
- },
24
- disabled: {
25
- control: { type: 'boolean' },
26
- },
27
- },
28
- };
29
-
30
- export default meta;
31
- type Story = StoryObj<typeof Button>;
32
-
33
- export const Contained: Story = {
34
- args: {
35
- children: 'Button',
36
- variant: 'contained',
37
- color: 'primary',
38
- size: 'medium',
39
- },
40
- };
41
-
42
- export const Outlined: Story = {
43
- args: {
44
- children: 'Button',
45
- variant: 'outlined',
46
- color: 'primary',
47
- size: 'medium',
48
- },
49
- };
50
-
51
- export const Text: Story = {
52
- args: {
53
- children: 'Button',
54
- variant: 'text',
55
- color: 'primary',
56
- size: 'medium',
57
- },
58
- };
59
-
60
- export const Colors: Story = {
61
- render: () => (
62
- <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
63
- <Button color="primary">Primary</Button>
64
- <Button color="secondary">Secondary</Button>
65
- <Button color="success">Success</Button>
66
- <Button color="error">Error</Button>
67
- <Button color="warning">Warning</Button>
68
- <Button color="info">Info</Button>
69
- </div>
70
- ),
71
- };
72
-
73
- export const Sizes: Story = {
74
- render: () => (
75
- <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
76
- <Button size="small">Small</Button>
77
- <Button size="medium">Medium</Button>
78
- <Button size="large">Large</Button>
79
- </div>
80
- ),
81
- };
82
-
83
- export const Variants: Story = {
84
- render: () => (
85
- <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
86
- <Button variant="contained">Contained</Button>
87
- <Button variant="outlined">Outlined</Button>
88
- <Button variant="text">Text</Button>
89
- </div>
90
- ),
91
- };
92
-
93
- export const FullWidth: Story = {
94
- args: {
95
- children: 'Full Width Button',
96
- fullWidth: true,
97
- variant: 'contained',
98
- },
99
- };
100
-
101
- export const Disabled: Story = {
102
- render: () => (
103
- <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
104
- <Button variant="contained" disabled>Disabled</Button>
105
- <Button variant="outlined" disabled>Disabled</Button>
106
- <Button variant="text" disabled>Disabled</Button>
107
- </div>
108
- ),
109
- };
@@ -1,144 +0,0 @@
1
- import React from 'react';
2
- import { useTheme } from '../../theme';
3
- import { spacing } from '../../utils/styles';
4
-
5
- export type ButtonVariant = 'contained' | 'outlined' | 'text';
6
- export type ButtonColor = 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info';
7
- export type ButtonSize = 'small' | 'medium' | 'large';
8
-
9
- export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
10
- variant?: ButtonVariant;
11
- color?: ButtonColor;
12
- size?: ButtonSize;
13
- fullWidth?: boolean;
14
- disabled?: boolean;
15
- children: React.ReactNode;
16
- }
17
-
18
- export const Button: React.FC<ButtonProps> = ({
19
- variant = 'contained',
20
- color = 'primary',
21
- size = 'medium',
22
- fullWidth = false,
23
- disabled = false,
24
- children,
25
- style,
26
- ...props
27
- }) => {
28
- const theme = useTheme();
29
-
30
- const getVariantStyles = (): React.CSSProperties => {
31
- const colorValue = theme.palette[color][500];
32
- const textColor = variant === 'contained' ? '#ffffff' : colorValue;
33
-
34
- switch (variant) {
35
- case 'contained':
36
- return {
37
- backgroundColor: colorValue,
38
- color: textColor,
39
- border: 'none',
40
- boxShadow: theme.shadows[2],
41
- };
42
- case 'outlined':
43
- return {
44
- backgroundColor: 'transparent',
45
- color: colorValue,
46
- border: `1px solid ${colorValue}`,
47
- boxShadow: 'none',
48
- };
49
- case 'text':
50
- return {
51
- backgroundColor: 'transparent',
52
- color: colorValue,
53
- border: 'none',
54
- boxShadow: 'none',
55
- };
56
- default:
57
- return {};
58
- }
59
- };
60
-
61
- const getSizeStyles = (): React.CSSProperties => {
62
- switch (size) {
63
- case 'small':
64
- return {
65
- padding: spacing(theme, 0.5, 1.5),
66
- fontSize: theme.typography.button.fontSize,
67
- minWidth: '64px',
68
- };
69
- case 'medium':
70
- return {
71
- padding: spacing(theme, 1, 2),
72
- fontSize: theme.typography.button.fontSize,
73
- minWidth: '64px',
74
- };
75
- case 'large':
76
- return {
77
- padding: spacing(theme, 1.5, 3),
78
- fontSize: '1rem',
79
- minWidth: '64px',
80
- };
81
- default:
82
- return {};
83
- }
84
- };
85
-
86
- const baseStyles: React.CSSProperties = {
87
- fontFamily: theme.typography.button.fontFamily,
88
- fontWeight: theme.typography.button.fontWeight,
89
- lineHeight: theme.typography.button.lineHeight,
90
- letterSpacing: theme.typography.button.letterSpacing,
91
- textTransform: 'uppercase',
92
- borderRadius: `${theme.shape.borderRadius}px`,
93
- cursor: disabled ? 'not-allowed' : 'pointer',
94
- outline: 'none',
95
- transition: 'background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, border-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
96
- width: fullWidth ? '100%' : 'auto',
97
- opacity: disabled ? 0.6 : 1,
98
- ...getVariantStyles(),
99
- ...getSizeStyles(),
100
- ...style,
101
- };
102
-
103
- const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
104
- if (!disabled && props.onMouseEnter) {
105
- props.onMouseEnter(e);
106
- }
107
- };
108
-
109
- const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {
110
- if (!disabled && props.onMouseLeave) {
111
- props.onMouseLeave(e);
112
- }
113
- };
114
-
115
- return (
116
- <button
117
- {...props}
118
- disabled={disabled}
119
- style={baseStyles}
120
- onMouseEnter={handleMouseEnter}
121
- onMouseLeave={handleMouseLeave}
122
- onMouseOver={(e) => {
123
- if (!disabled) {
124
- e.currentTarget.style.backgroundColor =
125
- variant === 'contained'
126
- ? theme.palette[color][700]
127
- : variant === 'outlined'
128
- ? theme.palette.action.hover
129
- : theme.palette.action.hover;
130
- }
131
- }}
132
- onMouseOut={(e) => {
133
- if (!disabled) {
134
- e.currentTarget.style.backgroundColor =
135
- variant === 'contained'
136
- ? theme.palette[color][500]
137
- : 'transparent';
138
- }
139
- }}
140
- >
141
- {children}
142
- </button>
143
- );
144
- };
@@ -1 +0,0 @@
1
- export * from './Button';