-
Notifications
You must be signed in to change notification settings - Fork 325
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
feat: Improve visibility of card commands button #2127 #2147
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except for the obvious positioning. 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)? |
I don't think that would look good on all cards. |
53b19c0
to
8aeef62
Compare
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. |
@mturoci sure. For some cards (e.g. form card) it depends on its content: 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: Screen.Recording.2023-10-05.at.14.32.44.movCards to be fixed:
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() |
…ce if title is empty #2127
825fa81
to
faec6b7
Compare
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://private-user-images.githubusercontent.com/23740173/271958012-cd58ca41-3738-4e18-a6e5-c82a9e29e264.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjA5NzIxMzUsIm5iZiI6MTcyMDk3MTgzNSwicGF0aCI6Ii8yMzc0MDE3My8yNzE5NTgwMTItY2Q1OGNhNDEtMzczOC00ZTE4LWE2ZTUtYzgyYTllMjllMjY0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE0VDE1NDM1NVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTUxNWYwZmEwOTZhNjY5NTBlYzM2Mjc2ZjQyYzQwMTg5OWNmNDI2YWU1NzliZTI0YTZkZWQ1OGU1ZmFmYTcxNjQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.IPG3TNVx3ZR5NRr6avhxFqBK2XrLBjKbxOHGiBFdLNI)
Before:
![Screenshot 2023-10-02 at 13 28 01](https://private-user-images.githubusercontent.com/23740173/271958005-a44e4230-952a-4fa5-b10d-b371dfd9c432.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjA5NzIxMzUsIm5iZiI6MTcyMDk3MTgzNSwicGF0aCI6Ii8yMzc0MDE3My8yNzE5NTgwMDUtYTQ0ZTQyMzAtOTUyYS00ZmE1LWIxMGQtYjM3MWRmZDljNDMyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE0VDE1NDM1NVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAzNjZjN2UzNTNmYThlMTg2NzVkMzA2NDNmNjg0MDNkMDM4ZTBhMmVlNjExOTMyZTVjMzI0ZTUyMGM1M2Q3MTAmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.iOEE4VC5u-EYeEq0vffQ9Zs4nGkc9xovPvl3dlLL8cE)
Diff:
![image](https://private-user-images.githubusercontent.com/23740173/271983567-892432da-d4ff-44c0-b879-9c3fe361054c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjA5NzIxMzUsIm5iZiI6MTcyMDk3MTgzNSwicGF0aCI6Ii8yMzc0MDE3My8yNzE5ODM1NjctODkyNDMyZGEtZDRmZi00NGMwLWI4NzktOWMzZmUzNjEwNTRjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE0VDE1NDM1NVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTA4N2MzZWI1YWY2YzNmOTU2ZWU4MmE4ZTE2MTljZTM0NGE4ODBkZmQyNjdlMGU0ZDVhOGRhOWE2MzE4ZmUyNzkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.DsQDjXFkkV6MMKpzu6fc68kMOAV4fxs3_ptDXqRZbng)
With all themes:
Screen.Recording.2023-10-02.at.15.34.44.mov
Closes #2127