Skip to content

Commit 25360b8

Browse files
committed
Fix infinite height when fill_height=True and footer_links=[]. Use height: 100% instead of min-height: 100% on .wrap when fill_height is enabled, so the flex container has a definite height constraint even without a footer element. Closes #12992
1 parent bc53d08 commit 25360b8

File tree

3 files changed

+47
-23
lines changed

3 files changed

+47
-23
lines changed

demo/fill_height_no_footer/run.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import gradio as gr
2+
3+
with gr.Blocks(fill_height=True) as demo:
4+
gr.Chatbot()
5+
6+
if __name__ == "__main__":
7+
demo.launch(footer_links=[])

js/core/src/Blocks.svelte

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import type {
88
ComponentMeta,
99
Dependency as IDependency,
10-
LayoutNode
10+
LayoutNode,
1111
} from "./types";
1212
import type { ThemeMode, Payload } from "./types";
1313
import { Toast } from "@gradio/statustracker";
@@ -58,7 +58,7 @@
5858
render_complete = false,
5959
ready = $bindable(false),
6060
reload_count = $bindable(0),
61-
add_new_message = $bindable()
61+
add_new_message = $bindable(),
6262
}: {
6363
root: string;
6464
components: ComponentMeta[];
@@ -101,7 +101,7 @@
101101
function gradio_event_dispatcher(
102102
id: number,
103103
event: string,
104-
data: unknown
104+
data: unknown,
105105
): void {
106106
if (event === "share") {
107107
const { title, description } = data as ShareData;
@@ -123,9 +123,9 @@
123123
app_tree.update_state(
124124
id,
125125
{
126-
loading_status: {}
126+
loading_status: {},
127127
},
128-
false
128+
false,
129129
);
130130
dep_manager.clear_loading_status(id);
131131
// TODO: the loading_status store should handle this via a method
@@ -148,7 +148,7 @@
148148
type: "event",
149149
event_name: event,
150150
target_id: id,
151-
event_data: data
151+
event_data: data,
152152
});
153153
}
154154
}
@@ -164,23 +164,23 @@
164164
api_prefix,
165165
max_file_size,
166166
autoscroll,
167-
fill_height
167+
fill_height,
168168
},
169169
app,
170170
$reactive_formatter,
171-
gradio_event_dispatcher
171+
gradio_event_dispatcher,
172172
);
173173
174174
function dispatch_to_target(
175175
target_id: number,
176176
event: string,
177-
data: unknown
177+
data: unknown,
178178
): void {
179179
dep_manager.dispatch({
180180
type: "event",
181181
event_name: event,
182182
target_id: target_id,
183-
event_data: data
183+
event_data: data,
184184
});
185185
}
186186
@@ -206,7 +206,7 @@
206206
type: "error",
207207
id: _error_id,
208208
duration: null,
209-
visible: true
209+
visible: true,
210210
});
211211
212212
reconnect_interval = setInterval(async () => {
@@ -232,7 +232,7 @@
232232
app_tree.rerender.bind(app_tree),
233233
new_message,
234234
add_to_api_calls,
235-
handle_connection_lost
235+
handle_connection_lost,
236236
);
237237
238238
$effect(() => {
@@ -245,14 +245,14 @@
245245
api_prefix,
246246
max_file_size,
247247
autoscroll,
248-
fill_height
248+
fill_height,
249249
});
250250
dep_manager.reload(
251251
dependencies,
252252
app_tree.update_state.bind(app_tree),
253253
app_tree.get_state.bind(app_tree),
254254
app_tree.rerender.bind(app_tree),
255-
app
255+
app,
256256
);
257257
});
258258
});
@@ -261,11 +261,12 @@
261261
262262
// export let
263263
let api_docs_visible = $derived(
264-
search_params.get("view") === "api" && footer_links.includes("api")
264+
search_params.get("view") === "api" && footer_links.includes("api"),
265265
);
266266
let settings_visible = $derived(search_params.get("view") === "settings");
267267
let api_recorder_visible = $derived(
268-
search_params.get("view") === "api-recorder" && footer_links.includes("api")
268+
search_params.get("view") === "api-recorder" &&
269+
footer_links.includes("api"),
269270
);
270271
let allow_zoom = true;
271272
let allow_video_trim = true;
@@ -344,7 +345,7 @@
344345
fn_index: number,
345346
type: ToastMessage["type"],
346347
duration: number | null = 10,
347-
visible = false
348+
visible = false,
348349
): void {
349350
if (!visible) return;
350351
messages.push({
@@ -354,7 +355,7 @@
354355
type,
355356
id: ++_error_id,
356357
duration,
357-
visible
358+
visible,
358359
});
359360
}
360361
@@ -366,7 +367,7 @@
366367
367368
const DUPLICATE_MESSAGE = $reactive_formatter("blocks.long_requests_queue");
368369
const MOBILE_QUEUE_WARNING = $reactive_formatter(
369-
"blocks.connection_can_break"
370+
"blocks.connection_can_break",
370371
);
371372
const LOST_CONNECTION_MESSAGE =
372373
"Connection to the server was lost. Attempting reconnection...";
@@ -376,7 +377,7 @@
376377
const SESSION_NOT_FOUND_MESSAGE =
377378
"Session not found - this is likely because the machine you were connected to has changed. <a href=''>Refresh the page</a> to continue.";
378379
const WAITING_FOR_INPUTS_MESSAGE = $reactive_formatter(
379-
"blocks.waiting_for_inputs"
380+
"blocks.waiting_for_inputs",
380381
);
381382
const SHOW_DUPLICATE_MESSAGE_ON_ETA = 15;
382383
const SHOW_MOBILE_QUEUE_WARNING_ON_ETA = 10;
@@ -417,7 +418,7 @@
417418
onMount(() => {
418419
is_mobile_device =
419420
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
420-
navigator.userAgent
421+
navigator.userAgent,
421422
);
422423
423424
if ("parentIFrame" in window) {
@@ -430,7 +431,7 @@
430431
mut.observe(root_container, {
431432
childList: true,
432433
subtree: true,
433-
attributes: true
434+
attributes: true,
434435
});
435436
res.observe(root_container);
436437
@@ -464,7 +465,11 @@
464465
{/if}
465466
</svelte:head>
466467

467-
<div class="wrap" style:min-height={app_mode ? "100%" : "auto"}>
468+
<div
469+
class="wrap"
470+
style:min-height={app_mode && !fill_height ? "100%" : "auto"}
471+
style:height={app_mode && fill_height ? "100%" : "auto"}
472+
>
468473
<main
469474
class="contain"
470475
style:flex-grow={app_mode ? "1" : "auto"}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { test, expect } from "@self/tootils";
2+
3+
test("fill_height with empty footer_links does not cause infinite height", async ({
4+
page,
5+
}) => {
6+
const wrap = page.locator(".wrap");
7+
const viewportHeight = page.viewportSize()!.height;
8+
9+
const wrapHeight = await wrap.evaluate((el) => el.scrollHeight);
10+
11+
expect(wrapHeight).toBeLessThanOrEqual(viewportHeight);
12+
});

0 commit comments

Comments
 (0)