h2oai / wave

Realtime Web Apps and Dashboards for Python and R
https://wave.h2o.ai
Apache License 2.0
3.98k stars 326 forks source link

Image Grid #1599

Open dott1718 opened 2 years ago

dott1718 commented 2 years ago

Current implementations to nicely show multiple images or galleries in wave apps involve quite a bit of javascript and/or HTML & CSS usage. It would be helpful to further abstract that functionality to the wave framework and to add common image displays to speed up the app development process. It would also help to prevent speed issues and to align UX across wave apps.

We are looking for either a Carousel/Lightbox style implementation (https://www.joomforest.com/joomla-extensions/jf-responsive-carousel) or an Image Grid (https://www.w3schools.com/howto/howto_js_image_grid.asp)

Requirements:

mturoci commented 2 years ago

Some designs can be found here. Let's discuss the API prior to implementation. cc @lo5

aalencar commented 2 years ago

Proposal

Develop two separate components, Carousel Card and Image Grid Card. Both open a lightbox (modal with image) when an image is clicked. We could also somehow integrate Image Grid with Carousel Card by using a "View All" button that opens a modal with Image Grid.

Proposed API for Carousel Card

export interface State {
  /** An identifying name for this component. */
  name: Id
  /** List of images to be displayed. */
  images: Image[]
  /** True if the current image should be submitted when the image changes. */
  trigger?: B
}

// Similar to Image Card but with description
/** Create an image. */
export interface Image {
  /** The image title, displayed under the image. */
  title: S
  /** The image description, displayed under the title. */
  description: S
  /** The image MIME subtype. One of `apng`, `bmp`, `gif`, `x-icon`, `jpeg`, `png`, `webp`. Required only if `image` is set. */
  type?: S
  /** Image data, base64-encoded. */
  image?: S
  /** The path or URL or data URL of the image, e.g. `/foo.png` or `http://example.com/foo.png` or `data:image/png;base64,???`. */
  path?: S
  /** The width of the image, e.g. '100px'. */
  width?: S
  /** True if the component should be visible. Defaults to true. */
  visible?: B
}

Questions

@mturoci

Should we display multiple images (pages) in a Carousel?

image

Do we also need to support this variant?

image

What about having the title displayed between the image and description instead of using a tooltip?

Screenshot 2022-09-14 at 14 54 22

@dott1718 what do you mean exactly by "Automatic resizing for speed improvement"?

aalencar commented 2 years ago

related to #1542

dott1718 commented 2 years ago

Currently we implement it with a markup card, therefore we need to manually load, resize and save resized images for them to occupy same area sizes on the card. It would be great if the component will be able to e.g. take the raw image paths and take care of resizing, therefore saving resized images to disk will not be needed anymore.

aalencar commented 2 years ago

After discussing with @dott1718, we decided to go with Image Grid as of now. Resizing should be done on the Python side though.

mturoci commented 2 years ago

As for API I would reuse existing ui.image so the API I would start with would be:

export interface State {
  /** An identifying name for this component. */
  name: Id
  /** List of images to be displayed. */
  images: Image[]
}
aalencar commented 2 years ago

Implemetation notes: add virtualization and as a stretch goal create a dynamic grid that minimizes gaps between images of different sizes.

jding712 commented 1 year ago

Hi, I would like to work on this issue if it is still available.

mturoci commented 1 year ago

You can go for it if you feel like, but it's pretty complex. I would suggest having a look at good first issues if you are first-time contributor to this project.

knassre-cmu commented 1 year ago

Hello! I'm working alongside @jding712. We're basing our implementation on this PR: https://github.com/h2oai/wave/pull/1112. One question I had, mostly out of curiosity: how does wave know the connection between the Python-side components (i.e. TallStatsCard) with the typescript-side cards (i.e. cards.register('tall_stats', View)?

mturoci commented 1 year ago

how does wave know the connection between the Python-side components

We have a generator that creates python API off the TS API. See https://github.com/h2oai/wave/blob/master/tools/wavegen/src/wavegen.ts. Then these objects are serialized and sent over (browser => server, server => browser) via a websocket connection.

If you would like to test your changes by creating a python example (recommended), you need to run make generate once you have your TS interface ready to create it's Python counterpart. We also recommend going through the contributing guide first to get you started.