gradio-html / app.py
victor's picture
victor HF Staff
Use height: 100% instead of fixed min-height
cc97280
raw
history blame
6.92 kB
import gradio as gr
def add_numbers(data):
"""Python function that adds two numbers"""
try:
num1 = float(data.get("num1", 0))
num2 = float(data.get("num2", 0))
result = num1 + num2
return {"result": result, "expression": f"{num1} + {num2} = {result}"}
except (ValueError, TypeError) as e:
return {"result": "Error", "expression": f"Invalid input: {e}"}
# HTML for the math calculator
MATH_HTML = """
<div id="math-app">
<h1>Math Calculator</h1>
<p class="subtitle">Custom HTML calling Python via Gradio</p>
<div class="calculator">
<div class="input-row">
<div class="input-group">
<label>First Number</label>
<input type="number" id="num1" placeholder="Enter number..." value="0">
</div>
<div class="operator">+</div>
<div class="input-group">
<label>Second Number</label>
<input type="number" id="num2" placeholder="Enter number..." value="0">
</div>
</div>
<button id="calculate-btn">Calculate (calls Python)</button>
<div class="result-box" id="result-box">
<div class="result-label">Result from Python:</div>
<div class="result-value" id="result-value">${value.result !== undefined ? value.result : '—'}</div>
<div class="result-expression" id="result-expression">${value.expression || ''}</div>
</div>
<div class="status" id="status">Ready</div>
</div>
</div>
"""
# CSS for the math calculator
MATH_CSS = """
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
width: 100%;
overflow: hidden;
font-family: system-ui, -apple-system, sans-serif;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
}
#math-app {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
color: #fff;
padding: 2rem;
}
h1 {
font-size: 2.5rem;
text-align: center;
background: linear-gradient(90deg, #00d2ff, #3a7bd5);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.5rem;
}
.subtitle {
color: #aaa;
font-size: 1.1rem;
margin-bottom: 2rem;
}
.calculator {
background: rgba(255,255,255,0.05);
padding: 2rem;
border-radius: 1rem;
border: 1px solid rgba(255,255,255,0.1);
width: 100%;
max-width: 500px;
}
.input-row {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 1.5rem;
}
.input-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.input-group label {
font-size: 0.9rem;
color: #aaa;
}
.input-group input {
width: 120px;
padding: 1rem;
border: 1px solid rgba(255,255,255,0.2);
border-radius: 0.5rem;
background: rgba(255,255,255,0.05);
color: white;
font-size: 1.5rem;
text-align: center;
}
.input-group input:focus {
outline: none;
border-color: #00d2ff;
}
.operator {
font-size: 2rem;
color: #00d2ff;
margin-top: 1.5rem;
}
#calculate-btn {
width: 100%;
padding: 1rem;
border: none;
border-radius: 0.5rem;
background: linear-gradient(135deg, #00d2ff, #3a7bd5);
color: white;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
margin-bottom: 1.5rem;
}
#calculate-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 210, 255, 0.3);
}
#calculate-btn:active {
transform: translateY(0);
}
.result-box {
background: rgba(0, 210, 255, 0.1);
border: 1px solid rgba(0, 210, 255, 0.3);
border-radius: 0.5rem;
padding: 1.5rem;
text-align: center;
margin-bottom: 1rem;
}
.result-label {
font-size: 0.9rem;
color: #aaa;
margin-bottom: 0.5rem;
}
.result-value {
font-size: 3rem;
font-weight: bold;
color: #00d2ff;
}
.result-expression {
font-size: 1rem;
color: #aaa;
margin-top: 0.5rem;
}
.status {
text-align: center;
padding: 0.5rem;
color: #666;
font-size: 0.9rem;
}
/* Hide Gradio chrome */
footer { display: none !important; }
.gradio-container, [class*="gradio-container"] {
max-width: 100% !important;
width: 100% !important;
padding: 0 !important;
margin: 0 !important;
min-height: 0 !important;
height: 100% !important;
}
main.fillable, main[class*="fillable"], .app {
padding: 0 !important;
margin: 0 !important;
min-height: 0 !important;
}
.block, .block.padded {
padding: 0 !important;
border: none !important;
background: transparent !important;
}
html, body, #root, .gradio-container, .contain, gradio-app {
height: 100% !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
min-height: 0 !important;
}
[class*="svelte"] {
padding: 0 !important;
margin: 0 !important;
}
/* Prevent iframe resizer infinite loop */
.contain, .main, gradio-app {
min-height: 0 !important;
max-height: 100% !important;
}
</style>
"""
# JavaScript that wires up the UI and calls Python via trigger
MATH_JS = """
(function() {
function $(sel) { return element.querySelector(sel); }
function updateStatus(msg) {
$('#status').textContent = msg;
}
// When calculate button is clicked
$('#calculate-btn').addEventListener('click', function() {
var num1 = parseFloat($('#num1').value) || 0;
var num2 = parseFloat($('#num2').value) || 0;
updateStatus('Calling Python...');
// Update props.value with the data to send to Python
props.value = { num1: num1, num2: num2 };
// Trigger the 'submit' event which calls the Python function
trigger('submit');
});
// Allow Enter key to trigger calculation
$('#num1').addEventListener('keypress', function(e) {
if (e.key === 'Enter') $('#calculate-btn').click();
});
$('#num2').addEventListener('keypress', function(e) {
if (e.key === 'Enter') $('#calculate-btn').click();
});
updateStatus('Ready - Enter numbers and click Calculate');
})();
"""
# JavaScript to handle the response from Python
MATH_JS_CHANGE = """
(function() {
function $(sel) { return element.querySelector(sel); }
// This runs when the component value changes (i.e., when Python returns)
if (props.value && props.value.result !== undefined) {
$('#result-value').textContent = props.value.result;
$('#result-expression').textContent = props.value.expression || '';
$('#status').textContent = 'Calculated by Python at ' + new Date().toLocaleTimeString();
}
})();
"""
# Create the Gradio app
with gr.Blocks(fill_height=True, title="Math Calculator") as demo:
calculator = gr.HTML(
value={},
html_template=MATH_CSS + MATH_HTML,
js_on_load=MATH_JS,
container=False
)
# When JS triggers 'submit', call add_numbers and update the component
calculator.submit(add_numbers, inputs=calculator, outputs=calculator)
if __name__ == "__main__":
demo.launch()