From 5b7928820678609514a04eaef84baea90df09523 Mon Sep 17 00:00:00 2001 From: Anish Date: Fri, 4 Jul 2025 20:18:32 +0530 Subject: [PATCH 1/8] preview tab for copilot --- daras_ai_v2/base.py | 130 +++++++++++++++++++++--------------- daras_ai_v2/meta_content.py | 40 +++++------ recipes/VideoBots.py | 3 +- routers/root.py | 21 +++++- 4 files changed, 120 insertions(+), 74 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 910796937..e207aeda2 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -407,6 +407,37 @@ def render(self): & button { padding: 0.4rem !important; } + + & a:has(span.mobile-only-recipe-tab) { + display: block !important; + } + + & ul.nav-tabs { + overflow-x: auto; + overflow-y: hidden; + white-space: nowrap; + flex-wrap: nowrap !important; + display: flex; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + gap: 0.5rem; + } + + @media (min-width: 768px) { + & a:has(span.mobile-only-recipe-tab) { + display: none !important; + } + + /* RUN as active tab in lg view for preview route */ + & span.active-lg button { + color: #000; + border-bottom: 2px solid black; + } + + & ul.nav-tabs { + gap: 0; + } + } """ ), gui.div(className="position-relative"), @@ -414,8 +445,17 @@ def render(self): ): for tab in self.get_tabs(): url = self.current_app_url(tab) - with gui.nav_item(url, active=tab == self.tab): - gui.html(tab.title) + with gui.tag( + "span", + className="active-lg" + if (tab == RecipeTabs.run and self.tab == RecipeTabs.preview) + else "", + ): + with gui.nav_item( + url, + active=tab == self.tab, + ): + gui.html(tab.title) self._render_saved_generated_timestamp() with gui.nav_tab_content(): @@ -465,7 +505,7 @@ def _render_header(self): self.render_social_buttons() if tbreadcrumbs.has_breadcrumbs(): - if self.tab != RecipeTabs.run: + if self.tab != RecipeTabs.run and self.tab != RecipeTabs.preview: with gui.styled("& h1 { margin-top: 0 }"): self._render_title(tbreadcrumbs.h1_title) else: @@ -1189,7 +1229,7 @@ def get_tabs(self): def render_selected_tab(self): match self.tab: - case RecipeTabs.run: + case RecipeTabs.run | RecipeTabs.preview: if self.current_sr.retention_policy == RetentionPolicy.delete: self.render_deleted_output() return @@ -1202,9 +1242,7 @@ def render_selected_tab(self): ) with gui.styled(OUTPUT_TABS_CSS): - output_col, input_col = gui.tabs( - [f"{icons.preview} Preview", f"{icons.edit} Edit"] - ) + input_col, output_col = gui.columns([3, 2], gap="medium") with input_col: submitted = self._render_input_col() with output_col: @@ -1759,25 +1797,28 @@ def _render_report_button(self): show_settings = True def _render_input_col(self): - self.render_form_v2() - placeholder = gui.div() + with gui.div( + className="d-none d-lg-block" if self.tab == RecipeTabs.preview else "" + ): + self.render_form_v2() + placeholder = gui.div() - if self.show_settings: - with gui.div(className="bg-white"): - with gui.expander("⚙️ Settings"): - self.render_settings() - if self.functions_in_settings: - functions_input(self.request.user) + if self.show_settings: + with gui.div(className="bg-white"): + with gui.expander("⚙️ Settings"): + self.render_settings() + if self.functions_in_settings: + functions_input(self.request.user) - with placeholder: - self.render_variables() + with placeholder: + self.render_variables() - submitted = self.render_submit_button() - with gui.div(style={"textAlign": "right", "fontSize": "smaller"}): - terms_caption = self.get_terms_caption() - gui.caption(f"_{terms_caption}_") + submitted = self.render_submit_button() + with gui.div(style={"textAlign": "right", "fontSize": "smaller"}): + terms_caption = self.get_terms_caption() + gui.caption(f"_{terms_caption}_") - return submitted + return submitted def get_terms_caption(self): return "With each run, you agree to Gooey.AI's [terms](https://gooey.ai/terms) & [privacy policy](https://gooey.ai/privacy)." @@ -1829,7 +1870,12 @@ def _render_output_col(self, *, submitted: bool = False, is_deleted: bool = Fals if submitted: self.submit_and_redirect() - with gui.div(style=dict(position="sticky", top="0.5rem")): + with gui.div( + style=dict(position="sticky", top="0.5rem"), + className="d-none d-lg-block pb-2" + if self.tab == RecipeTabs.run and self.workflow in PREVIEW_ROUTE_WORKFLOWS + else "", + ): run_state = self.get_run_state(gui.session_state) if run_state == RecipeRunState.failed: self._render_failed_output() @@ -2553,36 +2599,16 @@ class TitleValidationError(Exception): pass +PREVIEW_ROUTE_WORKFLOWS = [Workflow.VIDEO_BOTS] OUTPUT_TABS_CSS = """ -& [data-reach-tab-list] { - text-align: center; margin-top: 0 -} -@media (min-width: 768px) { - & [data-reach-tab-list] { - display: none; + & { + margin: -1rem 0 1rem 0; + padding-top: 1rem; } - & [data-reach-tab-panels] { - display: flex; - flex-direction: row-reverse; - width: 100%; - background-color: #f9f9f9; - padding: 10px; - margin-top: -1rem; - } - & [data-reach-tab-panels] > div:nth-child(2) { - flex: 0 1 auto; - width: 60%; - max-width: 100%; - padding-right: 0.75rem; - } - & [data-reach-tab-panels] > div:nth-child(1) { - flex: 0 0 auto; - width: 40%; - max-width: 100%; - padding-left: 0.75rem; - } - & [data-reach-tab-panel][hidden] { - display: block !important; + @media (min-width: 768px) { + & { + background-color: #f9f9f9; + } } -} + """ diff --git a/daras_ai_v2/meta_content.py b/daras_ai_v2/meta_content.py index bb438ce62..88d919154 100644 --- a/daras_ai_v2/meta_content.py +++ b/daras_ai_v2/meta_content.py @@ -217,25 +217,27 @@ def robots_tag_for_page( is_root = pr and pr.saved_run == sr and pr.is_root() is_example = pr and pr.saved_run == sr and not pr.is_root() - if not page.is_user_authorized(None): - # nofollow & noindex if page is not open for anonymous users - no_follow, no_index = True, True - else: - match page.tab: - case RecipeTabs.run if is_root or is_example: - no_follow, no_index = False, False - case RecipeTabs.run: # ordinary run (not example) - no_follow, no_index = False, True - case RecipeTabs.examples: - no_follow, no_index = False, False - case RecipeTabs.run_as_api: - no_follow, no_index = False, True - case RecipeTabs.integrations: - no_follow, no_index = True, True - case RecipeTabs.history: - no_follow, no_index = True, True - case RecipeTabs.saved: - no_follow, no_index = True, True + match page.tab: + case RecipeTabs.run if is_root or is_example: + no_follow, no_index = False, False + case RecipeTabs.preview if is_root or is_example: + no_follow, no_index = False, False + case RecipeTabs.run: # ordinary run (not example) + no_follow, no_index = False, True + case RecipeTabs.preview: + no_follow, no_index = False, True + case RecipeTabs.examples: + no_follow, no_index = False, False + case RecipeTabs.run_as_api: + no_follow, no_index = False, True + case RecipeTabs.integrations: + no_follow, no_index = True, True + case RecipeTabs.history: + no_follow, no_index = True, True + case RecipeTabs.saved: + no_follow, no_index = True, True + case _: + raise ValueError(f"Unknown tab: {page.tab}") parts = [] if no_follow: diff --git a/recipes/VideoBots.py b/recipes/VideoBots.py index 524a6c7d7..030cd8d82 100644 --- a/recipes/VideoBots.py +++ b/recipes/VideoBots.py @@ -1507,11 +1507,12 @@ def lipsync_step(self, request, response): response.output_video.append(lip_state["output_video"]) def render_header_extra(self): - if self.tab == RecipeTabs.run: + if self.tab == RecipeTabs.run or self.tab == RecipeTabs.preview: render_demo_buttons_header(self.current_pr) def get_tabs(self): tabs = super().get_tabs() + tabs.insert(1, RecipeTabs.preview) tabs.extend([RecipeTabs.integrations]) return tabs diff --git a/routers/root.py b/routers/root.py index f112f8c49..8c69f191a 100644 --- a/routers/root.py +++ b/routers/root.py @@ -592,6 +592,18 @@ def chat_lib_route(request: Request, integration_id: str, integration_name: str ) +@gui.route( + app, + "/{page_slug}/preview/", + "/{page_slug}/{run_slug}/preview/", + "/{page_slug}/{run_slug}-{example_id}/preview/", +) +def preview_route( + request: Request, page_slug: str, run_slug: str = None, example_id: str = None +): + return render_recipe_page(request, page_slug, RecipeTabs.preview, example_id) + + @gui.route( app, "/{path:path}", @@ -821,8 +833,13 @@ class TabData(typing.NamedTuple): class RecipeTabs(TabData, Enum): + preview = TabData( + title=f"{icons.preview} Preview", + label="", + route=preview_route, + ) run = TabData( - title=f"{icons.run} Run", + title=f"{icons.run} Run", label="", route=recipe_or_handle_or_static, ) @@ -842,7 +859,7 @@ class RecipeTabs(TabData, Enum): route=history_route, ) integrations = TabData( - title=f'Facebook, Whatsapp, Slack, Instagram Icons Integrations', + title=f'Facebook, Whatsapp, Slack, Instagram Icons Integrations', label="Integrations", route=integrations_route, ) From fe1cb917ce29ee25af34210691c204599b55ec04 Mon Sep 17 00:00:00 2001 From: Anish Date: Mon, 7 Jul 2025 14:19:00 +0530 Subject: [PATCH 2/8] show save/update buttons in preview tab --- daras_ai_v2/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index e207aeda2..1c980ea25 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -668,7 +668,7 @@ def render_social_buttons(self): ): publish_dialog_ref = gui.use_alert_dialog(key="publish-modal") - if self.tab == RecipeTabs.run: + if self.tab == RecipeTabs.run or self.tab == RecipeTabs.preview: if self.current_pr.is_root(): render_help_button(self.workflow) if self.is_logged_in(): From 3ee376e80520cd2575f3733acf4cac825efd7df8 Mon Sep 17 00:00:00 2001 From: Anish Date: Mon, 7 Jul 2025 14:59:36 +0530 Subject: [PATCH 3/8] submit and redirect to /preview --- daras_ai_v2/base.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 1c980ea25..ee85a36d9 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -1948,7 +1948,12 @@ def submit_and_redirect( sr = self.on_submit(unsaved_state=unsaved_state) if not sr: return - raise gui.RedirectException(self.app_url(run_id=sr.run_id, uid=sr.uid)) + if self.workflow in PREVIEW_ROUTE_WORKFLOWS: + raise gui.RedirectException( + self.app_url(run_id=sr.run_id, uid=sr.uid, tab=RecipeTabs.preview) + ) + else: + raise gui.RedirectException(self.app_url(run_id=sr.run_id, uid=sr.uid)) def publish_and_redirect(self) -> typing.NoReturn | None: assert self.is_logged_in() @@ -1973,7 +1978,10 @@ def publish_and_redirect(self) -> typing.NoReturn | None: title=self._get_default_pr_title(), notes=self.current_pr.notes, ) - raise gui.RedirectException(pr.get_app_url()) + if self.workflow in PREVIEW_ROUTE_WORKFLOWS: + raise gui.RedirectException(pr.get_app_url()) + else: + raise gui.RedirectException(pr.get_app_url()) def on_submit(self, unsaved_state: dict[str, typing.Any] = None): sr = self.create_and_validate_new_run(enable_rate_limits=True) From 39ae83b038bdd03525df069fefed5008646d719e Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 9 Jul 2025 13:20:49 +0530 Subject: [PATCH 4/8] scroll to recipe nav tabs in copilot --- daras_ai_v2/base.py | 9 ++++++--- recipes/VideoBots.py | 4 ++-- routers/root.py | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index ee85a36d9..2bdc9179f 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -91,6 +91,7 @@ render_create_workspace_alert, set_current_workspace, ) +from routers.root import PREVIEW_ROUTE_WORKFLOWS MAX_SEED = 4294967294 gooey_rng = Random() @@ -440,7 +441,7 @@ def render(self): } """ ), - gui.div(className="position-relative"), + gui.div(className="position-relative", id="recipe-nav-tabs"), gui.nav_tabs(), ): for tab in self.get_tabs(): @@ -448,7 +449,10 @@ def render(self): with gui.tag( "span", className="active-lg" - if (tab == RecipeTabs.run and self.tab == RecipeTabs.preview) + if ( + tab == RecipeTabs.run + and self.workflow in PREVIEW_ROUTE_WORKFLOWS + ) else "", ): with gui.nav_item( @@ -2607,7 +2611,6 @@ class TitleValidationError(Exception): pass -PREVIEW_ROUTE_WORKFLOWS = [Workflow.VIDEO_BOTS] OUTPUT_TABS_CSS = """ & { margin: -1rem 0 1rem 0; diff --git a/recipes/VideoBots.py b/recipes/VideoBots.py index 030cd8d82..6b1d5cc52 100644 --- a/recipes/VideoBots.py +++ b/recipes/VideoBots.py @@ -698,11 +698,11 @@ def render_run_preview_output(self, state: dict): scroll_into_view = False def _render_running_output(self): - ## The embedded web widget includes a running output, so just scroll it into view + ## The embedded web widget includes a running output, so just scroll it into view to tabs which just above the widget # language=JavaScript gui.js( - """document.querySelector("#gooey-embed")?.scrollIntoView({ behavior: "smooth", block: "start" })""" + """document.querySelector("#recipe-nav-tabs")?.scrollIntoView({ behaviour: "smooth", block: "start" })""" ) def render_output(self): diff --git a/routers/root.py b/routers/root.py index 8c69f191a..831473a67 100644 --- a/routers/root.py +++ b/routers/root.py @@ -831,7 +831,7 @@ class TabData(typing.NamedTuple): label: str route: typing.Callable - +PREVIEW_ROUTE_WORKFLOWS = [Workflow.VIDEO_BOTS] class RecipeTabs(TabData, Enum): preview = TabData( title=f"{icons.preview} Preview", From e71aef14fac1f14dc2fcc98cd677452ec28ff684 Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 9 Jul 2025 14:05:52 +0530 Subject: [PATCH 5/8] remove col padding in mobile & fix start gap in tab line --- daras_ai_v2/base.py | 20 +++++++++++++++++++- routers/root.py | 5 ++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 2bdc9179f..5dd6f520c 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -413,6 +413,10 @@ def render(self): display: block !important; } + & li.nav-item:first-of-type button { + margin-left: 0 !important; + } + & ul.nav-tabs { overflow-x: auto; overflow-y: hidden; @@ -1246,7 +1250,10 @@ def render_selected_tab(self): ) with gui.styled(OUTPUT_TABS_CSS): - input_col, output_col = gui.columns([3, 2], gap="medium") + input_col, output_col = gui.columns( + [3, 2], + gap="medium", + ) with input_col: submitted = self._render_input_col() with output_col: @@ -2616,10 +2623,21 @@ class TitleValidationError(Exception): margin: -1rem 0 1rem 0; padding-top: 1rem; } + + /* reset col padding in mobile */ + & > div { + padding: 0; + } + @media (min-width: 768px) { & { background-color: #f9f9f9; } + /* set col padding in mobile */ + & > div { + padding-left: calc(var(--bs-gutter-x) * .5); + padding-right: calc(var(--bs-gutter-x) * .5); + } } """ diff --git a/routers/root.py b/routers/root.py index 831473a67..1b9e11c5d 100644 --- a/routers/root.py +++ b/routers/root.py @@ -831,7 +831,10 @@ class TabData(typing.NamedTuple): label: str route: typing.Callable + PREVIEW_ROUTE_WORKFLOWS = [Workflow.VIDEO_BOTS] + + class RecipeTabs(TabData, Enum): preview = TabData( title=f"{icons.preview} Preview", @@ -839,7 +842,7 @@ class RecipeTabs(TabData, Enum): route=preview_route, ) run = TabData( - title=f"{icons.run} Run", + title=f"{icons.run} Run", label="", route=recipe_or_handle_or_static, ) From d7bb368b9136e8ba76f519631ce875e698c24592 Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 9 Jul 2025 14:10:44 +0530 Subject: [PATCH 6/8] fix: run tab underline --- daras_ai_v2/base.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 5dd6f520c..13cc3f69e 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -453,10 +453,7 @@ def render(self): with gui.tag( "span", className="active-lg" - if ( - tab == RecipeTabs.run - and self.workflow in PREVIEW_ROUTE_WORKFLOWS - ) + if (tab == RecipeTabs.run and self.tab == RecipeTabs.preview) else "", ): with gui.nav_item( From 5e89f668c379a20ee1cc7ed5dd6a0a2890d31d52 Mon Sep 17 00:00:00 2001 From: Anish Date: Mon, 14 Jul 2025 11:39:06 +0530 Subject: [PATCH 7/8] remove unwanted condition --- daras_ai_v2/base.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 13cc3f69e..391f79502 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -1986,10 +1986,7 @@ def publish_and_redirect(self) -> typing.NoReturn | None: title=self._get_default_pr_title(), notes=self.current_pr.notes, ) - if self.workflow in PREVIEW_ROUTE_WORKFLOWS: - raise gui.RedirectException(pr.get_app_url()) - else: - raise gui.RedirectException(pr.get_app_url()) + raise gui.RedirectException(pr.get_app_url()) def on_submit(self, unsaved_state: dict[str, typing.Any] = None): sr = self.create_and_validate_new_run(enable_rate_limits=True) From 71a4e2916e39995a9608d750f8c8f7abe1d6d44a Mon Sep 17 00:00:00 2001 From: Dev Aggarwal Date: Tue, 12 Aug 2025 02:44:07 -0700 Subject: [PATCH 8/8] refactor: prefer if-conditional over inline if-statement --- daras_ai_v2/base.py | 182 +++++++++++++++++++++----------------------- routers/root.py | 2 +- 2 files changed, 89 insertions(+), 95 deletions(-) diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 6321f920a..df885419d 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -91,6 +91,7 @@ ) from routers.root import PREVIEW_ROUTE_WORKFLOWS + MAX_SEED = 4294967294 gooey_rng = Random() @@ -391,74 +392,18 @@ def render(self): header_placeholder = gui.div(className="my-3 w-100") with ( - gui.styled( - """ - @media (max-width: 768px) { - & button { - font-size: 0.9rem; - padding: 0.3rem !important - } - } - & .nav-item { - font-size: smaller; - font-weight: bold; - } - & button { - padding: 0.4rem !important; - } - - & a:has(span.mobile-only-recipe-tab) { - display: block !important; - } - - & li.nav-item:first-of-type button { - margin-left: 0 !important; - } - - & ul.nav-tabs { - overflow-x: auto; - overflow-y: hidden; - white-space: nowrap; - flex-wrap: nowrap !important; - display: flex; - -webkit-overflow-scrolling: touch; - scrollbar-width: none; - gap: 0.5rem; - } - - @media (min-width: 768px) { - & a:has(span.mobile-only-recipe-tab) { - display: none !important; - } - - /* RUN as active tab in lg view for preview route */ - & span.active-lg button { - color: #000; - border-bottom: 2px solid black; - } - - & ul.nav-tabs { - gap: 0; - } - } - """ - ), + gui.styled(NAV_TABS_CSS), gui.div(className="position-relative", id="recipe-nav-tabs"), gui.nav_tabs(), ): for tab in self.get_tabs(): url = self.current_app_url(tab) - with gui.tag( - "span", - className="active-lg" - if (tab == RecipeTabs.run and self.tab == RecipeTabs.preview) - else "", - ): - with gui.nav_item( - url, - active=tab == self.tab, - ): - gui.html(tab.title) + if tab == RecipeTabs.run and self.tab == RecipeTabs.preview: + force_active_lg = gui.tag("span", className="active-lg") + else: + force_active_lg = gui.dummy() + with force_active_lg, gui.nav_item(url, active=tab == self.tab): + gui.html(tab.title) self._render_saved_generated_timestamp() with gui.nav_tab_content(): @@ -1246,11 +1191,8 @@ def render_selected_tab(self): ), ) - with gui.styled(OUTPUT_TABS_CSS): - input_col, output_col = gui.columns( - [3, 2], - gap="medium", - ) + with gui.styled(INPUT_OUTPUT_COLS_CSS): + input_col, output_col = gui.columns([3, 2], gap="medium") with input_col: submitted = self._render_input_col() with output_col: @@ -1808,9 +1750,11 @@ def _render_report_button(self): show_settings = True def _render_input_col(self): - with gui.div( - className="d-none d-lg-block" if self.tab == RecipeTabs.preview else "" - ): + if self.tab == RecipeTabs.preview: + hide_on_mobile = "d-none d-lg-block" + else: + hide_on_mobile = "" + with gui.div(className=hide_on_mobile): self.render_form_v2() placeholder = gui.div() @@ -1881,11 +1825,12 @@ def _render_output_col(self, *, submitted: bool = False, is_deleted: bool = Fals if submitted: self.submit_and_redirect() + if self.tab == RecipeTabs.run and self.workflow in PREVIEW_ROUTE_WORKFLOWS: + hide_on_mobile = "d-none d-lg-block pb-2" + else: + hide_on_mobile = "" with gui.div( - style=dict(position="sticky", top="0.5rem"), - className="d-none d-lg-block pb-2" - if self.tab == RecipeTabs.run and self.workflow in PREVIEW_ROUTE_WORKFLOWS - else "", + style=dict(position="sticky", top="0.5rem"), className=hide_on_mobile ): run_state = self.get_run_state(gui.session_state) if run_state == RecipeRunState.failed: @@ -1960,11 +1905,10 @@ def submit_and_redirect( if not sr: return if self.workflow in PREVIEW_ROUTE_WORKFLOWS: - raise gui.RedirectException( - self.app_url(run_id=sr.run_id, uid=sr.uid, tab=RecipeTabs.preview) - ) + tab = RecipeTabs.preview else: - raise gui.RedirectException(self.app_url(run_id=sr.run_id, uid=sr.uid)) + tab = None + raise gui.RedirectException(self.app_url(run_id=sr.run_id, uid=sr.uid, tab=tab)) def publish_and_redirect(self) -> typing.NoReturn | None: assert self.is_logged_in() @@ -2614,26 +2558,76 @@ class TitleValidationError(Exception): pass -OUTPUT_TABS_CSS = """ +INPUT_OUTPUT_COLS_CSS = """ +& { + margin: -1rem 0 1rem 0; + padding-top: 1rem; +} + +/* reset col padding in mobile */ +& > div { + padding: 0; +} + +@media (min-width: 768px) { & { - margin: -1rem 0 1rem 0; - padding-top: 1rem; + background-color: #f9f9f9; } - - /* reset col padding in mobile */ + /* set col padding in mobile */ & > div { - padding: 0; + padding-left: calc(var(--bs-gutter-x) * .5); + padding-right: calc(var(--bs-gutter-x) * .5); } +} +""" - @media (min-width: 768px) { - & { - background-color: #f9f9f9; - } - /* set col padding in mobile */ - & > div { - padding-left: calc(var(--bs-gutter-x) * .5); - padding-right: calc(var(--bs-gutter-x) * .5); - } +NAV_TABS_CSS = """ +@media (max-width: 768px) { + & button { + font-size: 0.9rem; + padding: 0.3rem !important + } +} +& .nav-item { + font-size: smaller; + font-weight: bold; +} +& button { + padding: 0.4rem !important; +} + +& a:has(span.mobile-only-recipe-tab) { + display: block !important; +} + +& li.nav-item:first-of-type button { + margin-left: 0 !important; +} + +& ul.nav-tabs { + overflow-x: auto; + overflow-y: hidden; + white-space: nowrap; + flex-wrap: nowrap !important; + display: flex; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + gap: 0.5rem; +} + +@media (min-width: 768px) { + & a:has(span.mobile-only-recipe-tab) { + display: none !important; } + /* RUN as active tab in lg view for preview route */ + & span.active-lg button { + color: #000; + border-bottom: 2px solid black; + } + + & ul.nav-tabs { + gap: 0; + } +} """ diff --git a/routers/root.py b/routers/root.py index c54b96ae3..c0907225c 100644 --- a/routers/root.py +++ b/routers/root.py @@ -898,7 +898,7 @@ class RecipeTabs(TabData, Enum): route=preview_route, ) run = TabData( - title=f"{icons.run} Run", + title=f"{icons.run} Run", label="", route=recipe_or_handle_or_static, )