@actuate-media/cms-admin 0.54.0 → 0.56.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 (229) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/__tests__/components/posts-badges.test.js +3 -3
  3. package/dist/__tests__/components/posts-badges.test.js.map +1 -1
  4. package/dist/__tests__/lib/page-editor-service.test.js +1 -0
  5. package/dist/__tests__/lib/page-editor-service.test.js.map +1 -1
  6. package/dist/actuate-admin.css +1 -1
  7. package/dist/components/AICoauthorBubbleMenu.js +2 -2
  8. package/dist/components/AICoauthorBubbleMenu.js.map +1 -1
  9. package/dist/components/Breadcrumbs.js +2 -2
  10. package/dist/components/Breadcrumbs.js.map +1 -1
  11. package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
  12. package/dist/components/CoauthorResultPopover.js +1 -1
  13. package/dist/components/CoauthorResultPopover.js.map +1 -1
  14. package/dist/components/CommandPalette.d.ts.map +1 -1
  15. package/dist/components/CommandPalette.js +11 -11
  16. package/dist/components/CommandPalette.js.map +1 -1
  17. package/dist/components/CommentSidePanel.js +11 -11
  18. package/dist/components/CommentSidePanel.js.map +1 -1
  19. package/dist/components/ContentOverviewChart.js +2 -2
  20. package/dist/components/ContentOverviewChart.js.map +1 -1
  21. package/dist/components/FocalPointPicker.js +1 -1
  22. package/dist/components/FocalPointPicker.js.map +1 -1
  23. package/dist/components/LivePreview.d.ts.map +1 -1
  24. package/dist/components/LivePreview.js +5 -5
  25. package/dist/components/LivePreview.js.map +1 -1
  26. package/dist/components/LogoPlaceholder.js +1 -1
  27. package/dist/components/LogoPlaceholder.js.map +1 -1
  28. package/dist/components/MentionableTextarea.js +3 -3
  29. package/dist/components/MentionableTextarea.js.map +1 -1
  30. package/dist/components/NotificationBell.js +1 -1
  31. package/dist/components/NotificationBell.js.map +1 -1
  32. package/dist/components/OfflineStatus.js +8 -8
  33. package/dist/components/OfflineStatus.js.map +1 -1
  34. package/dist/components/PresenceChips.d.ts.map +1 -1
  35. package/dist/components/PresenceChips.js +10 -6
  36. package/dist/components/PresenceChips.js.map +1 -1
  37. package/dist/components/SEOConfigPanel.d.ts.map +1 -1
  38. package/dist/components/SEOConfigPanel.js +10 -10
  39. package/dist/components/SEOConfigPanel.js.map +1 -1
  40. package/dist/components/SEOPanel.js +12 -12
  41. package/dist/components/SEOPanel.js.map +1 -1
  42. package/dist/components/SEOPerformance.d.ts.map +1 -1
  43. package/dist/components/SEOPerformance.js +3 -3
  44. package/dist/components/SEOPerformance.js.map +1 -1
  45. package/dist/components/TipTapEditor.js +6 -6
  46. package/dist/components/TipTapEditor.js.map +1 -1
  47. package/dist/components/pages/tag-badges.js +6 -6
  48. package/dist/components/pages/tag-badges.js.map +1 -1
  49. package/dist/components/posts/badges.d.ts +0 -4
  50. package/dist/components/posts/badges.d.ts.map +1 -1
  51. package/dist/components/posts/badges.js +28 -42
  52. package/dist/components/posts/badges.js.map +1 -1
  53. package/dist/components/ui/Badge.js +5 -5
  54. package/dist/components/ui/Badge.js.map +1 -1
  55. package/dist/components/ui/Toast.d.ts.map +1 -1
  56. package/dist/components/ui/Toast.js +4 -4
  57. package/dist/components/ui/Toast.js.map +1 -1
  58. package/dist/fields/ComponentBlockField.js +2 -2
  59. package/dist/fields/ComponentBlockField.js.map +1 -1
  60. package/dist/fields/FieldRenderer.js +1 -1
  61. package/dist/fields/FieldRenderer.js.map +1 -1
  62. package/dist/fields/PropInput.js +1 -1
  63. package/dist/fields/PropInput.js.map +1 -1
  64. package/dist/fields/RelationshipField.js +5 -5
  65. package/dist/fields/RelationshipField.js.map +1 -1
  66. package/dist/fields/ToggleField.js +1 -1
  67. package/dist/fields/ToggleField.js.map +1 -1
  68. package/dist/lib/seo-service.d.ts +0 -2
  69. package/dist/lib/seo-service.d.ts.map +1 -1
  70. package/dist/lib/seo-service.js.map +1 -1
  71. package/dist/views/Dashboard.js +5 -5
  72. package/dist/views/Dashboard.js.map +1 -1
  73. package/dist/views/DocumentEdit.d.ts.map +1 -1
  74. package/dist/views/DocumentEdit.js +5 -5
  75. package/dist/views/DocumentEdit.js.map +1 -1
  76. package/dist/views/ForgotPassword.d.ts.map +1 -1
  77. package/dist/views/ForgotPassword.js +3 -2
  78. package/dist/views/ForgotPassword.js.map +1 -1
  79. package/dist/views/FormEditor.d.ts.map +1 -1
  80. package/dist/views/FormEditor.js +5 -5
  81. package/dist/views/FormEditor.js.map +1 -1
  82. package/dist/views/Login.d.ts.map +1 -1
  83. package/dist/views/Login.js +17 -17
  84. package/dist/views/Login.js.map +1 -1
  85. package/dist/views/PageEditor.d.ts.map +1 -1
  86. package/dist/views/PageEditor.js +2 -2
  87. package/dist/views/PageEditor.js.map +1 -1
  88. package/dist/views/Pages/PagesListView.js +6 -6
  89. package/dist/views/Pages/PagesListView.js.map +1 -1
  90. package/dist/views/Pages.d.ts.map +1 -1
  91. package/dist/views/Pages.js +16 -19
  92. package/dist/views/Pages.js.map +1 -1
  93. package/dist/views/ResetPassword.d.ts.map +1 -1
  94. package/dist/views/ResetPassword.js +3 -2
  95. package/dist/views/ResetPassword.js.map +1 -1
  96. package/dist/views/Settings.js +2 -2
  97. package/dist/views/Settings.js.map +1 -1
  98. package/dist/views/SetupWizard.d.ts.map +1 -1
  99. package/dist/views/SetupWizard.js +6 -5
  100. package/dist/views/SetupWizard.js.map +1 -1
  101. package/dist/views/page-builder/DesignScore.js +12 -12
  102. package/dist/views/page-builder/DesignScore.js.map +1 -1
  103. package/dist/views/page-builder/SEOPanel.js +9 -9
  104. package/dist/views/page-builder/SEOPanel.js.map +1 -1
  105. package/dist/views/page-editor/EditorCanvas.js +1 -1
  106. package/dist/views/page-editor/EditorCanvas.js.map +1 -1
  107. package/dist/views/page-editor/EditorTopBar.js +2 -2
  108. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  109. package/dist/views/page-editor/PagePreview.js +1 -1
  110. package/dist/views/page-editor/PagePreview.js.map +1 -1
  111. package/dist/views/page-editor/SectionInspector.js +1 -1
  112. package/dist/views/page-editor/SectionInspector.js.map +1 -1
  113. package/dist/views/page-editor/SitePreviewFrame.js +1 -1
  114. package/dist/views/page-editor/SitePreviewFrame.js.map +1 -1
  115. package/dist/views/page-editor/sections/ArticleBodySection.js +1 -1
  116. package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
  117. package/dist/views/page-editor/sections/AuthorBioSection.js +2 -2
  118. package/dist/views/page-editor/sections/AuthorBioSection.js.map +1 -1
  119. package/dist/views/page-editor/sections/ByTheNumbersSection.js +1 -1
  120. package/dist/views/page-editor/sections/ByTheNumbersSection.js.map +1 -1
  121. package/dist/views/page-editor/sections/CtaBannerSection.js +1 -1
  122. package/dist/views/page-editor/sections/CtaBannerSection.js.map +1 -1
  123. package/dist/views/page-editor/sections/EmbedSection.d.ts +10 -0
  124. package/dist/views/page-editor/sections/EmbedSection.d.ts.map +1 -0
  125. package/dist/views/page-editor/sections/EmbedSection.js +24 -0
  126. package/dist/views/page-editor/sections/EmbedSection.js.map +1 -0
  127. package/dist/views/page-editor/sections/FeatureHighlightSection.d.ts.map +1 -1
  128. package/dist/views/page-editor/sections/FeatureHighlightSection.js +2 -2
  129. package/dist/views/page-editor/sections/FeatureHighlightSection.js.map +1 -1
  130. package/dist/views/page-editor/sections/GallerySection.d.ts.map +1 -1
  131. package/dist/views/page-editor/sections/GallerySection.js +1 -1
  132. package/dist/views/page-editor/sections/GallerySection.js.map +1 -1
  133. package/dist/views/page-editor/sections/HeroBannerSection.js +1 -1
  134. package/dist/views/page-editor/sections/HeroBannerSection.js.map +1 -1
  135. package/dist/views/page-editor/sections/MissionSection.d.ts.map +1 -1
  136. package/dist/views/page-editor/sections/MissionSection.js +1 -1
  137. package/dist/views/page-editor/sections/MissionSection.js.map +1 -1
  138. package/dist/views/page-editor/sections/PullQuoteSection.js +1 -1
  139. package/dist/views/page-editor/sections/PullQuoteSection.js.map +1 -1
  140. package/dist/views/page-editor/sections/RelatedPostsSection.js +1 -1
  141. package/dist/views/page-editor/sections/RelatedPostsSection.js.map +1 -1
  142. package/dist/views/page-editor/sections/SectionRenderer.d.ts.map +1 -1
  143. package/dist/views/page-editor/sections/SectionRenderer.js +5 -1
  144. package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
  145. package/dist/views/page-editor/sections/parts.js +6 -6
  146. package/dist/views/page-editor/sections/parts.js.map +1 -1
  147. package/dist/views/post-editor/PostEditorCanvas.js +2 -2
  148. package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
  149. package/dist/views/post-editor/PostHeader.js +2 -2
  150. package/dist/views/post-editor/PostHeader.js.map +1 -1
  151. package/dist/views/post-editor/PostHeaderPanel.js +1 -1
  152. package/dist/views/post-editor/PostHeaderPanel.js.map +1 -1
  153. package/dist/views/post-editor/PostPreview.js +1 -1
  154. package/dist/views/post-editor/PostPreview.js.map +1 -1
  155. package/dist/views/profile/AccountSecurity.js +1 -1
  156. package/dist/views/profile/AccountSecurity.js.map +1 -1
  157. package/dist/views/seo/TechnicalTab.d.ts.map +1 -1
  158. package/dist/views/seo/TechnicalTab.js +0 -10
  159. package/dist/views/seo/TechnicalTab.js.map +1 -1
  160. package/dist/views/settings/components.js +1 -1
  161. package/dist/views/settings/components.js.map +1 -1
  162. package/package.json +2 -2
  163. package/src/__tests__/components/posts-badges.test.tsx +3 -3
  164. package/src/__tests__/lib/page-editor-service.test.ts +1 -0
  165. package/src/components/AICoauthorBubbleMenu.tsx +4 -4
  166. package/src/components/Breadcrumbs.tsx +5 -5
  167. package/src/components/CoauthorResultPopover.tsx +26 -23
  168. package/src/components/CommandPalette.tsx +41 -39
  169. package/src/components/CommentSidePanel.tsx +20 -20
  170. package/src/components/ContentOverviewChart.tsx +4 -4
  171. package/src/components/FocalPointPicker.tsx +2 -2
  172. package/src/components/LivePreview.tsx +20 -17
  173. package/src/components/LogoPlaceholder.tsx +1 -1
  174. package/src/components/MentionableTextarea.tsx +5 -5
  175. package/src/components/NotificationBell.tsx +10 -10
  176. package/src/components/OfflineStatus.tsx +8 -8
  177. package/src/components/PresenceChips.tsx +12 -8
  178. package/src/components/SEOConfigPanel.tsx +40 -38
  179. package/src/components/SEOPanel.tsx +15 -15
  180. package/src/components/SEOPerformance.tsx +25 -23
  181. package/src/components/TipTapEditor.tsx +7 -7
  182. package/src/components/pages/tag-badges.tsx +6 -6
  183. package/src/components/posts/badges.tsx +28 -46
  184. package/src/components/ui/Badge.tsx +5 -5
  185. package/src/components/ui/Toast.tsx +4 -5
  186. package/src/fields/ComponentBlockField.tsx +2 -2
  187. package/src/fields/FieldRenderer.tsx +1 -1
  188. package/src/fields/PropInput.tsx +1 -1
  189. package/src/fields/RelationshipField.tsx +5 -5
  190. package/src/fields/ToggleField.tsx +1 -1
  191. package/src/lib/seo-service.ts +0 -2
  192. package/src/views/Dashboard.tsx +5 -5
  193. package/src/views/DocumentEdit.tsx +13 -11
  194. package/src/views/ForgotPassword.tsx +21 -18
  195. package/src/views/FormEditor.tsx +74 -69
  196. package/src/views/Login.tsx +45 -39
  197. package/src/views/PageEditor.tsx +26 -22
  198. package/src/views/Pages/PagesListView.tsx +6 -6
  199. package/src/views/Pages.tsx +64 -65
  200. package/src/views/ResetPassword.tsx +32 -29
  201. package/src/views/Settings.tsx +2 -2
  202. package/src/views/SetupWizard.tsx +42 -33
  203. package/src/views/page-builder/DesignScore.tsx +12 -12
  204. package/src/views/page-builder/SEOPanel.tsx +12 -12
  205. package/src/views/page-editor/EditorCanvas.tsx +1 -1
  206. package/src/views/page-editor/EditorTopBar.tsx +2 -2
  207. package/src/views/page-editor/PagePreview.tsx +1 -1
  208. package/src/views/page-editor/SectionInspector.tsx +1 -1
  209. package/src/views/page-editor/SitePreviewFrame.tsx +1 -1
  210. package/src/views/page-editor/sections/ArticleBodySection.tsx +5 -5
  211. package/src/views/page-editor/sections/AuthorBioSection.tsx +6 -6
  212. package/src/views/page-editor/sections/ByTheNumbersSection.tsx +5 -5
  213. package/src/views/page-editor/sections/CtaBannerSection.tsx +1 -1
  214. package/src/views/page-editor/sections/EmbedSection.tsx +43 -0
  215. package/src/views/page-editor/sections/FeatureHighlightSection.tsx +7 -5
  216. package/src/views/page-editor/sections/GallerySection.tsx +6 -4
  217. package/src/views/page-editor/sections/HeroBannerSection.tsx +2 -2
  218. package/src/views/page-editor/sections/MissionSection.tsx +4 -2
  219. package/src/views/page-editor/sections/PullQuoteSection.tsx +4 -4
  220. package/src/views/page-editor/sections/RelatedPostsSection.tsx +5 -5
  221. package/src/views/page-editor/sections/SectionRenderer.tsx +6 -2
  222. package/src/views/page-editor/sections/parts.tsx +6 -6
  223. package/src/views/post-editor/PostEditorCanvas.tsx +4 -4
  224. package/src/views/post-editor/PostHeader.tsx +5 -5
  225. package/src/views/post-editor/PostHeaderPanel.tsx +1 -1
  226. package/src/views/post-editor/PostPreview.tsx +1 -1
  227. package/src/views/profile/AccountSecurity.tsx +1 -1
  228. package/src/views/seo/TechnicalTab.tsx +0 -10
  229. package/src/views/settings/components.tsx +1 -1
