Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a sticky Built with Reflex badge #4584

Merged
merged 21 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d4b6ab4
add the watermark class
Lendemor Jan 2, 2025
2dcd516
Merge branch 'main' into lendemor/add_sticky_logo
Lendemor Jan 21, 2025
184ef85
remove shortcut exposing badge publicly for now
Lendemor Jan 21, 2025
ad88c5d
Merge branch 'main' into lendemor/add_sticky_logo
Lendemor Jan 22, 2025
8d58234
Merge remote-tracking branch 'origin/main' into lendemor/add_sticky_logo
masenf Jan 24, 2025
87c1df3
Rename as "sticky" because "watermark" has a negative connotation
masenf Jan 24, 2025
bb7619e
Add config `show_built_with_reflex`
masenf Jan 24, 2025
6c76b91
py3.11 compatible f-string
masenf Jan 24, 2025
8c3defa
sticky badge inherit from A instead of using on_click/redirect
Lendemor Jan 24, 2025
a978684
fix integration test
Lendemor Jan 24, 2025
c64ed43
Move export checking logic to reflex CLI
masenf Jan 24, 2025
c6d874a
rx.logo: make it accessible to screen readers
masenf Jan 25, 2025
41cb507
Hide the built with reflex badge for localhost
masenf Jan 25, 2025
8fdf0ff
Merge remote-tracking branch 'origin/main' into lendemor/add_sticky_logo
masenf Jan 25, 2025
98fb2d5
Revert "fix integration test"
masenf Jan 25, 2025
44ce7d1
experimental: do not show warning for internal imports
masenf Jan 31, 2025
8df1890
add help link for show_built_with_reflex option
masenf Jan 31, 2025
aa5c9b7
Merge remote-tracking branch 'origin/main' into lendemor/add_sticky_logo
masenf Jan 31, 2025
ce6be1c
pre-commit fixes
masenf Jan 31, 2025
2630584
Merge branch 'main' into lendemor/add_sticky_logo
masenf Feb 1, 2025
ca18b1c
Merge remote-tracking branch 'origin/main' into lendemor/add_sticky_logo
masenf Feb 3, 2025
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
19 changes: 16 additions & 3 deletions reflex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
Default404Page,
wait_for_client_redirect,
)
from reflex.components.core.sticky import sticky
from reflex.components.core.upload import Upload, get_upload_dir
from reflex.components.radix import themes
from reflex.config import environment, get_config
Expand Down Expand Up @@ -858,6 +859,15 @@ def _setup_error_boundary(self):
continue
self._pages[k] = self._add_error_boundary_to_component(component)

def _setup_sticky_badge(self):
"""Add the sticky badge to the app."""
for k, component in self._pages.items():
# Would be nice to share single sticky_badge across all pages, but
# it bungles the StatefulComponent compile step.
sticky_badge = sticky()
sticky_badge._add_style_recursive({})
self._pages[k] = Fragment.create(sticky_badge, component)

def _apply_decorated_pages(self):
"""Add @rx.page decorated pages to the app.

Expand Down Expand Up @@ -946,10 +956,16 @@ def get_compilation_time() -> str:
if not should_compile:
return

# Get the env mode.
config = get_config()

self._validate_var_dependencies()
self._setup_overlay_component()
self._setup_error_boundary()

if config.show_built_with_reflex:
self._setup_sticky_badge()

# Create a progress bar.
progress = Progress(
*Progress.get_default_columns()[:-1],
Expand All @@ -968,9 +984,6 @@ def get_compilation_time() -> str:
+ adhoc_steps_without_executor,
)

# Get the env mode.
config = get_config()

# Store the compile results.
compile_results = []

Expand Down
160 changes: 160 additions & 0 deletions reflex/components/core/sticky.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
"""Components for displaying the Reflex sticky logo."""

from reflex.components.component import ComponentNamespace
from reflex.components.core.colors import color
from reflex.components.core.cond import color_mode_cond, cond
from reflex.components.core.responsive import tablet_and_desktop
from reflex.components.el.elements.inline import A
from reflex.components.el.elements.media import Path, Rect, Svg
from reflex.components.radix.themes.typography.text import Text
from reflex.experimental.client_state import ClientStateVar
from reflex.style import Style
from reflex.vars.base import Var, VarData


class StickyLogo(Svg):
"""A simple Reflex logo SVG with only the letter R."""

@classmethod
def create(cls):
"""Create the simple Reflex logo SVG.

