Преглед на файлове

MAESTRO: frontend retheme pass 2 — semantic tokens, display type, outlined-ember destructive

- Replace stock blue/green/red/yellow classes with semantic tokens
  (success/primary/destructive) in WiFiSetupPage, UpdateDialog, BrowsePage
- Destructive button variant: outlined ember instead of filled red, matching
  mobile (stop reads as boundary, not rival CTA)
- font-display (Bricolage Grotesque) on CardTitle/DialogTitle/SheetTitle
  primitives and BrowsePage headings + pattern names
- Dark-mode pattern previews warmed toward Bone instead of stark invert

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tuanchris преди 5 дни
родител
ревизия
442245ec54

+ 2 - 2
frontend/src/components/UpdateDialog.tsx

@@ -156,8 +156,8 @@ export function UpdateDialog({ open, onOpenChange, currentVersion, latestVersion
 
         {state === 'complete' && (
           <div className="flex flex-col items-center py-8 gap-4">
-            <div className="w-16 h-16 flex items-center justify-center rounded-full bg-green-100 dark:bg-green-900/30">
-              <span className="material-icons text-green-600 dark:text-green-400 text-4xl">check_circle</span>
+            <div className="w-16 h-16 flex items-center justify-center rounded-full bg-success/15">
+              <span className="material-icons text-success text-4xl">check_circle</span>
             </div>
             <div className="text-center space-y-1">
               <p className="text-lg font-medium">Update complete!</p>

+ 1 - 1
frontend/src/components/ui/button.tsx

@@ -12,7 +12,7 @@ const buttonVariants = cva(
         default: "bg-card text-foreground border border-border shadow-sm hover:bg-accent",
         primary: "bg-primary text-primary-foreground hover:bg-primary/90",
         destructive:
-          "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+          "border-[1.5px] border-destructive text-destructive bg-transparent hover:bg-destructive/10",
         outline:
           "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
         secondary:

+ 1 - 1
frontend/src/components/ui/card.tsx

@@ -36,7 +36,7 @@ const CardTitle = React.forwardRef<
   <div
     ref={ref}
     className={cn(
-      "text-2xl font-semibold leading-none tracking-tight",
+      "font-display text-2xl font-semibold leading-none tracking-tight",
       className
     )}
     {...props}

+ 1 - 1
frontend/src/components/ui/dialog.tsx

@@ -86,7 +86,7 @@ const DialogTitle = React.forwardRef<
   <DialogPrimitive.Title
     ref={ref}
     className={cn(
-      "text-lg font-semibold leading-none tracking-tight",
+      "font-display text-lg font-semibold leading-none tracking-tight",
       className
     )}
     {...props}

+ 1 - 1
frontend/src/components/ui/sheet.tsx

@@ -106,7 +106,7 @@ const SheetTitle = React.forwardRef<
 >(({ className, ...props }, ref) => (
   <SheetPrimitive.Title
     ref={ref}
-    className={cn("text-lg font-semibold text-foreground", className)}
+    className={cn("font-display text-lg font-semibold text-foreground", className)}
     {...props}
   />
 ))

+ 3 - 2
frontend/src/index.css

@@ -163,9 +163,10 @@ body {
   font-family: 'Material Icons Outlined';
 }
 
-/* Invert pattern previews in dark mode */
+/* Invert pattern previews in dark mode, warmed toward the Bone foreground
+   so strokes sit on basalt like sand, not stark white on black */
 .dark .pattern-preview {
-  filter: invert(1);
+  filter: invert(1) sepia(0.25) brightness(0.95);
 }
 
 /* Marquee animation for scrolling text */

+ 6 - 6
frontend/src/pages/BrowsePage.tsx

@@ -874,7 +874,7 @@ export function BrowsePage() {
       {/* Page Header */}
       <div className="flex items-start justify-between gap-4 pl-1">
         <div className="space-y-0.5">
-          <h1 className="text-xl font-semibold tracking-tight">Browse Patterns</h1>
+          <h1 className="font-display text-xl font-semibold tracking-tight">Browse Patterns</h1>
           <p className="text-xs text-muted-foreground">
             {patterns.length} patterns available
           </p>
@@ -1017,7 +1017,7 @@ export function BrowsePage() {
             </span>
           </div>
           <div className="space-y-1">
-            <h2 className="text-xl font-semibold">No patterns found</h2>
+            <h2 className="font-display text-xl font-semibold">No patterns found</h2>
             <p className="text-muted-foreground">Try adjusting your search or filters</p>
           </div>
           {(searchQuery || selectedCategory !== 'all') && (
@@ -1067,7 +1067,7 @@ export function BrowsePage() {
                   role="button"
                   tabIndex={0}
                   className={`shrink-0 transition-colors cursor-pointer flex items-center ${
-                    favorites.has(selectedPattern.path) ? 'text-red-500 hover:text-red-600' : 'text-muted-foreground hover:text-red-500'
+                    favorites.has(selectedPattern.path) ? 'text-destructive hover:text-destructive/80' : 'text-muted-foreground hover:text-destructive'
                   }`}
                   onClick={(e) => toggleFavorite(selectedPattern.path, e)}
                   onKeyDown={(e) => {
@@ -1242,7 +1242,7 @@ export function BrowsePage() {
           >
             {/* Modal Header */}
             <div className="flex items-center justify-between p-6 border-b shrink-0">
-              <h3 className="text-xl font-semibold">
+              <h3 className="font-display text-xl font-semibold">
                 {selectedPattern?.name || 'Animated Preview'}
               </h3>
               <Button
@@ -1458,14 +1458,14 @@ function PatternCard({ pattern, isSelected, isFavorite, playTime, playCount, onT
 
       {/* Name and favorite row */}
       <div className="flex items-center justify-between w-full gap-1 px-0.5">
-        <span className="text-xs font-bold text-foreground truncate" title={pattern.name}>
+        <span className="font-display text-xs font-bold text-foreground truncate" title={pattern.name}>
           {pattern.name}
         </span>
         <span
           role="button"
           tabIndex={0}
           className={`shrink-0 transition-colors cursor-pointer ${
-            isFavorite ? 'text-red-500 hover:text-red-600' : 'text-muted-foreground hover:text-red-500'
+            isFavorite ? 'text-destructive hover:text-destructive/80' : 'text-muted-foreground hover:text-destructive'
           }`}
           onClick={(e) => {
             e.stopPropagation()

+ 4 - 4
frontend/src/pages/WiFiSetupPage.tsx

@@ -42,7 +42,7 @@ function SignalIcon({ signal }: { signal: number }) {
                signal >= 50 ? 'network_wifi_3_bar' :
                signal >= 25 ? 'network_wifi_2_bar' :
                'network_wifi_1_bar'
-  const color = signal >= 50 ? 'text-green-500' : signal >= 25 ? 'text-yellow-500' : 'text-red-500'
+  const color = signal >= 50 ? 'text-success' : signal >= 25 ? 'text-primary' : 'text-destructive'
   return <span className={`material-icons text-lg ${color}`}>{bars}</span>
 }
 
@@ -230,8 +230,8 @@ export function WiFiSetupPage() {
     <div className="container max-w-lg mx-auto px-3 py-4 space-y-3">
       {/* Hotspot Welcome Banner */}
       {isHotspotMode && (
-        <Alert className="border-blue-200 bg-blue-50 dark:bg-blue-950/30 dark:border-blue-800">
-          <span className="material-icons text-blue-500 mr-2">wifi_tethering</span>
+        <Alert className="border-primary/30 bg-primary/10">
+          <span className="material-icons text-primary mr-2">wifi_tethering</span>
           <AlertDescription>
             <strong>Welcome to Dune Weaver!</strong>
             <br />
@@ -483,7 +483,7 @@ export function WiFiSetupPage() {
                 key={network.ssid}
                 onClick={() => openConnectDialog(network)}
                 className={`w-full flex items-center gap-2.5 px-2.5 py-2 rounded-lg text-left transition-colors hover:bg-muted/50
-                  ${network.active ? 'bg-green-50 dark:bg-green-950/20' : ''}`}
+                  ${network.active ? 'bg-success/10' : ''}`}
               >
                 <SignalIcon signal={network.signal} />
                 <div className="flex-1 min-w-0">

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
static/dist/assets/index-DJyhS4Mn.css


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
static/dist/assets/index-Dfvjm5gw.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
static/dist/assets/index-fbNDffn3.css


+ 2 - 2
static/dist/index.html

@@ -58,8 +58,8 @@
           .catch(function() {});
       })();
     </script>
-    <script type="module" crossorigin src="/assets/index-Comyu5NI.js"></script>
-    <link rel="stylesheet" crossorigin href="/assets/index-DJyhS4Mn.css">
+    <script type="module" crossorigin src="/assets/index-Dfvjm5gw.js"></script>
+    <link rel="stylesheet" crossorigin href="/assets/index-fbNDffn3.css">
   <script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
   <body>
     <div id="root"></div>

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
static/dist/sw.js


Някои файлове не бяха показани, защото твърде много файлове са промени