@edwinner/togo-react 0.1.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/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # ToGo Design System — React
2
+
3
+ A personal React component library built as a portfolio piece, inspired by
4
+ Goto's Chameleon design system.
5
+
6
+ > **Packages**
7
+ > | Package | Description |
8
+ > |---|---|
9
+ > | `@edwinner/togo-react` | This package — React web components |
10
+ > | `@edwinner/togo-react-native` | Coming soon — React Native mobile components |
11
+
12
+ ---
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @edwinner/togo-react
18
+ # or
19
+ yarn add @edwinner/togo-react
20
+ # or
21
+ pnpm add @edwinner/togo-react
22
+ ```
23
+
24
+ React 18+ and react-dom are peer dependencies; make sure they're installed in
25
+ your project.
26
+
27
+ ---
28
+
29
+ ## Usage
30
+
31
+ ### 1. Import the stylesheet
32
+
33
+ In your app's entry file (e.g. `main.tsx` or `_app.tsx`):
34
+
35
+ ```ts
36
+ import "@edwinner/togo-react/dist/style.css";
37
+ ```
38
+
39
+ ### 2. Use components
40
+
41
+ ```tsx
42
+ import { Button } from "@edwinner/togo-react";
43
+
44
+ export default function App() {
45
+ return (
46
+ <Button variant="filled" size="md" onClick={() => console.log("clicked")}>
47
+ Get Started
48
+ </Button>
49
+ );
50
+ }
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Components
56
+
57
+ | Component | Status |
58
+ |---|---|
59
+ | `Button` | Stable |
60
+
61
+ More coming soon.
62
+
63
+ ---
64
+
65
+ ## Design Tokens
66
+
67
+ Tokens are exported as a `tokens` object and as CSS custom properties (via the
68
+ stylesheet).
69
+
70
+ ```ts
71
+ import { tokens } from "@edwinner/togo-react";
72
+
73
+ console.log(tokens.colors.primary[500]); // "var(--togo-color-primary-500)"
74
+ ```
75
+
76
+ CSS custom properties are available on `:root` once the stylesheet is imported:
77
+
78
+ ```css
79
+ .my-element {
80
+ color: var(--togo-color-primary-600);
81
+ font-family: var(--togo-font-sans);
82
+ }
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Development
88
+
89
+ ### Prerequisites
90
+
91
+ - Node.js 18+
92
+ - npm 9+
93
+
94
+ ### Getting started
95
+
96
+ ```bash
97
+ # Install dependencies
98
+ npm install
99
+
100
+ # Start Storybook (component explorer + docs)
101
+ npm run dev
102
+
103
+ # Build the library
104
+ npm run build
105
+
106
+ # Type-check without emitting
107
+ npm run typecheck
108
+
109
+ # Lint
110
+ npm run lint
111
+ ```
112
+
113
+ ### Project structure
114
+
115
+ ```
116
+ src/
117
+ ├── components/ # Individual components
118
+ │ └── Button/
119
+ │ ├── Button.tsx
120
+ │ ├── Button.module.css
121
+ │ ├── Button.stories.tsx
122
+ │ └── index.ts
123
+ ├── tokens/ # Design token JS exports
124
+ │ └── index.ts
125
+ ├── styles/
126
+ │ └── global.css # CSS custom properties
127
+ └── index.ts # Library entry point
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Publishing
133
+
134
+ ```bash
135
+ # Bump version in package.json first, then:
136
+ npm publish --access public
137
+ ```
138
+
139
+ The `prepublishOnly` script runs `npm run build` automatically before
140
+ publishing.
141
+
142
+ ---
143
+
144
+ ## License
145
+
146
+ MIT
@@ -0,0 +1,19 @@
1
+ import { ButtonHTMLAttributes, ReactNode } from 'react';
2
+
3
+ export type ButtonVariant = "filled" | "outlined" | "ghost" | "destructive";
4
+ export type ButtonSize = "sm" | "md" | "lg";
5
+ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
6
+ /** Visual style of the button. */
7
+ variant?: ButtonVariant;
8
+ /** Size of the button. */
9
+ size?: ButtonSize;
10
+ /** Renders a loading spinner and disables interaction. */
11
+ loading?: boolean;
12
+ /** Icon displayed before the label. */
13
+ leadingIcon?: ReactNode;
14
+ /** Icon displayed after the label. */
15
+ trailingIcon?: ReactNode;
16
+ /** Stretches the button to fill its container. */
17
+ fullWidth?: boolean;
18
+ }
19
+ export declare const Button: import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './Button';
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),p=require("react"),_="_button_4wrmq_1",f="_sm_4wrmq_32",h="_md_4wrmq_39",y="_lg_4wrmq_46",w="_filled_4wrmq_56",b="_outlined_4wrmq_70",q="_ghost_4wrmq_85",k="_destructive_4wrmq_99",j="_spinner_4wrmq_110",S="_fullWidth_4wrmq_127",o={button:_,sm:f,md:h,lg:y,filled:w,outlined:b,ghost:q,destructive:k,spinner:j,"togo-spin":"_togo-spin_4wrmq_1",fullWidth:S},l=p.forwardRef(({variant:e="filled",size:s="md",loading:r=!1,leadingIcon:n,trailingIcon:g,fullWidth:c=!1,disabled:i,className:d,children:u,...v},m)=>{const t=i||r,x=[o.button,o[e],o[s],c?o.fullWidth:"",d??""].filter(Boolean).join(" ");return a.jsxs("button",{ref:m,disabled:t,"aria-disabled":t,"aria-busy":r,className:x,...v,children:[r?a.jsx("span",{className:o.spinner,"aria-hidden":"true"}):n,u,!r&&g]})});l.displayName="Button";const W={primary:{50:"var(--togo-color-primary-50)",100:"var(--togo-color-primary-100)",200:"var(--togo-color-primary-200)",300:"var(--togo-color-primary-300)",400:"var(--togo-color-primary-400)",500:"var(--togo-color-primary-500)",600:"var(--togo-color-primary-600)",700:"var(--togo-color-primary-700)",800:"var(--togo-color-primary-800)",900:"var(--togo-color-primary-900)"},neutral:{0:"var(--togo-color-neutral-0)",50:"var(--togo-color-neutral-50)",100:"var(--togo-color-neutral-100)",200:"var(--togo-color-neutral-200)",300:"var(--togo-color-neutral-300)",400:"var(--togo-color-neutral-400)",500:"var(--togo-color-neutral-500)",600:"var(--togo-color-neutral-600)",700:"var(--togo-color-neutral-700)",800:"var(--togo-color-neutral-800)",900:"var(--togo-color-neutral-900)",1e3:"var(--togo-color-neutral-1000)"},success:{light:"var(--togo-color-success-light)",default:"var(--togo-color-success)",dark:"var(--togo-color-success-dark)"},warning:{light:"var(--togo-color-warning-light)",default:"var(--togo-color-warning)",dark:"var(--togo-color-warning-dark)"},error:{light:"var(--togo-color-error-light)",default:"var(--togo-color-error)",dark:"var(--togo-color-error-dark)"},info:{light:"var(--togo-color-info-light)",default:"var(--togo-color-info)",dark:"var(--togo-color-info-dark)"}},B={0:"0px",1:"4px",2:"8px",3:"12px",4:"16px",5:"20px",6:"24px",8:"32px",10:"40px",12:"48px",16:"64px",20:"80px",24:"96px"},N={fontFamily:{sans:"var(--togo-font-sans)",mono:"var(--togo-font-mono)"},fontSize:{xs:"var(--togo-text-xs)",sm:"var(--togo-text-sm)",base:"var(--togo-text-base)",lg:"var(--togo-text-lg)",xl:"var(--togo-text-xl)","2xl":"var(--togo-text-2xl)","3xl":"var(--togo-text-3xl)","4xl":"var(--togo-text-4xl)"},fontWeight:{regular:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.2",snug:"1.375",normal:"1.5",relaxed:"1.625"}},z={none:"0px",sm:"4px",md:"8px",lg:"12px",xl:"16px",full:"9999px"},O={sm:"var(--togo-shadow-sm)",md:"var(--togo-shadow-md)",lg:"var(--togo-shadow-lg)",xl:"var(--togo-shadow-xl)"},M={base:0,raised:10,dropdown:100,sticky:200,overlay:300,modal:400,toast:500},P=Object.freeze(Object.defineProperty({__proto__:null,colors:W,radii:z,shadows:O,spacing:B,typography:N,zIndex:M},Symbol.toStringTag,{value:"Module"}));exports.Button=l;exports.tokens=P;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/Button/Button.tsx","../src/tokens/index.ts"],"sourcesContent":["import { forwardRef, ButtonHTMLAttributes, ReactNode } from \"react\";\nimport styles from \"./Button.module.css\";\n\nexport type ButtonVariant = \"filled\" | \"outlined\" | \"ghost\" | \"destructive\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style of the button. */\n variant?: ButtonVariant;\n /** Size of the button. */\n size?: ButtonSize;\n /** Renders a loading spinner and disables interaction. */\n loading?: boolean;\n /** Icon displayed before the label. */\n leadingIcon?: ReactNode;\n /** Icon displayed after the label. */\n trailingIcon?: ReactNode;\n /** Stretches the button to fill its container. */\n fullWidth?: boolean;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = \"filled\",\n size = \"md\",\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n disabled,\n className,\n children,\n ...rest\n },\n ref,\n ) => {\n const isDisabled = disabled || loading;\n\n const classNames = [\n styles.button,\n styles[variant],\n styles[size],\n fullWidth ? styles.fullWidth : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n aria-disabled={isDisabled}\n aria-busy={loading}\n className={classNames}\n {...rest}\n >\n {loading ? (\n <span className={styles.spinner} aria-hidden=\"true\" />\n ) : (\n leadingIcon\n )}\n {children}\n {!loading && trailingIcon}\n </button>\n );\n },\n);\n\nButton.displayName = \"Button\";\n","/**\n * ToGo Design System — Design Tokens\n *\n * These tokens are the single source of truth for all visual decisions.\n * They map to CSS custom properties defined in global.css.\n */\n\nexport const colors = {\n // Brand\n primary: {\n 50: \"var(--togo-color-primary-50)\",\n 100: \"var(--togo-color-primary-100)\",\n 200: \"var(--togo-color-primary-200)\",\n 300: \"var(--togo-color-primary-300)\",\n 400: \"var(--togo-color-primary-400)\",\n 500: \"var(--togo-color-primary-500)\",\n 600: \"var(--togo-color-primary-600)\",\n 700: \"var(--togo-color-primary-700)\",\n 800: \"var(--togo-color-primary-800)\",\n 900: \"var(--togo-color-primary-900)\",\n },\n\n // Neutrals\n neutral: {\n 0: \"var(--togo-color-neutral-0)\",\n 50: \"var(--togo-color-neutral-50)\",\n 100: \"var(--togo-color-neutral-100)\",\n 200: \"var(--togo-color-neutral-200)\",\n 300: \"var(--togo-color-neutral-300)\",\n 400: \"var(--togo-color-neutral-400)\",\n 500: \"var(--togo-color-neutral-500)\",\n 600: \"var(--togo-color-neutral-600)\",\n 700: \"var(--togo-color-neutral-700)\",\n 800: \"var(--togo-color-neutral-800)\",\n 900: \"var(--togo-color-neutral-900)\",\n 1000: \"var(--togo-color-neutral-1000)\",\n },\n\n // Semantic\n success: {\n light: \"var(--togo-color-success-light)\",\n default: \"var(--togo-color-success)\",\n dark: \"var(--togo-color-success-dark)\",\n },\n warning: {\n light: \"var(--togo-color-warning-light)\",\n default: \"var(--togo-color-warning)\",\n dark: \"var(--togo-color-warning-dark)\",\n },\n error: {\n light: \"var(--togo-color-error-light)\",\n default: \"var(--togo-color-error)\",\n dark: \"var(--togo-color-error-dark)\",\n },\n info: {\n light: \"var(--togo-color-info-light)\",\n default: \"var(--togo-color-info)\",\n dark: \"var(--togo-color-info-dark)\",\n },\n} as const;\n\nexport const spacing = {\n 0: \"0px\",\n 1: \"4px\",\n 2: \"8px\",\n 3: \"12px\",\n 4: \"16px\",\n 5: \"20px\",\n 6: \"24px\",\n 8: \"32px\",\n 10: \"40px\",\n 12: \"48px\",\n 16: \"64px\",\n 20: \"80px\",\n 24: \"96px\",\n} as const;\n\nexport const typography = {\n fontFamily: {\n sans: \"var(--togo-font-sans)\",\n mono: \"var(--togo-font-mono)\",\n },\n fontSize: {\n xs: \"var(--togo-text-xs)\",\n sm: \"var(--togo-text-sm)\",\n base: \"var(--togo-text-base)\",\n lg: \"var(--togo-text-lg)\",\n xl: \"var(--togo-text-xl)\",\n \"2xl\": \"var(--togo-text-2xl)\",\n \"3xl\": \"var(--togo-text-3xl)\",\n \"4xl\": \"var(--togo-text-4xl)\",\n },\n fontWeight: {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n },\n lineHeight: {\n tight: \"1.2\",\n snug: \"1.375\",\n normal: \"1.5\",\n relaxed: \"1.625\",\n },\n} as const;\n\nexport const radii = {\n none: \"0px\",\n sm: \"4px\",\n md: \"8px\",\n lg: \"12px\",\n xl: \"16px\",\n full: \"9999px\",\n} as const;\n\nexport const shadows = {\n sm: \"var(--togo-shadow-sm)\",\n md: \"var(--togo-shadow-md)\",\n lg: \"var(--togo-shadow-lg)\",\n xl: \"var(--togo-shadow-xl)\",\n} as const;\n\nexport const zIndex = {\n base: 0,\n raised: 10,\n dropdown: 100,\n sticky: 200,\n overlay: 300,\n modal: 400,\n toast: 500,\n} as const;\n"],"names":["Button","forwardRef","variant","size","loading","leadingIcon","trailingIcon","fullWidth","disabled","className","children","rest","ref","isDisabled","classNames","styles","jsxs","colors","spacing","typography","radii","shadows","zIndex"],"mappings":"sdAqBaA,EAASC,EAAAA,WACpB,CACE,CACE,QAAAC,EAAU,SACV,KAAAC,EAAO,KACP,QAAAC,EAAU,GACV,YAAAC,EACA,aAAAC,EACA,UAAAC,EAAY,GACZ,SAAAC,EACA,UAAAC,EACA,SAAAC,EACA,GAAGC,CAAA,EAELC,IACG,CACH,MAAMC,EAAaL,GAAYJ,EAEzBU,EAAa,CACjBC,EAAO,OACPA,EAAOb,CAAO,EACda,EAAOZ,CAAI,EACXI,EAAYQ,EAAO,UAAY,GAC/BN,GAAa,EAAA,EAEZ,OAAO,OAAO,EACd,KAAK,GAAG,EAEX,OACEO,EAAAA,KAAC,SAAA,CACC,IAAAJ,EACA,SAAUC,EACV,gBAAeA,EACf,YAAWT,EACX,UAAWU,EACV,GAAGH,EAEH,SAAA,CAAAP,QACE,OAAA,CAAK,UAAWW,EAAO,QAAS,cAAY,OAAO,EAEpDV,EAEDK,EACA,CAACN,GAAWE,CAAA,CAAA,CAAA,CAGnB,CACF,EAEAN,EAAO,YAAc,SC/Dd,MAAMiB,EAAS,CAEpB,QAAS,CACP,GAAI,+BACJ,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,+BAAA,EAIP,QAAS,CACP,EAAG,8BACH,GAAI,+BACJ,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAK,gCACL,IAAM,gCAAA,EAIR,QAAS,CACP,MAAO,kCACP,QAAS,4BACT,KAAM,gCAAA,EAER,QAAS,CACP,MAAO,kCACP,QAAS,4BACT,KAAM,gCAAA,EAER,MAAO,CACL,MAAO,gCACP,QAAS,0BACT,KAAM,8BAAA,EAER,KAAM,CACJ,MAAO,+BACP,QAAS,yBACT,KAAM,6BAAA,CAEV,EAEaC,EAAU,CACrB,EAAG,MACH,EAAG,MACH,EAAG,MACH,EAAG,OACH,EAAG,OACH,EAAG,OACH,EAAG,OACH,EAAG,OACH,GAAI,OACJ,GAAI,OACJ,GAAI,OACJ,GAAI,OACJ,GAAI,MACN,EAEaC,EAAa,CACxB,WAAY,CACV,KAAM,wBACN,KAAM,uBAAA,EAER,SAAU,CACR,GAAI,sBACJ,GAAI,sBACJ,KAAM,wBACN,GAAI,sBACJ,GAAI,sBACJ,MAAO,uBACP,MAAO,uBACP,MAAO,sBAAA,EAET,WAAY,CACV,QAAS,MACT,OAAQ,MACR,SAAU,MACV,KAAM,KAAA,EAER,WAAY,CACV,MAAO,MACP,KAAM,QACN,OAAQ,MACR,QAAS,OAAA,CAEb,EAEaC,EAAQ,CACnB,KAAM,MACN,GAAI,MACJ,GAAI,MACJ,GAAI,OACJ,GAAI,OACJ,KAAM,QACR,EAEaC,EAAU,CACrB,GAAI,wBACJ,GAAI,wBACJ,GAAI,wBACJ,GAAI,uBACN,EAEaC,EAAS,CACpB,KAAM,EACN,OAAQ,GACR,SAAU,IACV,OAAQ,IACR,QAAS,IACT,MAAO,IACP,MAAO,GACT"}
@@ -0,0 +1,4 @@
1
+ export { Button } from './components/Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './components/Button';
3
+ import * as tokens from "./tokens";
4
+ export { tokens };
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ import { jsxs as u, jsx as p } from "react/jsx-runtime";
2
+ import { forwardRef as x } from "react";
3
+ const _ = "_button_4wrmq_1", f = "_sm_4wrmq_32", h = "_md_4wrmq_39", w = "_lg_4wrmq_46", y = "_filled_4wrmq_56", b = "_outlined_4wrmq_70", q = "_ghost_4wrmq_85", k = "_destructive_4wrmq_99", j = "_spinner_4wrmq_110", W = "_fullWidth_4wrmq_127", o = {
4
+ button: _,
5
+ sm: f,
6
+ md: h,
7
+ lg: w,
8
+ filled: y,
9
+ outlined: b,
10
+ ghost: q,
11
+ destructive: k,
12
+ spinner: j,
13
+ "togo-spin": "_togo-spin_4wrmq_1",
14
+ fullWidth: W
15
+ }, N = x(
16
+ ({
17
+ variant: a = "filled",
18
+ size: l = "md",
19
+ loading: r = !1,
20
+ leadingIcon: s,
21
+ trailingIcon: e,
22
+ fullWidth: n = !1,
23
+ disabled: g,
24
+ className: c,
25
+ children: i,
26
+ ...d
27
+ }, m) => {
28
+ const t = g || r, v = [
29
+ o.button,
30
+ o[a],
31
+ o[l],
32
+ n ? o.fullWidth : "",
33
+ c ?? ""
34
+ ].filter(Boolean).join(" ");
35
+ return /* @__PURE__ */ u(
36
+ "button",
37
+ {
38
+ ref: m,
39
+ disabled: t,
40
+ "aria-disabled": t,
41
+ "aria-busy": r,
42
+ className: v,
43
+ ...d,
44
+ children: [
45
+ r ? /* @__PURE__ */ p("span", { className: o.spinner, "aria-hidden": "true" }) : s,
46
+ i,
47
+ !r && e
48
+ ]
49
+ }
50
+ );
51
+ }
52
+ );
53
+ N.displayName = "Button";
54
+ const z = {
55
+ // Brand
56
+ primary: {
57
+ 50: "var(--togo-color-primary-50)",
58
+ 100: "var(--togo-color-primary-100)",
59
+ 200: "var(--togo-color-primary-200)",
60
+ 300: "var(--togo-color-primary-300)",
61
+ 400: "var(--togo-color-primary-400)",
62
+ 500: "var(--togo-color-primary-500)",
63
+ 600: "var(--togo-color-primary-600)",
64
+ 700: "var(--togo-color-primary-700)",
65
+ 800: "var(--togo-color-primary-800)",
66
+ 900: "var(--togo-color-primary-900)"
67
+ },
68
+ // Neutrals
69
+ neutral: {
70
+ 0: "var(--togo-color-neutral-0)",
71
+ 50: "var(--togo-color-neutral-50)",
72
+ 100: "var(--togo-color-neutral-100)",
73
+ 200: "var(--togo-color-neutral-200)",
74
+ 300: "var(--togo-color-neutral-300)",
75
+ 400: "var(--togo-color-neutral-400)",
76
+ 500: "var(--togo-color-neutral-500)",
77
+ 600: "var(--togo-color-neutral-600)",
78
+ 700: "var(--togo-color-neutral-700)",
79
+ 800: "var(--togo-color-neutral-800)",
80
+ 900: "var(--togo-color-neutral-900)",
81
+ 1e3: "var(--togo-color-neutral-1000)"
82
+ },
83
+ // Semantic
84
+ success: {
85
+ light: "var(--togo-color-success-light)",
86
+ default: "var(--togo-color-success)",
87
+ dark: "var(--togo-color-success-dark)"
88
+ },
89
+ warning: {
90
+ light: "var(--togo-color-warning-light)",
91
+ default: "var(--togo-color-warning)",
92
+ dark: "var(--togo-color-warning-dark)"
93
+ },
94
+ error: {
95
+ light: "var(--togo-color-error-light)",
96
+ default: "var(--togo-color-error)",
97
+ dark: "var(--togo-color-error-dark)"
98
+ },
99
+ info: {
100
+ light: "var(--togo-color-info-light)",
101
+ default: "var(--togo-color-info)",
102
+ dark: "var(--togo-color-info-dark)"
103
+ }
104
+ }, B = {
105
+ 0: "0px",
106
+ 1: "4px",
107
+ 2: "8px",
108
+ 3: "12px",
109
+ 4: "16px",
110
+ 5: "20px",
111
+ 6: "24px",
112
+ 8: "32px",
113
+ 10: "40px",
114
+ 12: "48px",
115
+ 16: "64px",
116
+ 20: "80px",
117
+ 24: "96px"
118
+ }, S = {
119
+ fontFamily: {
120
+ sans: "var(--togo-font-sans)",
121
+ mono: "var(--togo-font-mono)"
122
+ },
123
+ fontSize: {
124
+ xs: "var(--togo-text-xs)",
125
+ sm: "var(--togo-text-sm)",
126
+ base: "var(--togo-text-base)",
127
+ lg: "var(--togo-text-lg)",
128
+ xl: "var(--togo-text-xl)",
129
+ "2xl": "var(--togo-text-2xl)",
130
+ "3xl": "var(--togo-text-3xl)",
131
+ "4xl": "var(--togo-text-4xl)"
132
+ },
133
+ fontWeight: {
134
+ regular: "400",
135
+ medium: "500",
136
+ semibold: "600",
137
+ bold: "700"
138
+ },
139
+ lineHeight: {
140
+ tight: "1.2",
141
+ snug: "1.375",
142
+ normal: "1.5",
143
+ relaxed: "1.625"
144
+ }
145
+ }, O = {
146
+ none: "0px",
147
+ sm: "4px",
148
+ md: "8px",
149
+ lg: "12px",
150
+ xl: "16px",
151
+ full: "9999px"
152
+ }, D = {
153
+ sm: "var(--togo-shadow-sm)",
154
+ md: "var(--togo-shadow-md)",
155
+ lg: "var(--togo-shadow-lg)",
156
+ xl: "var(--togo-shadow-xl)"
157
+ }, F = {
158
+ base: 0,
159
+ raised: 10,
160
+ dropdown: 100,
161
+ sticky: 200,
162
+ overlay: 300,
163
+ modal: 400,
164
+ toast: 500
165
+ }, M = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
166
+ __proto__: null,
167
+ colors: z,
168
+ radii: O,
169
+ shadows: D,
170
+ spacing: B,
171
+ typography: S,
172
+ zIndex: F
173
+ }, Symbol.toStringTag, { value: "Module" }));
174
+ export {
175
+ N as Button,
176
+ M as tokens
177
+ };
178
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/components/Button/Button.tsx","../src/tokens/index.ts"],"sourcesContent":["import { forwardRef, ButtonHTMLAttributes, ReactNode } from \"react\";\nimport styles from \"./Button.module.css\";\n\nexport type ButtonVariant = \"filled\" | \"outlined\" | \"ghost\" | \"destructive\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style of the button. */\n variant?: ButtonVariant;\n /** Size of the button. */\n size?: ButtonSize;\n /** Renders a loading spinner and disables interaction. */\n loading?: boolean;\n /** Icon displayed before the label. */\n leadingIcon?: ReactNode;\n /** Icon displayed after the label. */\n trailingIcon?: ReactNode;\n /** Stretches the button to fill its container. */\n fullWidth?: boolean;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = \"filled\",\n size = \"md\",\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n disabled,\n className,\n children,\n ...rest\n },\n ref,\n ) => {\n const isDisabled = disabled || loading;\n\n const classNames = [\n styles.button,\n styles[variant],\n styles[size],\n fullWidth ? styles.fullWidth : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n aria-disabled={isDisabled}\n aria-busy={loading}\n className={classNames}\n {...rest}\n >\n {loading ? (\n <span className={styles.spinner} aria-hidden=\"true\" />\n ) : (\n leadingIcon\n )}\n {children}\n {!loading && trailingIcon}\n </button>\n );\n },\n);\n\nButton.displayName = \"Button\";\n","/**\n * ToGo Design System — Design Tokens\n *\n * These tokens are the single source of truth for all visual decisions.\n * They map to CSS custom properties defined in global.css.\n */\n\nexport const colors = {\n // Brand\n primary: {\n 50: \"var(--togo-color-primary-50)\",\n 100: \"var(--togo-color-primary-100)\",\n 200: \"var(--togo-color-primary-200)\",\n 300: \"var(--togo-color-primary-300)\",\n 400: \"var(--togo-color-primary-400)\",\n 500: \"var(--togo-color-primary-500)\",\n 600: \"var(--togo-color-primary-600)\",\n 700: \"var(--togo-color-primary-700)\",\n 800: \"var(--togo-color-primary-800)\",\n 900: \"var(--togo-color-primary-900)\",\n },\n\n // Neutrals\n neutral: {\n 0: \"var(--togo-color-neutral-0)\",\n 50: \"var(--togo-color-neutral-50)\",\n 100: \"var(--togo-color-neutral-100)\",\n 200: \"var(--togo-color-neutral-200)\",\n 300: \"var(--togo-color-neutral-300)\",\n 400: \"var(--togo-color-neutral-400)\",\n 500: \"var(--togo-color-neutral-500)\",\n 600: \"var(--togo-color-neutral-600)\",\n 700: \"var(--togo-color-neutral-700)\",\n 800: \"var(--togo-color-neutral-800)\",\n 900: \"var(--togo-color-neutral-900)\",\n 1000: \"var(--togo-color-neutral-1000)\",\n },\n\n // Semantic\n success: {\n light: \"var(--togo-color-success-light)\",\n default: \"var(--togo-color-success)\",\n dark: \"var(--togo-color-success-dark)\",\n },\n warning: {\n light: \"var(--togo-color-warning-light)\",\n default: \"var(--togo-color-warning)\",\n dark: \"var(--togo-color-warning-dark)\",\n },\n error: {\n light: \"var(--togo-color-error-light)\",\n default: \"var(--togo-color-error)\",\n dark: \"var(--togo-color-error-dark)\",\n },\n info: {\n light: \"var(--togo-color-info-light)\",\n default: \"var(--togo-color-info)\",\n dark: \"var(--togo-color-info-dark)\",\n },\n} as const;\n\nexport const spacing = {\n 0: \"0px\",\n 1: \"4px\",\n 2: \"8px\",\n 3: \"12px\",\n 4: \"16px\",\n 5: \"20px\",\n 6: \"24px\",\n 8: \"32px\",\n 10: \"40px\",\n 12: \"48px\",\n 16: \"64px\",\n 20: \"80px\",\n 24: \"96px\",\n} as const;\n\nexport const typography = {\n fontFamily: {\n sans: \"var(--togo-font-sans)\",\n mono: \"var(--togo-font-mono)\",\n },\n fontSize: {\n xs: \"var(--togo-text-xs)\",\n sm: \"var(--togo-text-sm)\",\n base: \"var(--togo-text-base)\",\n lg: \"var(--togo-text-lg)\",\n xl: \"var(--togo-text-xl)\",\n \"2xl\": \"var(--togo-text-2xl)\",\n \"3xl\": \"var(--togo-text-3xl)\",\n \"4xl\": \"var(--togo-text-4xl)\",\n },\n fontWeight: {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n },\n lineHeight: {\n tight: \"1.2\",\n snug: \"1.375\",\n normal: \"1.5\",\n relaxed: \"1.625\",\n },\n} as const;\n\nexport const radii = {\n none: \"0px\",\n sm: \"4px\",\n md: \"8px\",\n lg: \"12px\",\n xl: \"16px\",\n full: \"9999px\",\n} as const;\n\nexport const shadows = {\n sm: \"var(--togo-shadow-sm)\",\n md: \"var(--togo-shadow-md)\",\n lg: \"var(--togo-shadow-lg)\",\n xl: \"var(--togo-shadow-xl)\",\n} as const;\n\nexport const zIndex = {\n base: 0,\n raised: 10,\n dropdown: 100,\n sticky: 200,\n overlay: 300,\n modal: 400,\n toast: 500,\n} as const;\n"],"names":["Button","forwardRef","variant","size","loading","leadingIcon","trailingIcon","fullWidth","disabled","className","children","rest","ref","isDisabled","classNames","styles","jsxs","colors","spacing","typography","radii","shadows","zIndex"],"mappings":"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"}
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ ._button_4wrmq_1{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:var(--togo-font-sans);font-weight:500;line-height:1;border:none;cursor:pointer;text-decoration:none;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background-color .12s ease,color .12s ease,box-shadow .12s ease,opacity .12s ease;outline-offset:2px}._button_4wrmq_1:focus-visible{outline:2px solid var(--togo-color-primary-500)}._button_4wrmq_1:disabled,._button_4wrmq_1[aria-disabled=true]{opacity:.4;cursor:not-allowed;pointer-events:none}._sm_4wrmq_32{height:32px;padding:0 12px;font-size:var(--togo-text-sm);border-radius:6px}._md_4wrmq_39{height:40px;padding:0 16px;font-size:var(--togo-text-sm);border-radius:8px}._lg_4wrmq_46{height:48px;padding:0 24px;font-size:var(--togo-text-base);border-radius:10px}._filled_4wrmq_56{background-color:var(--togo-color-primary-600);color:#fff}._filled_4wrmq_56:hover:not(:disabled){background-color:var(--togo-color-primary-700)}._filled_4wrmq_56:active:not(:disabled){background-color:var(--togo-color-primary-800)}._outlined_4wrmq_70{background-color:transparent;color:var(--togo-color-primary-600);border:1.5px solid var(--togo-color-primary-600)}._outlined_4wrmq_70:hover:not(:disabled){background-color:var(--togo-color-primary-50)}._outlined_4wrmq_70:active:not(:disabled){background-color:var(--togo-color-primary-100)}._ghost_4wrmq_85{background-color:transparent;color:var(--togo-color-primary-600)}._ghost_4wrmq_85:hover:not(:disabled){background-color:var(--togo-color-primary-50)}._ghost_4wrmq_85:active:not(:disabled){background-color:var(--togo-color-primary-100)}._destructive_4wrmq_99{background-color:var(--togo-color-error);color:#fff}._destructive_4wrmq_99:hover:not(:disabled){background-color:var(--togo-color-error-dark)}._spinner_4wrmq_110{width:1em;height:1em;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:_togo-spin_4wrmq_1 .6s linear infinite}@keyframes _togo-spin_4wrmq_1{to{transform:rotate(360deg)}}._fullWidth_4wrmq_127{width:100%}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * ToGo Design System — Design Tokens
3
+ *
4
+ * These tokens are the single source of truth for all visual decisions.
5
+ * They map to CSS custom properties defined in global.css.
6
+ */
7
+ export declare const colors: {
8
+ readonly primary: {
9
+ readonly 50: "var(--togo-color-primary-50)";
10
+ readonly 100: "var(--togo-color-primary-100)";
11
+ readonly 200: "var(--togo-color-primary-200)";
12
+ readonly 300: "var(--togo-color-primary-300)";
13
+ readonly 400: "var(--togo-color-primary-400)";
14
+ readonly 500: "var(--togo-color-primary-500)";
15
+ readonly 600: "var(--togo-color-primary-600)";
16
+ readonly 700: "var(--togo-color-primary-700)";
17
+ readonly 800: "var(--togo-color-primary-800)";
18
+ readonly 900: "var(--togo-color-primary-900)";
19
+ };
20
+ readonly neutral: {
21
+ readonly 0: "var(--togo-color-neutral-0)";
22
+ readonly 50: "var(--togo-color-neutral-50)";
23
+ readonly 100: "var(--togo-color-neutral-100)";
24
+ readonly 200: "var(--togo-color-neutral-200)";
25
+ readonly 300: "var(--togo-color-neutral-300)";
26
+ readonly 400: "var(--togo-color-neutral-400)";
27
+ readonly 500: "var(--togo-color-neutral-500)";
28
+ readonly 600: "var(--togo-color-neutral-600)";
29
+ readonly 700: "var(--togo-color-neutral-700)";
30
+ readonly 800: "var(--togo-color-neutral-800)";
31
+ readonly 900: "var(--togo-color-neutral-900)";
32
+ readonly 1000: "var(--togo-color-neutral-1000)";
33
+ };
34
+ readonly success: {
35
+ readonly light: "var(--togo-color-success-light)";
36
+ readonly default: "var(--togo-color-success)";
37
+ readonly dark: "var(--togo-color-success-dark)";
38
+ };
39
+ readonly warning: {
40
+ readonly light: "var(--togo-color-warning-light)";
41
+ readonly default: "var(--togo-color-warning)";
42
+ readonly dark: "var(--togo-color-warning-dark)";
43
+ };
44
+ readonly error: {
45
+ readonly light: "var(--togo-color-error-light)";
46
+ readonly default: "var(--togo-color-error)";
47
+ readonly dark: "var(--togo-color-error-dark)";
48
+ };
49
+ readonly info: {
50
+ readonly light: "var(--togo-color-info-light)";
51
+ readonly default: "var(--togo-color-info)";
52
+ readonly dark: "var(--togo-color-info-dark)";
53
+ };
54
+ };
55
+ export declare const spacing: {
56
+ readonly 0: "0px";
57
+ readonly 1: "4px";
58
+ readonly 2: "8px";
59
+ readonly 3: "12px";
60
+ readonly 4: "16px";
61
+ readonly 5: "20px";
62
+ readonly 6: "24px";
63
+ readonly 8: "32px";
64
+ readonly 10: "40px";
65
+ readonly 12: "48px";
66
+ readonly 16: "64px";
67
+ readonly 20: "80px";
68
+ readonly 24: "96px";
69
+ };
70
+ export declare const typography: {
71
+ readonly fontFamily: {
72
+ readonly sans: "var(--togo-font-sans)";
73
+ readonly mono: "var(--togo-font-mono)";
74
+ };
75
+ readonly fontSize: {
76
+ readonly xs: "var(--togo-text-xs)";
77
+ readonly sm: "var(--togo-text-sm)";
78
+ readonly base: "var(--togo-text-base)";
79
+ readonly lg: "var(--togo-text-lg)";
80
+ readonly xl: "var(--togo-text-xl)";
81
+ readonly "2xl": "var(--togo-text-2xl)";
82
+ readonly "3xl": "var(--togo-text-3xl)";
83
+ readonly "4xl": "var(--togo-text-4xl)";
84
+ };
85
+ readonly fontWeight: {
86
+ readonly regular: "400";
87
+ readonly medium: "500";
88
+ readonly semibold: "600";
89
+ readonly bold: "700";
90
+ };
91
+ readonly lineHeight: {
92
+ readonly tight: "1.2";
93
+ readonly snug: "1.375";
94
+ readonly normal: "1.5";
95
+ readonly relaxed: "1.625";
96
+ };
97
+ };
98
+ export declare const radii: {
99
+ readonly none: "0px";
100
+ readonly sm: "4px";
101
+ readonly md: "8px";
102
+ readonly lg: "12px";
103
+ readonly xl: "16px";
104
+ readonly full: "9999px";
105
+ };
106
+ export declare const shadows: {
107
+ readonly sm: "var(--togo-shadow-sm)";
108
+ readonly md: "var(--togo-shadow-md)";
109
+ readonly lg: "var(--togo-shadow-lg)";
110
+ readonly xl: "var(--togo-shadow-xl)";
111
+ };
112
+ export declare const zIndex: {
113
+ readonly base: 0;
114
+ readonly raised: 10;
115
+ readonly dropdown: 100;
116
+ readonly sticky: 200;
117
+ readonly overlay: 300;
118
+ readonly modal: 400;
119
+ readonly toast: 500;
120
+ };
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@edwinner/togo-react",
3
+ "version": "0.1.0",
4
+ "description": "ToGo Design System — a personal React component library",
5
+ "keywords": [
6
+ "design-system",
7
+ "react",
8
+ "components",
9
+ "ui",
10
+ "togo"
11
+ ],
12
+ "author": "Edwin",
13
+ "license": "MIT",
14
+ "type": "module",
15
+ "main": "./dist/index.cjs",
16
+ "module": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/index.cjs",
22
+ "types": "./dist/index.d.ts"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "sideEffects": false,
29
+ "scripts": {
30
+ "dev": "storybook dev -p 6006",
31
+ "demo": "vite --port 5173",
32
+ "build": "tsc -p tsconfig.build.json && vite build",
33
+ "build-storybook": "storybook build",
34
+ "lint": "eslint src --ext .ts,.tsx",
35
+ "typecheck": "tsc --noEmit",
36
+ "prepublishOnly": "npm run build"
37
+ },
38
+ "peerDependencies": {
39
+ "react": ">=18.0.0",
40
+ "react-dom": ">=18.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@storybook/addon-a11y": "^8.0.0",
44
+ "@storybook/addon-essentials": "^8.0.0",
45
+ "@storybook/addon-interactions": "^8.0.0",
46
+ "@storybook/react": "^8.0.0",
47
+ "@storybook/react-vite": "^8.0.0",
48
+ "@types/react": "^18.3.0",
49
+ "@types/react-dom": "^18.3.0",
50
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
51
+ "@typescript-eslint/parser": "^7.0.0",
52
+ "@vitejs/plugin-react": "^5.1.4",
53
+ "eslint": "^8.57.0",
54
+ "eslint-plugin-react": "^7.34.0",
55
+ "eslint-plugin-react-hooks": "^4.6.0",
56
+ "react": "^18.3.0",
57
+ "react-dom": "^18.3.0",
58
+ "storybook": "^8.0.0",
59
+ "typescript": "^5.4.0",
60
+ "vite": "^5.2.0",
61
+ "vite-plugin-dts": "^3.9.0"
62
+ }
63
+ }