@gadagi/design-system 1.0.0

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/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@gadagi/design-system",
3
+ "version": "1.0.0",
4
+ "description": "Design system for gadagi micro-frontends",
5
+ "main": "src/index.ts",
6
+ "module": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.ts",
11
+ "default": "./src/index.ts"
12
+ }
13
+ },
14
+ "files": ["src"],
15
+ "scripts": {
16
+ "build": "tsc && echo 'export * from \"./src/index\";' > dist/adi-design-system/index.js",
17
+ "dev": "tsc --watch"
18
+ },
19
+ "peerDependencies": {
20
+ "react": "^19.0.0",
21
+ "react-dom": "^19.0.0"
22
+ },
23
+ "dependencies": {
24
+ "@gadagi/types": "^1.0.1"
25
+ },
26
+ "devDependencies": {
27
+ "@types/react": "^19.0.0",
28
+ "@types/react-dom": "^19.0.0",
29
+ "css-loader": "^7.0.0",
30
+ "react": "^19.0.0",
31
+ "react-dom": "^19.0.0",
32
+ "style-loader": "^4.0.0",
33
+ "ts-loader": "^9.0.0",
34
+ "typescript": "^5.0.0",
35
+ "webpack": "^5.0.0",
36
+ "webpack-cli": "^5.0.0"
37
+ }
38
+ }
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { colors, spacing, typography } from '../../tokens';
3
+
4
+ type BadgeVariant = 'default' | 'success' | 'warning' | 'danger' | 'info';
5
+
6
+ interface BadgeProps {
7
+ children: React.ReactNode;
8
+ variant?: BadgeVariant;
9
+ }
10
+
11
+ const badgeColors: Record<BadgeVariant, { bg: string; text: string }> = {
12
+ default: { bg: colors.neutral[100], text: colors.neutral[600] },
13
+ success: { bg: colors.success[100], text: '#15803d' },
14
+ warning: { bg: colors.warning[100], text: '#92400e' },
15
+ danger: { bg: colors.danger[100], text: '#b91c1c' },
16
+ info: { bg: colors.primary[100], text: colors.primary[700] },
17
+ };
18
+
19
+ export const Badge: React.FC<BadgeProps> = ({ children, variant = 'default' }) => {
20
+ const { bg, text } = badgeColors[variant];
21
+ return (
22
+ <span
23
+ style={{
24
+ display: 'inline-flex',
25
+ alignItems: 'center',
26
+ padding: `${spacing[0]} ${spacing[2]}`,
27
+ borderRadius: '9999px',
28
+ fontSize: typography.fontSize.xs,
29
+ fontWeight: typography.fontWeight.medium,
30
+ background: bg,
31
+ color: text,
32
+ }}
33
+ >
34
+ {children}
35
+ </span>
36
+ );
37
+ };
@@ -0,0 +1 @@
1
+ export { Badge } from './Badge';
@@ -0,0 +1,59 @@
1
+ import React, { ButtonHTMLAttributes } from 'react';
2
+ import { colors, spacing, typography } from '../../tokens';
3
+
4
+ type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'ghost';
5
+ type ButtonSize = 'sm' | 'md' | 'lg';
6
+
7
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
8
+ variant?: ButtonVariant;
9
+ size?: ButtonSize;
10
+ loading?: boolean;
11
+ fullWidth?: boolean;
12
+ }
13
+
14
+ const sizeStyles: Record<ButtonSize, React.CSSProperties> = {
15
+ sm: { padding: `${spacing[1]} ${spacing[3]}`, fontSize: typography.fontSize.sm },
16
+ md: { padding: `${spacing[2]} ${spacing[4]}`, fontSize: typography.fontSize.base },
17
+ lg: { padding: `${spacing[3]} ${spacing[6]}`, fontSize: typography.fontSize.lg },
18
+ };
19
+
20
+ const variantStyles: Record<ButtonVariant, React.CSSProperties> = {
21
+ primary: { background: colors.primary[600], color: '#fff', border: 'none' },
22
+ secondary: { background: 'transparent', color: colors.primary[600], border: `1px solid ${colors.primary[600]}` },
23
+ danger: { background: colors.danger[500], color: '#fff', border: 'none' },
24
+ ghost: { background: 'transparent', color: colors.neutral[600], border: 'none' },
25
+ };
26
+
27
+ export const Button: React.FC<ButtonProps> = ({
28
+ variant = 'primary',
29
+ size = 'md',
30
+ loading = false,
31
+ fullWidth = false,
32
+ children,
33
+ disabled,
34
+ style,
35
+ ...rest
36
+ }) => {
37
+ const baseStyle: React.CSSProperties = {
38
+ display: 'inline-flex',
39
+ alignItems: 'center',
40
+ justifyContent: 'center',
41
+ gap: spacing[2],
42
+ borderRadius: '6px',
43
+ fontWeight: typography.fontWeight.medium,
44
+ fontFamily: typography.fontFamily.sans,
45
+ cursor: disabled || loading ? 'not-allowed' : 'pointer',
46
+ opacity: disabled || loading ? 0.6 : 1,
47
+ width: fullWidth ? '100%' : undefined,
48
+ transition: 'opacity 0.15s, transform 0.1s',
49
+ ...sizeStyles[size],
50
+ ...variantStyles[variant],
51
+ ...style,
52
+ };
53
+
54
+ return (
55
+ <button style={baseStyle} disabled={disabled || loading} {...rest}>
56
+ {loading ? 'Loading...' : children}
57
+ </button>
58
+ );
59
+ };
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ export type { } from './Button';
@@ -0,0 +1,55 @@
1
+ import React, { InputHTMLAttributes } from 'react';
2
+ import { colors, spacing, typography } from '../../tokens';
3
+
4
+ interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
5
+ label?: string;
6
+ error?: string;
7
+ hint?: string;
8
+ fullWidth?: boolean;
9
+ }
10
+
11
+ export const Input: React.FC<InputProps> = ({
12
+ label,
13
+ error,
14
+ hint,
15
+ fullWidth = false,
16
+ id,
17
+ style,
18
+ ...rest
19
+ }) => {
20
+ const inputId = id ?? label?.toLowerCase().replace(/\s+/g, '-');
21
+
22
+ const inputStyle: React.CSSProperties = {
23
+ display: 'block',
24
+ width: fullWidth ? '100%' : undefined,
25
+ padding: `${spacing[2]} ${spacing[3]}`,
26
+ fontSize: typography.fontSize.base,
27
+ fontFamily: typography.fontFamily.sans,
28
+ borderRadius: '6px',
29
+ border: `1px solid ${error ? colors.danger[500] : colors.neutral[200]}`,
30
+ outline: 'none',
31
+ background: '#fff',
32
+ color: colors.neutral[900],
33
+ ...style,
34
+ };
35
+
36
+ return (
37
+ <div style={{ display: 'flex', flexDirection: 'column', gap: spacing[1] }}>
38
+ {label && (
39
+ <label
40
+ htmlFor={inputId}
41
+ style={{ fontSize: typography.fontSize.sm, fontWeight: typography.fontWeight.medium, color: colors.neutral[600] }}
42
+ >
43
+ {label}
44
+ </label>
45
+ )}
46
+ <input id={inputId} style={inputStyle} {...rest} />
47
+ {error && (
48
+ <span style={{ fontSize: typography.fontSize.xs, color: colors.danger[500] }}>{error}</span>
49
+ )}
50
+ {hint && !error && (
51
+ <span style={{ fontSize: typography.fontSize.xs, color: colors.neutral[400] }}>{hint}</span>
52
+ )}
53
+ </div>
54
+ );
55
+ };
@@ -0,0 +1 @@
1
+ export { Input } from './Input';
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { Button } from './components/Button';
2
+ export { Input } from './components/Input';
3
+ export { Badge } from './components/Badge';
4
+ export { ThemeProvider } from './theme/ThemeProvider';
5
+ export { useTheme } from './theme/useTheme';
6
+ export * from './tokens';
@@ -0,0 +1,27 @@
1
+ import React, { createContext, useContext, useState, ReactNode } from 'react';
2
+ import { ThemeContextValue, Theme } from './interfaces/theme.interface'
3
+
4
+ const ThemeContext = createContext<ThemeContextValue>({
5
+ theme: 'system',
6
+ setTheme: () => {},
7
+ });
8
+
9
+ interface ThemeProviderProps {
10
+ children: ReactNode;
11
+ defaultTheme?: Theme;
12
+ }
13
+
14
+ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
15
+ children,
16
+ defaultTheme = 'system',
17
+ }) => {
18
+ const [theme, setTheme] = useState<Theme>(defaultTheme);
19
+
20
+ return (
21
+ <ThemeContext.Provider value={{ theme, setTheme }}>
22
+ <div data-theme={theme}>{children}</div>
23
+ </ThemeContext.Provider>
24
+ );
25
+ };
26
+
27
+ export const useTheme = (): ThemeContextValue => useContext(ThemeContext);
@@ -0,0 +1,9 @@
1
+
2
+ import { UserPreferences } from '@gadagi/types';
3
+
4
+ export type Theme = UserPreferences['theme'];
5
+
6
+ export interface ThemeContextValue {
7
+ theme: Theme;
8
+ setTheme: (theme: Theme) => void;
9
+ }
@@ -0,0 +1 @@
1
+ export { useTheme } from './ThemeProvider';
@@ -0,0 +1,77 @@
1
+ export const colors = {
2
+ primary: {
3
+ 50: '#f0f0ff',
4
+ 100: '#e6e6ff',
5
+ 500: '#4a3fb5', // WCAG compliant version of #5447c7
6
+ 600: '#4235a3',
7
+ 700: '#3a2c91',
8
+ 900: '#2a1f5f',
9
+ },
10
+ neutral: {
11
+ 50: '#f8fafc',
12
+ 100: '#ebedef', // Your lightColor
13
+ 200: '#e2e8f0',
14
+ 400: '#94a3b8',
15
+ 600: '#4b5463', // Your darkColor
16
+ 800: '#1e293b',
17
+ 900: '#0f172a',
18
+ },
19
+ success: {
20
+ 500: '#2fb855', // WCAG compliant version of #36cd69
21
+ 100: '#dcfce7',
22
+ },
23
+ warning: {
24
+ 500: '#e6a110', // WCAG compliant version of #f9b115
25
+ 100: '#fef3c7',
26
+ },
27
+ danger: {
28
+ 500: '#dc4c4c', // WCAG compliant version of #e55353
29
+ 100: '#fee2e2',
30
+ },
31
+ info: {
32
+ 500: '#2d7fd8', // WCAG compliant version of #3090f1
33
+ 100: '#dbeafe',
34
+ },
35
+ light: '#ebedef', // Your lightColor
36
+ dark: '#4b5463', // Your darkColor
37
+ } as const;
38
+
39
+ // Dark Theme Tokens - High contrast versions for dark backgrounds
40
+ export const darkColors = {
41
+ primary: {
42
+ 50: '#1a1a2e',
43
+ 100: '#252542',
44
+ 500: '#7c71e6', // Lighter purple for dark backgrounds
45
+ 600: '#8b82eb',
46
+ 700: '#9a93f0',
47
+ 900: '#b8b3f5',
48
+ },
49
+ neutral: {
50
+ 50: '#0f172a',
51
+ 100: '#1e293b',
52
+ 200: '#334155',
53
+ 400: '#64748b',
54
+ 600: '#cbd5e1', // Light gray for dark text
55
+ 800: '#f1f5f9',
56
+ 900: '#f8fafc',
57
+ },
58
+ success: {
59
+ 500: '#4ade80', // Bright green for dark backgrounds
60
+ 100: '#14532d',
61
+ },
62
+ warning: {
63
+ 500: '#fbbf24', // Bright amber for dark backgrounds
64
+ 100: '#713f12',
65
+ },
66
+ danger: {
67
+ 500: '#f87171', // Bright red for dark backgrounds
68
+ 100: '#7f1d1d',
69
+ },
70
+ info: {
71
+ 500: '#60a5fa', // Bright blue for dark backgrounds
72
+ 100: '#1e3a8a',
73
+ },
74
+ light: '#f8fafc', // Light text color for dark theme
75
+ dark: '#0f172a', // Dark background color
76
+ } as const;
77
+
@@ -0,0 +1,3 @@
1
+ export { colors } from './colors';
2
+ export { spacing } from './spacing';
3
+ export { typography } from './typography';
@@ -0,0 +1,13 @@
1
+ export const spacing = {
2
+ 0: '0',
3
+ 1: '0.25rem',
4
+ 2: '0.5rem',
5
+ 3: '0.75rem',
6
+ 4: '1rem',
7
+ 5: '1.25rem',
8
+ 6: '1.5rem',
9
+ 8: '2rem',
10
+ 10: '2.5rem',
11
+ 12: '3rem',
12
+ 16: '4rem',
13
+ } as const;
@@ -0,0 +1,21 @@
1
+ export const typography = {
2
+ fontFamily: {
3
+ sans: '"Inter", -apple-system, BlinkMacSystemFont, sans-serif',
4
+ mono: '"JetBrains Mono", "Fira Code", monospace',
5
+ },
6
+ fontSize: {
7
+ xs: '0.75rem',
8
+ sm: '0.875rem',
9
+ base: '1rem',
10
+ lg: '1.125rem',
11
+ xl: '1.25rem',
12
+ '2xl':'1.5rem',
13
+ '3xl':'1.875rem',
14
+ },
15
+ fontWeight: {
16
+ normal: 400,
17
+ medium: 500,
18
+ semibold:600,
19
+ bold: 700,
20
+ },
21
+ } as const;