nextussocial's picture
Create minimal reproduction case to isolate Gradio schema error
b6bbe57
import gradio as gr
import json
import os
from PIL import Image
import tempfile
# from utils.extractor import DesignTokenExtractor
# from utils.token_generator import TokenCodeGenerator
def create_token_preview(tokens):
"""Create HTML preview of extracted tokens"""
html = """
<div style="font-family: system-ui, sans-serif; padding: 20px; background: #f9fafb; border-radius: 8px;">
<h3 style="margin-top: 0; color: #1f2937;">Extracted Design Tokens</h3>
"""
# Color palette preview
if 'colors' in tokens and tokens['colors']:
html += """
<div style="margin-bottom: 24px;">
<h4 style="color: #6b7280; font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em;">Colors</h4>
<div style="display: flex; gap: 12px; flex-wrap: wrap;">
"""
for name, color in tokens['colors'].items():
html += f"""
<div style="text-align: center;">
<div style="width: 80px; height: 80px; background: {color['hex']};
border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"></div>
<div style="margin-top: 8px;">
<div style="font-size: 12px; font-weight: 600; color: #374151;">{name}</div>
<div style="font-size: 11px; color: #9ca3af;">{color['hex']}</div>
<div style="font-size: 10px; color: #9ca3af;">{int(color.get('proportion', 0) * 100)}%</div>
</div>
</div>
"""
html += "</div></div>"
# Spacing preview
if 'spacing' in tokens and tokens['spacing']:
html += """
<div style="margin-bottom: 24px;">
<h4 style="color: #6b7280; font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em;">Spacing</h4>
<div style="display: flex; gap: 16px; align-items: flex-end;">
"""
for name, value in tokens['spacing'].items():
try:
height = value.replace('px', '')
html += f"""
<div style="text-align: center;">
<div style="width: 60px; height: {height}px; background: #3b82f6;
border-radius: 4px; opacity: 0.8;"></div>
<div style="margin-top: 8px;">
<div style="font-size: 12px; font-weight: 600; color: #374151;">{name}</div>
<div style="font-size: 11px; color: #9ca3af;">{value}</div>
</div>
</div>
"""
except:
pass
html += "</div></div>"
# Typography preview
if 'typography' in tokens and tokens['typography']:
html += """
<div style="margin-bottom: 24px;">
<h4 style="color: #6b7280; font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em;">Typography</h4>
"""
for name, props in tokens['typography'].items():
size = props.get('size', '16px')
weight = props.get('weight', '400')
family = props.get('family', 'sans-serif')
html += f"""
<div style="margin-bottom: 12px; padding: 12px; background: white; border-radius: 6px;">
<div style="font-size: {size}; font-weight: {weight}; font-family: {family}; color: #1f2937;">
Sample {name.title()} Text
</div>
<div style="font-size: 11px; color: #9ca3af; margin-top: 4px;">
{family}{size} • Weight {weight}
</div>
</div>
"""
html += "</div>"
html += "</div>"
return html
def process_screenshot(image, output_format, progress=None):
"""Process uploaded screenshot and extract design tokens"""
if image is None:
return None, "Please upload a screenshot", None
# Temporary stub implementation for testing
try:
# Mock tokens for testing
tokens = {
"colors": {
"primary": {"hex": "#3B82F6", "rgb": "rgb(59, 130, 246)", "proportion": 0.25},
"secondary": {"hex": "#8B5CF6", "rgb": "rgb(139, 92, 246)", "proportion": 0.15}
},
"spacing": {
"small": "8px",
"medium": "16px",
"large": "32px"
},
"typography": {
"heading": {"family": "sans-serif", "size": "32px", "weight": "700"},
"body": {"family": "sans-serif", "size": "16px", "weight": "400"}
}
}
# Simple CSS output for testing
code_output = ":root {\n --color-primary: #3B82F6;\n --color-secondary: #8B5CF6;\n --spacing-small: 8px;\n --spacing-medium: 16px;\n --spacing-large: 32px;\n}"
# Save output file
output_filename = "design_tokens.css"
with open(output_filename, "w") as f:
f.write(code_output)
# Create preview visualization
preview_html = create_token_preview(tokens)
return preview_html, code_output, output_filename
except Exception as e:
return None, f"Error processing screenshot: {str(e)}", None
def create_gradio_app():
"""Create the main Gradio application"""
with gr.Blocks(
title="Design Token Extractor",
theme=gr.themes.Soft(),
css="""
.gradio-container {
font-family: 'Inter', system-ui, sans-serif;
}
.gr-button-primary {
background-color: #3b82f6 !important;
}
"""
) as app:
gr.Markdown(
"""
# 🎨 Design Token Extractor
Transform UI screenshots into structured design token libraries using AI-powered analysis.
Upload a screenshot to automatically extract colors, spacing, typography, and component tokens.
---
"""
)
with gr.Row():
with gr.Column(scale=1):
input_image = gr.Image(
label="Upload UI Screenshot",
type="pil",
sources=["upload", "clipboard"],
height=400
)
output_format = gr.Radio(
choices=[
"CSS Variables",
"Tailwind Config",
"JSON Tokens",
"Style Dictionary",
"SCSS Variables"
],
value="CSS Variables",
label="Output Format",
info="Choose the format for your design tokens"
)
extract_btn = gr.Button(
"🚀 Extract Design Tokens",
variant="primary",
size="lg"
)
gr.Markdown(
"""
### Tips for best results:
- Use high-quality screenshots (min 800px width)
- Include various UI elements for comprehensive extraction
- Screenshots with clear color hierarchy work best
- Ensure good contrast between elements
"""
)
with gr.Column(scale=1):
preview = gr.HTML(
label="Token Preview",
value="<div style='padding: 20px; text-align: center; color: #9ca3af;'>Upload a screenshot to see extracted tokens</div>"
)
code_output = gr.Code(
label="Generated Code",
language="css",
lines=20,
value="// Your design tokens will appear here"
)
download_file = gr.File(
label="Download Tokens",
visible=True
)
# Examples section commented out until example images are available
# gr.Markdown("### Example Screenshots")
# gr.Examples(
# examples=[
# ["examples/dashboard.png", "CSS Variables"],
# ["examples/landing_page.png", "Tailwind Config"],
# ["examples/mobile_app.png", "JSON Tokens"]
# ],
# inputs=[input_image, output_format],
# cache_examples=False
# )
# Connect the extraction function
extract_btn.click(
fn=process_screenshot,
inputs=[input_image, output_format],
outputs=[preview, code_output, download_file]
)
# Add footer
gr.Markdown(
"""
---
### Features:
- **Color Extraction**: Identifies dominant colors and creates semantic color roles
- **Spacing Detection**: Analyzes layout patterns to extract consistent spacing values
- **Typography Analysis**: Detects font styles and creates text hierarchy tokens
- **Multiple Output Formats**: Export to CSS, Tailwind, JSON, Style Dictionary, or SCSS
Built with ❤️ using Gradio and computer vision models
"""
)
return app
if __name__ == "__main__":
app = create_gradio_app()
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=True,
show_error=True
)