Skip to content

Commit 6f74a8d

Browse files
committed
feat: Add Products dropdown and Solutions dropdown to navbar
- Created Products dropdown containing AI Builder, Open Source, and Cloud - Created Solutions dropdown with App Types (Internal Tools, Data & AI Apps, Customer Facing Apps) and Industries (Finance, Healthcare, Energy, Enterprise) - Updated navbar menu trigger to support active states for dropdowns - Reorganized navbar items: Products, Docs, Resources, Solutions, Pricing - Fixed icon names to use valid icons from the icon library
1 parent a8ba44c commit 6f74a8d

File tree

1 file changed

+204
-51
lines changed

1 file changed

+204
-51
lines changed

pcweb/components/docpage/navbar/navbar.py

Lines changed: 204 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from pcweb.pages.framework.framework import framework
1414
from pcweb.pages.hosting.hosting import hosting_landing
1515
from pcweb.pages.use_cases.use_cases import use_cases_page
16+
from pcweb.pages.use_cases.finance_use_case import finance_use_case_page
1617

1718
from ...link_button import resources_button
1819
from ..sidebar import SidebarState
@@ -65,6 +66,14 @@ def link_item(name: str, url: str, active_str: str = ""):
6566
elif active_str == "hosting" or active_str == "cloud":
6667
active = router_path.contains("cloud") | router_path.contains("hosting")
6768

69+
elif active_str == "products":
70+
is_docs = router_path.contains("docs")
71+
is_open_source_page = router_path.contains("open-source")
72+
not_cloud = ~(router_path.contains("cloud") | router_path.contains("hosting"))
73+
not_ai_builder = ~router_path.contains("ai-builder")
74+
is_framework = (is_docs & not_cloud & not_ai_builder) | is_open_source_page
75+
active = router_path.contains("ai-builder") | router_path.contains("cloud") | router_path.contains("hosting") | is_framework
76+
6877
elif active_str == "pricing":
6978
active = router_path.contains("pricing")
7079

@@ -345,20 +354,126 @@ def _resource_section_column(
345354
)
346355

347356

