Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pcweb/components/icons/icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.7484 1.45825C13.2882 1.45825 12.9151 1.83135 12.9151 2.29159C12.9151 2.75182 13.2882 3.12492 13.7484 3.12492H14.2554C13.8453 3.49859 13.2917 3.96377 12.5801 4.48301C10.72 5.84039 7.77562 7.57079 3.48491 9.001C3.0483 9.14659 2.81233 9.6185 2.95787 10.0551C3.1034 10.4918 3.57534 10.7277 4.01196 10.5822C8.47125 9.09575 11.5685 7.28445 13.5626 5.82933C14.3457 5.25788 14.9579 4.74189 15.4151 4.32289V4.79159C15.4151 5.25182 15.7882 5.62492 16.2484 5.62492C16.7087 5.62492 17.0818 5.25182 17.0818 4.79159V2.29159C17.0818 1.83135 16.7087 1.45825 16.2484 1.45825H13.7484ZM15.8332 7.29159H15.815C15.6364 7.29158 15.4724 7.29157 15.3347 7.30097C15.1867 7.31107 15.0238 7.33408 14.8584 7.40259C14.5011 7.55061 14.2172 7.83451 14.0692 8.19184C14.0007 8.35725 13.9777 8.52 13.9676 8.66809C13.9582 8.80584 13.9582 8.96984 13.9582 9.14842V9.16659V16.6848C13.9582 16.8633 13.9582 17.0273 13.9676 17.1651C13.9777 17.3132 14.0007 17.4759 14.0692 17.6413C14.2172 17.9987 14.5011 18.2826 14.8584 18.4306C15.0238 18.4991 15.1867 18.5221 15.3347 18.5322C15.4724 18.5416 15.6365 18.5416 15.815 18.5416H15.8513C16.0298 18.5416 16.1939 18.5416 16.3317 18.5322C16.4798 18.5221 16.6425 18.4991 16.8079 18.4306C17.1653 18.2826 17.4492 17.9987 17.5972 17.6413C17.6657 17.4759 17.6887 17.3132 17.6988 17.1651C17.7082 17.0273 17.7082 16.8633 17.7082 16.6848V9.14842C17.7082 8.96992 17.7082 8.80584 17.6988 8.66809C17.6887 8.52 17.6657 8.35725 17.5972 8.19184C17.4492 7.83451 17.1653 7.55061 16.8079 7.40259C16.6425 7.33408 16.4798 7.31107 16.3317 7.30097C16.1939 7.29157 16.0299 7.29158 15.8513 7.29159H15.8332ZM9.98167 10.2083H9.99984H10.018C10.1966 10.2083 10.3606 10.2083 10.4983 10.2177C10.6464 10.2278 10.8092 10.2508 10.9746 10.3193C11.3319 10.4673 11.6158 10.7512 11.7638 11.1085C11.8323 11.2739 11.8553 11.4367 11.8654 11.5848C11.8748 11.7225 11.8748 11.8865 11.8748 12.0651V16.6848C11.8748 16.8633 11.8748 17.0273 11.8654 17.1651C11.8553 17.3132 11.8323 17.4759 11.7638 17.6413C11.6158 17.9987 11.3319 18.2826 10.9746 18.4306C10.8092 18.4991 10.6464 18.5221 10.4983 18.5322C10.3606 18.5416 10.1965 18.5416 10.018 18.5416H9.98167C9.80317 18.5416 9.63909 18.5416 9.50134 18.5322C9.35334 18.5221 9.19051 18.4991 9.02509 18.4306C8.66776 18.2826 8.38384 17.9987 8.23585 17.6413C8.16733 17.4759 8.14432 17.3132 8.13422 17.1651C8.12482 17.0273 8.12483 16.8633 8.12484 16.6848V12.0833V12.0651C8.12483 11.8865 8.12482 11.7225 8.13422 11.5848C8.14432 11.4367 8.16733 11.2739 8.23585 11.1085C8.38384 10.7512 8.66776 10.4673 9.02509 10.3193C9.19051 10.2508 9.35334 10.2278 9.50134 10.2177C9.63909 10.2083 9.80309 10.2083 9.98167 10.2083ZM4.1665 12.2916H4.14838C3.96983 12.2916 3.80576 12.2916 3.668 12.301C3.51996 12.3111 3.35718 12.3341 3.19176 12.4026C2.83443 12.5506 2.55053 12.8345 2.40251 13.1918C2.334 13.3573 2.31099 13.52 2.30089 13.6681C2.29149 13.8058 2.2915 13.9698 2.2915 14.1484V14.1666V16.6848C2.2915 16.8633 2.29149 17.0273 2.30089 17.1651C2.31099 17.3132 2.334 17.4759 2.40251 17.6413C2.55053 17.9987 2.83443 18.2826 3.19176 18.4306C3.35718 18.4991 3.51996 18.5221 3.668 18.5322C3.80575 18.5416 3.96978 18.5416 4.14833 18.5416H4.18464C4.36318 18.5416 4.52725 18.5416 4.66501 18.5322C4.81305 18.5221 4.97583 18.4991 5.14125 18.4306C5.49859 18.2826 5.78249 17.9987 5.9305 17.6413C5.99901 17.4759 6.02203 17.3132 6.03213 17.1651C6.04153 17.0273 6.04152 16.8633 6.0415 16.6848V14.1484C6.04152 13.9699 6.04153 13.8058 6.03213 13.6681C6.02203 13.52 5.99901 13.3573 5.9305 13.1918C5.78249 12.8345 5.49859 12.5506 5.14125 12.4026C4.97583 12.3341 4.81305 12.3111 4.66501 12.301C4.52725 12.2916 4.36322 12.2916 4.18467 12.2916H4.1665Z" fill="currentColor"/>
</svg>"""

markdown = """<svg width="27" height="16" viewBox="0 0 27 16" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M24.337 0q-.027 0-.052.026H2.168q-.47 0-.875.22Q.888.469.627.832q-.444.676-.34 1.48v11.975q.027.467.288.844t.626.584q.653.365 1.437.26V16l22.012-.026a1.63 1.63 0 0 0 .849-.286q.378-.259.587-.623.366-.624.261-1.429h.026l-.026-11.922a1.6 1.6 0 0 0-.287-.818 2.2 2.2 0 0 0-.626-.61A2.6 2.6 0 0 0 24.336 0m-.105 1.247h.053q.314 0 .522.13a.6.6 0 0 1 .222.168q.065.091.065.247l.026 11.844v.078q.052.415-.13.753a.6.6 0 0 1-.17.195.42.42 0 0 1-.248.065l-21.934.026h-.079a1.14 1.14 0 0 1-.73-.13.6.6 0 0 1-.223-.168.4.4 0 0 1-.065-.247V2.312l-.026-.104a.9.9 0 0 1 .143-.65q.196-.285.483-.285h21.856zM4.048 3.767v8.493h2.506V7.377l2.507 3.116 2.507-3.116v4.883h2.507V3.766h-2.507L9.06 6.883 6.554 3.766zm14.414 0V8.13h-2.507l3.76 4.13 3.76-4.13h-2.507V3.766z" fill="currentColor"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h27v16H0z"/></clipPath></defs></svg>"""

ICONS = {
# Socials
"github": github,
Expand Down Expand Up @@ -596,6 +598,7 @@
"python-01": python_01,
"shield-key": shield_key,
"chart-up": chart_up,
"markdown": markdown,
}


Expand Down
2 changes: 1 addition & 1 deletion pcweb/pages/docs_landing/views/hero.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def hero() -> rx.Component:
rx.el.div(
rx.el.p(
"About Reflex",
class_name="text-sm font-[525] text-m-slate-10 dark:text-m-slate-6",
class_name="text-sm font-[525] text-primary-10 dark:text-m-slate-6",
),
rx.el.h1(
"Reflex Documentation",
Expand Down
193 changes: 125 additions & 68 deletions pcweb/templates/docpage/docpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
import reflex as rx
import reflex_ui as ui
from reflex.components.radix.themes.base import LiteralAccentColor
from reflex.experimental.client_state import ClientStateVar
from reflex.utils.format import to_snake_case, to_title_case

from pcweb.components.button import button
from pcweb.components.icons.icons import get_icon
from pcweb.components.marketing_button import button as marketing_button
from pcweb.route import Route, get_path
from pcweb.styles.colors import c_color

Expand Down Expand Up @@ -156,8 +157,8 @@ def footer_link_flex(heading: str, links):

def thumb_card(score: int, icon: str) -> rx.Component:
return rx.el.button(
rx.icon(
tag=icon,
ui.icon(
icon,
color=rx.cond(
FeedbackState.score == score, c_color("slate", 11), c_color("slate", 9)
),
Expand All @@ -173,53 +174,39 @@ def thumb_card(score: int, icon: str) -> rx.Component:

def thumbs_cards() -> rx.Component:
return rx.hstack(
thumb_card(1, "thumbs-up"),
thumb_card(0, "thumbs-down"),
thumb_card(1, "ThumbsUpIcon"),
thumb_card(0, "ThumbsDownIcon"),
gap="8px",
)


def feedback_content() -> rx.Component:
return rx.box(
rx.box(
rx.text(
"Send feedback",
class_name="font-md text-slate-11",
),
return rx.el.div(
rx.el.div(
rx.form(
rx.box(
rx.el.textarea(
rx.el.div(
ui.textarea(
name="feedback",
placeholder="Write a comment…",
type="text",
max_length=500,
enter_key_submit=True,
resize="vertical",
required=True,
class_name="w-full h-full p-2 text-slate-11 font-small bg-white-1 border border-slate-4 rounded-[10px] max-h-[300px] min-h-[72px] outline-none overflow-y-auto placeholder-slate-9 focus:border-violet-9 focus:border-1",
),
thumbs_cards(),
rx.el.input(
ui.input(
name="email",
type="email",
placeholder="Contact email (optional)",
max_length=100,
class_name="w-full h-full p-2 text-slate-11 font-small bg-white-1 border border-slate-4 rounded-[10px] box-border outline-none placeholder-slate-9 focus:border-violet-9 focus:border-1",
),
rx.box(
rx.popover.close(
button(
"Send",
type="submit",
)
),
rx.popover.close(
button(
"Cancel",
variant="secondary",
)
),
class_name="flex flex-row gap-4 justify-between items-center",
ui.popover.close(
ui.button(
"Send feedback",
type="submit",
class_name="w-full",
)
),
class_name="w-full gap-4 flex flex-col",
),
Expand All @@ -229,48 +216,102 @@ def feedback_content() -> rx.Component:
),
class_name="flex flex-col gap-4 w-full",
),
class_name="rounded-[26px] bg-white-1 w-[341px] max-h-[564px] shadow-large h-auto p-4",
class_name="p-2",
)


def feedback_button() -> rx.Component:
thumb_cn = " flex flex-row items-center justify-center gap-2 text-slate-9 whitespace-nowrap border border-slate-5 bg-slate-1 shadow-large cursor-pointer transition-bg hover:bg-slate-3 font-small"
return rx.popover.root(
rx.box(
rx.popover.trigger(
rx.box(
rx.icon(tag="thumbs-up", size=15, class_name="!text-slate-9"),
rx.text(
"Yes",
return ui.popover.root(
ui.popover.trigger(
render_=rx.el.div(
rx.el.button(
ui.icon("ThumbsUpIcon"),
"Yes",
type="button",
class_name=ui.cn(
"w-full gap-2 border-r-0 px-3 py-0.5 rounded-[20px_0_0_20px]",
thumb_cn,
),
class_name="w-full gap-2 border-r-0 px-3 py-0.5 rounded-[20px_0_0_20px]"
+ thumb_cn,
aria_label="Yes",
on_click=FeedbackState.set_score(1),
),
custom_attrs={"role": "button"},
aria_label="Yes",
on_click=FeedbackState.set_score(1),
),
rx.popover.trigger(
rx.box(
rx.icon(tag="thumbs-down", size=15, class_name="!text-slate-9"),
rx.text(
"No",
rx.el.button(
ui.icon("ThumbsDownIcon"),
"No",
type="button",
class_name=ui.cn(
"w-full gap-2 border-r-0 px-3 py-0.5 rounded-[0_20px_20px_0]",
thumb_cn,
),
class_name="w-full gap-2 px-3 py-0.5 rounded-[0_20px_20px_0]"
+ thumb_cn,
aria_label="No",
on_click=FeedbackState.set_score(0),
),
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",
),
class_name="w-full lg:w-auto items-center flex flex-row",
),
rx.popover.content(
feedback_content(),
align="start",
class_name="border-none left-0 lg:left-[-255px] origin-bottom lg:origin-bottom-right !p-0 overflow-visible !bg-transparent shadow-none",
avoid_collisions=True,
ui.popover.portal(
ui.popover.positioner(
ui.popover.popup(
render_=feedback_content(),
),
),
),
)


def feedback_button_toc() -> rx.Component:
return ui.popover(
trigger=marketing_button(
ui.icon("ThumbsUpIcon"),
"Send feedback",
variant="ghost",
size="sm",
type="button",
on_click=FeedbackState.set_score(1),
class_name="justify-start text-m-slate-7 dark:text-m-slate-6",
),
content=feedback_content(),
)


@rx.memo
def copy_to_markdown(text: str) -> rx.Component:
copied = ClientStateVar.create("is_copied", default=False, global_ref=False)
return marketing_button(
rx.cond(
copied.value,
ui.icon(
"CheckmarkCircle02Icon",
),
get_icon("markdown", class_name="[&_svg]:h-4 [&_svg]:w-auto"),
),
"Copy to markdown",
type="button",
size="sm",
variant="ghost",
class_name="justify-start text-m-slate-7 dark:text-m-slate-6",
on_click=[
rx.call_function(copied.set_value(True)),
rx.set_clipboard(text),
],
on_mouse_down=rx.call_function(copied.set_value(False)).debounce(1500),
)


def ask_ai_chat() -> rx.Component:
from pcweb.pages.docs import ai_builder as ai_builder_pages

return rx.el.a(
marketing_button(
ui.icon("AiChat02Icon"),
"Ask AI about this page",
size="sm",
variant="ghost",
class_name="justify-start text-m-slate-7 dark:text-m-slate-6",
native_button=False,
),
to=ai_builder_pages.integrations.mcp_overview.path,
)


Expand Down Expand Up @@ -474,11 +515,11 @@ def get_toc(source, href, component_list=None):
env["__xd"] = xd

# Get the content of the document.
source = source.content
doc_content = source.content

# Get the blocks in the source code.
# Note: we must use reflex-web's special flexdown instance xd here - it knows about all custom block types (like DemoBlock)
blocks = xd.get_blocks(source, href)
blocks = xd.get_blocks(doc_content, href)

content_pieces = []
for block in blocks:
Expand All @@ -502,7 +543,7 @@ def get_toc(source, href, component_list=None):
headings.append((1, "API Reference"))
for component_tuple in component_list:
headings.append((2, component_tuple[1]))
return headings
return headings, doc_content


def docpage(
Expand Down Expand Up @@ -617,13 +658,21 @@ def wrapper(*args, **kwargs) -> rx.Component:
links.append(rx.fragment())

toc = []
doc_content = None
if not isinstance(contents, rx.Component):
comp = contents(*args, **kwargs)
else:
comp = contents

if isinstance(comp, tuple):
toc, comp = comp
if isinstance(comp, tuple) and len(comp) == 2:
first, second = comp
# Check if first is (toc, doc_content) from get_toc
if isinstance(first, tuple) and len(first) == 2:
toc, doc_content = first
comp = second
else:
# Legacy format: (toc, comp)
toc, comp = first, second

show_right_sidebar = right_sidebar and len(toc) >= 2
return rx.box(
Expand Down Expand Up @@ -720,9 +769,18 @@ def wrapper(*args, **kwargs) -> rx.Component:
)
for level, text in toc
],
class_name="flex flex-col gap-y-1 list-none shadow-[1.5px_0_0_0_var(--m-slate-4)_inset] dark:shadow-[1.5px_0_0_0_var(--m-slate-9)_inset]",
id="toc-navigation",
class_name="flex flex-col gap-y-1 list-none shadow-[1.5px_0_0_0_var(--m-slate-4)_inset] dark:shadow-[1.5px_0_0_0_var(--m-slate-9)_inset] max-h-[80vh]",
),
rx.el.div(
feedback_button_toc(),
copy_to_markdown(text=doc_content)
if doc_content
else None,
ask_ai_chat(),
class_name="flex flex-col mt-1.5 justify-start",
),
class_name="flex flex-col justify-start gap-y-4 max-h-[80vh] overflow-y-auto sticky top-4",
class_name="flex flex-col justify-start gap-y-4 overflow-y-auto sticky top-4",
),
class_name=(
"w-full h-full"
Expand All @@ -732,7 +790,6 @@ def wrapper(*args, **kwargs) -> rx.Component:
" mt-[90px]",
)
),
id="toc-navigation",
),
class_name=(
"w-[240px] h-screen sticky top-0 shrink-0 hidden xl:block"
Expand Down
Loading