@@ -28,14 +28,11 @@ export interface PagesProps {
28
28
  }
29
29
 
30
30
  const COLOR_PALETTE = [
31
- { bg: 'bg-blue-100', text: 'text-blue-700' },
32
- { bg: 'bg-green-100', text: 'text-green-700' },
33
- { bg: 'bg-purple-100', text: 'text-purple-700' },
34
- { bg: 'bg-orange-100', text: 'text-orange-700' },
35
- { bg: 'bg-pink-100', text: 'text-pink-700' },
36
- { bg: 'bg-teal-100', text: 'text-teal-700' },
37
- { bg: 'bg-indigo-100', text: 'text-indigo-700' },
38
- { bg: 'bg-rose-100', text: 'text-rose-700' },
31
+ { bg: 'bg-chart-1/15', text: 'text-chart-1' },
32
+ { bg: 'bg-chart-2/15', text: 'text-chart-2' },
33
+ { bg: 'bg-chart-3/15', text: 'text-chart-3' },
34
+ { bg: 'bg-chart-4/15', text: 'text-chart-4' },
35
+ { bg: 'bg-chart-5/15', text: 'text-chart-5' },
39
36
  ]
40
37
 
41
38
  function hashString(s: string): number {
@@ -70,11 +67,11 @@ function textValue(value: unknown): string {
70
67
  }
71
68
 
72
69
  function SeoScoreBadge({ score }: { score: number }) {
73
- const color = score >= 80 ? 'bg-green-500' : score >= 60 ? 'bg-amber-500' : 'bg-red-500'
70
+ const color = score >= 80 ? 'bg-success' : score >= 60 ? 'bg-warning' : 'bg-destructive'
74
71
  return (
75
72
  <div className="flex items-center gap-1.5">
76
73
  <span className={`h-2.5 w-2.5 rounded-full ${color}`} />
77
- <span className="text-xs text-gray-600">{score}</span>
74
+ <span className="text-muted-foreground text-xs">{score}</span>
78
75
  </div>
79
76
  )
80
77
  }
@@ -229,7 +226,7 @@ export function Pages({ onNavigate }: PagesProps) {
229
226
  <button
230
227
  type="button"
231
228
  onClick={() => setSortConfig(toggleSort(sortConfig, sortKey))}
232
- className="flex items-center gap-1 text-xs font-medium text-gray-700 transition-colors hover:text-gray-900"
229
+ className="text-foreground hover:text-foreground flex items-center gap-1 text-xs font-medium transition-colors"
233
230
  >
234
231
  {label}
235
232
  {active ? (
@@ -239,7 +236,7 @@ export function Pages({ onNavigate }: PagesProps) {
239
236
  <ArrowDown className="h-3 w-3" />
240
237
  )
241
238
  ) : (
242
- <ArrowUpDown className="h-3 w-3 text-gray-400" />
239
+ <ArrowUpDown className="text-muted-foreground h-3 w-3" />
243
240
  )}
244
241
  </button>
245
242
  )
@@ -248,7 +245,7 @@ export function Pages({ onNavigate }: PagesProps) {
248
245
  if (loading) {
249
246
  return (
250
247
  <div className="flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8">
251
- <Loader2 className="h-6 w-6 animate-spin text-blue-600" />
248
+ <Loader2 className="text-primary h-6 w-6 animate-spin" />
252
249
  </div>
253
250
  )
254
251
  }
@@ -256,12 +253,12 @@ export function Pages({ onNavigate }: PagesProps) {
256
253
  return (
257
254
  <div className="flex h-full flex-col p-3 pr-6 sm:p-4 sm:pr-8">
258
255
  {error && (
259
- <div className="mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3">
260
- <AlertTriangle className="h-5 w-5 shrink-0 text-red-600" />
261
- <span className="flex-1 text-sm text-red-800">{error}</span>
256
+ <div className="border-destructive/30 bg-destructive/10 mb-4 flex items-center gap-3 rounded-lg border p-3">
257
+ <AlertTriangle className="text-destructive h-5 w-5 shrink-0" />
258
+ <span className="text-destructive flex-1 text-sm">{error}</span>
262
259
  <button
263
260
  onClick={refetch}
264
- className="rounded-lg border border-red-300 px-3 py-1 text-sm text-red-700 transition-colors hover:bg-red-100"
261
+ className="border-destructive text-destructive hover:bg-destructive/10 rounded-lg border px-3 py-1 text-sm transition-colors"
265
262
  >
266
263
  Retry
267
264
  </button>
@@ -273,21 +270,21 @@ export function Pages({ onNavigate }: PagesProps) {
273
270
  <button
274
271
  type="button"
275
272
  onClick={() => setSidebarOpen((prev) => !prev)}
276
- className="rounded-lg p-1.5 transition-colors hover:bg-gray-100"
273
+ className="hover:bg-muted rounded-lg p-1.5 transition-colors"
277
274
  title={sidebarOpen ? 'Hide folders' : 'Show folders'}
278
275
  >
279
- <FolderInput className="h-5 w-5 text-gray-600" />
276
+ <FolderInput className="text-muted-foreground h-5 w-5" />
280
277
  </button>
281
278
  <div>
282
- <h1 className="text-xl font-medium text-gray-900 sm:text-2xl">Pages</h1>
283
- <p className="text-sm text-gray-500">
279
+ <h1 className="text-foreground text-xl font-medium sm:text-2xl">Pages</h1>
280
+ <p className="text-muted-foreground text-sm">
284
281
  {totalCount} page{totalCount !== 1 ? 's' : ''}
285
282
  </p>
286
283
  </div>
287
284
  </div>
288
285
  <button
289
286
  onClick={() => onNavigate?.('/pages/new')}
290
- className="flex items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700"
287
+ className="bg-primary text-primary-foreground hover:bg-primary/90 flex items-center justify-center gap-2 rounded-lg px-4 py-2 text-sm transition-colors"
291
288
  >
292
289
  <Plus className="h-4 w-4" />
293
290
  <span className="hidden sm:inline">New Page</span>
@@ -297,7 +294,7 @@ export function Pages({ onNavigate }: PagesProps) {
297
294
 
298
295
  <div className="flex min-h-0 flex-1 gap-4 overflow-hidden">
299
296
  {sidebarOpen && (
300
- <div className="flex w-56 shrink-0 flex-col overflow-hidden rounded-lg border border-gray-200 bg-white">
297
+ <div className="border-border bg-card flex w-56 shrink-0 flex-col overflow-hidden rounded-lg border">
301
298
  <FolderTree
302
299
  scope="pages"
303
300
  selected={folderSel}
@@ -313,23 +310,23 @@ export function Pages({ onNavigate }: PagesProps) {
313
310
  )}
314
311
 
315
312
  <div className="flex min-w-0 flex-1 flex-col">
316
- <div className="mb-4 rounded-lg border border-gray-200 bg-white">
313
+ <div className="border-border bg-card mb-4 rounded-lg border">
317
314
  <div className="flex flex-col gap-3 p-3">
318
315
  <div className="relative">
319
- <Search className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-400" />
316
+ <Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
320
317
  <input
321
318
  type="text"
322
319
  placeholder="Search pages..."
323
320
  value={searchQuery}
324
321
  onChange={(e) => setSearchQuery(e.target.value)}
325
- className="w-full rounded-lg border border-gray-300 py-2 pr-3 pl-9 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none"
322
+ className="border-border focus-visible:ring-ring/50 w-full rounded-lg border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
326
323
  />
327
324
  </div>
328
325
  <div className="flex flex-col gap-2 sm:flex-row">
329
326
  <select
330
327
  value={filterStatus}
331
328
  onChange={(e) => setFilterStatus(e.target.value)}
332
- className="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none"
329
+ className="border-border focus-visible:ring-ring/50 flex-1 rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
333
330
  >
334
331
  <option value="all">All Status</option>
335
332
  <option value="published">Published</option>
@@ -338,7 +335,7 @@ export function Pages({ onNavigate }: PagesProps) {
338
335
  <select
339
336
  value={filterTemplate}
340
337
  onChange={(e) => setFilterTemplate(e.target.value)}
341
- className="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none"
338
+ className="border-border focus-visible:ring-ring/50 flex-1 rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
342
339
  >
343
340
  <option value="all">All Templates</option>
344
341
  <option value="landing">Landing</option>
@@ -348,7 +345,7 @@ export function Pages({ onNavigate }: PagesProps) {
348
345
  </select>
349
346
  <button
350
347
  type="button"
351
- className="flex items-center justify-center gap-2 rounded-lg border border-gray-300 px-3 py-2 text-sm transition-colors hover:bg-gray-50"
348
+ className="border-border hover:bg-muted flex items-center justify-center gap-2 rounded-lg border px-3 py-2 text-sm transition-colors"
352
349
  >
353
350
  <SlidersHorizontal className="h-4 w-4" />
354
351
  <span className="hidden sm:inline">More Filters</span>
@@ -358,37 +355,37 @@ export function Pages({ onNavigate }: PagesProps) {
358
355
  </div>
359
356
 
360
357
  {selectedPages.length > 0 && (
361
- <div className="mb-4 rounded-lg border border-blue-200 bg-blue-50 p-3">
358
+ <div className="border-info/30 bg-info/10 mb-4 rounded-lg border p-3">
362
359
  <div className="flex flex-col justify-between gap-2 sm:flex-row sm:items-center">
363
- <span className="text-sm text-blue-900">
360
+ <span className="text-foreground text-sm">
364
361
  {selectedPages.length} page{selectedPages.length !== 1 ? 's' : ''} selected
365
362
  </span>
366
363
  <div className="flex items-center gap-2">
367
364
  <button
368
365
  type="button"
369
366
  onClick={handleBulkPublish}
370
- className="flex-1 rounded-lg bg-green-600 px-3 py-1.5 text-sm text-white transition-colors hover:bg-green-700 sm:flex-none"
367
+ className="bg-success text-success-foreground hover:bg-success/90 flex-1 rounded-lg px-3 py-1.5 text-sm transition-colors sm:flex-none"
371
368
  >
372
369
  Publish
373
370
  </button>
374
371
  <button
375
372
  type="button"
376
373
  onClick={handleBulkUnpublish}
377
- className="flex-1 rounded-lg bg-yellow-600 px-3 py-1.5 text-sm text-white transition-colors hover:bg-yellow-700 sm:flex-none"
374
+ className="bg-warning text-warning-foreground hover:bg-warning/90 flex-1 rounded-lg px-3 py-1.5 text-sm transition-colors sm:flex-none"
378
375
  >
379
376
  Unpublish
380
377
  </button>
381
378
  <button
382
379
  type="button"
383
380
  onClick={handleBulkDelete}
384
- className="flex-1 rounded-lg bg-red-600 px-3 py-1.5 text-sm text-white transition-colors hover:bg-red-700 sm:flex-none"
381
+ className="bg-destructive text-destructive-foreground hover:bg-destructive/90 flex-1 rounded-lg px-3 py-1.5 text-sm transition-colors sm:flex-none"
385
382
  >
386
383
  Delete
387
384
  </button>
388
385
  <button
389
386
  type="button"
390
387
  onClick={() => setSelectedPages([])}
391
- className="flex-1 rounded-lg border border-gray-300 bg-white px-3 py-1.5 text-sm transition-colors hover:bg-gray-50 sm:flex-none"
388
+ className="border-border bg-card hover:bg-muted flex-1 rounded-lg border px-3 py-1.5 text-sm transition-colors sm:flex-none"
392
389
  >
393
390
  Cancel
394
391
  </button>
@@ -398,8 +395,8 @@ export function Pages({ onNavigate }: PagesProps) {
398
395
  )}
399
396
 
400
397
  {filteredAndSorted.length === 0 && !error ? (
401
- <div className="flex flex-1 flex-col items-center justify-center rounded-lg border border-gray-200 bg-white p-8 text-center">
402
- <p className="mb-2 text-sm text-gray-500">
398
+ <div className="border-border bg-card flex flex-1 flex-col items-center justify-center rounded-lg border p-8 text-center">
399
+ <p className="text-muted-foreground mb-2 text-sm">
403
400
  {folderSel.type === 'smart' && folderSel.smart === 'uncategorized'
404
401
  ? 'No uncategorized pages'
405
402
  : folderSel.type === 'folder'
@@ -408,17 +405,17 @@ export function Pages({ onNavigate }: PagesProps) {
408
405
  </p>
409
406
  <button
410
407
  onClick={() => onNavigate?.('/pages/new')}
411
- className="rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700"
408
+ className="bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg px-4 py-2 text-sm transition-colors"
412
409
  >
413
410
  Create your first page
414
411
  </button>
415
412
  </div>
416
413
  ) : (
417
414
  <>
418
- <div className="hidden flex-1 overflow-hidden rounded-lg border border-gray-200 bg-white md:block">
415
+ <div className="border-border bg-card hidden flex-1 overflow-hidden rounded-lg border md:block">
419
416
  <div className="h-full overflow-x-auto">
420
417
  <table className="w-full">
421
- <thead className="sticky top-0 border-b border-gray-200 bg-gray-50">
418
+ <thead className="border-border bg-muted sticky top-0 border-b">
422
419
  <tr>
423
420
  <th className="w-8 px-3 py-2 text-left">
424
421
  <input
@@ -428,20 +425,20 @@ export function Pages({ onNavigate }: PagesProps) {
428
425
  filteredAndSorted.length > 0
429
426
  }
430
427
  onChange={(e) => handleSelectAll(e.target.checked)}
431
- className="rounded border-gray-300"
428
+ className="border-border rounded"
432
429
  />
433
430
  </th>
434
431
  <th className="w-6 px-1 py-2"></th>
435
432
  <th className="px-3 py-2 text-left">
436
433
  <SortHeader label="Title" sortKey="title" />
437
434
  </th>
438
- <th className="px-3 py-2 text-left text-xs font-medium text-gray-700">
435
+ <th className="text-foreground px-3 py-2 text-left text-xs font-medium">
439
436
  Folder
440
437
  </th>
441
438
  <th className="px-3 py-2 text-left">
442
439
  <SortHeader label="Author" sortKey="author" />
443
440
  </th>
444
- <th className="px-3 py-2 text-left text-xs font-medium text-gray-700">
441
+ <th className="text-foreground px-3 py-2 text-left text-xs font-medium">
445
442
  SEO
446
443
  </th>
447
444
  <th className="px-3 py-2 text-left">
@@ -450,19 +447,19 @@ export function Pages({ onNavigate }: PagesProps) {
450
447
  <th className="px-3 py-2 text-left">
451
448
  <SortHeader label="Date" sortKey="date" />
452
449
  </th>
453
- <th className="px-3 py-2 text-left text-xs font-medium text-gray-700">
450
+ <th className="text-foreground px-3 py-2 text-left text-xs font-medium">
454
451
  Actions
455
452
  </th>
456
453
  </tr>
457
454
  </thead>
458
- <tbody className="divide-y divide-gray-200">
455
+ <tbody className="divide-border divide-y">
459
456
  {filteredAndSorted.map((page: any) => {
460
457
  const seoScore = computeSeoScore(page.data)
461
458
  const folderName = page.folder?.name ?? page.folderName
462
459
  return (
463
460
  <tr
464
461
  key={page.id}
465
- className="transition-colors hover:bg-gray-50"
462
+ className="hover:bg-muted transition-colors"
466
463
  draggable
467
464
  onDragStart={(e) => handleDragStart(e, page.id)}
468
465
  >
@@ -471,17 +468,17 @@ export function Pages({ onNavigate }: PagesProps) {
471
468
  type="checkbox"
472
469
  checked={selectedPages.includes(page.id)}
473
470
  onChange={() => handleSelectPage(page.id)}
474
- className="rounded border-gray-300"
471
+ className="border-border rounded"
475
472
  />
476
473
  </td>
477
474
  <td className="cursor-grab px-1 py-2">
478
- <GripVertical className="h-4 w-4 text-gray-300" />
475
+ <GripVertical className="text-muted-foreground h-4 w-4" />
479
476
  </td>
480
477
  <td className="px-3 py-2">
481
478
  <button
482
479
  type="button"
483
480
  onClick={() => onNavigate?.(`/pages/${page.id}`)}
484
- className="text-left text-sm font-medium text-gray-900 hover:text-blue-600"
481
+ className="text-foreground hover:text-primary text-left text-sm font-medium"
485
482
  >
486
483
  {page.title}
487
484
  </button>
@@ -490,38 +487,40 @@ export function Pages({ onNavigate }: PagesProps) {
490
487
  {folderName ? (
491
488
  <FolderBadge name={folderName} />
492
489
  ) : (
493
- <span className="text-xs text-gray-400">—</span>
490
+ <span className="text-muted-foreground text-xs">—</span>
494
491
  )}
495
492
  </td>
496
- <td className="px-3 py-2 text-sm text-gray-600">{page.author}</td>
493
+ <td className="text-muted-foreground px-3 py-2 text-sm">
494
+ {page.author}
495
+ </td>
497
496
  <td className="px-3 py-2">
498
497
  <SeoScoreBadge score={seoScore} />
499
498
  </td>
500
499
  <td className="px-3 py-2">
501
500
  <span
502
- className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${page.status === 'Published' || page.status === 'PUBLISHED' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`}
501
+ className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${page.status === 'Published' || page.status === 'PUBLISHED' ? 'bg-success/10 text-success' : 'bg-muted text-foreground'}`}
503
502
  >
504
503
  {page.status}
505
504
  </span>
506
505
  </td>
507
- <td className="px-3 py-2 text-sm text-gray-600">{page.date}</td>
506
+ <td className="text-muted-foreground px-3 py-2 text-sm">{page.date}</td>
508
507
  <td className="px-3 py-2">
509
508
  <div className="flex items-center gap-2">
510
509
  <button
511
510
  type="button"
512
511
  onClick={() => onNavigate?.(`/pages/${page.id}`)}
513
- className="rounded p-1.5 transition-colors hover:bg-gray-100"
512
+ className="hover:bg-muted rounded p-1.5 transition-colors"
514
513
  title="Edit"
515
514
  >
516
- <Pencil className="h-4 w-4 text-gray-600" />
515
+ <Pencil className="text-muted-foreground h-4 w-4" />
517
516
  </button>
518
517
  <button
519
518
  type="button"
520
519
  onClick={() => handleDelete(page.id)}
521
- className="rounded p-1.5 transition-colors hover:bg-gray-100"
520
+ className="hover:bg-muted rounded p-1.5 transition-colors"
522
521
  title="Delete"
523
522
  >
524
- <Trash2 className="h-4 w-4 text-red-600" />
523
+ <Trash2 className="text-destructive h-4 w-4" />
525
524
  </button>
526
525
  </div>
527
526
  </td>
@@ -533,8 +532,8 @@ export function Pages({ onNavigate }: PagesProps) {
533
532
  </div>
534
533
  </div>
535
534
 
536
- <div className="flex-1 overflow-auto rounded-lg border border-gray-200 bg-white md:hidden">
537
- <div className="divide-y divide-gray-200">
535
+ <div className="border-border bg-card flex-1 overflow-auto rounded-lg border md:hidden">
536
+ <div className="divide-border divide-y">
538
537
  {filteredAndSorted.map((page: any) => {
539
538
  const seoScore = computeSeoScore(page.data)
540
539
  const folderName = page.folder?.name ?? page.folderName
@@ -550,24 +549,24 @@ export function Pages({ onNavigate }: PagesProps) {
550
549
  type="checkbox"
551
550
  checked={selectedPages.includes(page.id)}
552
551
  onChange={() => handleSelectPage(page.id)}
553
- className="mt-1 rounded border-gray-300"
552
+ className="border-border mt-1 rounded"
554
553
  />
555
554
  <div className="min-w-0 flex-1">
556
555
  <button
557
556
  type="button"
558
557
  onClick={() => onNavigate?.(`/pages/${page.id}`)}
559
- className="mb-1 block text-left text-sm font-medium text-gray-900 hover:text-blue-600"
558
+ className="text-foreground hover:text-primary mb-1 block text-left text-sm font-medium"
560
559
  >
561
560
  {page.title}
562
561
  </button>
563
- <div className="mb-2 flex flex-wrap items-center gap-2 text-xs text-gray-600">
562
+ <div className="text-muted-foreground mb-2 flex flex-wrap items-center gap-2 text-xs">
564
563
  {folderName && <FolderBadge name={folderName} />}
565
564
  <span>{page.author}</span>
566
565
  <span>&middot;</span>
567
566
  <span>{page.date}</span>
568
567
  <SeoScoreBadge score={seoScore} />
569
568
  <span
570
- className={`rounded-full px-2 py-0.5 text-xs font-medium ${page.status === 'Published' || page.status === 'PUBLISHED' ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'}`}
569
+ className={`rounded-full px-2 py-0.5 text-xs font-medium ${page.status === 'Published' || page.status === 'PUBLISHED' ? 'bg-success/10 text-success' : 'bg-muted text-foreground'}`}
571
570
  >
572
571
  {page.status}
573
572
  </span>
@@ -576,9 +575,9 @@ export function Pages({ onNavigate }: PagesProps) {
576
575
  <button
577
576
  type="button"
578
577
  onClick={() => handleDelete(page.id)}
579
- className="rounded p-1.5 transition-colors hover:bg-gray-100"
578
+ className="hover:bg-muted rounded p-1.5 transition-colors"
580
579
  >
581
- <Trash2 className="h-4 w-4 text-red-600" />
580
+ <Trash2 className="text-destructive h-4 w-4" />
582
581
  </button>
583
582
  </div>
584
583
  </div>
@@ -9,6 +9,9 @@ export interface ResetPasswordProps {
9
9
  token: string | null
10
10
  }
11
11
 
12
+ const fieldClass =
13
+ 'w-full rounded-lg border border-border bg-input-background px-3 py-2.5 text-sm text-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none'
14
+
12
15
  export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
13
16
  const [password, setPassword] = useState('')
14
17
  const [confirmPassword, setConfirmPassword] = useState('')
@@ -19,29 +22,29 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
19
22
 
20
23
  if (!token) {
21
24
  return (
22
- <div className="flex min-h-screen items-center justify-center bg-gray-50 px-4">
25
+ <div className="bg-muted flex min-h-screen items-center justify-center px-4">
23
26
  <div className="w-full max-w-md">
24
27
  <div className="mb-8 text-center">
25
- <div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-red-100">
26
- <XCircle className="h-7 w-7 text-red-600" />
28
+ <div className="bg-destructive/10 mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl">
29
+ <XCircle className="text-destructive h-7 w-7" />
27
30
  </div>
28
- <h1 className="text-2xl font-medium text-gray-900">Invalid Reset Link</h1>
29
- <p className="mt-2 text-gray-600">
31
+ <h1 className="text-foreground text-2xl font-medium">Invalid Reset Link</h1>
32
+ <p className="text-muted-foreground mt-2">
30
33
  This password reset link is invalid or has expired.
31
34
  </p>
32
35
  </div>
33
- <div className="space-y-4 rounded-xl border border-gray-200 bg-white p-6 text-center shadow-sm">
36
+ <div className="border-border bg-card space-y-4 rounded-xl border p-6 text-center shadow-sm">
34
37
  <button
35
38
  type="button"
36
39
  onClick={() => onNavigate('/forgot-password')}
37
- className="w-full rounded-lg bg-blue-600 py-2.5 font-medium text-white transition-colors hover:bg-blue-700"
40
+ className="bg-primary text-primary-foreground hover:bg-primary/90 w-full rounded-lg py-2.5 font-medium transition-colors"
38
41
  >
39
42
  Request New Reset Link
40
43
  </button>
41
44
  <button
42
45
  type="button"
43
46
  onClick={() => onNavigate('/login')}
44
- className="w-full text-sm text-gray-600 transition-colors hover:text-gray-800"
47
+ className="text-muted-foreground hover:text-foreground w-full text-sm transition-colors"
45
48
  >
46
49
  Back to Sign In
47
50
  </button>
@@ -81,34 +84,34 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
81
84
  }
82
85
 
83
86
  return (
84
- <div className="flex min-h-screen items-center justify-center bg-gray-50 px-4">
87
+ <div className="bg-muted flex min-h-screen items-center justify-center px-4">
85
88
  <div className="w-full max-w-md">
86
89
  <div className="mb-8 text-center">
87
- <div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl bg-blue-600">
88
- <Shield className="h-7 w-7 text-white" />
90
+ <div className="bg-primary mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl">
91
+ <Shield className="text-primary-foreground h-7 w-7" />
89
92
  </div>
90
- <h1 className="text-2xl font-medium text-gray-900">
93
+ <h1 className="text-foreground text-2xl font-medium">
91
94
  {success ? 'Password Reset' : 'Choose New Password'}
92
95
  </h1>
93
- <p className="mt-2 text-gray-600">
96
+ <p className="text-muted-foreground mt-2">
94
97
  {success ? 'Your password has been updated' : 'Enter your new password below'}
95
98
  </p>
96
99
  </div>
97
100
 
98
- <div className="space-y-5 rounded-xl border border-gray-200 bg-white p-6 shadow-sm">
101
+ <div className="border-border bg-card space-y-5 rounded-xl border p-6 shadow-sm">
99
102
  {success ? (
100
103
  <div className="space-y-4 text-center">
101
- <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
102
- <CheckCircle2 className="h-6 w-6 text-green-600" />
104
+ <div className="bg-success/10 mx-auto flex h-12 w-12 items-center justify-center rounded-full">
105
+ <CheckCircle2 className="text-success h-6 w-6" />
103
106
  </div>
104
- <p className="text-sm text-gray-600">
107
+ <p className="text-muted-foreground text-sm">
105
108
  Your password has been successfully reset. All existing sessions have been revoked
106
109
  for security.
107
110
  </p>
108
111
  <button
109
112
  type="button"
110
113
  onClick={() => onNavigate('/login')}
111
- className="w-full rounded-lg bg-blue-600 py-2.5 font-medium text-white transition-colors hover:bg-blue-700"
114
+ className="bg-primary text-primary-foreground hover:bg-primary/90 w-full rounded-lg py-2.5 font-medium transition-colors"
112
115
  >
113
116
  Sign In with New Password
114
117
  </button>
@@ -116,16 +119,16 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
116
119
  ) : (
117
120
  <form onSubmit={handleSubmit} className="space-y-5">
118
121
  {error && (
119
- <div className="flex items-start gap-3 rounded-lg border border-red-200 bg-red-50 p-3">
120
- <AlertTriangle className="mt-0.5 h-5 w-5 shrink-0 text-red-600" />
121
- <p className="text-sm text-red-800">{error}</p>
122
+ <div className="border-destructive/30 bg-destructive/10 flex items-start gap-3 rounded-lg border p-3">
123
+ <AlertTriangle className="text-destructive mt-0.5 h-5 w-5 shrink-0" />
124
+ <p className="text-destructive text-sm">{error}</p>
122
125
  </div>
123
126
  )}
124
127
 
125
128
  <div>
126
129
  <label
127
130
  htmlFor="reset-password"
128
- className="mb-1.5 block text-sm font-medium text-gray-700"
131
+ className="text-foreground mb-1.5 block text-sm font-medium"
129
132
  >
130
133
  New Password
131
134
  </label>
@@ -136,7 +139,7 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
136
139
  value={password}
137
140
  onChange={(e) => setPassword(e.target.value)}
138
141
  placeholder="Enter new password"
139
- className="w-full rounded-lg border border-gray-300 px-3 py-2.5 pr-10 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"
142
+ className={`${fieldClass} pr-10`}
140
143
  required
141
144
  autoFocus
142
145
  autoComplete="new-password"
@@ -145,14 +148,14 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
145
148
  <button
146
149
  type="button"
147
150
  onClick={() => setShowPassword(!showPassword)}
148
- className="absolute top-1/2 right-3 -translate-y-1/2 text-gray-400 hover:text-gray-600"
151
+ className="text-muted-foreground hover:text-foreground absolute top-1/2 right-3 -translate-y-1/2"
149
152
  tabIndex={-1}
150
153
  >
151
154
  {showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
152
155
  </button>
153
156
  </div>
154
157
  {password && !meetsLength && (
155
- <p className="mt-1 text-xs text-red-600">
158
+ <p className="text-destructive mt-1 text-xs">
156
159
  Password must be at least 8 characters
157
160
  </p>
158
161
  )}
@@ -161,7 +164,7 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
161
164
  <div>
162
165
  <label
163
166
  htmlFor="reset-confirm"
164
- className="mb-1.5 block text-sm font-medium text-gray-700"
167
+ className="text-foreground mb-1.5 block text-sm font-medium"
165
168
  >
166
169
  Confirm Password
167
170
  </label>
@@ -171,19 +174,19 @@ export function ResetPassword({ onNavigate, token }: ResetPasswordProps) {
171
174
  value={confirmPassword}
172
175
  onChange={(e) => setConfirmPassword(e.target.value)}
173
176
  placeholder="Confirm new password"
174
- className="w-full rounded-lg border border-gray-300 px-3 py-2.5 text-sm focus:border-blue-500 focus:ring-2 focus:ring-blue-500 focus:outline-none"
177
+ className={fieldClass}
175
178
  required
176
179
  autoComplete="new-password"
177
180
  />
178
181
  {confirmPassword && !passwordsMatch && (
179
- <p className="mt-1 text-xs text-red-600">Passwords do not match</p>
182
+ <p className="text-destructive mt-1 text-xs">Passwords do not match</p>
180
183
  )}
181
184
  </div>
182
185
 
183
186
  <button
184
187
  type="submit"
185
188
  disabled={!canSubmit}
186
- className="flex w-full items-center justify-center gap-2 rounded-lg bg-blue-600 py-2.5 font-medium text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50"
189
+ className="bg-primary text-primary-foreground hover:bg-primary/90 flex w-full items-center justify-center gap-2 rounded-lg py-2.5 font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50"
187
190
  >
188
191
  {submitting ? (
189
192
  <>
@@ -155,7 +155,7 @@ export function Settings({
155
155
  if (loading) {
156
156
  return (
157
157
  <div className="flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8">
158
- <Loader2 className="h-6 w-6 animate-spin text-blue-600" />
158
+ <Loader2 className="text-primary h-6 w-6 animate-spin" />
159
159
  </div>
160
160
  )
161
161
  }
@@ -347,7 +347,7 @@ export function Settings({
347
347
  type="button"
348
348
  onClick={handleSave}
349
349
  disabled={saving}
350
- className="rounded-lg bg-blue-600 px-6 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:opacity-50"
350
+ className="bg-primary hover:bg-primary/90 rounded-lg px-6 py-2 text-sm text-white transition-colors disabled:opacity-50"
351
351
  >
352
352
  {saving ? 'Saving...' : 'Save Changes'}
353
353
  </button>