@tanstack/create 0.68.0 → 0.68.2

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 (132) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/create-app.js +22 -0
  3. package/dist/frameworks/react/add-ons/ai/assets/src/components/demo-AIAssistant.tsx +15 -15
  4. package/dist/frameworks/react/add-ons/ai/assets/src/components/demo-GuitarRecommendation.tsx +8 -6
  5. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.css +21 -21
  6. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.tsx +14 -18
  7. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-image.tsx +20 -26
  8. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-structured.tsx +56 -67
  9. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/$guitarId.tsx +17 -22
  10. package/dist/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/index.tsx +21 -27
  11. package/dist/frameworks/react/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx +35 -38
  12. package/dist/frameworks/react/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +64 -64
  13. package/dist/frameworks/react/add-ons/clerk/assets/src/routes/demo/clerk.tsx +17 -25
  14. package/dist/frameworks/react/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -45
  15. package/dist/frameworks/react/add-ons/db/assets/src/components/demo.chat-area.tsx +5 -5
  16. package/dist/frameworks/react/add-ons/db/assets/src/components/demo.messages.tsx +7 -11
  17. package/dist/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat.tsx +5 -3
  18. package/dist/frameworks/react/add-ons/drizzle/assets/src/routes/demo/drizzle.tsx.ejs +29 -79
  19. package/dist/frameworks/react/add-ons/form/assets/src/components/demo.FormComponents.tsx.ejs +12 -12
  20. package/dist/frameworks/react/add-ons/form/assets/src/routes/demo/form.address.tsx.ejs +11 -10
  21. package/dist/frameworks/react/add-ons/form/assets/src/routes/demo/form.simple.tsx.ejs +11 -10
  22. package/dist/frameworks/react/add-ons/mcp/assets/src/routes/demo/mcp-todos.tsx +10 -18
  23. package/dist/frameworks/react/add-ons/neon/assets/src/routes/demo/neon.tsx +38 -57
  24. package/dist/frameworks/react/add-ons/oRPC/assets/src/routes/demo/orpc-todo.tsx +10 -18
  25. package/dist/frameworks/react/add-ons/paraglide/assets/src/routes/demo.i18n.tsx.ejs +6 -7
  26. package/dist/frameworks/react/add-ons/posthog/assets/src/routes/demo/posthog.tsx +19 -22
  27. package/dist/frameworks/react/add-ons/powersync/assets/src/routes/demo/powersync.tsx +19 -18
  28. package/dist/frameworks/react/add-ons/prisma/assets/src/routes/demo/prisma.tsx.ejs +29 -79
  29. package/dist/frameworks/react/add-ons/sentry/assets/src/routes/demo/sentry.testing.tsx +71 -102
  30. package/dist/frameworks/react/add-ons/store/assets/src/lib/demo-store-devtools.tsx +3 -3
  31. package/dist/frameworks/react/add-ons/store/assets/src/routes/demo/store.tsx.ejs +9 -14
  32. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.tsx +23 -26
  33. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.tsx +12 -16
  34. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.tsx +14 -17
  35. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.tsx +15 -15
  36. package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.tsx +17 -17
  37. package/dist/frameworks/react/add-ons/storybook/assets/src/routes/demo/storybook.tsx +25 -25
  38. package/dist/frameworks/react/add-ons/strapi/assets/src/components/blocks/media.tsx +9 -9
  39. package/dist/frameworks/react/add-ons/strapi/assets/src/components/blocks/quote.tsx +8 -8
  40. package/dist/frameworks/react/add-ons/strapi/assets/src/components/markdown-content.tsx +52 -35
  41. package/dist/frameworks/react/add-ons/strapi/assets/src/components/pagination.tsx +8 -14
  42. package/dist/frameworks/react/add-ons/strapi/assets/src/components/search.tsx +12 -12
  43. package/dist/frameworks/react/add-ons/strapi/assets/src/components/strapi-image.tsx +15 -15
  44. package/dist/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.$articleId.tsx +52 -63
  45. package/dist/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.tsx +46 -61
  46. package/dist/frameworks/react/add-ons/tRPC/assets/src/routes/demo/trpc-todo.tsx +10 -18
  47. package/dist/frameworks/react/add-ons/table/assets/src/routes/demo/table.tsx.ejs +23 -22
  48. package/dist/frameworks/react/add-ons/tanstack-query/assets/src/routes/demo/tanstack-query.tsx.ejs +21 -35
  49. package/dist/frameworks/react/add-ons/workos/assets/src/components/workos-user.tsx +1 -1
  50. package/dist/frameworks/react/add-ons/workos/assets/src/routes/demo/workos.tsx +33 -43
  51. package/dist/frameworks/react/project/base/package.json +1 -0
  52. package/dist/frameworks/react/project/base/src/styles.css.ejs +203 -0
  53. package/dist/frameworks/react/project/base/tsr.config.json +3 -0
  54. package/dist/frameworks/react/project/packages.json +3 -0
  55. package/dist/frameworks/solid/add-ons/better-auth/assets/src/routes/demo.better-auth.tsx +62 -64
  56. package/dist/frameworks/solid/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -43
  57. package/dist/frameworks/solid/add-ons/form/assets/src/routes/demo.form.tsx.ejs +22 -22
  58. package/dist/frameworks/solid/add-ons/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +15 -10
  59. package/dist/frameworks/solid/add-ons/store/assets/src/routes/demo.store.tsx.ejs +9 -14
  60. package/dist/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi.tsx +11 -15
  61. package/dist/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi_.$articleId.tsx +11 -18
  62. package/dist/frameworks/solid/project/base/package.json +1 -0
  63. package/dist/frameworks/solid/project/base/src/styles.css.ejs +203 -0
  64. package/dist/frameworks/solid/project/base/tsr.config.json +3 -0
  65. package/dist/frameworks/solid/project/packages.json +3 -0
  66. package/package.json +1 -1
  67. package/src/create-app.ts +32 -1
  68. package/src/frameworks/react/add-ons/ai/assets/src/components/demo-AIAssistant.tsx +15 -15
  69. package/src/frameworks/react/add-ons/ai/assets/src/components/demo-GuitarRecommendation.tsx +8 -6
  70. package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.css +21 -21
  71. package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-chat.tsx +14 -18
  72. package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-image.tsx +20 -26
  73. package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/ai-structured.tsx +56 -67
  74. package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/$guitarId.tsx +17 -22
  75. package/src/frameworks/react/add-ons/ai/assets/src/routes/demo/guitars/index.tsx +21 -27
  76. package/src/frameworks/react/add-ons/apollo-client/assets/src/routes/demo.apollo-client.tsx +35 -38
  77. package/src/frameworks/react/add-ons/better-auth/assets/src/routes/demo/better-auth.tsx +64 -64
  78. package/src/frameworks/react/add-ons/clerk/assets/src/routes/demo/clerk.tsx +17 -25
  79. package/src/frameworks/react/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -45
  80. package/src/frameworks/react/add-ons/db/assets/src/components/demo.chat-area.tsx +5 -5
  81. package/src/frameworks/react/add-ons/db/assets/src/components/demo.messages.tsx +7 -11
  82. package/src/frameworks/react/add-ons/db/assets/src/routes/demo/db-chat.tsx +5 -3
  83. package/src/frameworks/react/add-ons/drizzle/assets/src/routes/demo/drizzle.tsx.ejs +29 -79
  84. package/src/frameworks/react/add-ons/form/assets/src/components/demo.FormComponents.tsx.ejs +12 -12
  85. package/src/frameworks/react/add-ons/form/assets/src/routes/demo/form.address.tsx.ejs +11 -10
  86. package/src/frameworks/react/add-ons/form/assets/src/routes/demo/form.simple.tsx.ejs +11 -10
  87. package/src/frameworks/react/add-ons/mcp/assets/src/routes/demo/mcp-todos.tsx +10 -18
  88. package/src/frameworks/react/add-ons/neon/assets/src/routes/demo/neon.tsx +38 -57
  89. package/src/frameworks/react/add-ons/oRPC/assets/src/routes/demo/orpc-todo.tsx +10 -18
  90. package/src/frameworks/react/add-ons/paraglide/assets/src/routes/demo.i18n.tsx.ejs +6 -7
  91. package/src/frameworks/react/add-ons/posthog/assets/src/routes/demo/posthog.tsx +19 -22
  92. package/src/frameworks/react/add-ons/powersync/assets/src/routes/demo/powersync.tsx +19 -18
  93. package/src/frameworks/react/add-ons/prisma/assets/src/routes/demo/prisma.tsx.ejs +29 -79
  94. package/src/frameworks/react/add-ons/sentry/assets/src/routes/demo/sentry.testing.tsx +71 -102
  95. package/src/frameworks/react/add-ons/store/assets/src/lib/demo-store-devtools.tsx +3 -3
  96. package/src/frameworks/react/add-ons/store/assets/src/routes/demo/store.tsx.ejs +9 -14
  97. package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.tsx +23 -26
  98. package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.tsx +12 -16
  99. package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.tsx +14 -17
  100. package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.tsx +15 -15
  101. package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.tsx +17 -17
  102. package/src/frameworks/react/add-ons/storybook/assets/src/routes/demo/storybook.tsx +25 -25
  103. package/src/frameworks/react/add-ons/strapi/assets/src/components/blocks/media.tsx +9 -9
  104. package/src/frameworks/react/add-ons/strapi/assets/src/components/blocks/quote.tsx +8 -8
  105. package/src/frameworks/react/add-ons/strapi/assets/src/components/markdown-content.tsx +52 -35
  106. package/src/frameworks/react/add-ons/strapi/assets/src/components/pagination.tsx +8 -14
  107. package/src/frameworks/react/add-ons/strapi/assets/src/components/search.tsx +12 -12
  108. package/src/frameworks/react/add-ons/strapi/assets/src/components/strapi-image.tsx +15 -15
  109. package/src/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.$articleId.tsx +52 -63
  110. package/src/frameworks/react/add-ons/strapi/assets/src/routes/demo/strapi.tsx +46 -61
  111. package/src/frameworks/react/add-ons/tRPC/assets/src/routes/demo/trpc-todo.tsx +10 -18
  112. package/src/frameworks/react/add-ons/table/assets/src/routes/demo/table.tsx.ejs +23 -22
  113. package/src/frameworks/react/add-ons/tanstack-query/assets/src/routes/demo/tanstack-query.tsx.ejs +21 -35
  114. package/src/frameworks/react/add-ons/workos/assets/src/components/workos-user.tsx +1 -1
  115. package/src/frameworks/react/add-ons/workos/assets/src/routes/demo/workos.tsx +33 -43
  116. package/src/frameworks/react/project/base/package.json +1 -0
  117. package/src/frameworks/react/project/base/src/styles.css.ejs +203 -0
  118. package/src/frameworks/react/project/base/tsr.config.json +3 -0
  119. package/src/frameworks/react/project/packages.json +3 -0
  120. package/src/frameworks/solid/add-ons/better-auth/assets/src/routes/demo.better-auth.tsx +62 -64
  121. package/src/frameworks/solid/add-ons/convex/assets/src/routes/demo/convex.tsx +30 -43
  122. package/src/frameworks/solid/add-ons/form/assets/src/routes/demo.form.tsx.ejs +22 -22
  123. package/src/frameworks/solid/add-ons/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +15 -10
  124. package/src/frameworks/solid/add-ons/store/assets/src/routes/demo.store.tsx.ejs +9 -14
  125. package/src/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi.tsx +11 -15
  126. package/src/frameworks/solid/add-ons/strapi/assets/src/routes/demo/strapi_.$articleId.tsx +11 -18
  127. package/src/frameworks/solid/project/base/package.json +1 -0
  128. package/src/frameworks/solid/project/base/src/styles.css.ejs +203 -0
  129. package/src/frameworks/solid/project/base/tsr.config.json +3 -0
  130. package/src/frameworks/solid/project/packages.json +3 -0
  131. package/tests/create-app.test.ts +39 -3
  132. package/tests/framework-template.test.ts +34 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @tanstack/create
