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 = """
Extracted Design Tokens
"""
# Color palette preview
if 'colors' in tokens and tokens['colors']:
html += """
Colors
"""
for name, color in tokens['colors'].items():
html += f"""
{name}
{color['hex']}
{int(color.get('proportion', 0) * 100)}%
"""
html += "
"
# Spacing preview
if 'spacing' in tokens and tokens['spacing']:
html += """
Spacing
"""
for name, value in tokens['spacing'].items():
try:
height = value.replace('px', '')
html += f"""
"""
except:
pass
html += "
"
# Typography preview
if 'typography' in tokens and tokens['typography']:
html += """
Typography
"""
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"""
Sample {name.title()} Text
{family} • {size} • Weight {weight}
"""
html += "
"
html += "
"
return html
def process_screenshot(image, output_format, progress=gr.Progress()):
"""Process uploaded screenshot and extract design tokens"""
if image is None:
return None, "Please upload a screenshot", None
extractor = DesignTokenExtractor()
generator = TokenCodeGenerator()
try:
progress(0.1, desc="Initializing extraction...")
# Resize image if needed
image = extractor.resize_for_processing(image)
# Save temporary file for colorgram
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp:
temp_path = tmp.name
image.save(temp_path)
progress(0.3, desc="Extracting colors...")
colors = extractor.extract_colors(temp_path)
progress(0.5, desc="Detecting spacing...")
spacing = extractor.detect_spacing(image)
progress(0.6, desc="Analyzing typography...")
typography = extractor.detect_typography(image)
progress(0.7, desc="Analyzing components...")
components = extractor.analyze_components(image)
# Combine all tokens
tokens = {
"colors": colors,
"spacing": spacing,
"typography": typography,
"components": components
}
progress(0.8, desc="Generating code...")
# Generate output based on selected format
if output_format == "CSS Variables":
code_output = generator.generate_css_variables(tokens)
file_ext = "css"
elif output_format == "Tailwind Config":
code_output = generator.generate_tailwind_config(tokens)
file_ext = "js"
elif output_format == "JSON Tokens":
code_output = generator.generate_json_tokens(tokens)
file_ext = "json"
elif output_format == "Style Dictionary":
code_output = generator.generate_style_dictionary(tokens)
file_ext = "json"
elif output_format == "SCSS Variables":
code_output = generator.generate_scss_variables(tokens)
file_ext = "scss"
else:
code_output = json.dumps(tokens, indent=2)
file_ext = "json"
# Save output file
output_filename = f"design_tokens.{file_ext}"
with open(output_filename, "w") as f:
f.write(code_output)
# Clean up temp file
try:
os.unlink(temp_path)
except:
pass
progress(1.0, desc="Complete!")
# 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="