jbilcke-hf HF staff commited on
Commit
ec121fd
1 Parent(s): 15d4bd5

UI improvement + about

Browse files
src/app/interface/about/index.tsx ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Button } from "@/components/ui/button"
2
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
3
+ import { useState } from "react"
4
+
5
+ export function About() {
6
+ const [isOpen, setOpen] = useState(false)
7
+
8
+ return (
9
+ <Dialog open={isOpen} onOpenChange={setOpen}>
10
+ <DialogTrigger asChild>
11
+ <Button variant="outline">
12
+ <span className="hidden md:inline">About this project</span>
13
+ <span className="inline md:hidden">About</span>
14
+ </Button>
15
+ </DialogTrigger>
16
+ <DialogContent className="sm:max-w-[425px]">
17
+ <DialogHeader>
18
+ <DialogTitle>The AI Comic Factory</DialogTitle>
19
+ <DialogDescription className="w-full text-center text-lg font-bold text-stone-800">
20
+ What is the AI Comic Factory?
21
+ </DialogDescription>
22
+ </DialogHeader>
23
+ <div className="grid gap-4 py-4 text-stone-800">
24
+ <p className="">
25
+ The AI Comic Factory is a free and open-source application made to demonstrate the capabilities of AI models.
26
+ </p>
27
+ <p>
28
+ 👉 The language model used to generate the descriptions of each panel is <a className="text-stone-600 underline" href="https://huggingface.co/blog/llama2" target="_blank">Llama-2 70b</a>.
29
+ </p>
30
+ <p>
31
+ 👉 The stable diffusion model used to generate the images is the base <a className="text-stone-600 underline" href="https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0" target="_blank">SDXL 1.0</a>.
32
+ </p>
33
+ <p>
34
+ The code is public and can be deployed at home with some changes in the code. See the <a className="text-stone-600 underline" href="https://huggingface.co/spaces/jbilcke-hf/ai-comic-factory/blob/main/README.md" target="_blank">README</a> for details about the architecture.
35
+ </p>
36
+ </div>
37
+ <DialogFooter>
38
+ <Button type="submit" onClick={() => setOpen(false)}>Got it</Button>
39
+ </DialogFooter>
40
+ </DialogContent>
41
+ </Dialog>
42
+ )
43
+ }
src/app/interface/bottom-bar/index.tsx CHANGED
@@ -4,6 +4,7 @@ import { Button } from "@/components/ui/button"
4
  import { base64ToFile } from "@/lib/base64ToFile"
5
  import { uploadToHuggingFace } from "@/lib/uploadToHuggingFace"
6
  import { cn } from "@/lib/utils"
 
7
 
