albertodela-design-system 1.0.1

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.
@@ -0,0 +1,9 @@
1
+ import { default as React } from 'react';
2
+ export type BadgeVariant = 'primary' | 'success' | 'warning' | 'error' | 'info' | 'neutral';
3
+ export interface BadgeProps {
4
+ variant?: BadgeVariant;
5
+ children: React.ReactNode;
6
+ className?: string;
7
+ }
8
+ export declare const Badge: React.FC<BadgeProps>;
9
+ export default Badge;
@@ -0,0 +1,2 @@
1
+ export { Badge } from './Badge';
2
+ export type { BadgeProps, BadgeVariant } from './Badge';
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ export type ButtonVariant = 'primary' | 'secondary' | 'ghost';
3
+ export type ButtonSize = 'sm' | 'md' | 'lg';
4
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
5
+ variant?: ButtonVariant;
6
+ size?: ButtonSize;
7
+ fullWidth?: boolean;
8
+ }
9
+ export declare const Button: React.FC<ButtonProps>;
10
+ export default Button;
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './Button';
@@ -0,0 +1,10 @@
1
+ import { default as React } from 'react';
2
+ export interface CardProps {
3
+ title?: string;
4
+ description?: string;
5
+ footer?: React.ReactNode;
6
+ children?: React.ReactNode;
7
+ className?: string;
8
+ }
9
+ export declare const Card: React.FC<CardProps>;
10
+ export default Card;
@@ -0,0 +1,2 @@
1
+ export { Card } from './Card';
2
+ export type { CardProps } from './Card';
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
3
+ label?: string;
4
+ error?: string;
5
+ hint?: string;
6
+ }
7
+ export declare const Input: React.FC<InputProps>;
8
+ export default Input;
@@ -0,0 +1,2 @@
1
+ export { Input } from './Input';
2
+ export type { InputProps } from './Input';
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
3
+ label?: string;
4
+ error?: string;
5
+ hint?: string;
6
+ }
7
+ export declare const Textarea: React.FC<TextareaProps>;
8
+ export default Textarea;
@@ -0,0 +1,2 @@
1
+ export { Textarea } from './Textarea';
2
+ export type { TextareaProps } from './Textarea';
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),u=({variant:s="primary",size:r="md",fullWidth:a=!1,className:t="",children:d,...n})=>{const c=["ds-btn",`ds-btn--${s}`,`ds-btn--${r}`,a?"ds-btn--full-width":"",t].filter(Boolean).join(" ");return e.jsx("button",{className:c,...n,children:d})},x=({variant:s="neutral",children:r,className:a=""})=>{const t=["ds-badge",`ds-badge--${s}`,a].filter(Boolean).join(" ");return e.jsx("span",{className:t,children:r})},p=({title:s,description:r,footer:a,children:t,className:d=""})=>{const n=["ds-card",d].filter(Boolean).join(" ");return e.jsxs("div",{className:n,children:[(s||r)&&e.jsxs("div",{className:"ds-card__header",children:[s&&e.jsx("h3",{className:"ds-card__title",children:s}),r&&e.jsx("p",{className:"ds-card__description",children:r})]}),t&&e.jsx("div",{className:"ds-card__body",children:t}),a&&e.jsx("div",{className:"ds-card__footer",children:a})]})},g=({label:s,error:r,hint:a,id:t,className:d="",...n})=>{const c=t||(s==null?void 0:s.toLowerCase().replace(/\s+/g,"-")),o=["ds-input",r?"ds-input--error":"",d].filter(Boolean).join(" ");return e.jsxs("div",{className:"ds-form-group",children:[s&&e.jsx("label",{className:"ds-form-label",htmlFor:c,children:s}),e.jsx("input",{id:c,className:o,...n}),r&&e.jsx("p",{className:"ds-form-error",children:r}),a&&!r&&e.jsx("p",{className:"ds-form-hint",children:a})]})},h=({label:s,error:r,hint:a,id:t,className:d="",...n})=>{const c=t||(s==null?void 0:s.toLowerCase().replace(/\s+/g,"-")),o=["ds-textarea",r?"ds-textarea--error":"",d].filter(Boolean).join(" ");return e.jsxs("div",{className:"ds-form-group",children:[s&&e.jsx("label",{className:"ds-form-label",htmlFor:c,children:s}),e.jsx("textarea",{id:c,className:o,...n}),r&&e.jsx("p",{className:"ds-form-error",children:r}),a&&!r&&e.jsx("p",{className:"ds-form-hint",children:a})]})},m={primary:"#2563eb",primaryHover:"#1d4ed8",primaryLight:"#dbeafe",success:"#16a34a",successLight:"#dcfce7",warning:"#ea580c",warningLight:"#fed7aa",error:"#dc2626",errorLight:"#fecaca",info:"#0891b2",infoLight:"#cffafe",neutral:{50:"#fafaf9",100:"#f5f5f4",200:"#e7e5e4",300:"#d6d3d1",400:"#a8a29e",500:"#78716c",600:"#57534e",700:"#44403c",800:"#292524",900:"#1c1917"},bgPage:"#fafaf9",bgSurface:"#ffffff",textPrimary:"#1c1917",textSecondary:"#57534e",textTertiary:"#78716c",borderSubtle:"#e7e5e4",borderDefault:"#d6d3d1"},i={1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem"},l={fontFamily:"'Funnel Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},f={sm:"0.25rem",md:"0.5rem",lg:"0.75rem",xl:"1rem"},j={colors:m,spacing:i,typography:l,borderRadius:f};exports.Badge=x;exports.Button=u;exports.Card=p;exports.Input=g;exports.Textarea=h;exports.borderRadius=f;exports.colors=m;exports.spacing=i;exports.tokens=j;exports.typography=l;
@@ -0,0 +1,11 @@
1
+ export { Button } from './components/Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './components/Button';
3
+ export { Badge } from './components/Badge';
4
+ export type { BadgeProps, BadgeVariant } from './components/Badge';
5
+ export { Card } from './components/Card';
6
+ export type { CardProps } from './components/Card';
7
+ export { Input } from './components/Input';
8
+ export type { InputProps } from './components/Input';
9
+ export { Textarea } from './components/Textarea';
10
+ export type { TextareaProps } from './components/Textarea';
11
+ export { tokens, colors, spacing, typography, borderRadius } from './tokens';
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ import { jsx as r, jsxs as o } from "react/jsx-runtime";
2
+ const h = ({
3
+ variant: e = "primary",
4
+ size: s = "md",
5
+ fullWidth: a = !1,
6
+ className: t = "",
7
+ children: d,
8
+ ...c
9
+ }) => {
10
+ const n = [
11
+ "ds-btn",
12
+ `ds-btn--${e}`,
13
+ `ds-btn--${s}`,
14
+ a ? "ds-btn--full-width" : "",
15
+ t
16
+ ].filter(Boolean).join(" ");
17
+ return /* @__PURE__ */ r("button", { className: n, ...c, children: d });
18
+ }, g = ({
19
+ variant: e = "neutral",
20
+ children: s,
21
+ className: a = ""
22
+ }) => {
23
+ const t = ["ds-badge", `ds-badge--${e}`, a].filter(Boolean).join(" ");
24
+ return /* @__PURE__ */ r("span", { className: t, children: s });
25
+ }, N = ({
26
+ title: e,
27
+ description: s,
28
+ footer: a,
29
+ children: t,
30
+ className: d = ""
31
+ }) => {
32
+ const c = ["ds-card", d].filter(Boolean).join(" ");
33
+ return /* @__PURE__ */ o("div", { className: c, children: [
34
+ (e || s) && /* @__PURE__ */ o("div", { className: "ds-card__header", children: [
35
+ e && /* @__PURE__ */ r("h3", { className: "ds-card__title", children: e }),
36
+ s && /* @__PURE__ */ r("p", { className: "ds-card__description", children: s })
37
+ ] }),
38
+ t && /* @__PURE__ */ r("div", { className: "ds-card__body", children: t }),
39
+ a && /* @__PURE__ */ r("div", { className: "ds-card__footer", children: a })
40
+ ] });
41
+ }, x = ({
42
+ label: e,
43
+ error: s,
44
+ hint: a,
45
+ id: t,
46
+ className: d = "",
47
+ ...c
48
+ }) => {
49
+ const n = t || (e == null ? void 0 : e.toLowerCase().replace(/\s+/g, "-")), m = ["ds-input", s ? "ds-input--error" : "", d].filter(Boolean).join(" ");
50
+ return /* @__PURE__ */ o("div", { className: "ds-form-group", children: [
51
+ e && /* @__PURE__ */ r("label", { className: "ds-form-label", htmlFor: n, children: e }),
52
+ /* @__PURE__ */ r("input", { id: n, className: m, ...c }),
53
+ s && /* @__PURE__ */ r("p", { className: "ds-form-error", children: s }),
54
+ a && !s && /* @__PURE__ */ r("p", { className: "ds-form-hint", children: a })
55
+ ] });
56
+ }, y = ({
57
+ label: e,
58
+ error: s,
59
+ hint: a,
60
+ id: t,
61
+ className: d = "",
62
+ ...c
63
+ }) => {
64
+ const n = t || (e == null ? void 0 : e.toLowerCase().replace(/\s+/g, "-")), m = ["ds-textarea", s ? "ds-textarea--error" : "", d].filter(Boolean).join(" ");
65
+ return /* @__PURE__ */ o("div", { className: "ds-form-group", children: [
66
+ e && /* @__PURE__ */ r("label", { className: "ds-form-label", htmlFor: n, children: e }),
67
+ /* @__PURE__ */ r("textarea", { id: n, className: m, ...c }),
68
+ s && /* @__PURE__ */ r("p", { className: "ds-form-error", children: s }),
69
+ a && !s && /* @__PURE__ */ r("p", { className: "ds-form-hint", children: a })
70
+ ] });
71
+ }, i = {
72
+ primary: "#2563eb",
73
+ primaryHover: "#1d4ed8",
74
+ primaryLight: "#dbeafe",
75
+ success: "#16a34a",
76
+ successLight: "#dcfce7",
77
+ warning: "#ea580c",
78
+ warningLight: "#fed7aa",
79
+ error: "#dc2626",
80
+ errorLight: "#fecaca",
81
+ info: "#0891b2",
82
+ infoLight: "#cffafe",
83
+ neutral: {
84
+ 50: "#fafaf9",
85
+ 100: "#f5f5f4",
86
+ 200: "#e7e5e4",
87
+ 300: "#d6d3d1",
88
+ 400: "#a8a29e",
89
+ 500: "#78716c",
90
+ 600: "#57534e",
91
+ 700: "#44403c",
92
+ 800: "#292524",
93
+ 900: "#1c1917"
94
+ },
95
+ bgPage: "#fafaf9",
96
+ bgSurface: "#ffffff",
97
+ textPrimary: "#1c1917",
98
+ textSecondary: "#57534e",
99
+ textTertiary: "#78716c",
100
+ borderSubtle: "#e7e5e4",
101
+ borderDefault: "#d6d3d1"
102
+ }, l = {
103
+ 1: "0.25rem",
104
+ 2: "0.5rem",
105
+ 3: "0.75rem",
106
+ 4: "1rem",
107
+ 5: "1.25rem",
108
+ 6: "1.5rem",
109
+ 8: "2rem",
110
+ 10: "2.5rem",
111
+ 12: "3rem"
112
+ }, f = {
113
+ fontFamily: "'Funnel Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
114
+ fontSize: {
115
+ xs: "0.75rem",
116
+ sm: "0.875rem",
117
+ base: "1rem",
118
+ lg: "1.125rem",
119
+ xl: "1.25rem",
120
+ "2xl": "1.5rem",
121
+ "3xl": "1.875rem",
122
+ "4xl": "2.25rem"
123
+ },
124
+ fontWeight: {
125
+ light: 300,
126
+ normal: 400,
127
+ medium: 500,
128
+ semibold: 600,
129
+ bold: 700
130
+ }
131
+ }, p = {
132
+ sm: "0.25rem",
133
+ md: "0.5rem",
134
+ lg: "0.75rem",
135
+ xl: "1rem"
136
+ }, b = { colors: i, spacing: l, typography: f, borderRadius: p };
137
+ export {
138
+ g as Badge,
139
+ h as Button,
140
+ N as Card,
141
+ x as Input,
142
+ y as Textarea,
143
+ p as borderRadius,
144
+ i as colors,
145
+ l as spacing,
146
+ b as tokens,
147
+ f as typography
148
+ };
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Funnel+Sans:wght@300;400;500;600;700&display=swap";.ds-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;font-family:Funnel Sans,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-weight:500;border:1px solid transparent;border-radius:.5rem;cursor:pointer;transition:all .2s;text-decoration:none;white-space:nowrap}.ds-btn:disabled{opacity:.5;cursor:not-allowed}.ds-btn--primary{background:#2563eb;color:#fff;border-color:#2563eb}.ds-btn--primary:hover:not(:disabled){background:#1d4ed8;border-color:#1d4ed8}.ds-btn--secondary{background:transparent;color:#1c1917;border-color:#d6d3d1}.ds-btn--secondary:hover:not(:disabled){background:#f5f5f4}.ds-btn--ghost{background:transparent;color:#57534e;border-color:transparent}.ds-btn--ghost:hover:not(:disabled){background:#f5f5f4;color:#1c1917}.ds-btn--sm{padding:.25rem .75rem;font-size:.75rem}.ds-btn--md{padding:.5rem 1rem;font-size:.875rem}.ds-btn--lg{padding:.75rem 1.5rem;font-size:1rem}.ds-btn--full-width{width:100%}.ds-badge{display:inline-flex;align-items:center;padding:.25rem .5rem;font-family:Funnel Sans,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:.75rem;font-weight:500;border-radius:.25rem;white-space:nowrap}.ds-badge--primary{background:#dbeafe;color:#2563eb}.ds-badge--success{background:#dcfce7;color:#16a34a}.ds-badge--warning{background:#fed7aa;color:#ea580c}.ds-badge--error{background:#fecaca;color:#dc2626}.ds-badge--info{background:#cffafe;color:#0891b2}.ds-badge--neutral{background:#f5f5f4;color:#44403c}.ds-card{background:#fff;border:1px solid #e7e5e4;border-radius:.75rem;padding:1.25rem;font-family:Funnel Sans,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.ds-card__header{margin-bottom:1rem}.ds-card__title{font-size:1.125rem;font-weight:600;color:#1c1917;margin:0 0 .5rem}.ds-card__description{font-size:.875rem;color:#57534e;margin:0;line-height:1.6}.ds-card__body{font-size:.875rem;color:#57534e}.ds-card__footer{margin-top:1.25rem;padding-top:1rem;border-top:1px solid #e7e5e4}.ds-form-group{display:flex;flex-direction:column;gap:.5rem;font-family:Funnel Sans,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.ds-form-label{font-size:.875rem;font-weight:600;color:#57534e}.ds-input{width:100%;padding:.5rem .75rem;font-family:Funnel Sans,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:.875rem;color:#1c1917;background:#fff;border:1px solid #d6d3d1;border-radius:.5rem;transition:border-color .2s;box-sizing:border-box}.ds-input:focus{outline:none;border-color:#2563eb}.ds-input::placeholder{color:#a8a29e}.ds-input:disabled{background:#f5f5f4;color:#a8a29e;cursor:not-allowed}.ds-input--error{border-color:#dc2626}.ds-form-error{font-size:.75rem;color:#dc2626;margin:0}.ds-form-hint{font-size:.75rem;color:#78716c;margin:0}.ds-textarea{width:100%;padding:.5rem .75rem;font-family:Funnel Sans,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:.875rem;color:#1c1917;background:#fff;border:1px solid #d6d3d1;border-radius:.5rem;transition:border-color .2s;resize:vertical;min-height:100px;box-sizing:border-box}.ds-textarea:focus{outline:none;border-color:#2563eb}.ds-textarea::placeholder{color:#a8a29e}.ds-textarea:disabled{background:#f5f5f4;color:#a8a29e;cursor:not-allowed}.ds-textarea--error{border-color:#dc2626}
@@ -0,0 +1,141 @@
1
+ export declare const colors: {
2
+ primary: string;
3
+ primaryHover: string;
4
+ primaryLight: string;
5
+ success: string;
6
+ successLight: string;
7
+ warning: string;
8
+ warningLight: string;
9
+ error: string;
10
+ errorLight: string;
11
+ info: string;
12
+ infoLight: string;
13
+ neutral: {
14
+ 50: string;
15
+ 100: string;
16
+ 200: string;
17
+ 300: string;
18
+ 400: string;
19
+ 500: string;
20
+ 600: string;
21
+ 700: string;
22
+ 800: string;
23
+ 900: string;
24
+ };
25
+ bgPage: string;
26
+ bgSurface: string;
27
+ textPrimary: string;
28
+ textSecondary: string;
29
+ textTertiary: string;
30
+ borderSubtle: string;
31
+ borderDefault: string;
32
+ };
33
+ export declare const spacing: {
34
+ 1: string;
35
+ 2: string;
36
+ 3: string;
37
+ 4: string;
38
+ 5: string;
39
+ 6: string;
40
+ 8: string;
41
+ 10: string;
42
+ 12: string;
43
+ };
44
+ export declare const typography: {
45
+ fontFamily: string;
46
+ fontSize: {
47
+ xs: string;
48
+ sm: string;
49
+ base: string;
50
+ lg: string;
51
+ xl: string;
52
+ '2xl': string;
53
+ '3xl': string;
54
+ '4xl': string;
55
+ };
56
+ fontWeight: {
57
+ light: number;
58
+ normal: number;
59
+ medium: number;
60
+ semibold: number;
61
+ bold: number;
62
+ };
63
+ };
64
+ export declare const borderRadius: {
65
+ sm: string;
66
+ md: string;
67
+ lg: string;
68
+ xl: string;
69
+ };
70
+ export declare const tokens: {
71
+ colors: {
72
+ primary: string;
73
+ primaryHover: string;
74
+ primaryLight: string;
75
+ success: string;
76
+ successLight: string;
77
+ warning: string;
78
+ warningLight: string;
79
+ error: string;
80
+ errorLight: string;
81
+ info: string;
82
+ infoLight: string;
83
+ neutral: {
84
+ 50: string;
85
+ 100: string;
86
+ 200: string;
87
+ 300: string;
88
+ 400: string;
89
+ 500: string;
90
+ 600: string;
91
+ 700: string;
92
+ 800: string;
93
+ 900: string;
94
+ };
95
+ bgPage: string;
96
+ bgSurface: string;
97
+ textPrimary: string;
98
+ textSecondary: string;
99
+ textTertiary: string;
100
+ borderSubtle: string;
101
+ borderDefault: string;
102
+ };
103
+ spacing: {
104
+ 1: string;
105
+ 2: string;
106
+ 3: string;
107
+ 4: string;
108
+ 5: string;
109
+ 6: string;
110
+ 8: string;
111
+ 10: string;
112
+ 12: string;
113
+ };
114
+ typography: {
115
+ fontFamily: string;
116
+ fontSize: {
117
+ xs: string;
118
+ sm: string;
119
+ base: string;
120
+ lg: string;
121
+ xl: string;
122
+ '2xl': string;
123
+ '3xl': string;
124
+ '4xl': string;
125
+ };
126
+ fontWeight: {
127
+ light: number;
128
+ normal: number;
129
+ medium: number;
130
+ semibold: number;
131
+ bold: number;
132
+ };
133
+ };
134
+ borderRadius: {
135
+ sm: string;
136
+ md: string;
137
+ lg: string;
138
+ xl: string;
139
+ };
140
+ };
141
+ export default tokens;
@@ -0,0 +1,27 @@
1
+ # Design System – Alberto de la Puente
2
+
3
+ This is a minimal and functional design system. Always use components from `@alberto-delapuente/design-system` when building UI.
4
+
5
+ ## Available components
6
+ See `components.md` for detailed usage of each component.
7
+
8
+ - **Button** – primary, secondary and ghost actions
9
+ - **Badge** – status labels: primary, success, warning, error, info, neutral
10
+ - **Card** – content containers with optional title, description and footer
11
+ - **Input** – text inputs with label, hint and error states
12
+ - **Textarea** – multiline inputs
13
+
14
+ ## Available tokens
15
+ See `tokens.md` for all design tokens (colors, spacing, typography, border radius).
16
+
17
+ ## Setup
18
+ ```tsx
19
+ import { Button, Badge, Card, Input, Textarea } from '@alberto-delapuente/design-system';
20
+ import '@alberto-delapuente/design-system/dist/style.css';
21
+ ```
22
+
23
+ ## Design principles
24
+ - Minimal – no decorative elements
25
+ - Functional – colors have specific semantic purposes
26
+ - Consistent – unified typography (Funnel Sans) and spacing (4px base)
27
+ - Clean – clear visual hierarchy, no emojis
@@ -0,0 +1,92 @@
1
+ # Components
2
+
3
+ ## Button
4
+ Variants: `primary` | `secondary` | `ghost`
5
+ Sizes: `sm` | `md` | `lg`
6
+
7
+ ```tsx
8
+ import { Button } from '@alberto-delapuente/design-system';
9
+
10
+ <Button variant="primary" size="md" onClick={fn}>Save</Button>
11
+ <Button variant="secondary" size="md">Cancel</Button>
12
+ <Button variant="ghost" size="sm">Learn more</Button>
13
+ <Button variant="primary" disabled>Disabled</Button>
14
+ <Button variant="primary" fullWidth>Full width</Button>
15
+ ```
16
+
17
+ Use `primary` for the main call to action on a page.
18
+ Use `secondary` for alternative actions alongside a primary.
19
+ Use `ghost` for subtle or tertiary actions.
20
+
21
+ ---
22
+
23
+ ## Badge
24
+ Variants: `primary` | `success` | `warning` | `error` | `info` | `neutral`
25
+
26
+ ```tsx
27
+ import { Badge } from '@alberto-delapuente/design-system';
28
+
29
+ <Badge variant="success">Active</Badge>
30
+ <Badge variant="warning">Pending</Badge>
31
+ <Badge variant="error">Failed</Badge>
32
+ <Badge variant="info">Info</Badge>
33
+ <Badge variant="neutral">Draft</Badge>
34
+ <Badge variant="primary">New</Badge>
35
+ ```
36
+
37
+ Use `success` for active/completed states.
38
+ Use `warning` for pending/in-progress states.
39
+ Use `error` for failed/blocked states.
40
+ Use `neutral` for draft/inactive states.
41
+
42
+ ---
43
+
44
+ ## Card
45
+ Props: `title`, `description`, `footer`, `children`
46
+
47
+ ```tsx
48
+ import { Card } from '@alberto-delapuente/design-system';
49
+ import { Button } from '@alberto-delapuente/design-system';
50
+
51
+ // Simple card
52
+ <Card title="Project Name" description="A brief description of the project." />
53
+
54
+ // Card with footer action
55
+ <Card
56
+ title="Project Name"
57
+ description="A brief description."
58
+ footer={<Button variant="primary" size="sm">Open</Button>}
59
+ />
60
+
61
+ // Card with custom children
62
+ <Card title="Stats">
63
+ <p>Custom content here</p>
64
+ </Card>
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Input
70
+ Props: `label`, `error`, `hint`, plus all native input attributes
71
+
72
+ ```tsx
73
+ import { Input } from '@alberto-delapuente/design-system';
74
+
75
+ <Input label="Email" type="email" placeholder="you@example.com" />
76
+ <Input label="Name" hint="Enter your full name" />
77
+ <Input label="Username" error="Username is already taken" />
78
+ <Input label="Read only" value="Fixed value" readOnly />
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Textarea
84
+ Props: `label`, `error`, `hint`, plus all native textarea attributes
85
+
86
+ ```tsx
87
+ import { Textarea } from '@alberto-delapuente/design-system';
88
+
89
+ <Textarea label="Description" placeholder="Write something..." rows={4} />
90
+ <Textarea label="Notes" hint="Max 500 characters" />
91
+ <Textarea label="Feedback" error="This field is required" />
92
+ ```
@@ -0,0 +1,66 @@
1
+ # Design Tokens
2
+
3
+ ## Colors – Functional
4
+
5
+ | Token | Value | Use |
6
+ |---|---|---|
7
+ | primary | #2563eb | Main actions, links, primary buttons |
8
+ | primaryHover | #1d4ed8 | Hover state of primary |
9
+ | primaryLight | #dbeafe | Primary badge background |
10
+ | success | #16a34a | Success states |
11
+ | successLight | #dcfce7 | Success badge background |
12
+ | warning | #ea580c | Warning states |
13
+ | warningLight | #fed7aa | Warning badge background |
14
+ | error | #dc2626 | Error states |
15
+ | errorLight | #fecaca | Error badge background |
16
+ | info | #0891b2 | Informational states |
17
+ | infoLight | #cffafe | Info badge background |
18
+
19
+ ## Colors – Neutral scale
20
+
21
+ | Token | Value | Use |
22
+ |---|---|---|
23
+ | neutral[50] | #fafaf9 | Page background |
24
+ | neutral[100] | #f5f5f4 | Hover backgrounds |
25
+ | neutral[200] | #e7e5e4 | Subtle borders |
26
+ | neutral[300] | #d6d3d1 | Default borders |
27
+ | neutral[400] | #a8a29e | Placeholder text |
28
+ | neutral[500] | #78716c | Tertiary text |
29
+ | neutral[600] | #57534e | Secondary text |
30
+ | neutral[700] | #44403c | Body text |
31
+ | neutral[800] | #292524 | Dark text |
32
+ | neutral[900] | #1c1917 | Primary text |
33
+
34
+ ## Spacing (4px base)
35
+
36
+ | Token | Value |
37
+ |---|---|
38
+ | spacing[1] | 0.25rem (4px) |
39
+ | spacing[2] | 0.5rem (8px) |
40
+ | spacing[3] | 0.75rem (12px) |
41
+ | spacing[4] | 1rem (16px) |
42
+ | spacing[6] | 1.5rem (24px) |
43
+ | spacing[8] | 2rem (32px) |
44
+ | spacing[12] | 3rem (48px) |
45
+
46
+ ## Typography
47
+
48
+ Font: **Funnel Sans** (weights: 300, 400, 500, 600, 700)
49
+
50
+ | Token | Value |
51
+ |---|---|
52
+ | fontSize.xs | 0.75rem (12px) |
53
+ | fontSize.sm | 0.875rem (14px) |
54
+ | fontSize.base | 1rem (16px) |
55
+ | fontSize.lg | 1.125rem (18px) |
56
+ | fontSize.xl | 1.25rem (20px) |
57
+ | fontSize.2xl | 1.5rem (24px) |
58
+
59
+ ## Border Radius
60
+
61
+ | Token | Value |
62
+ |---|---|
63
+ | borderRadius.sm | 0.25rem (4px) |
64
+ | borderRadius.md | 0.5rem (8px) |
65
+ | borderRadius.lg | 0.75rem (12px) |
66
+ | borderRadius.xl | 1rem (16px) |
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "albertodela-design-system",
3
+ "version": "1.0.1",
4
+ "description": "Minimal and functional design system. Buttons, Badges, Cards and Form components with Funnel Sans typography.",
5
+ "keywords": [
6
+ "design-system",
7
+ "react",
8
+ "components",
9
+ "ui"
10
+ ],
11
+ "author": "Alberto de la Puente",
12
+ "license": "MIT",
13
+ "type": "module",
14
+ "main": "dist/index.cjs",
15
+ "module": "dist/index.js",
16
+ "types": "dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "import": "./dist/index.js",
20
+ "require": "./dist/index.cjs",
21
+ "types": "./dist/index.d.ts"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "guidelines"
27
+ ],
28
+ "scripts": {
29
+ "build": "vite build && tsc --emitDeclarationOnly --declaration --outDir dist",
30
+ "dev": "vite build --watch"
31
+ },
32
+ "peerDependencies": {
33
+ "react": ">=18",
34
+ "react-dom": ">=18"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^25.3.0",
38
+ "@types/react": "^18.3.0",
39
+ "@types/react-dom": "^18.3.0",
40
+ "@vitejs/plugin-react": "^4.3.0",
41
+ "typescript": "^5.5.0",
42
+ "vite": "^5.4.0",
43
+ "vite-plugin-dts": "^4.0.0"
44
+ }
45
+ }