@breakergames/design-system 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.
Files changed (57) hide show
  1. package/dist/components/Avatar/Avatar.d.ts +8 -0
  2. package/dist/components/Avatar/index.d.ts +2 -0
  3. package/dist/components/Badge/Badge.d.ts +9 -0
  4. package/dist/components/Badge/index.d.ts +2 -0
  5. package/dist/components/BottomInputBar/BottomInputBar.d.ts +10 -0
  6. package/dist/components/BottomInputBar/index.d.ts +2 -0
  7. package/dist/components/Button/Button.d.ts +10 -0
  8. package/dist/components/Button/index.d.ts +2 -0
  9. package/dist/components/Card/Card.d.ts +9 -0
  10. package/dist/components/Card/FeaturedCard.d.ts +15 -0
  11. package/dist/components/Card/GeneratingCard.d.ts +7 -0
  12. package/dist/components/Card/ScenarioCard.d.ts +15 -0
  13. package/dist/components/Card/index.d.ts +8 -0
  14. package/dist/components/ChatBubble/ChatBubble.d.ts +7 -0
  15. package/dist/components/ChatBubble/index.d.ts +2 -0
  16. package/dist/components/GameGrid/GameGrid.d.ts +8 -0
  17. package/dist/components/GameGrid/HotGrid.d.ts +9 -0
  18. package/dist/components/GameGrid/WaterfallGrid.d.ts +8 -0
  19. package/dist/components/GameGrid/index.d.ts +6 -0
  20. package/dist/components/Header/Header.d.ts +21 -0
  21. package/dist/components/Header/index.d.ts +2 -0
  22. package/dist/components/Input/Input.d.ts +8 -0
  23. package/dist/components/Input/index.d.ts +2 -0
  24. package/dist/components/LikeButton/LikeButton.d.ts +9 -0
  25. package/dist/components/LikeButton/index.d.ts +2 -0
  26. package/dist/components/Modal/BottomSheet.d.ts +11 -0
  27. package/dist/components/Modal/Modal.d.ts +10 -0
  28. package/dist/components/Modal/index.d.ts +4 -0
  29. package/dist/components/StatCard/StatCard.d.ts +8 -0
  30. package/dist/components/StatCard/index.d.ts +2 -0
  31. package/dist/icons/ArrowUpIcon.d.ts +4 -0
  32. package/dist/icons/CloseIcon.d.ts +4 -0
  33. package/dist/icons/HeartIcon.d.ts +5 -0
  34. package/dist/icons/PlayIcon.d.ts +4 -0
  35. package/dist/icons/index.d.ts +4 -0
  36. package/dist/index.cjs.js +1 -0
  37. package/dist/index.d.ts +30 -0
  38. package/dist/index.es.js +361 -0
  39. package/dist/style.css +1 -0
  40. package/dist/tokens/colors.d.ts +14 -0
  41. package/dist/tokens/spacing.d.ts +20 -0
  42. package/dist/tokens/typography.d.ts +9 -0
  43. package/dist/types/index.d.ts +19 -0
  44. package/guidelines/Guidelines.md +41 -0
  45. package/guidelines/components/badge.md +25 -0
  46. package/guidelines/components/button.md +30 -0
  47. package/guidelines/components/card.md +51 -0
  48. package/guidelines/components/chat-bubble.md +17 -0
  49. package/guidelines/components/game-grid.md +34 -0
  50. package/guidelines/components/header.md +38 -0
  51. package/guidelines/components/input.md +22 -0
  52. package/guidelines/components/modal.md +42 -0
  53. package/guidelines/design-tokens/colors.md +47 -0
  54. package/guidelines/design-tokens/spacing.md +47 -0
  55. package/guidelines/design-tokens/typography.md +30 -0
  56. package/guidelines/overview-components.md +43 -0
  57. package/package.json +38 -0