8
  export function BottomBar() {
9
  const download = useStore(state => state.download)
@@ -59,13 +60,20 @@ ${uploadUrl
59
  return (
60
  <div className={cn(
61
  `print:hidden`,
62
- `fixed bottom-6 right-3`,
63
  `flex flex-row`,
64
- `animation-all duration-300 ease-in-out`,
65
- isGeneratingStory ? `scale-0 opacity-0` : ``,
66
- `space-x-3`,
67
- `scale-[0.9]`
68
  )}>
 
 
 
 
 
 
 
 
 
 
69
  {/*
70
  <div>
71
  <Button
@@ -75,32 +83,48 @@ ${uploadUrl
75
  Upscale
76
  </Button>
77
  </div>
78
- */}
79
- <div>
80
- <Button
81
- onClick={handlePrint}
82
- disabled={!prompt?.length}
83
- >
84
- Print
85
- </Button>
86
- </div>
87
- <div>
88
- <Button
89
- onClick={download}
90
- disabled={!prompt?.length}
91
- >{
92
- remainingImages ? `${allStatus.length - remainingImages}/4 panels ⌛` : `Save`
93
- }</Button>
94
- </div>
95
- <div>
96
- <Button
97
- onClick={handleShare}
98
- disabled={!prompt?.length}
99
- className="space-x-2"
100
- >
101
- <span className="scale-105"><HuggingClap /></span>
102
- <span>Share to community</span>
103
- </Button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  </div>
105
  </div>
106
  )
 
4
  import { base64ToFile } from "@/lib/base64ToFile"
5
  import { uploadToHuggingFace } from "@/lib/uploadToHuggingFace"
6
  import { cn } from "@/lib/utils"
7
+ import { About } from "../about"
8
 
9
  export function BottomBar() {
10
  const download = useStore(state => state.download)
 
60
  return (
61
  <div className={cn(
62
  `print:hidden`,
63
+ `fixed bottom-2 md:bottom-4 left-2 right-0 md:left-3 md:right-1`,
64
  `flex flex-row`,
65
+ `justify-between`
 
 
 
66
  )}>
67
+ <div className={cn(
68
+ `flex flex-row`,
69
+ `items-end`,
70
+ `animation-all duration-300 ease-in-out`,
71
+ isGeneratingStory ? `scale-0 opacity-0` : ``,
72
+ `space-x-3`,
73
+ `scale-[0.9]`
74
+ )}>
75
+ <About />
76
+ </div>
77
  {/*
78
  <div>
79
  <Button
 
83
  Upscale
84
  </Button>
85
  </div>
86
+ */}
87
+ <div className={cn(
88
+ `flex flex-row`,
89
+ `animation-all duration-300 ease-in-out`,
90
+ isGeneratingStory ? `scale-0 opacity-0` : ``,
91
+ `space-x-3`,
92
+ `scale-[0.9]`
93
+ )}>
94
+ <div>
95
+ <Button
96
+ onClick={handlePrint}
97
+ disabled={!prompt?.length}
98
+ >
99
+ Print
100
+ </Button>
101
+ </div>
102
+ <div>
103
+ <Button
104
+ onClick={download}
105
+ disabled={!prompt?.length}
106
+ >
107
+ <span className="hidden md:inline">{
108
+ remainingImages ? `${allStatus.length - remainingImages}/4 panels ⌛` : `Save`
109
+ }</span>
110
+ <span className="inline md:hidden">{
111
+ remainingImages ? `${allStatus.length - remainingImages}/4 ⌛` : `Save`
112
+ }</span>
113
+ </Button>
114
+ </div>
115
+ <div>
116
+ <Button
117
+ onClick={handleShare}
118
+ disabled={!prompt?.length}
119
+ className="space-x-2"
120
+ >
121
+ <div className="scale-105"><HuggingClap /></div>
122
+ <div>
123
+ <span className="hidden md:inline">Share to community</span>
124
+ <span className="inline md:hidden">Share</span>
125
+ </div>
126
+ </Button>
127
+ </div>
128
  </div>
129
  </div>
130
  )
src/app/interface/panel/index.tsx CHANGED
@@ -231,7 +231,7 @@ export function Panel({
231
  )
232
  }
233
 
234
-
235
  return (
236
  <div className={cn(
237
  frameClassName,
@@ -251,13 +251,29 @@ export function Panel({
251
  `print:border-b-[1.5px]`,
252
  showCaptions ? `block` : `hidden`,
253
  `truncate`,
254
- `max-h-32`,
255
- `p-2`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  )}
257
- style={{
258
- fontSize: zoomLevel * 0.2
259
- }}
260
- >{caption}</div>
261
  {rendered.assetUrl &&
262
  <img
263
  ref={ref}
 
231
  )
232
  }
233
 
234
+ console.log("eoomLevel:", zoomLevel)
235
  return (
236
  <div className={cn(
237
  frameClassName,
 
251
  `print:border-b-[1.5px]`,
252
  showCaptions ? `block` : `hidden`,
253
  `truncate`,
254
+
255
+ zoomLevel > 200 ? `p-4 md:p-8` :
256
+ zoomLevel > 180 ? `p-[14px] md:p-8` :
257
+ zoomLevel > 160 ? `p-[12px] md:p-[28px]` :
258
+ zoomLevel > 140 ? `p-[10px] md:p-[26px]` :
259
+ zoomLevel > 120 ? `p-2 md:p-6` :
260
+ zoomLevel > 100 ? `p-1.5 md:p-[20px]` :
261
+ zoomLevel > 90 ? `p-1.5 md:p-4` :
262
+ zoomLevel > 40 ? `p-1 md:p-2` :
263
+ `p-0.5 md:p-2`,
264
+
265
+ zoomLevel > 220 ? `text-xl md:text-4xl` :
266
+ zoomLevel > 200 ? `text-lg md:text-3xl` :
267
+ zoomLevel > 180 ? `text-md md:text-2xl` :
268
+ zoomLevel > 140 ? `text-2xs md:text-2xl` :
269
+ zoomLevel > 120 ? `text-3xs md:text-xl` :
270
+ zoomLevel > 100 ? `text-4xs md:text-lg` :
271
+ zoomLevel > 90 ? `text-5xs md:text-sm` :
272
+ zoomLevel > 40 ? `hidden md:block md:text-xs` :
273
+ `hidden md:block md:text-2xs`,
274
  )}
275
+ >{caption || "Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, "}
276
+ </div>
 
 
277
  {rendered.assetUrl &&
278
  <img
279
  ref={ref}
src/app/interface/top-menu/index.tsx CHANGED
@@ -89,13 +89,14 @@ export function TopMenu() {
89
  `bg-stone-900/70 dark:bg-stone-900/70 text-gray-50 dark:text-gray-50`,
90
  `space-y-2 md:space-y-0 md:space-x-3 lg:space-x-6`
91
  )}>
92
- <div className="flex flex-row space-x-6 md:space-x-3">
93
- <div className={cn(
94
  `transition-all duration-200 ease-in-out`,
95
- `flex flex-row items-center justify-start space-x-3 font-mono w-1/2 md:w-auto`
 
96
  )}>
97
 
98
- {/* <Label className="flex text-xs md:text-sm md:w-24">Style:</Label> */}
99
 
100
  <Select
101
  defaultValue={defaultPreset}
@@ -103,7 +104,7 @@ export function TopMenu() {
103
  disabled={isBusy}
104
  >
105
  <SelectTrigger className="flex-grow">
106
- <SelectValue className="text-xs md:text-sm" placeholder="Style" />
107
  </SelectTrigger>
108
  <SelectContent>
109
  {nonRandomPresets.map(key =>
@@ -114,10 +115,11 @@ export function TopMenu() {
114
  </div>
115
  <div className={cn(
116
  `transition-all duration-200 ease-in-out`,
117
- `flex flex-row items-center justify-start space-x-3 font-mono w-1/2 md:w-auto`
 
118
  )}>
119
 
120
- {/* <Label className="flex text-xs md:text-sm md:w-24">Style:</Label> */}
121
 
122
  <Select
123
  defaultValue={defaultLayout}
@@ -125,7 +127,7 @@ export function TopMenu() {
125
  disabled={isBusy}
126
  >
127
  <SelectTrigger className="flex-grow">
128
- <SelectValue className="text-xs md:text-sm" placeholder="Layout" />
129
  </SelectTrigger>
130
  <SelectContent>
131
  {nonRandomLayouts.map(key =>
@@ -150,19 +152,29 @@ export function TopMenu() {
150
  </SelectContent>
151
  </Select>
152
  </div>
 
 
 
 
 
 
 
 
 
 
153
  {/*
154
  <div className={cn(
155
  `transition-all duration-200 ease-in-out`,
156
  `flex flex-row items-center space-x-3 font-mono w-1/2 md:w-auto md:hidden`
157
  )}>
158
- <Label className="flex text-xs md:text-sm md:w-24">Font:</Label>
159
  <Select
160
  defaultValue={fontList.includes(preset.font) ? preset.font : "cartoonist"}
161
  onValueChange={(value) => { setFont(value as FontName) }}
162
  disabled={atLeastOnePanelIsBusy}
163
  >
164
  <SelectTrigger className="flex-grow">
165
- <SelectValue className="text-xs md:text-sm" placeholder="Type" />
166
  </SelectTrigger>
167
  <SelectContent>
168
  {Object.keys(fonts)
@@ -180,11 +192,12 @@ export function TopMenu() {
180
  </div>
181
  <div className={cn(
182
  `transition-all duration-200 ease-in-out`,
183
- `flex flex-row flex-grow items-center space-x-3 font-mono w-full md:w-auto`
184
  )}>
 
185
  <Input
186
  placeholder="Story"
187
- className="w-full bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800"
188
  // disabled={atLeastOnePanelIsBusy}
189
  onChange={(e) => {
190
  setDraftPrompt(e.target.value)
@@ -197,20 +210,18 @@ export function TopMenu() {
197
  value={draftPrompt}
198
  />
199
  <Button
 
 
 
 
200
  onClick={() => {
201
  handleSubmit()
202
  }}
203
  disabled={!draftPrompt?.trim().length || isBusy}
204
  >
205
- Generate
206
  </Button>
207
- <Switch
208
- checked={showCaptions}
209
- onCheckedChange={setShowCaptions}
210
- />
211
- <Label>
212
- Caption
213
- </Label>
214
  </div>
215
  {/*
216
  Let's add this feature later, because right now people
@@ -219,7 +230,7 @@ export function TopMenu() {
219
  `transition-all duration-200 ease-in-out`,
220
  `hidden md:flex flex-row items-center space-x-3 font-mono w-full md:w-auto`
221
  )}>
222
- <Label className="flex text-xs md:text-sm w-24">Font:</Label>
223
  <Select
224
  defaultValue={fontList.includes(preset.font) ? preset.font : "actionman"}
225
  onValueChange={(value) => { setFont(value as FontName) }}
@@ -227,7 +238,7 @@ export function TopMenu() {
227
  disabled={true}
228
  >
229
  <SelectTrigger className="flex-grow">
230
- <SelectValue className="text-xs md:text-sm" placeholder="Type" />
231
  </SelectTrigger>
232
  <SelectContent>
233
  {Object.keys(fonts)
 
89
  `bg-stone-900/70 dark:bg-stone-900/70 text-gray-50 dark:text-gray-50`,
90
  `space-y-2 md:space-y-0 md:space-x-3 lg:space-x-6`
91
  )}>
92
+ <div className="flex flex-row space-x-2 md:space-x-3 w-full md:w-auto">
93
+ <div className={cn(
94
  `transition-all duration-200 ease-in-out`,
95
+ `flex flex-row items-center justify-start space-x-3 font-mono`,
96
+ `flex-grow`
97
  )}>
98
 
99
+ {/* <Label className="flex text-2xs md:text-sm md:w-24">Style:</Label> */}
100
 
101
  <Select
102
  defaultValue={defaultPreset}
 
104
  disabled={isBusy}
105
  >
106
  <SelectTrigger className="flex-grow">
107
+ <SelectValue className="text-2xs md:text-sm" placeholder="Style" />
108
  </SelectTrigger>
109
  <SelectContent>
110
  {nonRandomPresets.map(key =>
 
115
  </div>
116
  <div className={cn(
117
  `transition-all duration-200 ease-in-out`,
118
+ `flex flex-row items-center justify-start space-x-3 font-mono`,
119
+ `w-40`
120
  )}>
121
 
122
+ {/* <Label className="flex text-2xs md:text-sm md:w-24">Style:</Label> */}
123
 
124
  <Select
125
  defaultValue={defaultLayout}
 
127
  disabled={isBusy}
128
  >
129
  <SelectTrigger className="flex-grow">
130
+ <SelectValue className="text-2xs md:text-sm" placeholder="Layout" />
131
  </SelectTrigger>
132
  <SelectContent>
133
  {nonRandomLayouts.map(key =>
 
152
  </SelectContent>
153
  </Select>
154
  </div>
155
+ <div className="flex flex-row items-center space-x-3">
156
+ <Switch
157
+ checked={showCaptions}
158
+ onCheckedChange={setShowCaptions}
159
+ />
160
+ <Label>
161
+ <span className="hidden md:inline">Caption</span>
162
+ <span className="inline md:hidden">Cap.</span>
163
+ </Label>
164
+ </div>
165
  {/*
166
  <div className={cn(
167
  `transition-all duration-200 ease-in-out`,
168
  `flex flex-row items-center space-x-3 font-mono w-1/2 md:w-auto md:hidden`
169
  )}>
170
+ <Label className="flex text-2xs md:text-sm md:w-24">Font:</Label>
171
  <Select
172
  defaultValue={fontList.includes(preset.font) ? preset.font : "cartoonist"}
173
  onValueChange={(value) => { setFont(value as FontName) }}
174
  disabled={atLeastOnePanelIsBusy}
175
  >
176
  <SelectTrigger className="flex-grow">
177
+ <SelectValue className="text-2xs md:text-sm" placeholder="Type" />
178
  </SelectTrigger>
179
  <SelectContent>
180
  {Object.keys(fonts)
 
192
  </div>
193
  <div className={cn(
194
  `transition-all duration-200 ease-in-out`,
195
+ `flex flex-grow flex-col space-y-2 md:space-y-0 md:flex-row items-center md:space-x-3 font-mono w-full md:w-auto`
196
  )}>
197
+ <div className="flex flex-row flex-grow w-full">
198
  <Input
199
  placeholder="Story"
200
+ className="w-full bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800 rounded-r-none"
201
  // disabled={atLeastOnePanelIsBusy}
202
  onChange={(e) => {
203
  setDraftPrompt(e.target.value)
 
210
  value={draftPrompt}
211
  />
212
  <Button
213
+ className={cn(
214
+ `rounded-l-none cursor-pointer`,
215
+ `transition-all duration-200 ease-in-out`,
216
+ )}
217
  onClick={() => {
218
  handleSubmit()
219
  }}
220
  disabled={!draftPrompt?.trim().length || isBusy}
221
  >
222
+ Go
223
  </Button>
224
+ </div>
 
 
 
 
 
 
225
  </div>
226
  {/*
227
  Let's add this feature later, because right now people
 
230
  `transition-all duration-200 ease-in-out`,
231
  `hidden md:flex flex-row items-center space-x-3 font-mono w-full md:w-auto`
232
  )}>
233
+ <Label className="flex text-2xs md:text-sm w-24">Font:</Label>
234
  <Select
235
  defaultValue={fontList.includes(preset.font) ? preset.font : "actionman"}
236
  onValueChange={(value) => { setFont(value as FontName) }}
 
238
  disabled={true}
239
  >
240
  <SelectTrigger className="flex-grow">
241
+ <SelectValue className="text-2xs md:text-sm" placeholder="Type" />
242
  </SelectTrigger>
243
  <SelectContent>
244
  {Object.keys(fonts)
src/app/interface/zoom/index.tsx CHANGED
@@ -11,11 +11,11 @@ export function Zoom() {
11
  <div className={cn(
12
  `print:hidden`,
13
  // `fixed flex items-center justify-center bottom-8 top-32 right-8 z-10 h-screen`,
14
- `fixed flex flex-col items-center bottom-8 top-32 md:top-20 right-6 z-10`,
15
  `animation-all duration-300 ease-in-out`,
16
  isGeneratingStory ? `scale-0 opacity-0` : ``,
17
  )}>
18
- <div className="font-mono text-xs pb-1 text-stone-700 bg-stone-50 p-1 rounded-sm">
19
  Zoom
20
  </div>
21
  <div className="w-2">
@@ -26,7 +26,7 @@ export function Zoom() {
26
  step={1}
27
  onValueChange={value => setZoomLevel(value[0] || 10)}
28
  value={[zoomLevel]}
29
- className="h-48"
30
  orientation="vertical"
31
  />
32
  </div>
 
11
  <div className={cn(
12
  `print:hidden`,
13
  // `fixed flex items-center justify-center bottom-8 top-32 right-8 z-10 h-screen`,
14
+ `fixed flex flex-col items-center bottom-8 top-28 right-2 md:top-20 md:right-6 z-10`,
15
  `animation-all duration-300 ease-in-out`,
16
  isGeneratingStory ? `scale-0 opacity-0` : ``,
17
  )}>
18
+ <div className="font-mono font-bold text-xs pb-2 text-stone-600 bg-stone-50 p-1 rounded-sm">
19
  Zoom
20
  </div>
21
  <div className="w-2">
 
26
  step={1}
27
  onValueChange={value => setZoomLevel(value[0] || 10)}
28
  value={[zoomLevel]}
29
+ className="h-64 md:h-80"
30
  orientation="vertical"
31
  />
32
  </div>
src/app/main.tsx CHANGED
@@ -80,9 +80,9 @@ export default function Main() {
80
  <div>
81
  <TopMenu />
82
  <div className={cn(
83
- `flex items-start w-screen h-screen pt-[120px] md:pt-[72px] overflow-y-scroll`,
84
  `transition-all duration-200 ease-in-out`,
85
- zoomLevel > 105 ? `px-0` : `pl-2 pr-16 md:pl-16 md:pr-16`,
86
  `print:pt-0 print:px-0 print:pl-0 print:pr-0`,
87
  fonts.actionman.className
88
  )}>
 
80
  <div>
81
  <TopMenu />
82
  <div className={cn(
83
+ `flex items-start w-screen h-screen pt-24 md:pt-[72px] overflow-y-scroll`,
84
  `transition-all duration-200 ease-in-out`,
85
+ zoomLevel > 105 ? `px-0` : `pl-1 pr-8 md:pl-16 md:pr-16`,
86
  `print:pt-0 print:px-0 print:pl-0 print:pr-0`,
87
  fonts.actionman.className
88
  )}>