nico-martin HF Staff commited on
Commit
6e10499
·
1 Parent(s): 8a573f8

some long due refactoring

Browse files
src/Initialize.tsx CHANGED
@@ -2,6 +2,9 @@ import { Button } from "./theme";
2
  import cn from "./utils/classnames.ts";
3
  import { formatBytes } from "./utils/format.ts";
4
  import Translator from "./ai/Translator.ts";
 
 
 
5
 
6
  interface InitializeProps {
7
  progress: number;
@@ -17,102 +20,29 @@ export default function Initialize({
17
  className = "",
18
  }: InitializeProps) {
19
  return (
20
- <div className={cn("max-w-2xl mx-auto px-8 animate-fade-in-up", className)}>
21
- <div className="bg-white rounded-lg shadow-md p-8 border border-border">
22
- <div className="flex flex-col items-center gap-6">
23
- {/* Description */}
24
- <div className="space-y-4 text-left w-full">
25
- <div
26
- className="animate-fade-in-up"
27
- style={{ animationDelay: "0.1s", opacity: 0 }}
28
- >
29
- <h3 className="font-semibold text-base mb-1">
30
- About TranslateGemma 4B
31
- </h3>
32
- <p className="text-sm text-secondary-foreground">
33
- TranslateGemma is a family of translation models from Google,
34
- built on top of Gemma 2B. This 4B parameter model supports
35
- translations across 100+ languages with state-of-the-art
36
- quality.{" "}
37
- <a
38
- href="https://blog.google/innovation-and-ai/technology/developers-tools/translategemma/"
39
- target="_blank"
40
- rel="noopener noreferrer"
41
- className="text-primary hover:underline underline-offset-2 transition-all hover:underline-offset-4"
42
- >
43
- Learn more
44
- </a>
45
- </p>
46
- </div>
47
-
48
- <div
49
- className="animate-fade-in-up"
50
- style={{ animationDelay: "0.2s", opacity: 0 }}
51
- >
52
- <h3 className="font-semibold text-base mb-1">
53
- Completely private & offline-capable
54
- </h3>
55
- <p className="text-sm text-secondary-foreground">
56
- Everything runs entirely in your browser with 🤗 Transformers.js
57
- and ONNX Runtime Web — no data is ever sent to a server. Once
58
- loaded, it works offline.
59
- </p>
60
- </div>
61
-
62
- <div
63
- className="animate-fade-in-up"
64
- style={{ animationDelay: "0.3s", opacity: 0 }}
65
- >
66
- <h3 className="font-semibold text-base mb-1">
67
- Experimental — WebGPU required
68
- </h3>
69
- <p className="text-sm text-secondary-foreground">
70
- This is experimental and requires a browser with WebGPU support
71
- and enough VRAM to run the model.
72
- </p>
73
- </div>
74
- </div>
75
-
76
- {/* Initialize button or progress indicator */}
77
- {isInitializing ? (
78
- <div
79
- className="w-full space-y-2 animate-fade-in-up"
80
- style={{ animationDelay: "0.4s", opacity: 0 }}
81
- >
82
- <div className="flex justify-between items-center">
83
- <span className="text-sm font-medium text-muted-foreground">
84
- Loading model...
85
- </span>
86
- <span className="text-sm font-medium text-primary animate-pulse-soft">
87
- {progress}%
88
- </span>
89
- </div>
90
- <div className="w-full bg-muted rounded-full h-2 overflow-hidden">
91
- <div
92
- className="bg-primary h-full transition-all duration-300 ease-out relative overflow-hidden"
93
- style={{ width: `${progress}%` }}
94
- >
95
- <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-[shimmer_2s_infinite]" />
96
- </div>
97
- </div>
98
- <p className="text-xs text-muted-foreground text-center">
99
- This may take a few moments. Please don't close the page.
100
- </p>
101
- </div>
102
- ) : (
103
  <Button
104
  variant="primary"
105
  onClick={onInitialize}
106
  disabled={isInitializing}
107
- className="text-lg! mt-4"
108
  >
109
- {isInitializing
110
- ? "Initializing..."
111
- : `Download TranslateGemma (${formatBytes(Translator.size)})`}
112
  </Button>
113
- )}
114
- </div>
115
- </div>
116
  </div>
117
  );
118
  }
 
2
  import cn from "./utils/classnames.ts";
3
  import { formatBytes } from "./utils/format.ts";
4
  import Translator from "./ai/Translator.ts";
5
+ import Card from "./theme/misc/Card.tsx";
6
+ import Introduction from "./components/Introduction.tsx";
7
+ import ModelLoader from "./components/ModelLoader.tsx";
8
 
9
  interface InitializeProps {
10
  progress: number;
 
20
  className = "",
21
  }: InitializeProps) {
22
  return (
23
+ <div
24
+ className={cn(
25
+ "max-w-2xl w-full mx-auto px-8 animate-fade-in-up",
26
+ className
27
+ )}
28
+ >
29
+ <Card className="flex flex-col items-center gap-6">
30
+ {isInitializing ? (
31
+ <ModelLoader className="w-full" progress={progress} />
32
+ ) : (
33
+ <div className="w-full space-y-8">
34
+ <Introduction />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  <Button
36
  variant="primary"
37
  onClick={onInitialize}
38
  disabled={isInitializing}
39
+ className="text-lg! w-full"
40
  >
41
+ Download TranslateGemma ({formatBytes(Translator.size)})
 
 
42
  </Button>
43
+ </div>
44
+ )}
45
+ </Card>
46
  </div>
47
  );
48
  }
