material-components / material-components-web

Modular and customizable Material Design UI components for the web
https://material.io/develop/web
MIT License
17.15k stars 2.14k forks source link

Add classes to control how many column Images List is taking by device type (like Grid Layout) #5388

Open khalyomede opened 4 years ago

khalyomede commented 4 years ago

Feature Request

Currently, one can customize by how many columns the Images List is displayed, by using the following example (quoted from the official GitHub documentation):

Changing number of columns across breakpoints Presenting a different number of columns for different viewport sizes is straightforward, since the only thing that needs to be changed are styles:

.my-image-list {
 @include mdc-image-list-standard-columns(5);
}

@media (max-width: 599px) {
 .my-image-list {
   @include mdc-image-list-standard-columns(3);
 }
}

(source: https://github.com/material-components/material-components-web/tree/master/packages/mdc-image-list

However, this task can be hard (or impossible?) for components developer (Angular, VueJS, React, ...) to use Javascript variables in SCSS.

Here is what I propose

To have classes that let us "tell" how the components should expand in the different devices sizes (mdc-image-list--span-<NUMBER_OF_COLUMNS>-<TYPE_OF_DEVICE>).

Proposed solution

Here is an example of how we could use the class I mentioned above (using HTML).

<ul class="mdc-image-list mdc-image-list--masonry mdc-image-list--span-1-phone mdc-image-list--span-2-tablet mdc-image-list--span-3-desktop">
  <li class="mdc-image-list__item">
    <img class="mdc-image-list__image" src="..." />
    <div class="mdc-image-list__supporting">
      <span class="mdc-image-list__label">Text label</span>
    </div>
  </li>
  ...
</ul>

Note proposed available classes would be

mdc-image-list--span-1-phone
mdc-image-list--span-2-phone
mdc-image-list--span-3-phone
mdc-image-list--span-4-phone

mdc-image-list--span-1-tablet
mdc-image-list--span-2-tablet
mdc-image-list--span-3-tablet
mdc-image-list--span-4-tablet
mdc-image-list--span-5-tablet
mdc-image-list--span-6-tablet
mdc-image-list--span-7-tablet
mdc-image-list--span-8-tablet

mdc-image-list--span-1-desktop
mdc-image-list--span-2-desktop
mdc-image-list--span-3-desktop
mdc-image-list--span-4-desktop
mdc-image-list--span-5-desktop
mdc-image-list--span-6-desktop
mdc-image-list--span-7-desktop
mdc-image-list--span-8-desktop
mdc-image-list--span-9-desktop
mdc-image-list--span-10-desktop
mdc-image-list--span-11-desktop
mdc-image-list--span-12-desktop

Alternatives considered

I handcrafted these classes for my Vue.js image list component, using these classes names above.

Additional context

Here is how we (developer of components) could easily expose a components for a user.

Below an example of Vue.js page, made by the end user.

<template>
  <h1>Welcome to my blog</h1>
  <mdc-image-list :phone="1" :tablet="2" :desktop="3">
    <mdc-image-list-item src="/img/cat.jpg" alt="A cat" />
    <mdc-image-list-item src="/img/dog.jpg" alt="A dog" />
    <mdc-image-list-item src="/img/bird.jpg" alt="A bird" />
  </mdc-image-list>
</template>

<script>
import { MdcImageList, MdcImageListItem } from "../components";

export default {
  components: {
      MdcImageList,
      MdcImageListItem
  }
}
</script>

And here is the component developed by the Vue.js component developer.

<template>
  <ul :class="classes">
    <slot />
  </ul>
</template>

<script>
export default {
  props: {
    phone: {
      type: Number,
      default: 4,
      validator: value => 1 <= value && value <= 4
    },
    tablet: {
      type: Number,
      default: 8,
      validator: value => 1 <= value && value <= 8
    },
    desktop: {
      type: Number,
      default: 12,
      validator: value => 1 <= value && value <= 12
    }
  },
  computed: {
    classes() {
      return `mdc-image-list mdc-image-list--span-${this.phone}-phone mdc-image-list--span-${this.tablet}-tablet mdc-image-list--span-${this.desktop}-desktop`;
    }
  }
}
</script>
abhiomkar commented 4 years ago

Thanks for detailed explanation!

Overall this sounds like a good idea and reasonable feature request. My only worry is that it leads to CSS bloat which will be unused. Grid List component only provides foundation for consumers to create their own utility classes when it fits.

PR Welcome!

khalyomede commented 4 years ago

Thought of the same about the CSS load...

I'll try to come up with a PR, for the moment I guess it remains user-land, and folks can inspire from the description if needed.

Happy new year to you and the whole Material team!