Spaces:
Running
Running
from dataclasses import fields | |
import mesop as me | |
def load(e: me.LoadEvent): | |
me.set_theme_mode("system") | |
def app(): | |
is_mobile = me.viewport_size().width < 640 | |
with me.box(style=me.Style(margin=me.Margin(bottom=15))): | |
# Two section basic header with fluid width. | |
# As an example, we don't use mobile view here since the header is short enough. | |
with header(max_width=None): | |
with header_section(): | |
me.text( | |
"Mesop", type="headline-6", style=me.Style(margin=me.Margin(bottom=0)) | |
) | |
with header_section(): | |
me.button("Home") | |
me.button("About") | |
me.button("FAQ") | |
with me.box(style=me.Style(margin=me.Margin(bottom=15))): | |
# Two section basic header. | |
with header(is_mobile=is_mobile): | |
with header_section(): | |
me.text( | |
"Mesop", type="headline-6", style=me.Style(margin=me.Margin(bottom=0)) | |
) | |
with header_section(): | |
me.button("Home") | |
me.button("About") | |
me.button("FAQ") | |
with me.box(style=me.Style(margin=me.Margin(bottom=15))): | |
# Three section basic header. | |
with header(is_mobile=is_mobile): | |
with header_section(): | |
me.text( | |
"Mesop", type="headline-6", style=me.Style(margin=me.Margin(bottom=0)) | |
) | |
with header_section(): | |
me.button("Home") | |
me.button("About") | |
me.button("FAQ") | |
with header_section(): | |
me.button("Login", type="flat") | |
with me.box(style=me.Style(margin=me.Margin(bottom=15))): | |
# Centered header with overrides and icons | |
with header(is_mobile=is_mobile, style=me.Style(justify_content="center")): | |
with header_section(): | |
with me.content_button( | |
style=me.Style( | |
padding=me.Padding.symmetric(vertical=30, horizontal=25) | |
) | |
): | |
me.icon("home") | |
me.text("Home") | |
with me.content_button( | |
style=me.Style( | |
padding=me.Padding.symmetric(vertical=30, horizontal=25) | |
) | |
): | |
me.icon("info") | |
me.text("About") | |
with me.content_button( | |
style=me.Style( | |
padding=me.Padding.symmetric(vertical=30, horizontal=25) | |
) | |
): | |
me.icon("contact_support") | |
me.text("FAQ") | |
with me.content_button( | |
style=me.Style( | |
padding=me.Padding.symmetric(vertical=30, horizontal=25) | |
) | |
): | |
me.icon("login") | |
me.text("Login") | |
with me.box(style=me.Style(margin=me.Margin(bottom=15))): | |
# Header with overridden background | |
with header( | |
is_mobile=is_mobile, style=me.Style(background="#0F0F11", color="#E3E3E3") | |
): | |
with header_section(): | |
me.text( | |
"Mesop", type="headline-6", style=me.Style(margin=me.Margin(bottom=0)) | |
) | |
with header_section(): | |
me.button("Home", type="stroked", style=me.Style(color="#E3E3E3")) | |
me.button("About", type="stroked", style=me.Style(color="#E3E3E3")) | |
me.button("FAQ", type="stroked", style=me.Style(color="#E3E3E3")) | |
with header_section(): | |
me.button("Login", type="flat") | |
def header( | |
*, | |
style: me.Style | None = None, | |
is_mobile: bool = False, | |
max_width: int | None = 1000, | |
): | |
"""Creates a simple header component. | |
Args: | |
style: Override the default styles, such as background color, etc. | |
is_mobile: Use mobile layout. Arranges each section vertically. | |
max_width: Sets the maximum width of the header. Use None for fluid header. | |
""" | |
default_flex_style = ( | |
_DEFAULT_MOBILE_FLEX_STYLE if is_mobile else _DEFAULT_FLEX_STYLE | |
) | |
if max_width and me.viewport_size().width >= max_width: | |
default_flex_style = merge_styles( | |
default_flex_style, | |
me.Style(width=max_width, margin=me.Margin.symmetric(horizontal="auto")), | |
) | |
# The style override is a bit hacky here since we apply the override styles to both | |
# boxes here which could cause problems depending on what styles are added. | |
with me.box(style=merge_styles(_DEFAULT_STYLE, style)): | |
with me.box(style=merge_styles(default_flex_style, style)): | |
me.slot() | |
def header_section(): | |
"""Adds a section to the header.""" | |
with me.box(style=me.Style(display="flex", gap=5)): | |
me.slot() | |
def merge_styles( | |
default: me.Style, overrides: me.Style | None = None | |
) -> me.Style: | |
"""Merges two styles together. | |
Args: | |
default: The starting style | |
overrides: Any set styles will override styles in default | |
""" | |
if not overrides: | |
overrides = me.Style() | |
default_fields = { | |
field.name: getattr(default, field.name) for field in fields(me.Style) | |
} | |
override_fields = { | |
field.name: getattr(overrides, field.name) | |
for field in fields(me.Style) | |
if getattr(overrides, field.name) is not None | |
} | |
return me.Style(**default_fields | override_fields) | |
_DEFAULT_STYLE = me.Style( | |
background=me.theme_var("surface-container"), | |
border=me.Border.symmetric( | |
vertical=me.BorderSide( | |
width=1, | |
style="solid", | |
color=me.theme_var("outline-variant"), | |
) | |
), | |
padding=me.Padding.all(10), | |
) | |
_DEFAULT_FLEX_STYLE = me.Style( | |
align_items="center", | |
display="flex", | |
gap=5, | |
justify_content="space-between", | |
) | |
_DEFAULT_MOBILE_FLEX_STYLE = me.Style( | |
align_items="center", | |
display="flex", | |
flex_direction="column", | |
gap=12, | |
justify_content="center", | |
) | |