@@ -0,0 +1,361 @@
1
+ import { jsxs as c, jsx as a, Fragment as u } from "react/jsx-runtime";
2
+ import p from "react";
3
+ function x({
4
+ variant: e = "primary",
5
+ size: n = "md",
6
+ fullWidth: r = !1,
7
+ loading: l = !1,
8
+ icon: i,
9
+ children: s,
10
+ disabled: t,
11
+ className: d = "",
12
+ ...o
13
+ }) {
14
+ const m = [
15
+ "maka-btn",
16
+ `maka-btn--${e}`,
17
+ `maka-btn--${n}`,
18
+ r && "maka-btn--full",
19
+ d
20
+ ].filter(Boolean).join(" ");
21
+ return /* @__PURE__ */ c("button", { className: m, disabled: t || l, ...o, children: [
22
+ l && /* @__PURE__ */ a("span", { className: "maka-btn__spinner" }),
23
+ !l && i,
24
+ s
25
+ ] });
26
+ }
27
+ const b = p.forwardRef(
28
+ ({ label: e, error: n, helperText: r, className: l = "", ...i }, s) => /* @__PURE__ */ c("div", { className: "maka-input-wrapper", children: [
29
+ e && /* @__PURE__ */ a("label", { className: "maka-input-label", children: e }),
30
+ /* @__PURE__ */ a(
31
+ "input",
32
+ {
33
+ ref: s,
34
+ className: `maka-input ${n ? "maka-input--error" : ""} ${l}`,
35
+ ...i
36
+ }
37
+ ),
38
+ n && /* @__PURE__ */ a("span", { className: "maka-input-error", children: n }),
39
+ !n && r && /* @__PURE__ */ a("span", { className: "maka-input-helper", children: r })
40
+ ] })
41
+ );
42
+ b.displayName = "Input";
43
+ const v = {
44
+ "staff-pick": { icon: "⭐", labelEn: "Pick", labelZh: "精选" },
45
+ hot: { icon: "🔥", labelEn: "Hot", labelZh: "热门" },
46
+ liked: { icon: "❤️", labelEn: "Loved", labelZh: "好评" },
47
+ rising: { icon: "📈", labelEn: "Rising", labelZh: "上升" },
48
+ new: { icon: "✨", labelEn: "New", labelZh: "新品" },
49
+ trending: { icon: "🚀", labelEn: "Trend", labelZh: "趋势" }
50
+ };
51
+ function $({ type: e, label: n, language: r = "en", className: l = "" }) {
52
+ const i = v[e], s = n || (r === "zh" ? i.labelZh : i.labelEn);
53
+ return /* @__PURE__ */ c("span", { className: `maka-badge maka-badge--${e} ${l}`, children: [
54
+ /* @__PURE__ */ a("span", { children: i.icon }),
55
+ /* @__PURE__ */ a("span", { children: s })
56
+ ] });
57
+ }
58
+ function y({ name: e, imageUrl: n, size: r = "md", className: l = "" }) {
59
+ var s;
60
+ const i = ((s = e == null ? void 0 : e.charAt(0)) == null ? void 0 : s.toUpperCase()) || "U";
61
+ return /* @__PURE__ */ a("div", { className: `maka-avatar maka-avatar--${r} ${l}`, children: n ? /* @__PURE__ */ a("img", { src: n, alt: e || "avatar" }) : /* @__PURE__ */ a("span", { children: i }) });
62
+ }
63
+ function w({ label: e, value: n, color: r = "primary", className: l = "" }) {
64
+ return /* @__PURE__ */ c("div", { className: `maka-stat-card ${l}`, children: [
65
+ /* @__PURE__ */ a("span", { className: "maka-stat-card__label", children: e }),
66
+ /* @__PURE__ */ a("span", { className: `maka-stat-card__value maka-stat-card__value--${r}`, children: n })
67
+ ] });
68
+ }
69
+ function B({ children: e, className: n = "", clickable: r = !1, onClick: l }) {
70
+ return /* @__PURE__ */ a(
71
+ "div",
72
+ {
73
+ className: `maka-card ${r ? "maka-card--clickable" : ""} ${n}`,
74
+ onClick: l,
75
+ role: r ? "button" : void 0,
76
+ tabIndex: r ? 0 : void 0,
77
+ children: e
78
+ }
79
+ );
80
+ }
81
+ function C({
82
+ title: e,
83
+ tagline: n,
84
+ imageUrl: r,
85
+ gradientFrom: l,
86
+ gradientTo: i,
87
+ badge: s,
88
+ playCount: t,
89
+ likeCount: d,
90
+ onClick: o,
91
+ className: m = ""
92
+ }) {
93
+ const h = r ? { backgroundImage: `url(${r})` } : { background: `linear-gradient(135deg, ${l || "#7c5cfa"}, ${i || "#5c9cfa"})` };
94
+ return /* @__PURE__ */ c("div", { className: `maka-featured-card ${m}`, onClick: o, children: [
95
+ /* @__PURE__ */ a("div", { className: "maka-featured-card__bg", style: h }),
96
+ /* @__PURE__ */ a("div", { className: "maka-featured-card__overlay" }),
97
+ s && /* @__PURE__ */ a("div", { className: "maka-featured-card__badge", children: s }),
98
+ /* @__PURE__ */ c("div", { className: "maka-featured-card__content", children: [
99
+ /* @__PURE__ */ a("div", { className: "maka-featured-card__title", children: e }),
100
+ n && /* @__PURE__ */ a("div", { className: "maka-featured-card__tagline", children: n }),
101
+ /* @__PURE__ */ c("div", { className: "maka-featured-card__stats", children: [
102
+ t !== void 0 && /* @__PURE__ */ c("span", { children: [
103
+ "▶ ",
104
+ t
105
+ ] }),
106
+ d !== void 0 && /* @__PURE__ */ c("span", { children: [
107
+ "❤ ",
108
+ d
109
+ ] })
110
+ ] })
111
+ ] })
112
+ ] });
113
+ }
114
+ function I({
115
+ title: e,
116
+ tagline: n,
117
+ imageUrl: r,
118
+ primaryColor: l,
119
+ backgroundColor: i,
120
+ badge: s,
121
+ playCount: t,
122
+ likeCount: d,
123
+ onClick: o,
124
+ className: m = ""
125
+ }) {
126
+ const h = r ? { backgroundImage: `url(${r})` } : { background: `linear-gradient(135deg, ${l || "#7c5cfa"}, ${i || "#1e2a3a"})` };
127
+ return /* @__PURE__ */ c("div", { className: `maka-scenario-card ${m}`, onClick: o, children: [
128
+ /* @__PURE__ */ c("div", { className: "maka-scenario-card__image", style: h, children: [
129
+ /* @__PURE__ */ a("div", { className: "maka-scenario-card__image-overlay" }),
130
+ /* @__PURE__ */ c("div", { className: "maka-scenario-card__image-stats", children: [
131
+ t !== void 0 && /* @__PURE__ */ c("span", { children: [
132
+ "▶ ",
133
+ t
134
+ ] }),
135
+ d !== void 0 && /* @__PURE__ */ c("span", { children: [
136
+ "❤ ",
137
+ d
138
+ ] })
139
+ ] }),
140
+ s && /* @__PURE__ */ a("div", { className: "maka-scenario-card__badge-slot", children: s }),
141
+ /* @__PURE__ */ a("div", { className: "maka-scenario-card__play-overlay", children: /* @__PURE__ */ a("span", { style: { fontSize: 32, color: "white" }, children: "▶" }) })
142
+ ] }),
143
+ /* @__PURE__ */ c("div", { className: "maka-scenario-card__body", children: [
144
+ /* @__PURE__ */ a("div", { className: "maka-scenario-card__title", children: e }),
145
+ n && /* @__PURE__ */ a("div", { className: "maka-scenario-card__tagline", children: n })
146
+ ] })
147
+ ] });
148
+ }
149
+ const N = {
150
+ searching: "Searching...",
151
+ generating: "Generating...",
152
+ ready: "Ready!"
153
+ };
154
+ function S({ status: e = "generating", statusText: n, className: r = "" }) {
155
+ return /* @__PURE__ */ c("div", { className: `maka-generating-card ${r}`, children: [
156
+ /* @__PURE__ */ c("div", { className: "maka-generating-card__dots", children: [
157
+ /* @__PURE__ */ a("div", { className: "maka-generating-card__dot" }),
158
+ /* @__PURE__ */ a("div", { className: "maka-generating-card__dot" }),
159
+ /* @__PURE__ */ a("div", { className: "maka-generating-card__dot" })
160
+ ] }),
161
+ /* @__PURE__ */ a("div", { className: "maka-generating-card__text", children: n || N[e] })
162
+ ] });
163
+ }
164
+ function E({ content: e, role: n, className: r = "" }) {
165
+ return /* @__PURE__ */ a("div", { className: `maka-chat-bubble maka-chat-bubble--${n} ${r}`, children: e });
166
+ }
167
+ function G({ liked: e = !1, count: n = 0, onToggle: r, disabled: l, className: i = "" }) {
168
+ return /* @__PURE__ */ c(
169
+ "button",
170
+ {
171
+ className: `maka-like-btn ${e ? "maka-like-btn--liked" : ""} ${i}`,
172
+ onClick: r,
173
+ disabled: l,
174
+ children: [
175
+ /* @__PURE__ */ a("span", { children: e ? "❤️" : "🤍" }),
176
+ n > 0 && /* @__PURE__ */ a("span", { children: n })
177
+ ]
178
+ }
179
+ );
180
+ }
181
+ function Z({
182
+ placeholder: e = "Search or create games...",
183
+ onClick: n,
184
+ isLoading: r = !1,
185
+ icon: l,
186
+ className: i = ""
187
+ }) {
188
+ return /* @__PURE__ */ a("div", { className: `maka-bottom-bar ${r ? "maka-bottom-bar--loading" : ""} ${i}`, children: /* @__PURE__ */ c("div", { className: "maka-bottom-bar__pill", onClick: n, role: "button", tabIndex: 0, children: [
189
+ /* @__PURE__ */ a("span", { className: "maka-bottom-bar__icon", children: l || "🦙" }),
190
+ /* @__PURE__ */ a("span", { className: "maka-bottom-bar__placeholder", children: e }),
191
+ r ? /* @__PURE__ */ a("span", { className: "maka-bottom-bar__spinner" }) : /* @__PURE__ */ a("span", { className: "maka-bottom-bar__send", children: "↑" })
192
+ ] }) });
193
+ }
194
+ function H({
195
+ logoText: e = "Makabaka",
196
+ logoIcon: n,
197
+ tabs: r = [],
198
+ activeTab: l,
199
+ onTabChange: i,
200
+ userName: s,
201
+ avatar: t,
202
+ onSignIn: d,
203
+ onLogout: o,
204
+ languageLabel: m = "EN",
205
+ onLanguageToggle: h,
206
+ className: _ = ""
207
+ }) {
208
+ return /* @__PURE__ */ a("header", { className: `maka-header ${_}`, children: /* @__PURE__ */ c("div", { className: "maka-header__inner", children: [
209
+ /* @__PURE__ */ c("a", { className: "maka-header__logo", href: "/", children: [
210
+ /* @__PURE__ */ a("span", { className: "maka-header__logo-icon", children: n || "🦙" }),
211
+ /* @__PURE__ */ a("span", { className: "maka-header__logo-text", children: e })
212
+ ] }),
213
+ r.length > 0 && /* @__PURE__ */ a("nav", { className: "maka-header__nav", children: r.map((k) => /* @__PURE__ */ a(
214
+ "button",
215
+ {
216
+ className: `maka-header__tab ${l === k.id ? "maka-header__tab--active" : ""}`,
217
+ onClick: () => i == null ? void 0 : i(k.id),
218
+ children: k.label
219
+ },
220
+ k.id
221
+ )) }),
222
+ /* @__PURE__ */ c("div", { className: "maka-header__actions", children: [
223
+ h && /* @__PURE__ */ a("button", { className: "maka-header__lang-btn", onClick: h, children: m }),
224
+ s ? /* @__PURE__ */ c(u, { children: [
225
+ /* @__PURE__ */ a("span", { className: "maka-header__username", children: s }),
226
+ t,
227
+ o && /* @__PURE__ */ a("button", { className: "maka-header__tab", onClick: o, style: { display: "none" }, children: "Logout" })
228
+ ] }) : d && /* @__PURE__ */ a("button", { className: "maka-header__tab", onClick: d, children: "Sign In" })
229
+ ] })
230
+ ] }) });
231
+ }
232
+ function L({ isOpen: e, onClose: n, children: r, size: l = "md", className: i = "" }) {
233
+ return e ? /* @__PURE__ */ a("div", { className: "maka-modal-backdrop", onClick: n, children: /* @__PURE__ */ c(
234
+ "div",
235
+ {
236
+ className: `maka-modal maka-modal--${l} ${i}`,
237
+ onClick: (s) => s.stopPropagation(),
238
+ children: [
239
+ /* @__PURE__ */ a("button", { className: "maka-modal__close", onClick: n, children: "✕" }),
240
+ r
241
+ ]
242
+ }
243
+ ) }) : null;
244
+ }
245
+ function P({ isOpen: e, onClose: n, children: r, title: l, subtitle: i, className: s = "" }) {
246
+ return e ? /* @__PURE__ */ a("div", { className: "maka-bottom-sheet-backdrop", onClick: n, children: /* @__PURE__ */ c("div", { className: `maka-bottom-sheet ${s}`, onClick: (t) => t.stopPropagation(), children: [
247
+ /* @__PURE__ */ a("div", { className: "maka-bottom-sheet__handle" }),
248
+ (l || i) && /* @__PURE__ */ c("div", { className: "maka-bottom-sheet__header", children: [
249
+ /* @__PURE__ */ c("div", { children: [
250
+ l && /* @__PURE__ */ a("div", { className: "maka-bottom-sheet__title", children: l }),
251
+ i && /* @__PURE__ */ a("div", { className: "maka-bottom-sheet__subtitle", children: i })
252
+ ] }),
253
+ /* @__PURE__ */ a("button", { className: "maka-bottom-sheet__close", onClick: n, children: "✕" })
254
+ ] }),
255
+ /* @__PURE__ */ a("div", { className: "maka-bottom-sheet__body", children: r })
256
+ ] }) }) : null;
257
+ }
258
+ function A({ children: e, columns: n = 3, className: r = "" }) {
259
+ return /* @__PURE__ */ a("div", { className: `maka-game-grid ${n === 4 ? "maka-game-grid--4" : ""} ${r}`, children: e });
260
+ }
261
+ function M({ title: e, icon: n, children: r, className: l = "" }) {
262
+ return /* @__PURE__ */ c("div", { className: l, children: [
263
+ (e || n) && /* @__PURE__ */ c("div", { className: "maka-hot-grid__header", children: [
264
+ n && /* @__PURE__ */ a("span", { className: "maka-hot-grid__header-icon", children: n }),
265
+ e && /* @__PURE__ */ a("span", { children: e })
266
+ ] }),
267
+ /* @__PURE__ */ a("div", { className: "maka-hot-grid__content", children: r })
268
+ ] });
269
+ }
270
+ function R({ leftColumn: e, rightColumn: n, className: r = "" }) {
271
+ return /* @__PURE__ */ c("div", { className: `maka-waterfall ${r}`, children: [
272
+ /* @__PURE__ */ a("div", { className: "maka-waterfall__col", children: e }),
273
+ /* @__PURE__ */ a("div", { className: "maka-waterfall__col maka-waterfall__col--offset", children: n })
274
+ ] });
275
+ }
276
+ function W({ size: e = 24, color: n = "currentColor" }) {
277
+ return /* @__PURE__ */ a("svg", { width: e, height: e, viewBox: "0 0 24 24", fill: n, children: /* @__PURE__ */ a("path", { d: "M8 5v14l11-7L8 5z" }) });
278
+ }
279
+ function j({ size: e = 24, color: n = "currentColor" }) {
280
+ return /* @__PURE__ */ c("svg", { width: e, height: e, viewBox: "0 0 24 24", fill: "none", stroke: n, strokeWidth: "2", strokeLinecap: "round", children: [
281
+ /* @__PURE__ */ a("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
282
+ /* @__PURE__ */ a("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
283
+ ] });
284
+ }
285
+ function D({ size: e = 24, color: n = "currentColor", filled: r = !1 }) {
286
+ return /* @__PURE__ */ a("svg", { width: e, height: e, viewBox: "0 0 24 24", fill: r ? n : "none", stroke: n, strokeWidth: "2", children: /* @__PURE__ */ a("path", { d: "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" }) });
287
+ }
288
+ function F({ size: e = 24, color: n = "currentColor" }) {
289
+ return /* @__PURE__ */ c("svg", { width: e, height: e, viewBox: "0 0 24 24", fill: "none", stroke: n, strokeWidth: "2", strokeLinecap: "round", children: [
290
+ /* @__PURE__ */ a("line", { x1: "12", y1: "19", x2: "12", y2: "5" }),
291
+ /* @__PURE__ */ a("polyline", { points: "5 12 12 5 19 12" })
292
+ ] });
293
+ }
294
+ const J = {
295
+ primary: "#7c5cfa",
296
+ primaryHover: "#6b4ee0",
297
+ secondary: "#5c9cfa",
298
+ accent: "#06d6a0",
299
+ bgDark: "#1b2838",
300
+ bgCard: "#1e2a3a",
301
+ bgHover: "#2a3a4a",
302
+ textPrimary: "#e8e8ec",
303
+ danger: "#ef4444",
304
+ success: "#22c55e",
305
+ warning: "#f59e0b",
306
+ like: "#f43f5e"
307
+ }, O = {
308
+ fontDisplay: '"Plus Jakarta Sans", "Inter", sans-serif',
309
+ fontBody: '"Inter", sans-serif',
310
+ weightRegular: 400,
311
+ weightMedium: 500,
312
+ weightSemibold: 600,
313
+ weightBold: 700,
314
+ weightExtrabold: 800
315
+ }, U = {
316
+ 1: "4px",
317
+ 2: "8px",
318
+ 3: "12px",
319
+ 4: "16px",
320
+ 5: "20px",
321
+ 6: "24px",
322
+ 8: "32px",
323
+ 10: "40px",
324
+ 12: "48px",
325
+ 16: "64px"
326
+ }, X = {
327
+ sm: "4px",
328
+ md: "8px",
329
+ lg: "12px",
330
+ xl: "16px",
331
+ "2xl": "24px",
332
+ full: "9999px"
333
+ };
334
+ export {
335
+ F as ArrowUpIcon,
336
+ y as Avatar,
337
+ $ as Badge,
338
+ Z as BottomInputBar,
339
+ P as BottomSheet,
340
+ x as Button,
341
+ B as Card,
342
+ E as ChatBubble,
343
+ j as CloseIcon,
344
+ C as FeaturedCard,
345
+ A as GameGrid,
346
+ S as GeneratingCard,
347
+ H as Header,
348
+ D as HeartIcon,
349
+ M as HotGrid,
350
+ b as Input,
351
+ G as LikeButton,
352
+ L as Modal,
353
+ W as PlayIcon,
354
+ I as ScenarioCard,
355
+ w as StatCard,
356
+ R as WaterfallGrid,
357
+ J as colors,
358
+ X as radius,
359
+ U as spacing,
360
+ O as typography
361
+ };
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@500;600;700;800&family=Inter:wght@400;500;600&display=swap";:root{--maka-primary: #7c5cfa;--maka-primary-hover: #6b4ee0;--maka-secondary: #5c9cfa;--maka-accent: #06d6a0;--maka-bg-dark: #1b2838;--maka-bg-card: #1e2a3a;--maka-bg-hover: #2a3a4a;--maka-bg-overlay: rgba(0, 0, 0, .8);--maka-bg-frosted: rgba(0, 0, 0, .7);--maka-text-primary: #e8e8ec;--maka-text-secondary: rgba(255, 255, 255, .7);--maka-text-muted: rgba(255, 255, 255, .4);--maka-text-disabled: rgba(255, 255, 255, .3);--maka-danger: #ef4444;--maka-danger-bg: rgba(239, 68, 68, .1);--maka-success: #22c55e;--maka-success-bg: rgba(34, 197, 94, .2);--maka-warning: #f59e0b;--maka-warning-bg: rgba(245, 158, 11, .2);--maka-like: #f43f5e;--maka-badge-staff-from: #f59e0b;--maka-badge-staff-to: #eab308;--maka-badge-hot-from: #f97316;--maka-badge-hot-to: #ef4444;--maka-badge-liked-from: #ec4899;--maka-badge-liked-to: #f43f5e;--maka-badge-rising-from: #22c55e;--maka-badge-rising-to: #10b981;--maka-badge-new-from: #a855f7;--maka-badge-new-to: #6366f1;--maka-badge-trending-from: #06b6d4;--maka-badge-trending-to: #3b82f6;--maka-font-display: "Plus Jakarta Sans", "Inter", sans-serif;--maka-font-body: "Inter", sans-serif;--maka-radius-sm: 4px;--maka-radius-md: 8px;--maka-radius-lg: 12px;--maka-radius-xl: 16px;--maka-radius-2xl: 24px;--maka-radius-full: 9999px;--maka-border-subtle: rgba(255, 255, 255, .1);--maka-border-medium: rgba(255, 255, 255, .2);--maka-border-emphasis: rgba(255, 255, 255, .4);--maka-border-primary: rgba(124, 92, 250, .4);--maka-shadow-card: 0 8px 24px rgba(0, 0, 0, .3);--maka-shadow-button: 0 4px 16px rgba(124, 92, 250, .35);--maka-transition-fast: .15s ease;--maka-transition-normal: .3s ease;--maka-space-1: 4px;--maka-space-2: 8px;--maka-space-3: 12px;--maka-space-4: 16px;--maka-space-5: 20px;--maka-space-6: 24px;--maka-space-8: 32px;--maka-space-10: 40px;--maka-space-12: 48px;--maka-space-16: 64px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}.maka-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:var(--maka-font-body);font-weight:600;border:none;cursor:pointer;transition:all var(--maka-transition-normal);border-radius:var(--maka-radius-md);white-space:nowrap}.maka-btn:disabled{opacity:.5;cursor:not-allowed}.maka-btn--sm{padding:6px 12px;font-size:13px}.maka-btn--md{padding:10px 24px;font-size:14px}.maka-btn--lg{padding:14px 28px;font-size:16px}.maka-btn--primary{background:linear-gradient(to right,var(--maka-primary),var(--maka-secondary));color:#fff}.maka-btn--primary:hover:not(:disabled){transform:scale(1.03);box-shadow:var(--maka-shadow-button)}.maka-btn--secondary{background:transparent;border:1px solid var(--maka-border-primary);color:var(--maka-primary)}.maka-btn--secondary:hover:not(:disabled){background:#7c5cfa1a;border-color:var(--maka-primary)}.maka-btn--ghost{background:#ffffff0d;border:1px solid var(--maka-border-subtle);color:var(--maka-text-secondary)}.maka-btn--ghost:hover:not(:disabled){background:#ffffff1a;color:var(--maka-text-primary)}.maka-btn--danger{background:var(--maka-danger-bg);border:1px solid rgba(239,68,68,.3);color:var(--maka-danger)}.maka-btn--danger:hover:not(:disabled){background:#ef444433}.maka-btn--full{width:100%}.maka-btn__spinner{width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:maka-spin .6s linear infinite}.maka-input-wrapper{display:flex;flex-direction:column;gap:6px}.maka-input-label{font-family:var(--maka-font-body);font-size:14px;font-weight:500;color:var(--maka-text-secondary)}.maka-input{width:100%;padding:10px 16px;font-family:var(--maka-font-body);font-size:14px;color:var(--maka-text-primary);background:var(--maka-bg-dark);border:1px solid var(--maka-border-medium);border-radius:var(--maka-radius-md);outline:none;transition:border-color var(--maka-transition-fast),box-shadow var(--maka-transition-fast)}.maka-input::placeholder{color:var(--maka-text-muted)}.maka-input:focus{border-color:var(--maka-primary);box-shadow:0 0 0 1px var(--maka-primary)}.maka-input--error{border-color:var(--maka-danger)}.maka-input--error:focus{box-shadow:0 0 0 1px var(--maka-danger)}.maka-input-error{font-size:13px;color:var(--maka-danger)}.maka-input-helper{font-size:13px;color:var(--maka-text-muted)}.maka-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:var(--maka-radius-full);font-family:var(--maka-font-body);font-size:11px;font-weight:500;color:#fff;white-space:nowrap}.maka-badge--staff-pick{background:linear-gradient(135deg,var(--maka-badge-staff-from),var(--maka-badge-staff-to))}.maka-badge--hot{background:linear-gradient(135deg,var(--maka-badge-hot-from),var(--maka-badge-hot-to))}.maka-badge--liked{background:linear-gradient(135deg,var(--maka-badge-liked-from),var(--maka-badge-liked-to))}.maka-badge--rising{background:linear-gradient(135deg,var(--maka-badge-rising-from),var(--maka-badge-rising-to))}.maka-badge--new{background:linear-gradient(135deg,var(--maka-badge-new-from),var(--maka-badge-new-to))}.maka-badge--trending{background:linear-gradient(135deg,var(--maka-badge-trending-from),var(--maka-badge-trending-to))}.maka-avatar{display:flex;align-items:center;justify-content:center;border-radius:50%;background:linear-gradient(135deg,var(--maka-primary),var(--maka-secondary));color:#fff;font-family:var(--maka-font-display);font-weight:700;flex-shrink:0;overflow:hidden}.maka-avatar--sm{width:28px;height:28px;font-size:12px}.maka-avatar--md{width:36px;height:36px;font-size:14px}.maka-avatar--lg{width:48px;height:48px;font-size:18px}.maka-avatar img{width:100%;height:100%;object-fit:cover}.maka-stat-card{display:flex;flex-direction:column;gap:4px;padding:16px;background:#ffffff0d;border:1px solid var(--maka-border-subtle);border-radius:var(--maka-radius-lg)}.maka-stat-card__label{font-family:var(--maka-font-body);font-size:12px;color:var(--maka-text-muted)}.maka-stat-card__value{font-family:var(--maka-font-display);font-size:28px;font-weight:700}.maka-stat-card__value--primary{color:var(--maka-primary)}.maka-stat-card__value--danger{color:var(--maka-like)}.maka-stat-card__value--success{color:var(--maka-accent)}.maka-card{background:var(--maka-bg-card);border:1px solid var(--maka-border-subtle);border-radius:var(--maka-radius-xl);padding:24px;transition:all var(--maka-transition-normal)}.maka-card--clickable{cursor:pointer}.maka-card--clickable:hover{border-color:#7c5cfa4d;box-shadow:var(--maka-shadow-card)}.maka-featured-card{position:relative;border-radius:var(--maka-radius-2xl);overflow:hidden;cursor:pointer;aspect-ratio:4/5}@media (min-width: 1024px){.maka-featured-card{aspect-ratio:3/2}}.maka-featured-card__bg{position:absolute;top:0;right:0;bottom:0;left:0;background-size:cover;background-position:center}.maka-featured-card__overlay{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,rgba(0,0,0,.85) 0%,rgba(0,0,0,.3) 50%,transparent 100%)}.maka-featured-card__badge{position:absolute;top:12px;left:12px;z-index:2}.maka-featured-card__content{position:absolute;bottom:0;left:0;right:0;padding:20px;z-index:2}.maka-featured-card__title{font-family:var(--maka-font-display);font-size:20px;font-weight:700;color:#fff;margin-bottom:4px}.maka-featured-card__tagline{font-size:14px;color:#ffffffb3;margin-bottom:12px}.maka-featured-card__stats{display:flex;align-items:center;gap:16px;font-size:13px;color:#fff9}.maka-featured-card__stats span{display:flex;align-items:center;gap:4px}.maka-featured-card:hover{box-shadow:0 0 0 2px #ffffff4d}.maka-scenario-card{position:relative;border-radius:var(--maka-radius-xl);overflow:hidden;cursor:pointer;background:var(--maka-bg-card);border:1px solid var(--maka-border-subtle);transition:all var(--maka-transition-normal)}.maka-scenario-card:hover{border-color:#7c5cfa4d;box-shadow:var(--maka-shadow-card)}.maka-scenario-card__image{width:100%;aspect-ratio:4/3;background-size:cover;background-position:center;position:relative}.maka-scenario-card__image-overlay{position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,rgba(0,0,0,.7) 0%,transparent 60%)}.maka-scenario-card__image-stats{position:absolute;bottom:8px;left:12px;right:12px;display:flex;align-items:center;gap:12px;font-size:12px;color:#fffc}.maka-scenario-card__image-stats span{display:flex;align-items:center;gap:3px}.maka-scenario-card__body{padding:12px 16px}.maka-scenario-card__title{font-family:var(--maka-font-display);font-size:15px;font-weight:600;color:var(--maka-text-primary);margin-bottom:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.maka-scenario-card__tagline{font-size:13px;color:var(--maka-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.maka-scenario-card__badge-slot{position:absolute;top:8px;left:8px;z-index:2}.maka-scenario-card__play-overlay{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:#00000080;opacity:0;transition:opacity var(--maka-transition-normal)}.maka-scenario-card:hover .maka-scenario-card__play-overlay{opacity:1}.maka-generating-card{aspect-ratio:16/9;border-radius:var(--maka-radius-xl);background:linear-gradient(135deg,#7c5cfa33,#6b728033);border:1px solid var(--maka-border-subtle);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.maka-generating-card__dots{display:flex;gap:8px}.maka-generating-card__dot{width:8px;height:8px;background:var(--maka-primary);border-radius:50%;animation:maka-bounce 1s infinite}.maka-generating-card__dot:nth-child(2){animation-delay:.15s}.maka-generating-card__dot:nth-child(3){animation-delay:.3s}@keyframes maka-bounce{0%,80%,to{transform:scale(.6);opacity:.4}40%{transform:scale(1);opacity:1}}.maka-generating-card__text{font-size:13px;color:var(--maka-text-muted)}.maka-chat-bubble{max-width:80%;padding:10px 16px;font-family:var(--maka-font-body);font-size:14px;line-height:1.6;color:#fff;word-break:break-word}.maka-chat-bubble--user{margin-left:auto;background:#7c5cfacc;border-radius:var(--maka-radius-xl) var(--maka-radius-xl) var(--maka-radius-sm) var(--maka-radius-xl)}.maka-chat-bubble--assistant{margin-right:auto;background:#ffffff1a;border-radius:var(--maka-radius-xl) var(--maka-radius-xl) var(--maka-radius-xl) var(--maka-radius-sm)}.maka-like-btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid var(--maka-border-medium);border-radius:var(--maka-radius-full);background:#ffffff0d;cursor:pointer;transition:all var(--maka-transition-normal);font-family:var(--maka-font-body);font-size:13px;color:var(--maka-text-secondary)}.maka-like-btn:hover{background:#ffffff1a;border-color:var(--maka-border-emphasis)}.maka-like-btn--liked{border-color:#f43f5e80;background:#f43f5e1a;color:var(--maka-like)}.maka-like-btn:disabled{opacity:.5;cursor:not-allowed}.maka-bottom-bar{position:fixed;bottom:0;left:0;right:0;padding:12px 16px;padding-bottom:max(12px,env(safe-area-inset-bottom));background:var(--maka-bg-frosted);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);z-index:40}.maka-bottom-bar__pill{display:flex;align-items:center;gap:12px;padding:12px 16px;background:#ffffff0d;border:1px solid var(--maka-border-subtle);border-radius:var(--maka-radius-full);cursor:pointer;transition:all var(--maka-transition-normal);width:100%}.maka-bottom-bar__pill:hover{background:#ffffff14;border-color:var(--maka-border-medium)}.maka-bottom-bar__icon{font-size:20px;flex-shrink:0}.maka-bottom-bar__placeholder{flex:1;font-family:var(--maka-font-body);font-size:14px;color:var(--maka-text-muted)}.maka-bottom-bar__send{width:32px;height:32px;border-radius:50%;background:#7c5cfa80;border:none;display:flex;align-items:center;justify-content:center;color:#fff;font-size:16px;flex-shrink:0;cursor:pointer;transition:all var(--maka-transition-normal)}.maka-bottom-bar__send:hover{background:var(--maka-primary)}.maka-bottom-bar--loading .maka-bottom-bar__pill{border-color:var(--maka-border-primary)}.maka-bottom-bar__spinner{width:16px;height:16px;border:2px solid var(--maka-primary);border-top-color:transparent;border-radius:50%;animation:maka-spin .6s linear infinite;flex-shrink:0}@keyframes maka-spin{to{transform:rotate(360deg)}}.maka-header{position:fixed;top:0;left:0;right:0;z-index:50;background:linear-gradient(to bottom,#000000e6,#000000b3);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-bottom:1px solid rgba(255,255,255,.05)}.maka-header__inner{max-width:896px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;padding:12px 16px}@media (min-width: 1024px){.maka-header__inner{padding:12px 32px}}.maka-header__logo{display:flex;align-items:center;gap:8px;text-decoration:none;flex-shrink:0}.maka-header__logo-icon{font-size:28px}.maka-header__logo-text{font-family:var(--maka-font-display);font-size:24px;font-weight:700;background:linear-gradient(to right,var(--maka-primary),var(--maka-secondary));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;display:none}@media (min-width: 1024px){.maka-header__logo-text{display:inline}}.maka-header__nav{display:flex;align-items:center;gap:2px}@media (min-width: 1024px){.maka-header__nav{gap:8px}}.maka-header__tab{padding:6px 10px;border-radius:var(--maka-radius-full);font-family:var(--maka-font-body);font-size:14px;font-weight:500;border:none;cursor:pointer;transition:all var(--maka-transition-normal);background:transparent;color:#fff9}@media (min-width: 1024px){.maka-header__tab{padding:8px 20px;font-size:15px}}.maka-header__tab:hover{color:#fff;background:#ffffff1a}.maka-header__tab--active{background:var(--maka-primary);color:#fff}.maka-header__tab--active:hover{background:var(--maka-primary)}.maka-header__actions{display:flex;align-items:center;gap:8px}@media (min-width: 1024px){.maka-header__actions{gap:12px}}.maka-header__lang-btn{padding:6px 10px;border-radius:var(--maka-radius-full);border:1px solid var(--maka-border-medium);background:transparent;color:var(--maka-text-secondary);font-size:12px;font-weight:500;cursor:pointer;transition:all var(--maka-transition-normal)}.maka-header__lang-btn:hover{color:#fff;border-color:var(--maka-border-emphasis)}.maka-header__username{font-size:14px;color:var(--maka-text-secondary);display:none}@media (min-width: 1024px){.maka-header__username{display:inline}}.maka-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:var(--maka-bg-overlay);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;padding:16px}.maka-modal{background:var(--maka-bg-card);border:1px solid var(--maka-border-subtle);border-radius:var(--maka-radius-2xl);width:100%;max-height:90vh;overflow-y:auto;position:relative}.maka-modal--sm{max-width:400px}.maka-modal--md{max-width:560px}.maka-modal--lg{max-width:896px}.maka-modal__close{position:absolute;top:12px;right:12px;width:32px;height:32px;border-radius:50%;background:#00000080;border:none;color:#fff;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:2;transition:background var(--maka-transition-fast)}.maka-modal__close:hover{background:#000000b3}.maka-bottom-sheet-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:var(--maka-bg-overlay);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:flex-end;justify-content:center}.maka-bottom-sheet{background:var(--maka-bg-card);border:1px solid var(--maka-border-subtle);border-radius:var(--maka-radius-2xl) var(--maka-radius-2xl) 0 0;width:100%;max-width:560px;max-height:85vh;overflow-y:auto;position:relative}@media (min-width: 1024px){.maka-bottom-sheet-backdrop{align-items:center}.maka-bottom-sheet{border-radius:var(--maka-radius-2xl);max-width:640px}}.maka-bottom-sheet__handle{width:40px;height:4px;border-radius:2px;background:#fff3;margin:12px auto}@media (min-width: 1024px){.maka-bottom-sheet__handle{display:none}}.maka-bottom-sheet__header{display:flex;align-items:center;justify-content:space-between;padding:4px 20px 12px}.maka-bottom-sheet__title{font-family:var(--maka-font-display);font-size:18px;font-weight:600;color:var(--maka-text-primary)}.maka-bottom-sheet__subtitle{font-size:13px;color:var(--maka-text-muted)}.maka-bottom-sheet__close{width:28px;height:28px;border-radius:50%;background:#ffffff1a;border:none;color:var(--maka-text-secondary);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center}.maka-bottom-sheet__body{padding:0 20px 20px}.maka-game-grid{display:grid;gap:12px;grid-template-columns:repeat(2,1fr)}@media (min-width: 768px){.maka-game-grid{grid-template-columns:repeat(3,1fr);gap:16px}}@media (min-width: 1024px){.maka-game-grid--4{grid-template-columns:repeat(4,1fr)}}.maka-hot-grid__header{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-family:var(--maka-font-display);font-size:18px;font-weight:700;color:var(--maka-text-primary)}.maka-hot-grid__header-icon{font-size:20px}.maka-hot-grid__content{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}@media (min-width: 768px){.maka-hot-grid__content{grid-template-columns:repeat(3,1fr)}}.maka-waterfall{display:grid;grid-template-columns:1fr 1fr;gap:12px}.maka-waterfall__col{display:flex;flex-direction:column;gap:12px}.maka-waterfall__col--offset{padding-top:24px}
@@ -0,0 +1,14 @@
1
+ export declare const colors: {
2
+ readonly primary: "#7c5cfa";
3
+ readonly primaryHover: "#6b4ee0";
4
+ readonly secondary: "#5c9cfa";
5
+ readonly accent: "#06d6a0";
6
+ readonly bgDark: "#1b2838";
7
+ readonly bgCard: "#1e2a3a";
8
+ readonly bgHover: "#2a3a4a";
9
+ readonly textPrimary: "#e8e8ec";
10
+ readonly danger: "#ef4444";
11
+ readonly success: "#22c55e";
12
+ readonly warning: "#f59e0b";
13
+ readonly like: "#f43f5e";
14
+ };
@@ -0,0 +1,20 @@
1
+ export declare const spacing: {
2
+ readonly 1: "4px";
3
+ readonly 2: "8px";
4
+ readonly 3: "12px";
5
+ readonly 4: "16px";
6
+ readonly 5: "20px";
7
+ readonly 6: "24px";
8
+ readonly 8: "32px";
9
+ readonly 10: "40px";
10
+ readonly 12: "48px";
11
+ readonly 16: "64px";
12
+ };
13
+ export declare const radius: {
14
+ readonly sm: "4px";
15
+ readonly md: "8px";
16
+ readonly lg: "12px";
17
+ readonly xl: "16px";
18
+ readonly '2xl': "24px";
19
+ readonly full: "9999px";
20
+ };
@@ -0,0 +1,9 @@
1
+ export declare const typography: {
2
+ readonly fontDisplay: "\"Plus Jakarta Sans\", \"Inter\", sans-serif";
3
+ readonly fontBody: "\"Inter\", sans-serif";
4
+ readonly weightRegular: 400;
5
+ readonly weightMedium: 500;
6
+ readonly weightSemibold: 600;
7
+ readonly weightBold: 700;
8
+ readonly weightExtrabold: 800;
9
+ };
@@ -0,0 +1,19 @@
1
+ export type BadgeType = 'staff-pick' | 'hot' | 'liked' | 'rising' | 'new' | 'trending';
2
+ export interface DiscoveryScenario {
3
+ id: string;
4
+ name: string;
5
+ tagline?: string;
6
+ coverImageUrl?: string;
7
+ primaryColor?: string;
8
+ backgroundColor?: string;
9
+ playCount?: number;
10
+ likeCount?: number;
11
+ commentCount?: number;
12
+ rating?: number;
13
+ tags?: string[];
14
+ badge?: BadgeType;
15
+ templateId?: string;
16
+ creator?: {
17
+ displayName: string;
18
+ };
19
+ }
@@ -0,0 +1,41 @@
1
+ # Makabaka Design System
2
+
3
+ Design system for **makabaka.io**, a UGC game discovery and creation platform.
4
+
5
+ ## Visual Identity
6
+ - **Dark theme only** — page background: `#1b2838`, card surface: `#1e2a3a`
7
+ - **Primary purple gradient** — `#7c5cfa` to `#5c9cfa`
8
+ - **Accent green** — `#06d6a0` for success states and highlights
9
+ - **Frosted glass effects** — `backdrop-filter: blur(12px)` on overlays and headers
10
+ - **Rounded corners** — 12px–24px on cards, full-round on pills/badges
11
+ - **Game community aesthetic** — inspired by Steam/Epic Games Store, not retro arcade
12
+
13
+ ## Installation
14
+ ```tsx
15
+ import '@makabaka/design-system/theme.css';
16
+ import { Button, Card, Header, ... } from '@makabaka/design-system';
17
+ ```
18
+
19
+ ## Rules
20
+ 1. Always import `theme.css` at the root of your app.
21
+ 2. Use `@makabaka/design-system` components instead of native HTML elements.
22
+ 3. Use CSS variables (`--maka-*`) for all colors. Never hardcode hex values in custom styles.
23
+ 4. All pages use dark background (`--maka-bg-dark`).
24
+ 5. Text is always light on dark. Primary: `--maka-text-primary`, secondary: `--maka-text-secondary`.
25
+ 6. Action buttons use `variant="primary"` (gradient purple→blue).
26
+ 7. Cards show a purple border glow on hover.
27
+ 8. Modals/sheets use frosted backdrop overlay.
28
+ 9. The `Header` component is always fixed at the top of the page.
29
+ 10. The `BottomInputBar` is always fixed at the bottom of discovery pages.
30
+
31
+ ## Fonts
32
+ - **Display**: Plus Jakarta Sans (headings, logos, card titles)
33
+ - **Body**: Inter (paragraphs, labels, buttons)
34
+ - Import: `https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@500;600;700;800&family=Inter:wght@400;500;600&display=swap`
35
+
36
+ ## Component Reference
37
+ - See `overview-components.md` for the full component catalog
38
+ - See `design-tokens/colors.md` for color palette
39
+ - See `design-tokens/typography.md` for typography scale
40
+ - See `design-tokens/spacing.md` for spacing and radius
41
+ - See `components/*.md` for individual component guides
@@ -0,0 +1,25 @@
1
+ # Badge
2
+
3
+ Colored pill label for game status/category.
4
+
5
+ ## Types
6
+ | Type | Icon | Colors |
7
+ |------|------|--------|
8
+ | `staff-pick` | ⭐ | Amber gradient |
9
+ | `hot` | 🔥 | Orange→Red gradient |
10
+ | `liked` | ❤️ | Pink→Rose gradient |
11
+ | `rising` | 📈 | Green gradient |
12
+ | `new` | ✨ | Purple→Indigo gradient |
13
+ | `trending` | 🚀 | Cyan→Blue gradient |
14
+
15
+ ## Props
16
+ - `type`: BadgeType (required)
17
+ - `label`: string — custom label override
18
+ - `language`: 'en' | 'zh' — auto label language
19
+
20
+ ## Usage
21
+ ```tsx
22
+ <Badge type="hot" />
23
+ <Badge type="staff-pick" language="zh" />
24
+ <Badge type="new" label="Fresh!" />
25
+ ```
@@ -0,0 +1,30 @@
1
+ # Button
2
+
3
+ Action button with multiple variants.
4
+
5
+ ## Variants
6
+ - `primary` — Gradient purple→blue, white text. For main actions (Play, Create, Sign In).
7
+ - `secondary` — Transparent with purple border. For secondary actions (Join Room, Cancel).
8
+ - `ghost` — Subtle white/5% background. For tertiary actions (Logout, language toggle).
9
+ - `danger` — Red tint background. For destructive actions (Delete, Remove).
10
+
11
+ ## Sizes
12
+ - `sm` — 13px font, compact padding. For inline/compact contexts.
13
+ - `md` — 14px font, standard padding. Default size.
14
+ - `lg` — 16px font, large padding. For hero CTAs, full-width form buttons.
15
+
16
+ ## Props
17
+ - `variant`: 'primary' | 'secondary' | 'ghost' | 'danger'
18
+ - `size`: 'sm' | 'md' | 'lg'
19
+ - `fullWidth`: boolean — stretches to container width
20
+ - `loading`: boolean — shows spinner, disables interaction
21
+ - `icon`: ReactNode — icon before label
22
+ - `disabled`: boolean
23
+
24
+ ## Usage
25
+ ```tsx
26
+ <Button variant="primary" size="lg" fullWidth>Play Now</Button>
27
+ <Button variant="secondary" icon={<PlayIcon size={16} />}>Create Room</Button>
28
+ <Button variant="ghost" size="sm">Cancel</Button>
29
+ <Button variant="danger" loading>Deleting...</Button>
30
+ ```
@@ -0,0 +1,51 @@
1
+ # Card Components
2
+
3
+ ## Card (base)
4
+ Generic container with dark surface, subtle border, and optional hover effect.
5
+ Use as a wrapper for custom card layouts.
6
+
7
+ ```tsx
8
+ <Card clickable onClick={handleClick}>
9
+ <h3>Custom Content</h3>
10
+ </Card>
11
+ ```
12
+
13
+ ## FeaturedCard
14
+ Large hero card for promoted games. Shows full-bleed background image with gradient overlay, badge, title, tagline, and stats.
15
+
16
+ ```tsx
17
+ <FeaturedCard
18
+ title="Survival Challenge"
19
+ tagline="Can you survive the apocalypse?"
20
+ imageUrl="/covers/survival.jpg"
21
+ badge={<Badge type="staff-pick" />}
22
+ playCount={1234}
23
+ likeCount={567}
24
+ onClick={handleClick}
25
+ />
26
+ ```
27
+
28
+ **Aspect ratio**: 4:5 on mobile, 3:2 on desktop.
29
+
30
+ ## ScenarioCard
31
+ Standard game listing card with 4:3 image area, hover play overlay, title, and tagline. Used in grids.
32
+
33
+ ```tsx
34
+ <ScenarioCard
35
+ title="Office Politics"
36
+ tagline="Navigate corporate drama"
37
+ imageUrl="/covers/office.jpg"
38
+ badge={<Badge type="hot" />}
39
+ playCount={890}
40
+ likeCount={234}
41
+ onClick={handleClick}
42
+ />
43
+ ```
44
+
45
+ ## GeneratingCard
46
+ Loading placeholder while AI generates a game. Shows animated bouncing dots and status text.
47
+
48
+ ```tsx
49
+ <GeneratingCard status="generating" />
50
+ <GeneratingCard status="searching" statusText="Finding games..." />
51
+ ```
@@ -0,0 +1,17 @@
1
+ # ChatBubble
2
+
3
+ Message bubble for MakaAI chat conversations.
4
+
5
+ ## Variants
6
+ - `user` — Right-aligned, purple background (#7c5cfa at 80% opacity), sharp bottom-left corner
7
+ - `assistant` — Left-aligned, translucent white background (10% opacity), sharp bottom-right corner
8
+
9
+ ## Props
10
+ - `content`: string — message text
11
+ - `role`: 'user' | 'assistant'
12
+
13
+ ## Usage
14
+ ```tsx
15
+ <ChatBubble role="user" content="Make me a survival game" />
16
+ <ChatBubble role="assistant" content="I'll create a post-apocalyptic survival scenario for you!" />
17
+ ```