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

feat: Improve visibility of card commands button #2127 #2147

Merged
merged 6 commits into from
Oct 6, 2023
Merged

Conversation

marek-mihok
Copy link
Contributor

@marek-mihok marek-mihok commented Oct 2, 2023

The PR fulfills these requirements: (check all the apply)

  • It's submitted to the main branch.
  • When resolving a specific issue, it's referenced in the PR's title (e.g. feat: Add a button #xxx, where "xxx" is the issue number).
  • When resolving a specific issue, the PR description includes Closes #xxx, where "xxx" is the issue number.
  • If changes were made to ui folder, unit tests (make test) still pass.
  • New/updated tests are included

After improvement:
Screenshot 2023-10-02 at 13 28 16

Before:
Screenshot 2023-10-02 at 13 28 01

Diff:
image

With all themes:

Screen.Recording.2023-10-02.at.15.34.44.mov

Closes #2127

@marek-mihok marek-mihok changed the title Feat/issue 2127 feat: Improve visibility of card commands button #2127 Oct 2, 2023
@marek-mihok marek-mihok marked this pull request as ready for review October 2, 2023 13:36
mturoci
mturoci previously approved these changes Oct 2, 2023
Copy link
Collaborator

@mturoci mturoci left a 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.

@marek-mihok
Copy link
Contributor Author

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)?

@mturoci
Copy link
Collaborator

mturoci commented Oct 2, 2023

shift the card content down if the CardMenu has some content

I don't think that would look good on all cards.

@marek-mihok
Copy link
Contributor Author

@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

image

With commands only

image

With title only

image

Without title and without commands

image

@mturoci
Copy link
Collaborator

mturoci commented Oct 4, 2023

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.

ui/src/plot.tsx Outdated Show resolved Hide resolved
ui/src/plot.tsx Outdated Show resolved Hide resolved
@marek-mihok
Copy link
Contributor Author

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:

image

Should we implement the fix for it anyway?

@mturoci
Copy link
Collaborator

mturoci commented Oct 4, 2023

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.

@marek-mihok
Copy link
Contributor Author

@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.mov

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()

@mturoci mturoci merged commit 913a7c4 into main Oct 6, 2023
2 checks passed
@mturoci mturoci deleted the feat/issue-2127 branch October 6, 2023 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhancing visibility of commands on certain cards
2 participants