Returns:
The simple Reflex logo SVG.
"""
return super().create(
Rect.create(width="16", height="16", rx="2", fill="#6E56CF"),
Path.create(d="M10 9V13H12V9H10Z", fill="white"),
Path.create(d="M4 3V13H6V9H10V7H6V5H10V7H12V3H4Z", fill="white"),
width="16",
height="16",
viewBox="0 0 16 16",
xmlns="http://www.w3.org/2000/svg",
)

def add_style(self):
"""Add the style to the component.

Returns:
The style of the component.
"""
return Style(
{
"fill": "white",
}
)


class StickyLabel(Text):
"""A label that displays the Reflex sticky."""

@classmethod
def create(cls):
"""Create the sticky label.

Returns:
The sticky label.
"""
return super().create("Built with Reflex")

def add_style(self):
"""Add the style to the component.

Returns:
The style of the component.
"""
return Style(
{
"color": color("slate", 1),
"font_weight": "600",
"font_family": "'Instrument Sans', sans-serif",
"font_size": "0.875rem",
"line_height": "1rem",
"letter_spacing": "-0.00656rem",
}
)


class StickyBadge(A):
"""A badge that displays the Reflex sticky logo."""

@classmethod
def create(cls):
"""Create the sticky badge.

Returns:
The sticky badge.
"""
return super().create(
StickyLogo.create(),
tablet_and_desktop(StickyLabel.create()),
href="https://reflex.dev",
target="_blank",
width="auto",
padding="0.375rem",
align="center",
text_align="center",
)

def add_style(self):
"""Add the style to the component.

Returns:
The style of the component.
"""
is_localhost_cs = ClientStateVar.create(
"is_localhost",
default=True,
global_ref=False,
)
localhost_hostnames = Var.create(
["localhost", "127.0.0.1", "[::1]"]
).guess_type()
is_localhost_expr = localhost_hostnames.contains(
Var("window.location.hostname", _var_type=str).guess_type(),
)
check_is_localhost = Var(
f"useEffect(({is_localhost_cs}) => {is_localhost_cs.set}({is_localhost_expr}), [])",
_var_data=VarData(
imports={"react": "useEffect"},
),
)
is_localhost = is_localhost_cs.value._replace(
merge_var_data=VarData.merge(
check_is_localhost._get_all_var_data(),
VarData(hooks={str(check_is_localhost): None}),
),
)
return Style(
{
"position": "fixed",
"bottom": "1rem",
"right": "1rem",
# Do not show the badge on localhost.
"display": cond(is_localhost, "none", "flex"),
"flex-direction": "row",
"gap": "0.375rem",
"align-items": "center",
"width": "auto",
"border-radius": "0.5rem",
"color": color_mode_cond("#E5E7EB", "#27282B"),
"border": color_mode_cond("1px solid #27282B", "1px solid #E5E7EB"),
"background-color": color_mode_cond("#151618", "#FCFCFD"),
"padding": "0.375rem",
"transition": "background-color 0.2s ease-in-out",
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
"z-index": "9998",
"cursor": "pointer",
},
)


class StickyNamespace(ComponentNamespace):
"""Sticky components namespace."""

__call__ = staticmethod(StickyBadge.create)
label = staticmethod(StickyLabel.create)
logo = staticmethod(StickyLogo.create)


sticky = StickyNamespace()
Loading
Loading