2
2
 
3
+ ## 0.68.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Keep the generated route tree tracked in new React and Solid apps and run route generation once during scaffold. ([#464](https://github.com/TanStack/cli/pull/464))
8
+
9
+ ## 0.68.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Keep the generated AI assistant demo panel inside the viewport. ([#459](https://github.com/TanStack/cli/pull/459))
14
+
15
+ - Normalize generated demo pages to use the base template styling instead of bespoke full-page gradients and mismatched color treatments. ([#461](https://github.com/TanStack/cli/pull/461))
16
+
17
+ - Ignore the generated route tree in new React and Solid app gitignores. ([#460](https://github.com/TanStack/cli/pull/460))
18
+
3
19
  ## 0.68.0
4
20
 
5
21
  ### Minor Changes
@@ -202,6 +202,28 @@ async function runCommandsAndInstallDependencies(environment, options) {
202
202
  }
203
203
  await installShadcnComponents(environment, options.targetDir, options);
204
204
  await setupIntent(environment, options.targetDir, options);
205
+ if (shouldGenerateRoutes(options)) {
206
+ s.start(`Generating route tree...`);
207
+ const command = getPackageManagerScriptCommand(options.packageManager, [
208
+ 'generate-routes',
209
+ ]);
210
+ const cmd = formatCommand(command);
211
+ environment.startStep({
212
+ id: 'generate-routes',
213
+ type: 'command',
214
+ message: cmd,
215
+ });
216
+ await environment.execute(command.command, command.args, options.targetDir, {
217
+ inherit: true,
218
+ });
219
+ environment.finishStep('generate-routes', 'Route tree generated');
220
+ s.stop(`Route tree generated`);
221
+ }
222
+ }
223
+ function shouldGenerateRoutes(options) {
224
+ return (options.install !== false &&
225
+ options.mode === 'file-router' &&
226
+ (options.framework.id === 'react' || options.framework.id === 'solid'));
205
227
  }
206
228
  async function seedEnvValues(environment, options) {
207
229
  const envVarValues = options.envVarValues || {};
@@ -24,7 +24,7 @@ function Messages({ messages }: { messages: ChatMessages }) {
24
24
 
25
25
  if (!messages.length) {
26
26
  return (
27
- <div className="flex-1 flex items-center justify-center text-gray-400 text-sm">
27
+ <div className="demo-muted flex flex-1 items-center justify-center text-sm">
28
28
  Ask me anything! I'm here to help.
29
29
  </div>
30
30
  )
@@ -36,9 +36,7 @@ function Messages({ messages }: { messages: ChatMessages }) {
36
36
  <div
37
37
  key={id}
38
38
  className={`py-3 ${
39
- role === 'assistant'
40
- ? 'bg-linear-to-r from-orange-500/5 to-red-600/5'
41
- : 'bg-transparent'
39
+ role === 'assistant' ? 'bg-[var(--chip-bg)]' : 'bg-transparent'
42
40
  }`}
43
41
  >
44
42
  {parts.map((part, index) => {
@@ -46,15 +44,15 @@ function Messages({ messages }: { messages: ChatMessages }) {
46
44
  return (
47
45
  <div key={index} className="flex items-start gap-2 px-4">
48
46
  {role === 'assistant' ? (
49
- <div className="w-6 h-6 rounded-lg bg-linear-to-r from-orange-500 to-red-600 flex items-center justify-center text-xs font-medium text-white flex-shrink-0">
47
+ <div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--lagoon-deep)] text-xs font-medium text-white">
50
48
  AI
51
49
  </div>
52
50
  ) : (
53
- <div className="w-6 h-6 rounded-lg bg-gray-700 flex items-center justify-center text-xs font-medium text-white flex-shrink-0">
51
+ <div className="flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--sea-ink-soft)] text-xs font-medium text-white">
54
52
  Y
55
53
  </div>
56
54
  )}
57
- <div className="flex-1 min-w-0 text-white prose dark:prose-invert max-w-none prose-sm">
55
+ <div className="min-w-0 flex-1 max-w-none text-sm text-[var(--sea-ink)]">
58
56
  <Streamdown>{part.content}</Streamdown>
59
57
  </div>
60
58
  </div>
@@ -87,7 +85,7 @@ export default function AIAssistant() {
87
85
  <div className="relative z-50">
88
86
  <button
89
87
  onClick={() => showAIAssistant.setState((state) => !state)}
90
- className="w-full flex items-center justify-between px-4 py-2.5 rounded-lg bg-linear-to-r from-green-700 to-green-900 text-white hover:opacity-90 transition-opacity"
88
+ className="demo-button w-full justify-between px-4 py-2.5"
91
89
  >
92
90
  <div className="flex items-center gap-2">
93
91
  <BotIcon size={24} />
@@ -97,12 +95,14 @@ export default function AIAssistant() {
97
95
  </button>
98
96
 
99
97
  {isOpen && (
100
- <div className="absolute bottom-0 left-full ml-2 w-[700px] h-[600px] bg-gray-900 rounded-lg shadow-xl border border-orange-500/20 flex flex-col">
101
- <div className="flex items-center justify-between p-3 border-b border-orange-500/20">
102
- <h3 className="font-semibold text-white">AI Assistant</h3>
98
+ <div className="demo-panel fixed inset-x-4 top-20 z-[100] flex h-[calc(100vh-6rem)] max-h-[600px] flex-col overflow-hidden p-0 sm:left-auto sm:w-[min(calc(100vw-2rem),700px)]">
99
+ <div className="flex items-center justify-between border-b border-[var(--line)] p-3">
100
+ <h3 className="font-semibold text-[var(--sea-ink)]">
101
+ AI Assistant
102
+ </h3>
103
103
  <button
104
104
  onClick={() => showAIAssistant.setState((state) => !state)}
105
- className="text-gray-400 hover:text-white transition-colors"
105
+ className="demo-muted transition-colors hover:text-[var(--sea-ink)]"
106
106
  >
107
107
  <X className="w-4 h-4" />
108
108
  </button>
@@ -110,7 +110,7 @@ export default function AIAssistant() {
110
110
 
111
111
  <Messages messages={messages} />
112
112
 
113
- <div className="p-3 border-t border-orange-500/20">
113
+ <div className="border-t border-[var(--line)] p-3">
114
114
  <form
115
115
  onSubmit={(e) => {
116
116
  e.preventDefault()
@@ -125,7 +125,7 @@ export default function AIAssistant() {
125
125
  value={input}
126
126
  onChange={(e) => setInput(e.target.value)}
127
127
  placeholder="Type your message..."
128
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800/50 pl-3 pr-10 py-2 text-sm text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-orange-500/50 focus:border-transparent resize-none overflow-hidden"
128
+ className="demo-textarea pr-10 text-sm"
129
129
  rows={1}
130
130
  style={{ minHeight: '36px', maxHeight: '120px' }}
131
131
  onInput={(e) => {
@@ -145,7 +145,7 @@ export default function AIAssistant() {
145
145
  <button
146
146
  type="submit"
147
147
  disabled={!input.trim()}
148
- className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-orange-500 hover:text-orange-400 disabled:text-gray-500 transition-colors focus:outline-none"
148
+ className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-[var(--lagoon-deep)] transition-colors hover:text-[var(--sea-ink)] disabled:text-[var(--sea-ink-soft)]"
149
149
  >
150
150
  <Send className="w-4 h-4" />
151
151
  </button>
@@ -11,7 +11,7 @@ export default function GuitarRecommendation({ id }: { id: string }) {
11
11
  return null
12
12
  }
13
13
  return (
14
- <div className="my-4 rounded-lg overflow-hidden border border-orange-500/20 bg-gray-800/50">
14
+ <div className="demo-card my-4 overflow-hidden p-0">
15
15
  <div className="aspect-[4/3] relative overflow-hidden">
16
16
  <img
17
17
  src={guitar.image}
@@ -20,23 +20,25 @@ export default function GuitarRecommendation({ id }: { id: string }) {
20
20
  />
21
21
  </div>
22
22
  <div className="p-4">
23
- <h3 className="text-lg font-semibold text-white mb-2">{guitar.name}</h3>
24
- <p className="text-sm text-gray-300 mb-3 line-clamp-2">
23
+ <h3 className="mb-2 text-lg font-semibold text-[var(--sea-ink)]">
24
+ {guitar.name}
25
+ </h3>
26
+ <p className="demo-muted mb-3 line-clamp-2 text-sm">
25
27
  {guitar.shortDescription}
26
28
  </p>
27
29
  <div className="flex items-center justify-between">
28
- <div className="text-lg font-bold text-emerald-400">
30
+ <div className="text-lg font-bold text-[var(--lagoon-deep)]">
29
31
  ${guitar.price}
30
32
  </div>
31
33
  <button
32
34
  onClick={() => {
33
35
  navigate({
34
- to: '/example/guitars/$guitarId',
36
+ to: '/demo/guitars/$guitarId',
35
37
  params: { guitarId: guitar.id.toString() },
36
38
  })
37
39
  showAIAssistant.setState(() => false)
38
40
  }}
39
- className="bg-gradient-to-r from-orange-500 to-red-600 text-white px-4 py-1.5 rounded-lg text-sm hover:opacity-90 transition-opacity"
41
+ className="demo-button px-4 py-1.5 text-sm"
40
42
  >
41
43
  View Details
42
44
  </button>
@@ -1,5 +1,5 @@
1
1
  @import 'tailwindcss';
2
- @import 'highlight.js/styles/github-dark.css';
2
+ @import 'highlight.js/styles/github.css';
3
3
  @source "../../../../node_modules/streamdown/dist/*.js";
4
4
 
5
5
  /* Custom scrollbar styles */
@@ -28,7 +28,7 @@ html {
28
28
  /* Markdown content styles */
29
29
  .prose {
30
30
  max-width: none;
31
- color: #e5e7eb; /* text-gray-200 */
31
+ color: var(--sea-ink-soft);
32
32
  }
33
33
 
34
34
  /* .prose p {
@@ -37,15 +37,15 @@ html {
37
37
  } */
38
38
 
39
39
  .prose code {
40
- color: #e5e7eb;
41
- background-color: rgba(31, 41, 55, 0.5);
40
+ color: var(--sea-ink);
41
+ background-color: var(--chip-bg);
42
42
  padding: 0.2em 0.4em;
43
43
  border-radius: 0.375rem;
44
44
  font-size: 0.875em;
45
45
  }
46
46
 
47
47
  .prose pre {
48
- background-color: rgba(31, 41, 55, 0.5);
48
+ background-color: var(--chip-bg);
49
49
  border-radius: 0.5rem;
50
50
  padding: 1rem;
51
51
  margin: 1.25em 0;
@@ -63,7 +63,7 @@ html {
63
63
  .prose h2,
64
64
  .prose h3,
65
65
  .prose h4 {
66
- color: #f9fafb; /* text-gray-50 */
66
+ color: var(--sea-ink);
67
67
  /* margin-top: 2em; */
68
68
  /* margin-bottom: 1em; */
69
69
  }
@@ -81,27 +81,27 @@ html {
81
81
  }
82
82
 
83
83
  .prose blockquote {
84
- border-left-color: #f97316; /* orange-500 */
85
- background-color: rgba(249, 115, 22, 0.1);
84
+ border-left-color: var(--lagoon-deep);
85
+ background-color: var(--chip-bg);
86
86
  padding: 1em;
87
87
  margin: 1.25em 0;
88
88
  border-radius: 0.5rem;
89
89
  }
90
90
 
91
91
  .prose hr {
92
- border-color: rgba(249, 115, 22, 0.2);
92
+ border-color: var(--line);
93
93
  margin: 2em 0;
94
94
  }
95
95
 
96
96
  .prose a {
97
- color: #f97316; /* orange-500 */
97
+ color: var(--lagoon-deep);
98
98
  text-decoration: underline;
99
99
  text-decoration-thickness: 0.1em;
100
100
  text-underline-offset: 0.2em;
101
101
  }
102
102
 
103
103
  .prose a:hover {
104
- color: #fb923c; /* orange-400 */
104
+ color: var(--sea-ink);
105
105
  }
106
106
 
107
107
  .prose table {
@@ -113,11 +113,11 @@ html {
113
113
  .prose th,
114
114
  .prose td {
115
115
  padding: 0.75em;
116
- border: 1px solid rgba(249, 115, 22, 0.2);
116
+ border: 1px solid var(--line);
117
117
  }
118
118
 
119
119
  .prose th {
120
- background-color: rgba(249, 115, 22, 0.1);
120
+ background-color: var(--chip-bg);
121
121
  font-weight: 600;
122
122
  }
123
123
 
@@ -181,16 +181,16 @@ html {
181
181
 
182
182
  .prose th,
183
183
  .prose td {
184
- border: 1px solid rgba(249, 115, 22, 0.2);
184
+ border: 1px solid var(--line);
185
185
  padding: 0.5em;
186
186
  }
187
187
 
188
188
  .prose th {
189
- background-color: rgba(249, 115, 22, 0.1);
189
+ background-color: var(--chip-bg);
190
190
  }
191
191
 
192
192
  .prose strong {
193
- color: #f9fafb; /* text-gray-50 */
193
+ color: var(--sea-ink);
194
194
  font-weight: 600;
195
195
  }
196
196
 
@@ -199,23 +199,23 @@ html {
199
199
  }
200
200
 
201
201
  .prose blockquote {
202
- border-left: 4px solid #f97316; /* orange-500 */
202
+ border-left: 4px solid var(--lagoon-deep);
203
203
  padding-left: 1em;
204
204
  margin: 1em 0;
205
- color: #d1d5db; /* text-gray-300 */
205
+ color: var(--sea-ink-soft);
206
206
  }
207
207
 
208
208
  /* Ensure code blocks match the AI's formatting */
209
209
  .prose code {
210
- color: #e5e7eb;
211
- background-color: rgba(31, 41, 55, 0.5);
210
+ color: var(--sea-ink);
211
+ background-color: var(--chip-bg);
212
212
  padding: 0.2em 0.4em;
213
213
  border-radius: 0.375rem;
214
214
  font-size: 0.875em;
215
215
  }
216
216
 
217
217
  .prose pre {
218
- background-color: rgba(31, 41, 55, 0.5);
218
+ background-color: var(--chip-bg);
219
219
  border-radius: 0.5rem;
220
220
  padding: 1rem;
221
221
  margin: 1em 0;
@@ -24,10 +24,8 @@ function InitialLayout({ children }: { children: React.ReactNode }) {
24
24
  return (
25
25
  <div className="flex-1 flex items-center justify-center px-4">
26
26
  <div className="text-center max-w-3xl mx-auto w-full">
27
- <h1 className="text-6xl font-bold mb-4 bg-linear-to-r from-orange-500 to-red-600 text-transparent bg-clip-text uppercase">
28
- <span className="text-white">TanStack</span> Chat
29
- </h1>
30
- <p className="text-gray-400 mb-6 w-2/3 mx-auto text-lg">
27
+ <h1 className="demo-title mb-4">TanStack Chat</h1>
28
+ <p className="demo-muted mb-6 mx-auto max-w-2xl text-lg">
31
29
  You can ask me about anything, I might or might not have a good
32
30
  answer, but you can still ask.
33
31
  </p>
@@ -39,7 +37,7 @@ function InitialLayout({ children }: { children: React.ReactNode }) {
39
37
 
40
38
  function ChattingLayout({ children }: { children: React.ReactNode }) {
41
39
  return (
42
- <div className="sticky bottom-0 left-0 right-0 bg-gray-900/80 backdrop-blur-sm border-t border-orange-500/10 z-10">
40
+ <div className="sticky bottom-0 left-0 right-0 z-10 border-t border-[var(--line)] bg-[var(--header-bg)] backdrop-blur-sm">
43
41
  <div className="max-w-3xl mx-auto w-full px-4 py-3">{children}</div>
44
42
  </div>
45
43
  )
@@ -96,17 +94,17 @@ function Messages({
96
94
  key={message.id}
97
95
  className={`p-4 ${
98
96
  message.role === 'assistant'
99
- ? 'bg-linear-to-r from-orange-500/5 to-red-600/5'
97
+ ? 'bg-[var(--chip-bg)]'
100
98
  : 'bg-transparent'
101
99
  }`}
102
100
  >
103
101
  <div className="flex items-start gap-4 max-w-3xl mx-auto w-full">
104
102
  {message.role === 'assistant' ? (
105
- <div className="w-8 h-8 rounded-lg bg-linear-to-r from-orange-500 to-red-600 mt-2 flex items-center justify-center text-sm font-medium text-white flex-shrink-0">
103
+ <div className="mt-2 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--lagoon-deep)] text-sm font-medium text-white">
106
104
  AI
107
105
  </div>
108
106
  ) : (
109
- <div className="w-8 h-8 rounded-lg bg-gray-700 flex items-center justify-center text-sm font-medium text-white flex-shrink-0">
107
+ <div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--sea-ink-soft)] text-sm font-medium text-white">
110
108
  Y
111
109
  </div>
112
110
  )}
@@ -115,7 +113,7 @@ function Messages({
115
113
  if (part.type === 'text' && part.content) {
116
114
  return (
117
115
  <div
118
- className="flex-1 min-w-0 prose dark:prose-invert max-w-none prose-sm"
116
+ className="prose prose-sm min-w-0 max-w-none flex-1"
119
117
  key={index}
120
118
  >
121
119
  <Streamdown>{part.content}</Streamdown>
@@ -145,7 +143,7 @@ function Messages({
145
143
  ? onStopSpeak()
146
144
  : onSpeak(textContent, message.id)
147
145
  }
148
- className="flex-shrink-0 p-2 text-gray-400 hover:text-orange-400 transition-colors"
146
+ className="demo-muted flex-shrink-0 p-2 transition-colors hover:text-[var(--lagoon-deep)]"
149
147
  title={isPlaying ? 'Stop speaking' : 'Read aloud'}
150
148
  >
151
149
  {isPlaying ? (
@@ -190,7 +188,7 @@ function ChatPage() {
190
188
  const Layout = messages.length ? ChattingLayout : InitialLayout
191
189
 
192
190
  return (
193
- <div className="relative flex h-[calc(100vh-80px)] bg-gray-900">
191
+ <div className="relative flex h-[calc(100vh-12rem)] min-h-[32rem]">
194
192
  <div className="flex-1 flex flex-col min-h-0">
195
193
  <Messages
196
194
  messages={messages}
@@ -205,7 +203,7 @@ function ChatPage() {
205
203
  <div className="flex items-center justify-center">
206
204
  <button
207
205
  onClick={stop}
208
- className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2"
206
+ className="demo-button demo-button-danger"
209
207
  >
210
208
  <Square className="w-4 h-4 fill-current" />
211
209
  Stop
@@ -226,10 +224,8 @@ function ChatPage() {
226
224
  type="button"
227
225
  onClick={handleMicClick}
228
226
  disabled={isLoading || isTranscribing}
229
- className={`p-3 rounded-lg transition-colors ${
230
- isRecording
231
- ? 'bg-red-600 hover:bg-red-700 text-white'
232
- : 'bg-gray-800/50 text-gray-400 hover:text-orange-400 border border-orange-500/20'
227
+ className={`demo-button p-3 ${
228
+ isRecording ? 'demo-button-danger' : 'demo-button-secondary'
233
229
  } disabled:opacity-50`}
234
230
  title={isRecording ? 'Stop recording' : 'Start recording'}
235
231
  >
@@ -247,7 +243,7 @@ function ChatPage() {
247
243
  value={input}
248
244
  onChange={(e) => setInput(e.target.value)}
249
245
  placeholder="Type something clever..."
250
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800/50 pl-4 pr-12 py-3 text-sm text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-orange-500/50 focus:border-transparent resize-none overflow-hidden shadow-lg"
246
+ className="demo-textarea pr-12 text-sm"
251
247
  rows={1}
252
248
  style={{ minHeight: '44px', maxHeight: '200px' }}
253
249
  disabled={isLoading}
@@ -268,7 +264,7 @@ function ChatPage() {
268
264
  <button
269
265
  type="submit"
270
266
  disabled={!input.trim() || isLoading}
271
- className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-orange-500 hover:text-orange-400 disabled:text-gray-500 transition-colors focus:outline-none"
267
+ className="absolute right-2 top-1/2 -translate-y-1/2 p-2 text-[var(--lagoon-deep)] transition-colors hover:text-[var(--sea-ink)] disabled:text-[var(--sea-ink-soft)]"
272
268
  >
273
269
  <Send className="w-4 h-4" />
274
270
  </button>
@@ -73,26 +73,25 @@ function ImagePage() {
73
73
  }
74
74
 
75
75
  return (
76
- <div className="min-h-[calc(100vh-80px)] bg-gray-900 p-6">
77
- <div className="max-w-6xl mx-auto">
76
+ <main className="demo-page demo-page-wide">
77
+ <div>
78
78
  <div className="flex items-center gap-3 mb-6">
79
- <ImageIcon className="w-8 h-8 text-orange-500" />
80
- <h1 className="text-2xl font-bold text-white">Image Generation</h1>
79
+ <ImageIcon className="w-8 h-8 text-[var(--lagoon-deep)]" />
80
+ <h1 className="demo-title">Image Generation</h1>
81
81
  </div>
82
82
 
83
83
  <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
84
- {/* Input Panel */}
85
84
  <div className="space-y-4">
86
85
  <div className="grid grid-cols-2 gap-4">
87
86
  <div>
88
- <label className="block text-sm font-medium text-gray-300 mb-2">
87
+ <label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
89
88
  Size
90
89
  </label>
91
90
  <select
92
91
  value={size}
93
92
  onChange={(e) => setSize(e.target.value)}
94
93
  disabled={isLoading}
95
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800 px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-orange-500/50"
94
+ className="demo-select text-sm"
96
95
  >
97
96
  {SIZES.map((s) => (
98
97
  <option key={s} value={s}>
@@ -102,7 +101,7 @@ function ImagePage() {
102
101
  </select>
103
102
  </div>
104
103
  <div>
105
- <label className="block text-sm font-medium text-gray-300 mb-2">
104
+ <label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
106
105
  Count
107
106
  </label>
108
107
  <input
@@ -116,13 +115,13 @@ function ImagePage() {
116
115
  min={1}
117
116
  max={4}
118
117
  disabled={isLoading}
119
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800 px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-orange-500/50"
118
+ className="demo-input text-sm"
120
119
  />
121
120
  </div>
122
121
  </div>
123
122
 
124
123
  <div>
125
- <label className="block text-sm font-medium text-gray-300 mb-2">
124
+ <label className="mb-2 block text-sm font-medium text-[var(--sea-ink)]">
126
125
  Prompt
127
126
  </label>
128
127
  <textarea
@@ -130,7 +129,7 @@ function ImagePage() {
130
129
  onChange={(e) => setPrompt(e.target.value)}
131
130
  disabled={isLoading}
132
131
  rows={6}
133
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800 px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-orange-500/50 resize-none"
132
+ className="demo-textarea text-sm"
134
133
  placeholder="Describe the image you want to generate..."
135
134
  />
136
135
  </div>
@@ -138,7 +137,7 @@ function ImagePage() {
138
137
  <button
139
138
  onClick={handleGenerate}
140
139
  disabled={isLoading || !prompt.trim()}
141
- className="w-full px-4 py-3 bg-orange-600 hover:bg-orange-700 disabled:bg-gray-600 text-white rounded-lg font-medium transition-colors flex items-center justify-center gap-2"
140
+ className="demo-button w-full"
142
141
  >
143
142
  {isLoading ? (
144
143
  <>
@@ -151,16 +150,11 @@ function ImagePage() {
151
150
  </button>
152
151
  </div>
153
152
 
154
- {/* Output Panel */}
155
- <div className="lg:col-span-2 bg-gray-800 rounded-lg p-6 border border-orange-500/20">
156
- <h2 className="text-lg font-semibold text-white mb-4">
157
- Generated Images
158
- </h2>
153
+ <div className="demo-panel lg:col-span-2">
154
+ <h2 className="demo-section-title mb-4">Generated Images</h2>
159
155
 
160
156
  {error && (
161
- <div className="p-4 bg-red-500/10 border border-red-500/20 rounded-lg text-red-400 mb-4">
162
- {error}
163
- </div>
157
+ <div className="demo-alert demo-alert-danger mb-4">{error}</div>
164
158
  )}
165
159
 
166
160
  {images.length > 0 ? (
@@ -171,17 +165,17 @@ function ImagePage() {
171
165
  <img
172
166
  src={getImageSrc(image)}
173
167
  alt={`Generated image ${index + 1}`}
174
- className="w-full rounded-lg border border-gray-700"
168
+ className="w-full rounded-lg border border-[var(--line)]"
175
169
  />
176
170
  <button
177
171
  onClick={() => handleDownload(image, index)}
178
- className="absolute top-2 right-2 p-2 bg-gray-900/80 hover:bg-gray-900 rounded-lg opacity-0 group-hover:opacity-100 transition-opacity"
172
+ className="demo-button absolute right-2 top-2 p-2 opacity-0 transition-opacity group-hover:opacity-100"
179
173
  title="Download image"
180
174
  >
181
- <Download className="w-4 h-4 text-white" />
175
+ <Download className="w-4 h-4" />
182
176
  </button>
183
177
  {image.revisedPrompt && (
184
- <p className="mt-2 text-xs text-gray-400 italic">
178
+ <p className="demo-muted mt-2 text-xs italic">
185
179
  Revised: {image.revisedPrompt}
186
180
  </p>
187
181
  )}
@@ -190,7 +184,7 @@ function ImagePage() {
190
184
  </div>
191
185
  </div>
192
186
  ) : !error && !isLoading ? (
193
- <div className="flex flex-col items-center justify-center h-64 text-gray-500">
187
+ <div className="demo-muted flex h-64 flex-col items-center justify-center">
194
188
  <ImageIcon className="w-16 h-16 mb-4 opacity-50" />
195
189
  <p>
196
190
  Enter a prompt and click "Generate Image" to create an image.
@@ -200,7 +194,7 @@ function ImagePage() {
200
194
  </div>
201
195
  </div>
202
196
  </div>
203
- </div>
197
+ </main>
204
198
  )
205
199
  }
206
200