Closed marek-mihok closed 9 months ago
Feel free to either fix it in this PR or within a new one
@mturoci, I'll fix it within current one. Do you want to shift the card content down if the CardMenu has some content (e.g. commands button like in this case)?
shift the card content down if the CardMenu has some content
I don't think that would look good on all cards.
@mturoci I've fixed the positioning of commands button for both ui.plot_card
and ui.vega_card
while keeping #1923 in mind.
With title and commands
With commands only
With title only
Without title and without commands
Thanks @marek-mihok. Please go through the rest of the cards and make sure the context menu is rendered reasonably for each. The 2 posted above LGTM.
Please go through the rest of the cards and make sure the context menu is rendered reasonably for each.
@mturoci sure.
For some cards (e.g. form card) it depends on its content:
Should we implement the fix for it anyway?
Should we implement the fix for it anyway?
Sure. Just lift the menu up. We may not catch 100% of cases but should be okay for the majority.
@mturoci I've tested all of our cards for commands button positioning and results are as follows:
https://github.com/h2oai/wave/assets/23740173/b7270250-ef57-42f7-b55b-013496208baa
Cards to be fixed:
toolbar
tall_info
section_card
profile_card
preview_card
markdown_card
chat_card
chatbot_card
Test example from screen recording:
import json
from h2o_wave import main, app, Q, ui, data, on, pack
choices = [
ui.choice("default", "default"),
ui.choice("h2o-dark", "h2o-dark"),
ui.choice("one-dark-pro", "one-dark-pro"),
ui.choice("monokai", "monokai"),
ui.choice("nord", "nord"),
ui.choice("winter-is-coming", "winter-is-coming"),
ui.choice("fuchasia", "fuchasia"),
ui.choice("nature", "nature"),
ui.choice("solarized", "solarized"),
ui.choice("oceanic", "oceanic"),
ui.choice("ember", "ember"),
ui.choice("lighting", "lighting"),
ui.choice("kiwi", "kiwi"),
ui.choice("benext", "benext"),
]
content = '''
Duis porttitor tincidunt justo ac semper. Vestibulum et molestie lectus. Proin vel eros a ex condimentum aliquam.
Sed accumsan tellus sit amet nulla ullamcorper. Suspendisse bibendum tristique sem, quis lacinia ex pulvinar quis.
'''
html = '''
<!DOCTYPE html>
<html>
<body>
<h1>Hello World!</h1>
</body>
</html>
'''
menu = '''
<ol>
<li>Spam</li>
<li>Ham</li>
<li>Eggs</li>
</ol>
'''
spec = '''
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic bar chart example, with value labels shown upon mouse hover.",
"width": 500,
"height": 250,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
{"category": "E", "amount": 81},
{"category": "F", "amount": 53},
{"category": "G", "amount": 19},
{"category": "H", "amount": 87}
]
}
],
"signals": [
{
"name": "tooltip",
"value": {},
"on": [
{"events": "rect:mouseover", "update": "datum"},
{"events": "rect:mouseout", "update": "{}"}
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "category"},
"range": "width",
"padding": 0.05,
"round": true
},
{
"name": "yscale",
"domain": {"data": "table", "field": "amount"},
"nice": true,
"range": "height"
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale" },
{ "orient": "left", "scale": "yscale" }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "category"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "amount"},
"y2": {"scale": "yscale", "value": 0}
},
"update": {
"fill": {"value": "steelblue"}
},
"hover": {
"fill": {"value": "red"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"value": "#333"}
},
"update": {
"x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5},
"y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2},
"text": {"signal": "tooltip.amount"},
"fillOpacity": [
{"test": "datum === tooltip", "value": 0},
{"value": 1}
]
}
}
}
]
}
'''
commands= [ui.command(name="command",label="Some command",icon="Heart")]
image = "https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg?auto=compress&h=750&w=1260"
@app("/demo")
async def serve(q: Q):
if not q.client.initialized:
q.page["meta"] = ui.meta_card(box="", theme="default")
q.page["example"] = ui.plot_card(
box="1 1 4 5",
title="",
data=data("price low high", 8, rows=[
(4, 50, 100),
(6, 100, 150),
(8, 150, 200),
(16, 350, 400),
(18, 400, 450),
(10, 200, 250),
(12, 250, 300),
(14, 300, 350),
]),
plot=ui.plot([ui.mark(type="interval", y="=price", x1="=low", x2="=high", y_min=0)]),
commands=commands
)
q.page["form"] = ui.form_card(
box="5 1 2 5",
commands=commands,
items=[ui.dropdown(name="theme", label="Theme", trigger=True, choices=choices, value="default")]
)
q.page['breadcrumbs'] = ui.breadcrumbs_card(
box='7 1 3 1',
items= [
ui.breadcrumb(name='#menu', label='Menu'),
ui.breadcrumb(name='#submenu', label='Submenu'),
ui.breadcrumb(name='#subsubmenu', label='Subsubmenu'),
],
commands=[ui.command(name="to_log_scale",label="Log Scale",icon="LineChart")]
)
q.page["post"] = ui.post_card(
box="1 6 3 5",
persona=ui.persona(title="John Doe", subtitle="Data Scientist", image=image, caption="caption"),
commands=commands,
items=[
ui.inline(justify="end", items=[
ui.mini_buttons([
ui.mini_button(name="like", label="4", icon="Heart"),
ui.mini_button(name="comment", label="2", icon="Comment"),
ui.mini_button(name="share", label="1", icon="Share"),
]),
]),
ui.buttons(items=[
ui.button(name="like", label="Like"),
ui.button(name="comment", label="Comment"),
ui.button(name="share", label="Share"),
]),
],
caption=content,
aux_value="2h ago",
image="https://images.pexels.com/photos/3225517/pexels-photo-3225517.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260" # noqa
)
q.page["wide_article_preview"] = ui.wide_article_preview_card(
box="4 6 6 5",
name="wide_article_preview",
persona=ui.persona(title="Jasmine Grand", subtitle="Marketing Executive",
image=image, caption="caption"),
commands=commands,
aux_value="2h ago",
image="https://images.pexels.com/photos/1269968/pexels-photo-1269968.jpeg?auto=compress",
title="Jasmine Grand",
content=content,
items=[
ui.inline(justify="end", items=[
ui.mini_buttons([
ui.mini_button(name="like", label="4", icon="Heart"),
ui.mini_button(name="comment", label="2", icon="Comment"),
ui.mini_button(name="share", label="1", icon="Share"),
]),
])
],
)
q.page['arcticle'] = ui.article_card(
box='1 11 4 3',
title='Title',
items=[
ui.mini_buttons([
ui.mini_button(name='like', label='4', icon='Heart'),
ui.mini_button(name='comment', label='2', icon='Blog'),
ui.mini_button(name='share', label='1', icon='Relationship'),
])
],
content=content,
commands=commands
)
q.page['canvas'] = ui.canvas_card(
box='5 11 4 7',
title='Sample Canvas',
width=500,
height=500,
data=dict(),
commands=commands
)
q.page['chat'] = ui.chat_card(
box='1 14 4 4',
title='Chat room',
data=dict(),
commands=commands
)
q.page['chatbot'] = ui.chatbot_card(
box='1 18 4 5',
data=data('content from_user', t='list'),
name='chatbot',
commands=commands
)
q.page['frame'] = ui.frame_card(
box='5 18 2 2',
title='Example',
content=html,
commands=commands
)
q.page['footer'] = ui.footer_card(
box='1 23 -1 1',
caption='Made with 💛 by H2O Wave Team.',
commands=commands
)
q.page['header'] = ui.header_card(
box='1 24 -1 1',
title='Transparent header',
subtitle='And now for something completely different!',
image='https://wave.h2o.ai/img/h2o-logo.svg',
items=[ui.button(name='btn1', label='Button 1'),],
secondary_items=[ui.textbox(name='search', icon='Search', width='300px', placeholder='Search...')],
color='transparent',
commands=commands
)
q.page['image'] = ui.image_card(
box='1 25 2 4',
title='An image',
type='png',
path='https://via.placeholder.com/600x400',
commands=commands
)
# q.page['large_stat'] = ui.large_stat_card(
# box='1 1 2 2',
# title='Large stat',
# value='=${{intl qux minimum_fraction_digits=2 maximum_fraction_digits=2}}',
# aux_value='={{intl quux style="percent" minimum_fraction_digits=1 maximum_fraction_digits=1}}',
# data=dict(qux=val, quux=pc),
# caption='Caption'
# )
q.page['list'] = ui.list_card(
box='1 25 4 4',
item_view='list_item1',
item_props=pack(dict(title='=code', caption='=currency', value='=trades', aux_value='=returns')),
title='Exchange Rates',
data=data('currency code trades returns', -15),
commands=commands
)
q.page['markdown'] = ui.markdown_card(
box='5 25 4 4',
title='I was made using markdown!',
content='''
```py
from h2o_wave import main, app, Q, ui
async def serve(q: Q):
# Display a Hello, world! message.
q.page['hello'] = ui.markdown_card(
box='1 1 4 4',
title='Hello',
content='Hello, world!'
)
await q.page`.save()
''',
commands=commands
)
q.page['markup'] = ui.markup_card(
box='1 29 2 2',
title='Menu',
content=menu,
commands=commands
)
q.page['nav'] = ui.nav_card(
box='5 29 4 8',
value='#menu/ham',
# persona=ui.persona(title='John Doe', subtitle='Data Scientist', caption='Online', size='xl', image=image),
items=[
ui.nav_group('Menu', items=[
ui.nav_item(name='#menu/spam', label='Spam'),
ui.nav_item(name='#menu/ham', label='Ham'),
ui.nav_item(name='#menu/eggs', label='Eggs'),
ui.nav_item(name='#menu/toast', label='Toast', disabled=True),
]),
ui.nav_group('Help', items=[
ui.nav_item(name='#about', label='About', icon='Info'),
ui.nav_item(name='#support', label='Support', icon='Help'),
ui.nav_item(name='faq', label='FAQ', icon='OfficeChat', path='https://h2o.ai/'),
])
],
secondary_items=[ui.button(name='logout', label='Logout', width='100%')],
color='primary',
commands=commands
)
q.page['preview'] = ui.preview_card(
name='preview_card',
box='1 31 3 4',
image='https://images.pexels.com/photos/1269968/pexels-photo-1269968.jpeg?auto=compress',
title='Post title',
items=[ui.mini_buttons([
ui.mini_button(name='like', label='4', icon='Heart'),
ui.mini_button(name='comment', label='2', icon='Comment'),
ui.mini_button(name='share', label='1', icon='Share'),
])
],
caption='''
Lorem ipsum dolor sit amet, coectetur adipiscing elit. Etiam ut hendrerit lectus.As Etiam venenatis id nulla a molestie.
Lorem ipsum dolor sit amet, coectetur adipiscing elit. Etiam ut hendrerit lectus.As Etiam venenatis id nulla a molestie.
''',
label='Click me',
commands=commands
)
q.page['profile'] = ui.profile_card(
box='1 35 3 5',
image='https://images.pexels.com/photos/3225517/pexels-photo-3225517.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260', # noqa
persona=ui.persona(title='John Doe', subtitle='Data Scientist', image=image),
items=[
ui.inline(justify='center', items=[
ui.mini_buttons([
ui.mini_button(name='upload', label='Upload', icon='Upload'),
ui.mini_button(name='share', label='Share', icon='Share'),
ui.mini_button(name='download', label='Download', icon='Download'),
])
]),
ui.inline(justify='center', items=[
ui.button(name='btn1', label='Button 1'),
ui.button(name='btn2', label='Button 2'),
ui.button(name='btn3', label='Button 3'),
]),
],
commands=commands
)
q.page['section'] = ui.section_card(
box='5 38 4 4',
title='Section card',
subtitle='Toggle theme to see default plot colors change!',
items=[ui.toggle(name='toggle_theme', label='Dark theme', trigger=True)],
commands=commands
)
q.page['stat'] = ui.small_stat_card(
box='5 39 1 1',
title='Dollars',
value=f'$20.02',
commands=commands
)
q.page['tab'] = ui.tab_card(
box='1 40 2 1',
items=[
ui.tab(name='#menu/spam', label='Spam'),
ui.tab(name='#menu/ham', label='Ham'),
ui.tab(name='#menu/eggs', label='Eggs'),
ui.tab(name='#about', label='About'),
],
value=None,
commands=commands
)
q.page['tall_info'] = ui.tall_info_card(
box='5 40 2 5',
name='info_card',
title='Info Card',
caption='Lorem ipsum dolor sit amet consectetur adipisicing elit.',
category='Category',
label='Click me',
image='https://images.pexels.com/photos/3225517/pexels-photo-3225517.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
commands=commands
)
q.page['stat_table'] = ui.stat_table_card(
box='1 41 4 5',
title='Contacts',
subtitle=f'Last updated: 20.3.1211',
columns=['Name', 'Job', 'City'],
items=[
ui.stat_table_item(
label='Label',
values=['job', 'city'],
colors=['darkblue', '$amber']
) for i in range(10)
],
commands=commands
)
q.page['toolbar'] = ui.toolbar_card(
box='5 45 4 1',
items=[
ui.command(
name='new', label='New', icon='Add', items=[
ui.command(name='email', label='Email Message', icon='Mail'),
ui.command(name='calendar', label='Calendar Event', icon='Calendar'),
]
),
ui.command(name='upload', label='Upload', icon='Upload'),
ui.command(name='share', label='Share', icon='Share'),
ui.command(name='download', label='Download', icon='Download'),
],
secondary_items=[
ui.command(name='tile', caption='Grid View', icon='Tiles'),
ui.command(name='info', caption='Info', icon='Info'),
],
overflow_items=[
ui.command(name='move', label='Move to...', icon='MoveToFolder'),
ui.command(name='copy', label='Copy to...', icon='Copy'),
ui.command(name='rename', label='Rename', icon='Edit'),
],
commands=commands
)
q.page['vega'] = ui.vega_card(
box='1 46 4 4',
title='Full Vega spec grammar',
specification=spec,
grammar='vega',
commands=commands
)
q.page['wide_info'] = ui.wide_info_card(
box='5 46 4 5',
name='info_card',
title='Info Card',
subtitle='Subtitle',
caption=content,
category='Category',
label='Click me',
image=image,
commands=commands
)
q.client.initialized = True
if q.args.chatbot:
# Append user message.
q.page['chatbot'].data += [q.args.chatbot, True]
# Append bot response.
q.page['chatbot'].data += ['I am a fake chatbot. Sorry, I cannot help you.', False]
if q.args.theme:
q.page["meta"].theme = q.args.theme
await q.page.save()
The PR fulfills these requirements: (check all the apply)
main
branch.feat: Add a button #xxx
, where "xxx" is the issue number).Closes #xxx
, where "xxx" is the issue number.ui
folder, unit tests (make test
) still pass.After improvement:![Screenshot 2023-10-02 at 13 28 16](https://github.com/h2oai/wave/assets/23740173/cd58ca41-3738-4e18-a6e5-c82a9e29e264)
Before:![Screenshot 2023-10-02 at 13 28 01](https://github.com/h2oai/wave/assets/23740173/a44e4230-952a-4fa5-b10d-b371dfd9c432)
Diff:
With all themes:
https://github.com/h2oai/wave/assets/23740173/53e79077-470e-4784-b9f1-ff64f839a974
Closes #2127