arpit13 commited on
Commit
024c6a7
·
verified ·
1 Parent(s): f550c4b

Delete ui_components.py

Browse files
Files changed (1) hide show
  1. ui_components.py +0 -1135
ui_components.py DELETED
@@ -1,1135 +0,0 @@
1
- # AI Image Creator: Enhanced UI and UX
2
- # Part 2: Enhanced UI Components and Styling
3
-
4
- # CSS for styling the interface - Comprehensive styling for modern UI
5
- css = """
6
- /* Main theme colors with CSS variables for better customization */
7
- :root {
8
- --primary-color: #4F46E5;
9
- --primary-hover: #4338CA;
10
- --secondary-color: #7C3AED;
11
- --secondary-hover: #6D28D9;
12
- --background-color: #F8FAFC;
13
- --card-color: #FFFFFF;
14
- --text-color: #1E293B;
15
- --text-muted: #64748B;
16
- --accent-color: #3B82F6;
17
- --success-color: #10B981;
18
- --success-hover: #059669;
19
- --warning-color: #F59E0B;
20
- --error-color: #EF4444;
21
- --error-hover: #DC2626;
22
- --border-color: #E2E8F0;
23
- --border-hover: #CBD5E1;
24
- --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
25
- --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
26
- --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
27
- --radius-sm: 0.375rem;
28
- --radius: 0.5rem;
29
- --radius-lg: 0.75rem;
30
- --radius-xl: 1rem;
31
- --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
32
- }
33
-
34
- /* Global styles and resets */
35
- body, html {
36
- font-family: var(--font-sans);
37
- color: var(--text-color);
38
- background-color: var(--background-color);
39
- line-height: 1.5;
40
- margin: 0;
41
- padding: 0;
42
- }
43
-
44
- /* Container with responsive padding */
45
- .container {
46
- max-width: 1400px;
47
- margin: 0 auto;
48
- padding: 1rem;
49
- }
50
-
51
- @media (max-width: 640px) {
52
- .container {
53
- padding: 0.5rem;
54
- }
55
- }
56
-
57
- /* Card styling with elevation and hover effects */
58
- .gr-panel {
59
- border-radius: var(--radius) !important;
60
- border: 1px solid var(--border-color) !important;
61
- box-shadow: var(--shadow) !important;
62
- overflow: hidden;
63
- transition: transform 0.2s, box-shadow 0.2s;
64
- background-color: var(--card-color) !important;
65
- }
66
-
67
- .gr-panel:hover {
68
- transform: translateY(-2px);
69
- box-shadow: var(--shadow-lg) !important;
70
- }
71
-
72
- /* Button styling with gradient and hover states */
73
- button.primary {
74
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)) !important;
75
- color: white !important;
76
- border: none !important;
77
- border-radius: var(--radius) !important;
78
- font-weight: 600 !important;
79
- letter-spacing: 0.025em !important;
80
- padding: 0.75rem 1.5rem !important;
81
- transition: all 0.3s ease !important;
82
- box-shadow: var(--shadow-sm) !important;
83
- outline: none !important;
84
- text-transform: none !important;
85
- }
86
-
87
- button.primary:hover {
88
- transform: translateY(-1px);
89
- box-shadow: var(--shadow) !important;
90
- opacity: 0.9;
91
- }
92
-
93
- button.primary:active {
94
- transform: translateY(0);
95
- opacity: 0.8;
96
- }
97
-
98
- button.primary[disabled], button.primary[disabled]:hover {
99
- opacity: 0.5;
100
- cursor: not-allowed;
101
- transform: none;
102
- }
103
-
104
- /* Secondary button styling */
105
- button.secondary {
106
- background-color: transparent !important;
107
- color: var(--primary-color) !important;
108
- border: 1px solid var(--primary-color) !important;
109
- border-radius: var(--radius) !important;
110
- font-weight: 500 !important;
111
- padding: 0.625rem 1.25rem !important;
112
- transition: all 0.2s ease !important;
113
- text-transform: none !important;
114
- }
115
-
116
- button.secondary:hover {
117
- background-color: rgba(79, 70, 229, 0.05) !important;
118
- border-color: var(--primary-hover) !important;
119
- }
120
-
121
- /* Style for the example buttons */
122
- .example-button {
123
- font-size: 0.875rem !important;
124
- padding: 0.5rem 0.75rem !important;
125
- background-color: transparent !important;
126
- border: 1px solid var(--border-color) !important;
127
- border-radius: var(--radius) !important;
128
- transition: all 0.2s !important;
129
- text-align: left !important;
130
- justify-content: flex-start !important;
131
- height: auto !important;
132
- text-overflow: ellipsis;
133
- overflow: hidden;
134
- white-space: nowrap;
135
- width: 100%;
136
- color: var(--text-color) !important;
137
- }
138
-
139
- .example-button:hover {
140
- background-color: rgba(79, 70, 229, 0.05) !important;
141
- border-color: var(--primary-color) !important;
142
- transform: translateY(-1px);
143
- }
144
-
145
- /* Form controls styling */
146
- .gr-input, .gr-textarea, .gr-dropdown {
147
- border-radius: var(--radius) !important;
148
- border: 1px solid var(--border-color) !important;
149
- transition: border-color 0.2s, box-shadow 0.2s !important;
150
- font-family: var(--font-sans) !important;
151
- color: var(--text-color) !important;
152
- }
153
-
154
- .gr-input:focus, .gr-textarea:focus, .gr-dropdown:focus-within {
155
- border-color: var(--primary-color) !important;
156
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2) !important;
157
- outline: none !important;
158
- }
159
-
160
- .gr-form {
161
- gap: 1rem !important;
162
- }
163
-
164
- .gr-input-label, .gr-dropdown-label, .gr-textarea-label, .gr-checkbox-label, .gr-radio-label {
165
- font-size: 0.875rem !important;
166
- font-weight: 500 !important;
167
- color: var(--text-color) !important;
168
- margin-bottom: 0.25rem !important;
169
- }
170
-
171
- /* Input placeholder styling */
172
- .gr-input::placeholder, .gr-textarea::placeholder {
173
- color: var(--text-muted) !important;
174
- opacity: 0.7;
175
- }
176
-
177
- /* Input and textarea styling */
178
- textarea, input[type="text"] {
179
- border-radius: var(--radius) !important;
180
- border: 1px solid var(--border-color) !important;
181
- padding: 0.75rem 1rem !important;
182
- transition: border-color 0.2s, box-shadow 0.2s !important;
183
- font-family: var(--font-sans) !important;
184
- }
185
-
186
- textarea:focus, input[type="text"]:focus {
187
- border-color: var(--primary-color) !important;
188
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2) !important;
189
- outline: none !important;
190
- }
191
-
192
- /* Dropdown styling */
193
- .gr-dropdown {
194
- border-radius: var(--radius) !important;
195
- border: 1px solid var(--border-color) !important;
196
- background-color: var(--card-color) !important;
197
- }
198
-
199
- .gr-dropdown > div {
200
- border-radius: var(--radius) !important;
201
- min-height: 38px !important;
202
- }
203
-
204
- .gr-dropdown > div > span {
205
- font-size: 0.9375rem !important;
206
- }
207
-
208
- /* Dropdown menu styling */
209
- .gr-dropdown ul {
210
- background-color: var(--card-color) !important;
211
- border: 1px solid var(--border-color) !important;
212
- border-radius: var(--radius) !important;
213
- box-shadow: var(--shadow) !important;
214
- }
215
-
216
- .gr-dropdown ul li {
217
- padding: 0.5rem 0.75rem !important;
218
- }
219
-
220
- .gr-dropdown ul li:hover {
221
- background-color: rgba(79, 70, 229, 0.05) !important;
222
- }
223
-
224
- /* Custom header with gradient background */
225
- .app-header {
226
- text-align: center;
227
- padding: 1.75rem 1rem;
228
- margin-bottom: 2rem;
229
- background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(124, 58, 237, 0.08));
230
- border-radius: var(--radius-lg);
231
- border-bottom: 3px solid var(--primary-color);
232
- position: relative;
233
- overflow: hidden;
234
- }
235
-
236
- .app-header::before {
237
- content: '';
238
- position: absolute;
239
- top: -50px;
240
- left: -50px;
241
- right: -50px;
242
- height: 100px;
243
- background: linear-gradient(135deg, rgba(79, 70, 229, 0.2), rgba(124, 58, 237, 0.2));
244
- transform: rotate(-5deg);
245
- z-index: 0;
246
- }
247
-
248
- .app-header h1 {
249
- font-size: 2.5rem !important;
250
- font-weight: 800 !important;
251
- background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
252
- -webkit-background-clip: text;
253
- -webkit-text-fill-color: transparent;
254
- margin-bottom: 0.5rem !important;
255
- position: relative;
256
- z-index: 1;
257
- }
258
-
259
- .app-header p {
260
- font-size: 1.25rem !important;
261
- color: var(--text-color);
262
- opacity: 0.8;
263
- max-width: 40rem;
264
- margin: 0 auto;
265
- position: relative;
266
- z-index: 1;
267
- }
268
-
269
- /* Responsive header */
270
- @media (max-width: 640px) {
271
- .app-header h1 {
272
- font-size: 2rem !important;
273
- }
274
-
275
- .app-header p {
276
- font-size: 1rem !important;
277
- }
278
- }
279
-
280
- /* Examples gallery with grid layout */
281
- .example-gallery {
282
- display: grid;
283
- grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
284
- gap: 1rem;
285
- margin: 1rem 0;
286
- }
287
-
288
- .example-item {
289
- border-radius: var(--radius);
290
- overflow: hidden;
291
- cursor: pointer;
292
- border: 2px solid transparent;
293
- transition: all 0.2s;
294
- display: flex;
295
- flex-direction: column;
296
- background-color: var(--card-color);
297
- }
298
-
299
- .example-item:hover {
300
- transform: translateY(-2px);
301
- border-color: var(--accent-color);
302
- box-shadow: var(--shadow);
303
- }
304
-
305
- .example-item:active {
306
- transform: translateY(0);
307
- }
308
-
309
- .example-item-image {
310
- width: 100%;
311
- aspect-ratio: 1;
312
- background-color: #f0f0f0;
313
- display: flex;
314
- align-items: center;
315
- justify-content: center;
316
- color: var(--text-muted);
317
- font-size: 1.5rem;
318
- border-bottom: 1px solid var(--border-color);
319
- }
320
-
321
- .example-item-caption {
322
- padding: 0.5rem;
323
- font-size: 0.75rem;
324
- line-height: 1.25;
325
- color: var(--text-color);
326
- overflow: hidden;
327
- display: -webkit-box;
328
- -webkit-line-clamp: 2;
329
- -webkit-box-orient: vertical;
330
- }
331
-
332
- /* Loading indicator with animation */
333
- .loading-indicator {
334
- display: flex;
335
- align-items: center;
336
- justify-content: center;
337
- height: 100%;
338
- width: 100%;
339
- position: absolute;
340
- top: 0;
341
- left: 0;
342
- background-color: rgba(255, 255, 255, 0.8);
343
- z-index: 1000;
344
- backdrop-filter: blur(2px);
345
- border-radius: var(--radius);
346
- }
347
-
348
- .spinner {
349
- width: 40px;
350
- height: 40px;
351
- border: 4px solid rgba(79, 70, 229, 0.2);
352
- border-radius: 50%;
353
- border-top-color: var(--primary-color);
354
- animation: spin 1s linear infinite;
355
- }
356
-
357
- @keyframes spin {
358
- to {
359
- transform: rotate(360deg);
360
- }
361
- }
362
-
363
- /* Info cards with subtle styling */
364
- .info-card {
365
- background-color: var(--card-color);
366
- border-radius: var(--radius);
367
- padding: 1rem;
368
- border: 1px solid var(--border-color);
369
- margin-bottom: 1rem;
370
- transition: all 0.2s;
371
- }
372
-
373
- .info-card:hover {
374
- border-color: var(--border-hover);
375
- box-shadow: var(--shadow-sm);
376
- }
377
-
378
- .info-card h3 {
379
- margin-top: 0;
380
- margin-bottom: 0.5rem;
381
- font-size: 1rem;
382
- font-weight: 600;
383
- color: var(--primary-color);
384
- display: flex;
385
- align-items: center;
386
- gap: 0.5rem;
387
- }
388
-
389
- .info-card p {
390
- margin: 0;
391
- font-size: 0.875rem;
392
- color: var(--text-muted);
393
- line-height: 1.5;
394
- }
395
-
396
- /* Model info panel with branded styling */
397
- .model-info {
398
- background-color: rgba(79, 70, 229, 0.05);
399
- border-left: 3px solid var(--primary-color);
400
- padding: 0.75rem 1rem;
401
- border-radius: 0 var(--radius) var(--radius) 0;
402
- margin: 1rem 0;
403
- }
404
-
405
- .model-info h3 {
406
- display: flex;
407
- align-items: center;
408
- gap: 0.5rem;
409
- margin-top: 0;
410
- margin-bottom: 0.5rem;
411
- font-size: 1rem;
412
- font-weight: 600;
413
- color: var(--primary-color);
414
- }
415
-
416
- .model-info p {
417
- margin: 0 0 0.5rem 0;
418
- font-size: 0.875rem;
419
- color: var(--text-color);
420
- }
421
-
422
- .model-info .model-id {
423
- font-size: 0.75rem;
424
- color: var(--text-muted);
425
- font-family: monospace;
426
- background-color: rgba(0, 0, 0, 0.03);
427
- padding: 0.25rem 0.5rem;
428
- border-radius: 4px;
429
- margin-top: 0.5rem;
430
- word-break: break-all;
431
- }
432
-
433
- /* Parameter pills for displaying selections */
434
- .parameter-pill {
435
- display: inline-flex;
436
- align-items: center;
437
- background-color: rgba(79, 70, 229, 0.1);
438
- color: var(--primary-color);
439
- border-radius: 16px;
440
- padding: 0.25rem 0.75rem;
441
- margin-right: 0.5rem;
442
- margin-bottom: 0.5rem;
443
- font-size: 0.75rem;
444
- font-weight: 500;
445
- user-select: none;
446
- }
447
-
448
- .parameter-pill .icon {
449
- margin-right: 0.25rem;
450
- }
451
-
452
- /* Badge for showing model speed/quality */
453
- .badge {
454
- display: inline-flex;
455
- align-items: center;
456
- justify-content: center;
457
- border-radius: 9999px;
458
- padding: 0.125rem 0.5rem;
459
- font-size: 0.75rem;
460
- font-weight: 500;
461
- margin-left: 0.5rem;
462
- }
463
-
464
- .badge-success {
465
- background-color: rgba(16, 185, 129, 0.1);
466
- color: var(--success-color);
467
- }
468
-
469
- .badge-warning {
470
- background-color: rgba(245, 158, 11, 0.1);
471
- color: var(--warning-color);
472
- }
473
-
474
- .badge-error {
475
- background-color: rgba(239, 68, 68, 0.1);
476
- color: var(--error-color);
477
- }
478
-
479
- .badge-info {
480
- background-color: rgba(59, 130, 246, 0.1);
481
- color: var(--accent-color);
482
- }
483
-
484
- /* Enhanced accordion styling */
485
- .gr-accordion {
486
- border: 1px solid var(--border-color) !important;
487
- border-radius: var(--radius) !important;
488
- margin-bottom: 1rem !important;
489
- overflow: hidden;
490
- }
491
-
492
- .gr-accordion > div:first-child {
493
- padding: 0.75rem 1rem !important;
494
- background-color: rgba(0, 0, 0, 0.02) !important;
495
- font-weight: 600 !important;
496
- color: var(--text-color) !important;
497
- font-size: 0.9375rem !important;
498
- }
499
-
500
- .gr-accordion > div:last-child {
501
- padding: 1rem !important;
502
- }
503
-
504
- /* Tooltip styling */
505
- .tooltip {
506
- position: relative;
507
- display: inline-block;
508
- cursor: help;
509
- }
510
-
511
- .tooltip .tooltiptext {
512
- visibility: hidden;
513
- width: 200px;
514
- background-color: var(--text-color);
515
- color: white;
516
- text-align: center;
517
- border-radius: var(--radius-sm);
518
- padding: 0.5rem 0.75rem;
519
- position: absolute;
520
- z-index: 1000;
521
- bottom: 125%;
522
- left: 50%;
523
- transform: translateX(-50%);
524
- opacity: 0;
525
- transition: opacity 0.3s;
526
- font-size: 0.75rem;
527
- box-shadow: var(--shadow);
528
- pointer-events: none;
529
- }
530
-
531
- .tooltip .tooltiptext::after {
532
- content: "";
533
- position: absolute;
534
- top: 100%;
535
- left: 50%;
536
- margin-left: -5px;
537
- border-width: 5px;
538
- border-style: solid;
539
- border-color: var(--text-color) transparent transparent transparent;
540
- }
541
-
542
- .tooltip:hover .tooltiptext {
543
- visibility: visible;
544
- opacity: 1;
545
- }
546
-
547
- /* History item styling */
548
- .history-item {
549
- display: flex;
550
- align-items: center;
551
- padding: 0.75rem;
552
- border-radius: var(--radius);
553
- margin-bottom: 0.75rem;
554
- background-color: var(--card-color);
555
- border: 1px solid var(--border-color);
556
- cursor: pointer;
557
- transition: all 0.2s;
558
- }
559
-
560
- .history-item:hover {
561
- background-color: rgba(79, 70, 229, 0.05);
562
- transform: translateY(-1px);
563
- }
564
-
565
- .history-item-image {
566
- width: 48px;
567
- height: 48px;
568
- border-radius: var(--radius-sm);
569
- object-fit: cover;
570
- margin-right: 0.75rem;
571
- background-color: #f0f0f0;
572
- display: flex;
573
- align-items: center;
574
- justify-content: center;
575
- color: var(--text-muted);
576
- font-size: 1.25rem;
577
- }
578
-
579
- .history-item-content {
580
- flex: 1;
581
- overflow: hidden;
582
- }
583
-
584
- .history-item-title {
585
- margin: 0;
586
- font-size: 0.875rem;
587
- font-weight: 500;
588
- white-space: nowrap;
589
- overflow: hidden;
590
- text-overflow: ellipsis;
591
- color: var(--text-color);
592
- }
593
-
594
- .history-item-subtitle {
595
- margin: 0;
596
- font-size: 0.75rem;
597
- color: var(--text-muted);
598
- margin-top: 0.25rem;
599
- }
600
-
601
- /* Tabs styling */
602
- .tabs {
603
- display: flex;
604
- border-bottom: 1px solid var(--border-color);
605
- margin-bottom: 1rem;
606
- }
607
-
608
- .tab {
609
- padding: 0.75rem 1rem;
610
- cursor: pointer;
611
- border-bottom: 2px solid transparent;
612
- font-weight: 500;
613
- font-size: 0.9375rem;
614
- color: var(--text-muted);
615
- transition: all 0.2s;
616
- }
617
-
618
- .tab:hover {
619
- color: var(--primary-color);
620
- }
621
-
622
- .tab.active {
623
- color: var(--primary-color);
624
- border-bottom-color: var(--primary-color);
625
- }
626
-
627
- /* Progress bar */
628
- .progress-container {
629
- width: 100%;
630
- height: 8px;
631
- background-color: rgba(79, 70, 229, 0.1);
632
- border-radius: 4px;
633
- overflow: hidden;
634
- margin: 0.5rem 0;
635
- }
636
-
637
- .progress-bar {
638
- height: 100%;
639
- background: linear-gradient(to right, var(--primary-color), var(--secondary-color));
640
- width: 0%;
641
- transition: width 0.3s ease;
642
- border-radius: 4px;
643
- }
644
-
645
- /* Image output container */
646
- .image-output-container {
647
- position: relative;
648
- border-radius: var(--radius);
649
- overflow: hidden;
650
- transition: all 0.2s;
651
- background-color: #f5f5f5;
652
- min-height: 300px;
653
- }
654
-
655
- .image-output-container img {
656
- width: 100%;
657
- display: block;
658
- border-radius: var(--radius);
659
- }
660
-
661
- .image-placeholder {
662
- position: absolute;
663
- top: 0;
664
- left: 0;
665
- width: 100%;
666
- height: 100%;
667
- display: flex;
668
- flex-direction: column;
669
- align-items: center;
670
- justify-content: center;
671
- color: var(--text-muted);
672
- font-size: 1rem;
673
- text-align: center;
674
- padding: 1rem;
675
- }
676
-
677
- .image-placeholder .icon {
678
- font-size: 3rem;
679
- margin-bottom: 1rem;
680
- opacity: 0.6;
681
- }
682
-
683
- /* Image controls overlay */
684
- .image-controls {
685
- position: absolute;
686
- bottom: 0;
687
- left: 0;
688
- right: 0;
689
- padding: 0.75rem;
690
- background: linear-gradient(to top, rgba(0,0,0,0.7), rgba(0,0,0,0));
691
- display: flex;
692
- justify-content: flex-end;
693
- opacity: 0;
694
- transition: opacity 0.2s;
695
- }
696
-
697
- .image-output-container:hover .image-controls {
698
- opacity: 1;
699
- }
700
-
701
- .image-control-button {
702
- background-color: rgba(255, 255, 255, 0.9);
703
- border: none;
704
- border-radius: 50%;
705
- width: 36px;
706
- height: 36px;
707
- display: flex;
708
- align-items: center;
709
- justify-content: center;
710
- cursor: pointer;
711
- margin-left: 0.5rem;
712
- color: var(--text-color);
713
- transition: all 0.2s;
714
- }
715
-
716
- .image-control-button:hover {
717
- background-color: white;
718
- transform: translateY(-2px);
719
- box-shadow: var(--shadow);
720
- }
721
-
722
- /* Character counter */
723
- .character-counter {
724
- text-align: right;
725
- font-size: 0.75rem;
726
- color: var(--text-muted);
727
- margin-top: 0.25rem;
728
- transition: color 0.2s;
729
- }
730
-
731
- .character-counter.warning {
732
- color: var(--warning-color);
733
- }
734
-
735
- .character-counter.error {
736
- color: var(--error-color);
737
- }
738
-
739
- /* Status message */
740
- .status-message {
741
- padding: 0.75rem 1rem;
742
- border-radius: var(--radius);
743
- margin: 1rem 0;
744
- font-size: 0.875rem;
745
- display: flex;
746
- align-items: center;
747
- }
748
-
749
- .status-message .icon {
750
- margin-right: 0.75rem;
751
- font-size: 1.25rem;
752
- }
753
-
754
- .status-success {
755
- background-color: rgba(16, 185, 129, 0.1);
756
- color: var(--success-color);
757
- border-left: 3px solid var(--success-color);
758
- }
759
-
760
- .status-error {
761
- background-color: rgba(239, 68, 68, 0.1);
762
- color: var(--error-color);
763
- border-left: 3px solid var(--error-color);
764
- }
765
-
766
- .status-warning {
767
- background-color: rgba(245, 158, 11, 0.1);
768
- color: var(--warning-color);
769
- border-left: 3px solid var(--warning-color);
770
- }
771
-
772
- .status-info {
773
- background-color: rgba(59, 130, 246, 0.1);
774
- color: var(--accent-color);
775
- border-left: 3px solid var(--accent-color);
776
- }
777
-
778
- /* Responsive adjustments */
779
- @media (max-width: 768px) {
780
- .example-gallery {
781
- grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
782
- }
783
-
784
- .gr-panel {
785
- padding: 0.75rem !important;
786
- }
787
-
788
- .gr-accordion > div:first-child {
789
- padding: 0.625rem 0.75rem !important;
790
- }
791
-
792
- .gr-accordion > div:last-child {
793
- padding: 0.75rem !important;
794
- }
795
-
796
- button.primary {
797
- padding: 0.625rem 1.25rem !important;
798
- }
799
- }
800
- """
801
-
802
- # =============== ENHANCED UI COMPONENTS ===============
803
-
804
- # Function to create and show application UI
805
- def create_ui():
806
- with gr.Blocks(title="AI Image Creator", css=css) as interface:
807
- # Custom header with branding
808
- with gr.Row(elem_classes="app-header"):
809
- with gr.Column():
810
- gr.HTML("""
811
- <h1>🎨 AI Image Creator</h1>
812
- <p>Transform your ideas into stunning images with AI-powered text-to-image generation</p>
813
- """)
814
-
815
- # Main content area
816
- with gr.Row(equal_height=False):
817
- # Left column - Input controls
818
- with gr.Column(scale=1, min_width=380):
819
- # Description input with character counter
820
- with gr.Group(elem_classes="input-group"):
821
- description_input = gr.Textbox(
822
- label="Describe what you want to see",
823
- placeholder="Be detailed and specific about colors, composition, lighting, and subject...",
824
- lines=4,
825
- max_lines=8,
826
- elem_id="description-input"
827
- )
828
-
829
- # Character counter with dynamic updates
830
- char_counter = gr.HTML(
831
- value="<div class='character-counter'>0 characters</div>",
832
- elem_classes="char-counter-container"
833
- )
834
-
835
- # Examples gallery with clear visual structure
836
- with gr.Group(elem_classes="examples-group"):
837
- gr.HTML("<h3 style='margin-top: 0; font-size: 1rem; margin-bottom: 0.75rem;'>🌟 Try an example:</h3>")
838
-
839
- # Gallery of examples
840
- with gr.Row(elem_classes="example-gallery"):
841
- for i, example in enumerate(EXAMPLE_PROMPTS):
842
- with gr.Column(elem_classes="example-item"):
843
- # Example card with visual element and caption
844
- example_card = gr.Button(
845
- example["thumbnail_desc"],
846
- elem_classes="example-button"
847
- )
848
-
849
- # Event handler for example selection
850
- example_card.click(
851
- fn=lambda idx=i: load_example(idx),
852
- outputs=[description_input, creation_type, art_style, mood_dropdown]
853
- )
854
-
855
- # Creation settings with enhanced dropdowns
856
- with gr.Group(elem_classes="settings-group"):
857
- gr.HTML("<h3 style='margin-top: 0; font-size: 1rem; margin-bottom: 0.75rem;'>🛠️ Image Settings</h3>")
858
-
859
- # Creation Type and Art Style in one row
860
- with gr.Row():
861
- # Creation type dropdown with icons
862
- creation_type = gr.Dropdown(
863
- choices=format_dropdown_choices(CREATION_TYPES),
864
- value=f"{CREATION_TYPES['Digital Art']['icon']} Digital Art",
865
- label="Creation Type",
866
- elem_classes="enhanced-dropdown"
867
- )
868
-
869
- # Art style dropdown with icons
870
- art_style = gr.Dropdown(
871
- choices=format_dropdown_choices(ART_STYLES),
872
- value=f"{ART_STYLES['Photorealistic']['icon']} Photorealistic",
873
- label="Art Style",
874
- elem_classes="enhanced-dropdown"
875
- )
876
-
877
- # Mood and Model in one row
878
- with gr.Row():
879
- # Mood dropdown with icons
880
- mood_dropdown = gr.Dropdown(
881
- choices=format_dropdown_choices(MOODS),
882
- value=f"{MOODS['Peaceful']['icon']} Peaceful",
883
- label="Mood",
884
- elem_classes="enhanced-dropdown"
885
- )
886
-
887
- # Model selector with display names
888
- formatted_models = [f"{info['icon']} {info['display_name']}" for model_key, info in IMAGE_MODELS.items()]
889
- model_selector = gr.Dropdown(
890
- choices=formatted_models,
891
- value=f"{IMAGE_MODELS['stabilityai/stable-diffusion-xl-base-1.0']['icon']} {IMAGE_MODELS['stabilityai/stable-diffusion-xl-base-1.0']['display_name']}",
892
- label="Model",
893
- elem_classes="enhanced-dropdown"
894
- )
895
-
896
- # Information panels for selected options
897
- with gr.Group(elem_classes="info-panels"):
898
- # Creation type info
899
- creation_info = gr.HTML(value="", elem_classes="option-info")
900
-
901
- # Art style info
902
- art_info = gr.HTML(value="", elem_classes="option-info")
903
-
904
- # Model info panel
905
- model_info = gr.HTML(value="", elem_classes="option-info")
906
-
907
- # Generate button with clear call to action
908
- with gr.Group(elem_classes="action-group"):
909
- # Generate button with progress indicator
910
- generate_button = gr.Button(
911
- "✨ Generate Image",
912
- variant="primary",
913
- elem_classes="primary",
914
- elem_id="generate-button"
915
- )
916
-
917
- # Generation status message
918
- generation_status = gr.HTML(value="", elem_classes="generation-status")
919
-
920
- # Tips section in collapsible accordion
921
- with gr.Accordion("📝 Tips for better results", open=True):
922
- gr.HTML("""
923
- <div class="tips-container">
924
- <h3>Tips for better results:</h3>
925
- <ul>
926
- <li><strong>Be specific and detailed</strong> - Include information about subjects, environment, lighting, colors, perspective, time of day, etc.</li>
927
- <li><strong>Use descriptive adjectives</strong> - Words like "vibrant", "moody", "ethereal", "weathered" help set the tone.</li>
928
- <li><strong>Experiment with art styles</strong> - Different styles can dramatically change the look and feel.</li>
929
- <li><strong>Combine with the right model</strong> - SDXL provides the highest quality but takes longer.</li>
930
- <li><strong>Think about composition</strong> - Mention foreground/background elements and their relationships.</li>
931
- </ul>
932
- </div>
933
- """)
934
-
935
- # Right column - Output display
936
- with gr.Column(scale=1, min_width=480):
937
- # Image display area with placeholder
938
- with gr.Group(elem_classes="output-container"):
939
- # Output image with interactive elements
940
- image_output = gr.Image(
941
- label="Generated Image",
942
- elem_id="image-output",
943
- type="pil",
944
- height=512
945
- )
946
-
947
- # Image generation details
948
- with gr.Accordion("Image Details", open=True):
949
- parameters_display = gr.HTML(value="")
950
-
951
- # Enhanced prompt display
952
- with gr.Accordion("Enhanced Prompt", open=False):
953
- prompt_output = gr.Textbox(
954
- label="AI-Enhanced Prompt Used",
955
- lines=5,
956
- elem_id="prompt-output",
957
- elem_classes="prompt-display"
958
- )
959
-
960
- # Technical details for advanced users
961
- with gr.Accordion("Technical Details", open=False):
962
- technical_info = gr.HTML("""
963
- <div class="technical-info">
964
- <h4>How Image Generation Works</h4>
965
- <p>Images are generated using Stable Diffusion, a latent text-to-image diffusion model. Your text prompt is:
966
- <ol>
967
- <li>Enhanced with AI to add descriptive details and quality terms</li>
968
- <li>Processed through a neural network that gradually transforms random noise into an image</li>
969
- <li>Refined based on the parameters you select (model, style, mood)</li>
970
- </ol>
971
- </p>
972
- <p>Different models have different strengths:
973
- <ul>
974
- <li><strong>SDXL 1.0</strong>: Highest quality, best composition and details</li>
975
- <li><strong>SD 1.5</strong>: Faster generation, good for general purpose</li>
976
- <li><strong>SD 2.1</strong>: Better with human faces, improved consistency</li>
977
- <li><strong>OpenJourney</strong>: Midjourney-like stylized artistic results</li>
978
- <li><strong>Dreamlike</strong>: Dreamy, ethereal aesthetic with artistic flair</li>
979
- </ul>
980
- </p>
981
- </div>
982
- """)
983
-
984
- # Return all the UI components that need event handlers
985
- return interface, description_input, creation_type, art_style, mood_dropdown, model_selector, generate_button, image_output, generation_status, prompt_output, parameters_display, char_counter, creation_info, art_info, model_info
986
-
987
- # Helper function to update character count with color coding
988
- def update_char_count(text):
989
- count = len(text)
990
- if count == 0:
991
- color_class = ""
992
- elif count < 20:
993
- color_class = "warning"
994
- elif count > 300:
995
- color_class = "warning"
996
- elif count > 500:
997
- color_class = "error"
998
- else:
999
- color_class = ""
1000
-
1001
- return f"<div class='character-counter {color_class}'>{count} characters</div>"
1002
-
1003
- # Helper function to update creation type info
1004
- def update_creation_info(choice):
1005
- key = extract_key(choice)
1006
- if key in CREATION_TYPES:
1007
- info = CREATION_TYPES[key]
1008
- return f"""<div class="info-card">
1009
- <h3>{info['icon']} {key}</h3>
1010
- <p>{info['description']}</p>
1011
- <p style="margin-top: 0.5rem; font-style: italic; opacity: 0.8;">💡 {info['prompt_hint']}</p>
1012
- </div>"""
1013
- return ""
1014
-
1015
- # Helper function to update art style info
1016
- def update_art_style_info(choice):
1017
- key = extract_key(choice)
1018
- if key in ART_STYLES:
1019
- info = ART_STYLES[key]
1020
- return f"""<div class="info-card">
1021
- <h3>{info['icon']} {key}</h3>
1022
- <p>{info['description']}</p>
1023
- <p style="margin-top: 0.5rem; font-style: italic; opacity: 0.8;">🎨 Examples: {info['examples']}</p>
1024
- </div>"""
1025
- return ""
1026
-
1027
- # Helper function to update model info
1028
- def update_model_info(formatted_choice):
1029
- # Extract display name without the icon
1030
- if ' ' in formatted_choice:
1031
- display_name = formatted_choice.split(' ', 1)[1]
1032
- # Find the corresponding key and info
1033
- for key, info in IMAGE_MODELS.items():
1034
- if info['display_name'] == display_name:
1035
- # Create speed badge
1036
- speed_badge = ""
1037
- if info.get('speed') == 'fast':
1038
- speed_badge = '<span class="badge badge-success">Fast</span>'
1039
- elif info.get('speed') == 'medium':
1040
- speed_badge = '<span class="badge badge-warning">Medium</span>'
1041
- elif info.get('speed') == 'slow':
1042
- speed_badge = '<span class="badge badge-error">Slower</span>'
1043
-
1044
- # Create quality badge
1045
- quality_badge = ""
1046
- if info.get('quality') == 'excellent':
1047
- quality_badge = '<span class="badge badge-success">Excellent Quality</span>'
1048
- elif info.get('quality') == 'very good':
1049
- quality_badge = '<span class="badge badge-success">Very Good Quality</span>'
1050
- elif info.get('quality') == 'good':
1051
- quality_badge = '<span class="badge badge-info">Good Quality</span>'
1052
- elif info.get('quality') == 'stylized':
1053
- quality_badge = '<span class="badge badge-info">Stylized</span>'
1054
- elif info.get('quality') == 'artistic':
1055
- quality_badge = '<span class="badge badge-info">Artistic</span>'
1056
-
1057
- return f"""<div class="model-info">
1058
- <h3>{info['icon']} {info['display_name']} {speed_badge} {quality_badge}</h3>
1059
- <p>{info['description']}</p>
1060
- <div class="model-id">{key}</div>
1061
- </div>"""
1062
- return ""
1063
-
1064
- # Helper function to update status message
1065
- def update_status(message, is_error=False, is_warning=False, is_info=False):
1066
- if is_error:
1067
- status_class = "status-error"
1068
- icon = "❌"
1069
- elif is_warning:
1070
- status_class = "status-warning"
1071
- icon = "⚠️"
1072
- elif is_info:
1073
- status_class = "status-info"
1074
- icon = "ℹ️"
1075
- else:
1076
- status_class = "status-success"
1077
- icon = "✅"
1078
-
1079
- return f"""<div class="status-message {status_class}">
1080
- <span class="icon">{icon}</span>
1081
- <span>{message}</span>
1082
- </div>"""
1083
-
1084
- # Helper function to format parameters display as pills
1085
- def format_parameters(creation_type_val, art_style_val, mood_val, model_name):
1086
- creation_key = extract_key(creation_type_val)
1087
- art_key = extract_key(art_style_val)
1088
- mood_key = extract_key(mood_val)
1089
-
1090
- # Get model info
1091
- model_display_name = "Unknown Model"
1092
- model_id = ""
1093
- model_icon = "🤖"
1094
- for key, info in IMAGE_MODELS.items():
1095
- if f"{info['icon']} {info['display_name']}" == model_name:
1096
- model_display_name = info['display_name']
1097
- model_id = key
1098
- model_icon = info['icon']
1099
- break
1100
-
1101
- html = """<div style="margin-bottom: 1rem;">
1102
- <div style="font-weight: 500; margin-bottom: 0.75rem;">Generated with these parameters:</div>
1103
- <div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">"""
1104
-
1105
- # Add creation type pill
1106
- if creation_key in CREATION_TYPES:
1107
- html += f"""<div class="parameter-pill">
1108
- <span class="icon">{CREATION_TYPES[creation_key]['icon']}</span> {creation_key}
1109
- </div>"""
1110
-
1111
- # Add art style pill
1112
- if art_key in ART_STYLES:
1113
- html += f"""<div class="parameter-pill">
1114
- <span class="icon">{ART_STYLES[art_key]['icon']}</span> {art_key}
1115
- </div>"""
1116
-
1117
- # Add mood pill
1118
- if mood_key in MOODS:
1119
- html += f"""<div class="parameter-pill">
1120
- <span class="icon">{MOODS[mood_key]['icon']}</span> {mood_key}
1121
- </div>"""
1122
-
1123
- # Add model pill
1124
- html += f"""<div class="parameter-pill">
1125
- <span class="icon">{model_icon}</span> {model_display_name}
1126
- </div>"""
1127
-
1128
- # Close container
1129
- html += """</div>
1130
- <div style="margin-top: 1rem; font-size: 0.75rem; color: var(--text-muted);">
1131
- Image generated on {timestamp}
1132
- </div>
1133
- </div>""".replace("{timestamp}", time.strftime("%Y-%m-%d at %H:%M:%S"))
1134
-
1135
- return html