357+
def solutions_section():
358+
_app_types_items = [
359+
{
360+
"label": "Internal Tools",
361+
"url": use_cases_page.path,
362+
"icon": "Settings01Icon",
363+
},
364+
{
365+
"label": "Data & AI Apps",
366+
"url": use_cases_page.path,
367+
"icon": "Database02Icon",
368+
},
369+
{
370+
"label": "Customer Facing Apps",
371+
"url": use_cases_page.path,
372+
"icon": "UserGroupIcon",
373+
},
374+
]
375+
376+
_industries_items = [
377+
{
378+
"label": "Finance",
379+
"url": finance_use_case_page.path,
380+
"icon": "CreditCardPosIcon",
381+
},
382+
{
383+
"label": "Healthcare",
384+
"url": use_cases_page.path,
385+
"icon": "HealthIcon",
386+
},
387+
{
388+
"label": "Energy",
389+
"url": use_cases_page.path,
390+
"icon": "ZapIcon",
391+
},
392+
{
393+
"label": "Enterprise",
394+
"url": use_cases_page.path,
395+
"icon": "Building01Icon",
396+
},
397+
]
398+
399+
def _link_button(label: str, url: str, icon: str) -> rx.Component:
400+
return rx.el.a(
401+
resources_button(
402+
ui.icon(icon, size=16, class_name="flex-shrink-0"),
403+
label,
404+
size="md",
405+
variant="transparent",
406+
class_name="justify-start w-full items-center gap-3",
407+
),
408+
to=url,
409+
class_name="w-full",
410+
)
411+
412+
def _solutions_section_column(
413+
section_title: str, solution_item: list[dict[str, str]]
414+
):
415+
return rx.box(
416+
rx.box(
417+
rx.text(
418+
section_title,
419+
class_name="text-sm text-slate-12 font-semibold px-2.5 py-1 pb-2",
420+
),
421+
*[
422+
_link_button(item["label"], item["url"], item["icon"])
423+
for item in solution_item
424+
],
425+
class_name="flex flex-col w-full p-2",
426+
),
427+
class_name="flex flex-col w-full",
428+
)
429+
430+
return ui.navigation_menu.content(
431+
_solutions_section_column("App Types", _app_types_items),
432+
_solutions_section_column("Industries", _industries_items),
433+
unstyled=True,
434+
class_name=ui.cn(
435+
ui.navigation_menu.class_names.CONTENT,
436+
"flex flex-row gap-4 rounded-xl w-[28rem] font-sans overflow-hidden p-1.5",
437+
),
438+
)
439+
440+
348441
def new_menu_trigger(
349442
title: str, url: str | None = None, active_str: str = ""
350443
) -> rx.Component:
351444
if url:
352445
return ui.navigation_menu.trigger(link_item(title, url, active_str))
446+
447+
router_path = rx.State.router.page.path
448+
active = False
449+
450+
if active_str == "products":
451+
is_docs = router_path.contains("docs")
452+
is_open_source_page = router_path.contains("open-source")
453+
not_cloud = ~(router_path.contains("cloud") | router_path.contains("hosting"))
454+
not_ai_builder = ~router_path.contains("ai-builder")
455+
is_framework = (is_docs & not_cloud & not_ai_builder) | is_open_source_page
456+
active = router_path.contains("ai-builder") | router_path.contains("cloud") | router_path.contains("hosting") | is_framework
457+
elif active_str:
458+
active = router_path.contains(active_str)
459+
460+
common_cn = "p-[1.406rem_0px] font-medium text-sm transition-colors"
461+
active_cn = "shadow-[inset_0_-0.5px_0_0_var(--c-violet-9)] text-violet-9 group-hover:text-violet-9"
462+
unactive_cn = "shadow-none text-secondary-11 group-hover:text-secondary-12"
463+
353464
return ui.navigation_menu.trigger(
354465
rx.box(
355466
rx.text(
356467
title,
357-
class_name="p-[1.406rem_0px] font-medium text-sm text-secondary-11 group-hover:text-secondary-12 transition-colors",
468+
class_name=common_cn + " " + rx.cond(active, active_cn, unactive_cn),
358469
),
359470
rx.icon(
360471
"chevron-down",
361-
class_name="chevron size-5 !text-secondary-11 group-hover:!text-secondary-12 py-1 mr-0 transition-all ease-out",
472+
class_name=rx.cond(
473+
active,
474+
"chevron size-5 !text-violet-9 group-hover:!text-violet-9 py-1 mr-0 transition-all ease-out",
475+
"chevron size-5 !text-secondary-11 group-hover:!text-secondary-12 py-1 mr-0 transition-all ease-out",
476+
),
362477
aria_hidden="true",
363478
),
364479
class_name="flex-row items-center gap-x-1 group user-select-none cursor-pointer xl:flex hidden",
@@ -420,6 +535,80 @@ def doc_section():
420535
)
421536

422537

538+
def products_section():
539+
from pcweb.pages.docs import ai_builder as ai_builder_pages
540+
from pcweb.pages.docs import hosting as hosting_page
541+
542+
return rx.cond(
543+
rx.State.router.page.path.contains("docs")
544+
| rx.State.router.page.path.contains("ai-builder")
545+
| rx.State.router.page.path.contains("cloud"),
546+
ui.navigation_menu.content(
547+
resource_item(
548+
"AI Builder",
549+
ai_builder_pages.overview.best_practices.path,
550+
"MagicWand01Icon",
551+
0,
552+
),
553+
resource_item(
554+
"Open Source",
555+
getting_started.introduction.path,
556+
"SourceCodeCircleIcon",
557+
0,
558+
),
559+
resource_item(
560+
"Cloud",
561+
hosting_page.deploy_quick_start.path,
562+
"CloudServerIcon",
563+
0,
564+
),
565+
unstyled=True,
566+
class_name=ui.cn(
567+
ui.navigation_menu.class_names.CONTENT,
568+
"flex flex-col gap-1.5 m-0 p-1.5 w-[280px] min-w-max h-auto",
569+
),
570+
),
571+
ui.navigation_menu.content(
572+
rx.el.a(
573+
rx.box(
574+
ui.icon("MagicWand01Icon", size=16, class_name="flex-shrink-0 text-secondary-11"),
575+
rx.text(
576+
"AI Builder",
577+
class_name="font-small text-secondary-11 truncate text-start w-[150px]",
578+
),
579+
rx.icon(
580+
tag="chevron_right",
581+
size=14,
582+
stroke_width=2,
583+
class_name="flex-shrink-0 text-slate-8 ml-auto",
584+
),
585+
class_name="flex flex-row flex-nowrap items-center gap-4 hover:bg-secondary-3 px-[1.125rem] py-2 rounded-md w-full transition-colors",
586+
),
587+
class_name="w-full text-secondary-11 hover:text-secondary-11",
588+
href=REFLEX_BUILD_URL,
589+
is_external=True,
590+
),
591+
resource_item(
592+
"Open Source",
593+
framework.path,
594+
"SourceCodeCircleIcon",
595+
0,
596+
),
597+
resource_item(
598+
"Cloud",
599+
hosting_landing.path,
600+
"CloudServerIcon",
601+
0,
602+
),
603+
unstyled=True,
604+
class_name=ui.cn(
605+
ui.navigation_menu.class_names.CONTENT,
606+
"flex flex-col gap-1.5 m-0 p-1.5 w-[280px] min-w-max h-auto",
607+
),
608+
),
609+
)
610+
611+
423612
def new_component_section() -> rx.Component:
424613
from pcweb.pages.docs import ai_builder as ai_builder_pages
425614
from pcweb.pages.docs import hosting as hosting_page
@@ -447,56 +636,14 @@ def new_component_section() -> rx.Component:
447636
unstyled=True,
448637
),
449638
),
450-
rx.cond(
451-
rx.State.router.page.path.contains("docs")
452-
| rx.State.router.page.path.contains("ai-builder")
453-
| rx.State.router.page.path.contains("cloud"),
454-
ui.navigation_menu.list(
455-
ui.navigation_menu.item(
456-
render_=link_item(
457-
"AI Builder",
458-
ai_builder_pages.overview.best_practices.path,
459-
"builder",
460-
),
461-
unstyled=True,
462-
),
463-
ui.navigation_menu.item(
464-
render_=link_item(
465-
"Open Source",
466-
getting_started.introduction.path,
467-
"framework",
468-
),
469-
unstyled=True,
470-
class_name="whitespace-nowrap",
471-
),
472-
ui.navigation_menu.item(
473-
render_=link_item(
474-
"Cloud", hosting_page.deploy_quick_start.path, "hosting"
475-
),
476-
unstyled=True,
477-
),
478-
class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none",
479-
),
480-
ui.navigation_menu.list(
481-
ui.navigation_menu.item(
482-
render_=link_item(
483-
"AI Builder",
484-
REFLEX_BUILD_URL,
485-
"builder",
486-
),
487-
unstyled=True,
488-
),
489-
ui.navigation_menu.item(
490-
render_=link_item("Open Source", framework.path, "framework"),
491-
class_name="whitespace-nowrap",
492-
unstyled=True,
493-
),
494-
ui.navigation_menu.item(
495-
render_=link_item("Cloud", hosting_landing.path, "hosting"),
496-
unstyled=True,
497-
),
498-
class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none",
639+
ui.navigation_menu.list(
640+
ui.navigation_menu.item(
641+
new_menu_trigger("Product", active_str="products"),
642+
products_section(),
643+
class_name="cursor-pointer",
644+
unstyled=True,
499645
),
646+
class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none",
500647
),
501648
ui.navigation_menu.item(
502649
new_menu_trigger("Docs"),
@@ -517,6 +664,12 @@ def new_component_section() -> rx.Component:
517664
class_name="cursor-pointer",
518665
unstyled=True,
519666
),
667+
ui.navigation_menu.item(
668+
new_menu_trigger("Solutions", active_str="use-cases"),
669+
solutions_section(),
670+
class_name="cursor-pointer",
671+
unstyled=True,
672+
),
520673
ui.navigation_menu.item(
521674
ui.navigation_menu.item(
522675
render_=link_item(

0 commit comments

Comments
 (0)