src/components/Introduction.tsx ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cn from "../utils/classnames.ts";
2
+
3
+ export default function Introduction({
4
+ className = "",
5
+ }: {
6
+ className?: string;
7
+ }) {
8
+ return (
9
+ <div className={cn("space-y-4 text-left w-full", className)}>
10
+ <div
11
+ className="animate-fade-in-up"
12
+ style={{ animationDelay: "0.1s", opacity: 0 }}
13
+ >
14
+ <h3 className="font-semibold text-base mb-1">
15
+ About TranslateGemma 4B
16
+ </h3>
17
+ <p className="text-sm text-secondary-foreground">
18
+ TranslateGemma is a family of translation models from Google, built on
19
+ top of Gemma 2B. This 4B parameter model supports translations across
20
+ 100+ languages with state-of-the-art quality.{" "}
21
+ <a
22
+ href="https://blog.google/innovation-and-ai/technology/developers-tools/translategemma/"
23
+ target="_blank"
24
+ rel="noopener noreferrer"
25
+ className="text-primary hover:underline underline-offset-2 transition-all hover:underline-offset-4"
26
+ >
27
+ Learn more
28
+ </a>
29
+ </p>
30
+ </div>
31
+
32
+ <div
33
+ className="animate-fade-in-up"
34
+ style={{ animationDelay: "0.2s", opacity: 0 }}
35
+ >
36
+ <h3 className="font-semibold text-base mb-1">
37
+ Completely private & offline-capable
38
+ </h3>
39
+ <p className="text-sm text-secondary-foreground">
40
+ Everything runs entirely in your browser with 🤗 Transformers.js and
41
+ ONNX Runtime Web — no data is ever sent to a server. Once loaded, it
42
+ works offline.
43
+ </p>
44
+ </div>
45
+
46
+ <div
47
+ className="animate-fade-in-up"
48
+ style={{ animationDelay: "0.3s", opacity: 0 }}
49
+ >
50
+ <h3 className="font-semibold text-base mb-1">
51
+ Experimental — WebGPU required
52
+ </h3>
53
+ <p className="text-sm text-secondary-foreground">
54
+ This is experimental and requires a browser with WebGPU support and
55
+ enough VRAM to run the model.
56
+ </p>
57
+ </div>
58
+ </div>
59
+ );
60
+ }
src/components/ModelLoader.tsx ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cn from "../utils/classnames.ts";
2
+
3
+ export default function ModelLoader({
4
+ progress,
5
+ className = "",
6
+ }: {
7
+ progress: number;
8
+ className?: string;
9
+ }) {
10
+ return (
11
+ <div className={cn("space-y-2", className)}>
12
+ <div className="flex justify-between items-center">
13
+ <span className="text-sm font-medium text-muted-foreground">
14
+ Loading model...
15
+ </span>
16
+ <span className="text-sm font-medium text-primary animate-pulse-soft">
17
+ {progress}%
18
+ </span>
19
+ </div>
20
+ <div className="w-full bg-muted rounded-full h-2 overflow-hidden">
21
+ <div
22
+ className="bg-primary h-full transition-all duration-300 ease-out relative overflow-hidden"
23
+ style={{ width: `${progress}%` }}
24
+ >
25
+ <div className="absolute inset-0 bg-linear-to-r from-transparent via-white/20 to-transparent animate-[shimmer_2s_infinite]" />
26
+ </div>
27
+ </div>
28
+ <p className="text-xs text-muted-foreground text-center">
29
+ This may take a few moments. Please don't close the page.
30
+ </p>
31
+ </div>
32
+ );
33
+ }
src/index.css CHANGED
@@ -130,3 +130,46 @@ body {
130
  .animate-pulse-soft {
131
  animation: pulse-soft 2s ease-in-out infinite;
132
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  .animate-pulse-soft {
131
  animation: pulse-soft 2s ease-in-out infinite;
132
  }
133
+
134
+ /* View Transitions */
135
+ ::view-transition-old(initialize-content) {
136
+ animation-duration: 0.2s;
137
+ animation-timing-function: ease-out;
138
+ animation-name: fade-out;
139
+ mix-blend-mode: normal;
140
+ overflow: hidden;
141
+ }
142
+
143
+ ::view-transition-new(initialize-content) {
144
+ animation-duration: 0.6s;
145
+ animation-timing-function: ease-in;
146
+ animation-name: fade-in-after-scale;
147
+ mix-blend-mode: normal;
148
+ overflow: hidden;
149
+ }
150
+
151
+ ::view-transition-group(initialize-content) {
152
+ animation-duration: 0.4s;
153
+ animation-timing-function: ease-in-out;
154
+ }
155
+
156
+ @keyframes fade-out {
157
+ from {
158
+ opacity: 1;
159
+ }
160
+ to {
161
+ opacity: 0;
162
+ }
163
+ }
164
+
165
+ @keyframes fade-in-after-scale {
166
+ 0% {
167
+ opacity: 0;
168
+ }
169
+ 66% {
170
+ opacity: 0;
171
+ }
172
+ 100% {
173
+ opacity: 1;
174
+ }
175
+ }
src/theme/index.ts CHANGED
@@ -1,3 +1,4 @@
1
  export { default as Button } from "./button/Button";
2
  export { default as Textarea } from "./form/Textarea";
3
  export { default as Loader } from "./misc/Loader";
 
 
1
  export { default as Button } from "./button/Button";
2
  export { default as Textarea } from "./form/Textarea";
3
  export { default as Loader } from "./misc/Loader";
4
+ export { default as Card } from "./misc/Card";
src/theme/misc/Card.tsx ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ReactNode } from "react";
2
+ import cn from "../../utils/classnames.ts";
3
+
4
+ interface CardProps {
5
+ className?: string;
6
+ children?: ReactNode;
7
+ }
8
+
9
+ export default function Card({ className = "", children }: CardProps) {
10
+ return (
11
+ <div
12
+ className={cn(
13
+ "bg-white rounded-lg shadow-md p-8 border border-border",
14
+ className
15
+ )}
16
+ >
17
+ {children}
18
+ </div>
19
+ );
20
+ }