diff --git a/assets/fonts.css b/assets/fonts.css new file mode 100644 index 000000000..f922a1797 --- /dev/null +++ b/assets/fonts.css @@ -0,0 +1,18 @@ +@font-face { + font-family: 'Instrument Sans'; + font-style: normal; + font-weight: 400 700; + font-stretch: 100%; + font-display: swap; + src: local('Instrument Sans'), + url("/fonts/instrument-sans.woff2") format("woff2"); +} + +@font-face { + font-family: 'JetBrains Mono'; + font-style: normal; + font-weight: 400 700; + font-display: swap; + src: local('JetBrains Mono'), + url("/fonts/jetbrains-mono.woff2") format("woff2"); +} \ No newline at end of file diff --git a/assets/fonts/instrument-sans.woff2 b/assets/fonts/instrument-sans.woff2 new file mode 100644 index 000000000..af9b4c672 Binary files /dev/null and b/assets/fonts/instrument-sans.woff2 differ diff --git a/assets/fonts/jetbrains-mono.woff2 b/assets/fonts/jetbrains-mono.woff2 new file mode 100644 index 000000000..ad8149ba9 Binary files /dev/null and b/assets/fonts/jetbrains-mono.woff2 differ diff --git a/assets/landing/ai_bento/light/bento1.avif b/assets/landing/ai_bento/light/bento1.avif index b7212f678..71bd8f938 100644 Binary files a/assets/landing/ai_bento/light/bento1.avif and b/assets/landing/ai_bento/light/bento1.avif differ diff --git a/assets/landing/ai_bento/light/bento2.avif b/assets/landing/ai_bento/light/bento2.avif index e985b2f59..c99203879 100644 Binary files a/assets/landing/ai_bento/light/bento2.avif and b/assets/landing/ai_bento/light/bento2.avif differ diff --git a/assets/landing/ai_bento/light/bento3.avif b/assets/landing/ai_bento/light/bento3.avif index 90cc0fec3..5c9a6dd42 100644 Binary files a/assets/landing/ai_bento/light/bento3.avif and b/assets/landing/ai_bento/light/bento3.avif differ diff --git a/assets/landing/ai_bento/light/bento4.avif b/assets/landing/ai_bento/light/bento4.avif index e3142a834..96228cd02 100644 Binary files a/assets/landing/ai_bento/light/bento4.avif and b/assets/landing/ai_bento/light/bento4.avif differ diff --git a/assets/landing/ai_bento/light/bento5.avif b/assets/landing/ai_bento/light/bento5.avif index 505c5bcc3..1e0bf2ac8 100644 Binary files a/assets/landing/ai_bento/light/bento5.avif and b/assets/landing/ai_bento/light/bento5.avif differ diff --git a/assets/landing/app_build/user.avif b/assets/landing/app_build/user.avif new file mode 100644 index 000000000..5bd5581ec Binary files /dev/null and b/assets/landing/app_build/user.avif differ diff --git a/assets/landing/app_build/user.webp b/assets/landing/app_build/user.webp deleted file mode 100644 index df584c74b..000000000 Binary files a/assets/landing/app_build/user.webp and /dev/null differ diff --git a/assets/landing/products/light/product_ai.avif b/assets/landing/products/light/product_ai.avif index 799930ba5..ab7982289 100644 Binary files a/assets/landing/products/light/product_ai.avif and b/assets/landing/products/light/product_ai.avif differ diff --git a/assets/landing/products/light/product_framework.avif b/assets/landing/products/light/product_framework.avif index fffd95793..ff28b264d 100644 Binary files a/assets/landing/products/light/product_framework.avif and b/assets/landing/products/light/product_framework.avif differ diff --git a/pcweb/components/docpage/navbar/buttons/discord.py b/pcweb/components/docpage/navbar/buttons/discord.py index 85af131db..ec1892ce2 100644 --- a/pcweb/components/docpage/navbar/buttons/discord.py +++ b/pcweb/components/docpage/navbar/buttons/discord.py @@ -9,10 +9,11 @@ def discord() -> rx.Component: return ui.link( render_=ui.button( get_icon(icon="discord_navbar", class_name="shrink-0 text-secondary-11"), - custom_attrs={"aria-label": "Discord link"}, + custom_attrs={"aria-label": "Join Reflex Discord community"}, size="icon-sm", variant="outline", class_name="text-secondary-11", ), to=DISCORD_URL, + custom_attrs={"aria-label": "Join Reflex Discord community"}, ) diff --git a/pcweb/components/docpage/navbar/buttons/github.py b/pcweb/components/docpage/navbar/buttons/github.py index 0cd911fb5..6d87b7248 100644 --- a/pcweb/components/docpage/navbar/buttons/github.py +++ b/pcweb/components/docpage/navbar/buttons/github.py @@ -10,10 +10,15 @@ def github() -> rx.Component: render_=ui.button( get_icon(icon="github_navbar", class_name="shrink-0 text-secondary-11"), f"{GITHUB_STARS // 1000}K", - custom_attrs={"aria-label": "Github link"}, + custom_attrs={ + "aria-label": f"View Reflex on GitHub - {GITHUB_STARS // 1000}K stars" + }, size="sm", variant="outline", class_name="text-secondary-11", ), to=GITHUB_URL, + custom_attrs={ + "aria-label": f"View Reflex on GitHub - {GITHUB_STARS // 1000}K stars" + }, ) diff --git a/pcweb/components/docpage/navbar/buttons/sidebar.py b/pcweb/components/docpage/navbar/buttons/sidebar.py index bf65df8a4..f8bf1e59b 100644 --- a/pcweb/components/docpage/navbar/buttons/sidebar.py +++ b/pcweb/components/docpage/navbar/buttons/sidebar.py @@ -16,12 +16,18 @@ def social_menu_item( url="/", border: bool = False, ) -> rx.Component: + aria_labels = { + "github": "Visit Reflex on GitHub", + "twitter": "Follow Reflex on X", + "discord": "Join Reflex Discord community", + } return rx.link( get_icon(icon=icon, class_name="!text-slate-9"), class_name="flex justify-center items-center gap-2 hover:bg-slate-3 px-4 py-[0.875rem] w-full h-[47px] transition-bg overflow-hidden" + (" border-slate-4 border-x border-solid border-y-0" if border else ""), href=url, is_external=True, + custom_attrs={"aria-label": aria_labels.get(icon, f"Visit {icon}")}, ) @@ -90,6 +96,7 @@ def navbar_sidebar_drawer(trigger) -> rx.Component: ), on_click=toggle_color_mode, class_name="flex flex-row justify-center items-center px-3 py-0.5 w-full h-[47px]", + custom_attrs={"aria-label": "Toggle color mode"}, ), class_name="flex flex-col items-center bg-slate-1 w-full h-full", ), diff --git a/pcweb/components/docpage/navbar/navbar.py b/pcweb/components/docpage/navbar/navbar.py index 175d48a93..41ede2355 100644 --- a/pcweb/components/docpage/navbar/navbar.py +++ b/pcweb/components/docpage/navbar/navbar.py @@ -678,15 +678,14 @@ def new_component_section() -> rx.Component: class_name="flex flex-row gap-x-0 items-center", unstyled=True, ), + custom_attrs={"role": "menuitem"}, ), - ui.navigation_menu.list( - ui.navigation_menu.item( - new_menu_trigger("Product", active_str="products"), - products_section(), - class_name="cursor-pointer", - unstyled=True, - ), - class_name="xl:flex hidden flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none", + ui.navigation_menu.item( + new_menu_trigger("Product", active_str="products"), + products_section(), + class_name="cursor-pointer", + unstyled=True, + custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( new_menu_trigger("Docs"), @@ -700,38 +699,44 @@ def new_component_section() -> rx.Component: ), class_name="cursor-pointer", unstyled=True, + custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( new_menu_trigger("Resources"), new_resource_section(), class_name="cursor-pointer", unstyled=True, + custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( new_menu_trigger("Solutions", active_str="use-cases"), solutions_section(), class_name="cursor-pointer", unstyled=True, + custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( - ui.navigation_menu.item( - render_=link_item( - "Pricing", - "/pricing", - "pricing", - ), - unstyled=True, + link_item( + "Pricing", + "/pricing", + "pricing", ), - class_name="xl:flex hidden", + class_name="cursor-pointer", + custom_attrs={"role": "menuitem"}, + aria_label="Pricing", unstyled=True, ), class_name="flex flex-row items-center gap-0 lg:gap-5 2xl:gap-7 m-0 h-full list-none", custom_attrs={"role": "menubar"}, ), ui.navigation_menu.list( - ui.navigation_menu.item(search_bar()), - ui.navigation_menu.item(github()), - ui.navigation_menu.item(discord(), class_name="xl:flex hidden"), + ui.navigation_menu.item(search_bar(), custom_attrs={"role": "menuitem"}), + ui.navigation_menu.item(github(), custom_attrs={"role": "menuitem"}), + ui.navigation_menu.item( + discord(), + class_name="xl:flex hidden", + custom_attrs={"role": "menuitem"}, + ), ui.navigation_menu.item( rx.link( ui.button( @@ -745,6 +750,7 @@ def new_component_section() -> rx.Component: href=f"{REFLEX_CLOUD_URL.strip('/')}/?redirect_url={REFLEX_BUILD_URL}", ), class_name="desktop-only", + custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( demo_form_dialog( @@ -757,11 +763,13 @@ def new_component_section() -> rx.Component: ), unstyled=True, class_name="xl:flex hidden", + custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( navbar_sidebar_button(), class_name="xl:hidden flex", unstyled=True, + custom_attrs={"role": "menuitem"}, ), class_name="flex flex-row gap-2 m-0 h-full list-none items-center", custom_attrs={"role": "menubar"}, diff --git a/pcweb/components/docpage/sidebar/sidebar.py b/pcweb/components/docpage/sidebar/sidebar.py index 493ab5567..77ca712a7 100644 --- a/pcweb/components/docpage/sidebar/sidebar.py +++ b/pcweb/components/docpage/sidebar/sidebar.py @@ -332,6 +332,7 @@ def sidebar_category(name: str, url: str, icon: str, index: int): to=url, on_click=rx.prevent_default, class_name="inset-0 absolute z-[-1]", + aria_label=f"Navigate to {name}", ), class_name="w-full text-slate-9 hover:!text-slate-9 relative", on_click=[SidebarState.set_sidebar_index(index), rx.redirect(url)], @@ -353,7 +354,7 @@ def create_sidebar_section( index = index.to(list) return rx.el.li( rx.link( - rx.el.h5( + rx.el.h2( section_title, class_name="font-smbold text-[0.875rem] text-slate-12 hover:text-violet-9 leading-5 tracking-[-0.01313rem] transition-color", ), diff --git a/pcweb/pages/blog/blog.py b/pcweb/pages/blog/blog.py index 5b833bb70..a2589cce9 100644 --- a/pcweb/pages/blog/blog.py +++ b/pcweb/pages/blog/blog.py @@ -14,7 +14,8 @@ def first_post_card(meta: dict, path: str) -> rx.Component: rx.box( rx.image( src=meta["image"], - loading="lazy", + loading="eager", + custom_attrs={"fetchPriority": "high"}, alt="Image preview for blog post: " + str(meta["title"]), class_name="group-hover:scale-105 w-full h-full transition-transform duration-150 ease-out object-left object-cover", ), @@ -29,27 +30,27 @@ def first_post_card(meta: dict, path: str) -> rx.Component: rx.moment( str(meta["date"]), format="MMM DD, YYYY", - class_name="font-normal text-slate-9 text-sm", + class_name="font-normal text-secondary-11 text-sm", ), class_name="flex flex-col gap-1 p-[0.625rem_0.75rem_0rem_0.75rem] w-full", ), rx.box( rx.text( meta["description"], - class_name="line-clamp-2 font-base text-slate-11", + class_name="line-clamp-2 font-base text-secondary-11", ), rx.box( rx.text( meta["author"], - class_name="font-small text-slate-9 truncate overflow-hidden text-ellipsis max-w-[50%] min-w-0 flex-shrink", + class_name="font-small text-secondary-11 truncate overflow-hidden text-ellipsis max-w-[50%] min-w-0 flex-shrink", ), rx.el.button( rx.text( "Read more", - class_name="font-small text-slate-9", + class_name="font-small text-secondary-11", ), get_icon(icon="new_tab", class_name="p-[5px]"), - class_name="flex items-center border-slate-5 bg-slate-1 hover:bg-slate-3 shadow-small pl-[5px] border rounded-md w-auto max-w-full text-slate-9 transition-bg cursor-pointer overflow-hidden flex-shrink-0", + class_name="flex items-center border-slate-5 bg-slate-1 hover:bg-slate-3 shadow-small pl-[5px] border rounded-md w-auto max-w-full text-secondary-11 transition-bg cursor-pointer overflow-hidden flex-shrink-0", ), class_name="flex flex-row justify-between items-center gap-1 min-w-0 w-full h-auto", ), @@ -69,7 +70,8 @@ def card_content(meta: dict, path: str) -> rx.Component: rx.box( rx.image( src=meta["image"], - loading="lazy", + loading="eager", + custom_attrs={"fetchPriority": "high"}, alt="Image preview for blog post: " + str(meta["title"]), class_name="group-hover:scale-105 w-full h-full transition-transform duration-150 ease-out object-left object-cover", ), @@ -77,34 +79,34 @@ def card_content(meta: dict, path: str) -> rx.Component: ), rx.box( rx.box( - rx.el.h4( + rx.el.span( meta["title"], class_name="font-smbold text-slate-12", ), rx.moment( str(meta["date"]), format="MMM DD, YYYY", - class_name="font-normal text-slate-9 text-xs", + class_name="font-normal text-secondary-11 text-xs", ), class_name="flex flex-col gap-1 p-[0.625rem_0.75rem_0rem_0.75rem] w-full", ), rx.box( rx.text( meta["description"], - class_name="line-clamp-2 font-small text-slate-11", + class_name="line-clamp-2 font-small text-secondary-11", ), rx.box( rx.text( meta["author"], - class_name="font-small text-slate-9 truncate overflow-hidden text-ellipsis max-w-[50%] min-w-0 flex-shrink", + class_name="font-small text-secondary-11 truncate overflow-hidden text-ellipsis max-w-[50%] min-w-0 flex-shrink", ), rx.el.button( rx.text( "Read more", - class_name="font-small text-slate-9", + class_name="font-small text-secondary-11", ), get_icon(icon="new_tab", class_name="p-[5px]"), - class_name="flex items-center border-slate-5 bg-slate-1 hover:bg-slate-3 shadow-small pl-[5px] border rounded-md w-auto max-w-full text-slate-9 transition-bg cursor-pointer overflow-hidden", + class_name="flex items-center border-slate-5 bg-slate-1 hover:bg-slate-3 shadow-small pl-[5px] border rounded-md w-auto max-w-full text-secondary-11 transition-bg cursor-pointer overflow-hidden", ), class_name="flex flex-row justify-between items-center gap-1 w-full h-auto", ), diff --git a/pcweb/pages/blog/page.py b/pcweb/pages/blog/page.py index a5a539ad3..dfe7b228b 100644 --- a/pcweb/pages/blog/page.py +++ b/pcweb/pages/blog/page.py @@ -62,7 +62,7 @@ def page(document, route) -> rx.Component: rx.box( get_icon("arrow_right", class_name="rotate-180"), "Back to Blog", - class_name="box-border flex justify-center items-center gap-2 border-slate-5 bg-slate-1 hover:bg-slate-3 -mb-4 px-3 py-0.5 border rounded-full font-small text-slate-9 transition-bg cursor-pointer", + class_name="box-border flex justify-center items-center gap-2 border-slate-5 bg-slate-1 hover:bg-slate-3 -mb-4 px-3 py-0.5 border rounded-full font-small text-secondary-11 transition-bg cursor-pointer", ), underline="none", href="/blog", @@ -84,14 +84,15 @@ def page(document, route) -> rx.Component: str(meta["date"]), format="MMM DD, YYYY", ), - class_name="flex items-center gap-2 !font-normal font-small text-nowrap text-slate-9", + class_name="flex items-center gap-2 !font-normal font-small text-nowrap text-secondary-11", ), class_name="section-header", ), rx.image( src=f"{meta['image']}", alt=f"Image for blog post: {meta['title']}", - loading="lazy", + loading="eager", + custom_attrs={"fetchPriority": "high"}, class_name="rounded-[1.125rem] w-auto object-contain max-w-full max-h-[40rem]", ), rx.box( diff --git a/pcweb/pages/landing/views/app_build.py b/pcweb/pages/landing/views/app_build.py index e9ce48f96..860ceb26f 100644 --- a/pcweb/pages/landing/views/app_build.py +++ b/pcweb/pages/landing/views/app_build.py @@ -85,7 +85,7 @@ def user_profile(): return rx.el.div( rx.el.div( rx.image( - src="/landing/app_build/user.webp", + src="/landing/app_build/user.avif", loading="lazy", alt="User profile image", class_name="object-cover pointer-events-none", @@ -316,14 +316,14 @@ def graph_overview(): rx.el.div( rx.el.span(class_name="size-4 rounded-sm bg-violet-8"), "Peak Performance", - class_name="flex flex-row items-center gap-2 text-xs font-medium text-slate-10", + class_name="flex flex-row items-center gap-2 text-xs font-medium text-secondary-11", ), rx.el.div( rx.el.span( class_name="size-4 rounded-sm bg-violet-4 dark:bg-[#151618]" ), "Capacity Per Day", - class_name="flex flex-row items-center gap-2 text-xs font-medium text-slate-10", + class_name="flex flex-row items-center gap-2 text-xs font-medium text-secondary-11", ), class_name="flex flex-row items-center gap-4", ), @@ -333,7 +333,7 @@ def graph_overview(): "24 June ", rx.el.span(" - ", class_name="text-slate-8 ml-0.5"), " Today", - class_name="text-slate-10 dark:text-secondary-11 text-sm font-medium rounded-lg px-3.5 h-8 border border-slate-4 dark:border-[#1C2024] bg-white-1 flex items-center", + class_name="text-secondary-11 text-sm font-medium rounded-lg px-3.5 h-8 border border-slate-4 dark:border-[#1C2024] bg-white-1 flex items-center", ), class_name="flex flex-row justify-between items-baseline w-full", ), diff --git a/pcweb/pages/landing/views/hero.py b/pcweb/pages/landing/views/hero.py index aff10201e..f505bdd31 100644 --- a/pcweb/pages/landing/views/hero.py +++ b/pcweb/pages/landing/views/hero.py @@ -291,7 +291,7 @@ def prompt_box() -> rx.Component: type="button", variant="ghost", on_click=show_default_prompt.set_value(False), - class_name="rounded-[10px] font-semibold text-slate-10 dark:text-secondary-11", + class_name="rounded-[10px] font-semibold text-secondary-11", ), on_drop=SubmitPromptState.handle_upload( rx.upload_files( @@ -310,7 +310,6 @@ def prompt_box() -> rx.Component: max_size=MAX_FILE_SIZE_BYTES, multiple=True, id="upload-image-button", - aria_label="Upload images", ), ui.button( "Build with AI", @@ -331,6 +330,14 @@ def prompt_box() -> rx.Component: if (window.innerWidth < 1024) {{ {show_default_prompt.set}(false); }} + const uploadContainer = document.getElementById('upload-image-button'); + if (uploadContainer) {{ + const fileInput = uploadContainer.querySelector('input[type="file"]'); + if (fileInput) {{ + fileInput.setAttribute('aria-label', 'Upload images for AI builder'); + fileInput.setAttribute('title', 'Upload images'); + }} + }} """ ), on_submit=SubmitPromptState.redirect_to_ai_builder, diff --git a/pcweb/pcweb.py b/pcweb/pcweb.py index ba2594a8d..e7c0e7fc5 100644 --- a/pcweb/pcweb.py +++ b/pcweb/pcweb.py @@ -35,17 +35,18 @@ + favicons_links() + [ rx.el.link( - rel="preconnect", - href="https://fonts.googleapis.com", + rel="preload", + href="/fonts/instrument-sans.woff2", + custom_attrs={"as": "font"}, + type="font/woff2", + cross_origin="anonymous", ), rx.el.link( - rel="preconnect", - href="https://fonts.gstatic.com", - cross_origin="", - ), - rx.el.link( - href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400..700&family=JetBrains+Mono:wght@400..700&display=swap", - rel="stylesheet", + rel="preload", + href="/fonts/jetbrains-mono.woff2", + custom_attrs={"as": "font"}, + type="font/woff2", + cross_origin="anonymous", ), ], ) diff --git a/pcweb/styles/styles.py b/pcweb/styles/styles.py index 1b82950f4..56f853cac 100644 --- a/pcweb/styles/styles.py +++ b/pcweb/styles/styles.py @@ -66,6 +66,7 @@ def get_code_style_rdx(color: str): # Fonts to include. STYLESHEETS = [ + "fonts.css", "custom-colors.css", "tailwind-theme.css", ] diff --git a/pcweb/templates/docpage/docpage.py b/pcweb/templates/docpage/docpage.py index 6e75d2159..c4fe49cc1 100644 --- a/pcweb/templates/docpage/docpage.py +++ b/pcweb/templates/docpage/docpage.py @@ -242,6 +242,8 @@ def feedback_button() -> rx.Component: class_name="w-full gap-2 border-r-0 px-3 py-0.5 rounded-[20px_0_0_20px]" + thumb_cn, ), + custom_attrs={"role": "button"}, + aria_label="Yes", on_click=FeedbackState.set_score(1), ), rx.popover.trigger( @@ -253,6 +255,8 @@ def feedback_button() -> rx.Component: class_name="w-full gap-2 px-3 py-0.5 rounded-[0_20px_20px_0]" + thumb_cn, ), + custom_attrs={"role": "button"}, + aria_label="No", on_click=FeedbackState.set_score(0), ), class_name="w-full lg:w-auto items-center flex flex-row", diff --git a/pcweb/views/footer.py b/pcweb/views/footer.py index ac6f88b8d..e9b296dc7 100644 --- a/pcweb/views/footer.py +++ b/pcweb/views/footer.py @@ -25,7 +25,7 @@ def footer_link(text: str, href: str) -> rx.Component: return rx.link( text, href=href, - class_name="font-small text-slate-9 hover:!text-slate-11 no-underline transition-color", + class_name="font-small text-secondary-11 hover:!text-secondary-12 no-underline transition-color", ) @@ -48,6 +48,7 @@ def social_menu_item(icon: str, url: str = "/", class_name: str = "") -> rx.Comp + class_name, href=url, is_external=True, + aria_label=f"Social link for {icon}", ) @@ -80,7 +81,7 @@ def menu_socials() -> rx.Component: def newsletter_form() -> rx.Component: return ( rx.box( - rx.el.h4( + rx.el.span( "Join Newsletter", class_name="font-instrument-sans font-semibold text-slate-12 text-sm leading-tight", ),