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(VCard): port to v3 #13674

Merged
merged 32 commits into from May 26, 2021
Merged

feat(VCard): port to v3 #13674

merged 32 commits into from May 26, 2021

Conversation

johnleider
Copy link
Member

@johnleider johnleider commented May 18, 2021

Description

Here are various implementations of card (the component's specifications are garbage) for reference

Specification

image

Motivation and Context

Bug fixes

Features

  • added new props to v-card
    • append-avatar
    • append-icon
    • prepend-avatar
    • prepend-icon
    • title
    • subtitle
    • text
  • added new slots to v-card
    • append
    • prepend
    • image
    • text
    • subtitle
    • text
    • title
  • added image, icon, and density support to v-avatar
  • added new prop tile to rounded composable
  • added 3 new css variables, high-emphasis-opacity, medium-emphasis-opacity, and disabled-opacity

Styles

  • added new sass variables to v-btn for v-card-actions
  • added new sass variables to v-avatar for density

Breaking changes

  • renamed img prop to image
  • removed active-class prop
  • removed all router-link and nuxt props
  • removed dark and light props
  • removed loading/loader-height props
  • removed shaped prop / use rounded="shaped"
  • removed raised prop / use elevation="8"

Styles

  • renamed $card-outlined-border-width to $card-border-width-thin-width
  • renamed $card-btn-margin-x to $button-card-actions-margin
  • renamed $card-btn-padding to $button-card-actions-padding
  • removed $adjacent-sibling-text-padding-top
  • removed $card-btn-small-margin-x
  • removed $card-overflow-wrap
  • removed $card-raised-elevation
  • removed $card-shaped-border-radius
  • removed $card-title-adjacent-sibling-subtitle-margin-top
  • removed $card-title-adjacent-sibling-subtitle-text-padding-top
  • removed $card-whitespace

How Has This Been Tested?

Markup:

<template>
  <v-app>
    <div class="py-12">
      <v-container fluid>
        <v-row>
          <v-col cols="4">
            <v-card
              density="comfortable"
              elevation="6"
              append-icon="mdi-vuetify"
            >
              <template #media>
                <v-img
                  src="https://images.unsplash.com/photo-1621454804914-f197f2acfeb7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80"
                />
              </template>

              <template #prepend>
                <v-avatar image="https://images.unsplash.com/photo-1621454804914-f197f2acfeb7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80" />
              </template>

              <template #title>
                Default
              </template>

              <template #subtitle>
                Secondary text
              </template>

              <template #text>
                Lorem, ipsum dolor sit amet consectetur adipisicing elit. Id repellendus, veniam rem saepe earum obcaecati nisi optio! Voluptatem repellat eaque voluptate corrupti architecto, totam dicta. Magnam amet illo dolores porro.
              </template>

              <template #actions>
                <v-btn>Action 1</v-btn>

                <v-btn>Action 2</v-btn>
              </template>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              :text="text"
              density="comfortable"
              elevation="6"
              prepend-avatar="https://randomuser.me/api/portraits/men/76.jpg"
              subtitle="Secondary text"
              title="Comfortable"
            />
          </v-col>

          <v-col cols="4">
            <v-card
              :text="text"
              density="compact"
              elevation="24"
              prepend-avatar="https://randomuser.me/api/portraits/men/76.jpg"
              subtitle="Secondary text"
              title="Compact"
            />
          </v-col>

          <v-col cols="4">
            <v-card
              :text="text"
              append-avatar="https://randomuser.me/api/portraits/men/76.jpg"
              hover
              prepend-icon="mdi-vuetify"
              subtitle="Secondary text"
              title="Media card"
            >
              <v-card-media>
                <v-img
                  src="https://images.unsplash.com/photo-1621454804914-f197f2acfeb7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80"
                  cover
                />
              </v-card-media>

              <template #actions>
                <v-btn text>
                  Action 1
                </v-btn>
                <v-btn text>
                  Action 1
                </v-btn>
              </template>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card>
              <v-card-header>
                <v-card-header-text>
                  <v-card-title>Media card</v-card-title>

                  <v-card-subtitle>Secondary text</v-card-subtitle>
                </v-card-header-text>
              </v-card-header>

              <v-card-media>
                <v-img
                  src="https://images.unsplash.com/photo-1621390324893-ea412aa9453c?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80"
                  cover
                />
              </v-card-media>

              <v-card-text>
                Lorem ipsum dolor sit amet consectetur adipisicing elit. Perspiciatis voluptas, dolorum placeat cum, aliquid voluptates rem dignissimos neque voluptatem qui repudiandae ad minima, commodi quaerat impedit voluptatibus quis! Doloribus, vero.
              </v-card-text>

              <v-divider />

              <v-card-actions>
                <v-btn
                  text
                  color="primary"
                >
                  Action 1
                </v-btn>
                <v-btn
                  text
                  color="primary"
                >
                  Action 2
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card>
              <v-card-media>
                <v-img
                  src="https://images.unsplash.com/photo-1621454804914-f197f2acfeb7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80"
                  cover
                />
              </v-card-media>

              <v-card-header>
                <v-card-avatar>
                  <v-avatar image="https://randomuser.me/api/portraits/men/76.jpg" />
                </v-card-avatar>
                <v-card-header-text>
                  <v-card-title>Another card</v-card-title>

                  <v-card-subtitle>Secondary text</v-card-subtitle>
                </v-card-header-text>
              </v-card-header>

              <v-divider />

              <v-card-text>
                Lorem ipsum dolor sit amet consectetur adipisicing elit. Perspiciatis voluptas, dolorum placeat cum, aliquid voluptates rem dignissimos neque voluptatem qui repudiandae ad minima, commodi quaerat impedit voluptatibus quis! Doloribus, vero.
              </v-card-text>

              <v-card-actions>
                <v-btn
                  text
                  color="primary"
                >
                  Action 1
                </v-btn>
                <v-btn
                  text
                  color="primary"
                >
                  Action 2
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card max-width="400" class="mx-auto mb-2">
              <v-card-media>
                <v-img src="https://cdn.vuetifyjs.com/images/cards/cooking.png" />
              </v-card-media>

              <v-card-header>
                <v-card-header-text>
                  <v-card-title>Cafe Badilico</v-card-title>

                  <v-card-subtitle class="my-2">
                    <div class="d-flex mr-4">
                      <v-icon v-for="n in 5" :key="n" size="14" color="yellow-darken-3">mdi-star</v-icon>
                    </div>

                    4.5 (413)
                  </v-card-subtitle>

                  <v-card-subtitle class="text-subtitle-1">
                    $ • Italian, Cafe
                  </v-card-subtitle>
                </v-card-header-text>
              </v-card-header>

              <v-card-text>
                Small plates, salads & sandwiches - an intimate setting with 12 indoor seats plus patio seating.
              </v-card-text>

              <v-divider class="mx-4" />

              <v-card-title>
                Tonight's availability
              </v-card-title>

              <v-card-text class="d-flex">
                <v-btn class="mr-2" rounded="pill" flat color="grey-lighten-2">
                  5:30PM
                </v-btn>

                <v-btn class="mr-2" rounded="pill" flat color="primary">
                  7:30PM
                </v-btn>

                <v-btn class="mr-2" rounded="pill" flat color="grey-lighten-2">
                  8:00PM
                </v-btn>

                <v-btn rounded="pill" flat color="grey-lighten-2">
                  9:00PM
                </v-btn>
              </v-card-text>

              <v-card-actions>
                <v-btn
                  color="deep-purple-lighten-2"
                  text
                  @click="reserve"
                >
                  Reserve
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              class="mx-auto mb-2"
              max-width="344"
              outlined
            >
              <v-card-header>
                <v-card-header-text>
                  <div class="text-overline mb-4">
                    OVERLINE
                  </div>

                  <v-card-title class="text-headline mb-1">
                    Headline 5
                  </v-card-title>

                  <v-card-subtitle>
                    Greyhound divisely hello coldly fonwderfully
                  </v-card-subtitle>
                </v-card-header-text>

                <v-card-avatar>
                  <v-avatar
                    rounded="0"
                    size="80"
                    color="grey"
                  />
                </v-card-avatar>
              </v-card-header>

              <v-card-actions>
                <v-btn
                  outlined
                  rounded="pill"
                >
                  Button
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              class="mx-auto mb-2"
              max-width="344"
            >
              <v-card-header>
                <v-card-header-text>
                  <v-card-subtitle>Word of the Day</v-card-subtitle>

                  <v-card-title class="text-h4 mt-2 mb-6">el·ee·mos·y·nar·y</v-card-title>

                  <v-card-subtitle>adjective</v-card-subtitle>
                </v-card-header-text>
              </v-card-header>

              <v-card-text>
                relating to or dependent on charity; charitable.<br>
                "an eleemosynary educational institution."
              </v-card-text>

              <v-card-actions>
                <v-btn
                  text
                  color="teal-accent-4"
                >
                  Learn More
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              class="mx-auto mb-2"
              max-width="344"
            >
              <v-card-media>
                <v-img src="https://cdn.vuetifyjs.com/images/cards/sunshine.jpg" />
              </v-card-media>

              <v-card-header>
                <v-card-header-text>
                  <v-card-title>Top western road trips</v-card-title>

                  <v-card-subtitle>1,00 miles of wonder</v-card-subtitle>
                </v-card-header-text>
              </v-card-header>

              <v-card-actions>
                <v-btn text color="orange-lighten-2">Explore</v-btn>

                <v-spacer />

                <v-btn icon="mdi-chevron-down" density="comfortable" @click="show = !show" />
              </v-card-actions>

              <div v-show="show">
                <v-divider />

                <v-card-text>
                  I'm a thing. But, like most politicians, he promised more than he could deliver. You won't have time for sleeping, soldier, not with all the bed making you'll be doing. Then we'll go with that data file! Hey, you add a one and two zeros to that or we walk! You're going to do his laundry? I've got to find a way to escape.
                </v-card-text>
              </div>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              class="mx-auto mb-2"
              max-width="500"
            >
              <v-system-bar
                color="indigo-darken-2"
                dark
              >
                <v-spacer />

                <v-icon>mdi-window-minimize</v-icon>

                <v-icon>mdi-window-maximize</v-icon>

                <v-icon>mdi-close</v-icon>
              </v-system-bar>

              <v-app-bar
                color="indigo"
                dark
                style="position: relative;"
              >
                <v-app-bar-nav-icon />

                <v-app-bar-title>Discover</v-app-bar-title>

                <v-spacer />

                <v-btn icon>
                  <v-icon>mdi-magnify</v-icon>
                </v-btn>
              </v-app-bar>

              <v-container fluid>
                <v-row dense>
                  <v-col
                    v-for="card in cards"
                    :key="card.title"
                    :cols="card.flex"
                  >
                    <v-card>
                      <v-card-media>
                        <v-img
                          :src="card.src"
                          class="text-white"
                        >
                          <div class="d-flex align-end" style="height: 100%;">
                            <v-card-title v-text="card.title" />
                          </div>
                        </v-img>
                      </v-card-media>

                      <v-card-actions>
                        <v-spacer />

                        <v-btn icon="mdi-heart" density="comfortable" />

                        <v-btn icon="mdi-bookmark" density="comfortable" />

                        <v-btn icon="mdi-share-variant" density="comfortable" />
                      </v-card-actions>
                    </v-card>
                  </v-col>
                </v-row>
              </v-container>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              max-width="400"
              class="mx-auto mb-2"
            >
              <v-system-bar
                color="pink darken-2"
                dark
              >
                <v-spacer />

                <v-icon>mdi-window-minimize</v-icon>

                <v-icon>mdi-window-maximize</v-icon>

                <v-icon>mdi-close</v-icon>
              </v-system-bar>

              <v-app-bar
                dark
                color="pink"
                style="position: relative;"
              >
                <v-app-bar-nav-icon />

                <v-app-bar-title>My Music</v-app-bar-title>

                <v-spacer />

                <v-btn icon>
                  <v-icon>mdi-magnify</v-icon>
                </v-btn>
              </v-app-bar>

              <v-container>
                <v-row dense>
                  <v-col cols="12">
                    <v-card
                      color="#385F73"
                      title="Unlimited music now"
                      text="Listen to your favorite artists and albums whenever and wherever, online and offline."
                    >
                      <template #actions>
                        <v-btn>Listen Now</v-btn>
                      </template>
                    </v-card>
                  </v-col>

                  <v-col cols="12">
                    <v-card color="#1F7087">
                      <v-card-header>
                        <div class="flex-grow-1 d-flex flex-column justify-space-between align-self-stretch">
                          <v-card-header-text>
                            <v-card-title>Supermodel</v-card-title>

                            <v-card-subtitle>Foster the People</v-card-subtitle>
                          </v-card-header-text>

                          <div>
                            <v-btn
                              size="small"
                              rounded="pill"
                              outlined
                            >
                              Start Radio
                            </v-btn>
                          </div>
                        </div>

                        <v-card-avatar>
                          <v-avatar
                            rounded="0"
                            size="125"
                            image="https://cdn.vuetifyjs.com/images/cards/foster.jpg"
                          />
                        </v-card-avatar>
                      </v-card-header>
                    </v-card>
                  </v-col>

                  <v-col cols="12">
                    <v-card color="#952175">
                      <v-card-header>
                        <div class="flex-grow-1 d-flex flex-column justify-space-between align-self-stretch">
                          <v-card-header-text>
                            <v-card-title>Halcyon Days</v-card-title>

                            <v-card-subtitle>Ellie Goulding</v-card-subtitle>
                          </v-card-header-text>

                          <v-btn
                            size="small"
                            icon="mdi-play"
                            text
                          />
                        </div>

                        <v-card-avatar>
                          <v-avatar
                            rounded="0"
                            size="125"
                            image="https://cdn.vuetifyjs.com/images/cards/halcyon.png"
                          />
                        </v-card-avatar>
                      </v-card-header>
                    </v-card>
                  </v-col>
                </v-row>
              </v-container>
            </v-card>
          </v-col>

          <v-col cols="4">
            <v-card
              class="mx-auto mb-2"
              max-width="344"
            >
              <v-card-header>
                <v-card-header-text>
                  <v-card-subtitle>Word of the Day</v-card-subtitle>

                  <v-card-title class="text-h4 mt-2 mb-6">be•nev•o•lent</v-card-title>

                  <v-card-subtitle>adjective</v-card-subtitle>
                </v-card-header-text>
              </v-card-header>

              <v-card-text>
                well meaning and kindly.<br>
                "a benevolent smile"
              </v-card-text>

              <v-card-actions>
                <v-btn
                  text
                  color="deep-purple-accent-4"
                >
                  Learn More
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-col>
        </v-row>
      </v-container>
    </div>
  </v-app>
</template>

<script>
  export default {
    data: () => ({
      cards: [
        { title: 'Pre-fab homes', src: 'https://cdn.vuetifyjs.com/images/cards/house.jpg', flex: 12 },
        { title: 'Favorite road trips', src: 'https://cdn.vuetifyjs.com/images/cards/road.jpg', flex: 6 },
        { title: 'Best airlines', src: 'https://cdn.vuetifyjs.com/images/cards/plane.jpg', flex: 6 },
      ],
      text: 'Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aperiam necessitatibus eum numquam, earum maxime nisi ut temporibus, quia repellendus magnam ipsum voluptate saepe quos vitae, autem et id non modi.',
    }),
  }
</script>

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Improvement/refactoring (non-breaking change that doesn't add any features but makes things better)

Checklist:

  • The PR title is no longer than 64 characters.
  • The PR is submitted to the correct branch (master for bug fixes and documentation updates, dev for new features and backwards compatible changes and next for non-backwards compatible changes).
  • My code follows the code style of this project.
  • I've added relevant changes to the documentation (applies to new features and breaking changes in core library)

@nekosaur
Copy link
Member

Some thoughts:

  • What's the difference between media and image?
  • Are the prepend/append slot/prop names too general? Is it obvious that they are for the header?
  • It's not immediately clear how/where v-card-item fits into the markup of a card. Looking at how it's used in VCard, should it not be named v-card-header?

@johnleider johnleider requested review from nekosaur, KaelWD and jacekkarczmarczyk and removed request for nekosaur and KaelWD May 23, 2021 21:52
@johnleider johnleider added this to the v3.0.0 milestone May 23, 2021
@johnleider johnleider added this to In progress in Vuetify 3 - Titan via automation May 23, 2021
@johnleider johnleider self-assigned this May 23, 2021
@johnleider johnleider added the C: VCard VCard label May 23, 2021
@johnleider
Copy link
Member Author

Some thoughts:

  • What's the difference between media and image?
  • Are the prepend/append slot/prop names too general? Is it obvious that they are for the header?
  • It's not immediately clear how/where v-card-item fits into the markup of a card. Looking at how it's used in VCard, should it not be named v-card-header?
  • Media encompasses v-img and v-video in the future, image acts the same way as v-navigation-drawer, v-app-bar, etc. It is a background image that fills the component
  • This is to keep the API in line with other components that use prepend and append
  • v-card-item has 2 main purposes
    • it provides the markup required to support prepend/append icon/avatar support, and keep it similar to like components such as v-list-item
  • Answered above

@nekosaur
Copy link
Member

Some thoughts:

  • What's the difference between media and image?
  • Are the prepend/append slot/prop names too general? Is it obvious that they are for the header?
  • It's not immediately clear how/where v-card-item fits into the markup of a card. Looking at how it's used in VCard, should it not be named v-card-header?
  • Media encompasses v-img and v-video in the future, image acts the same way as v-navigation-drawer, v-app-bar, etc. It is a background image that fills the component

  • This is to keep the API in line with other components that use prepend and append

  • v-card-item has 2 main purposes

    • it provides the markup required to support prepend/append icon/avatar support, and keep it similar to like components such as v-list-item
  • Answered above

  • I wonder if that will cause confusion among users.
  • I personally don't see an issue with being more specific here. They will still share append/prepend with other usages
  • I don't think it's a good idea to try to equate v-card > header with v-list > v-list-item etc. They are two different things.

@johnleider
Copy link
Member Author

  • I wonder if that will cause confusion among users.
  • I personally don't see an issue with being more specific here. They will still share append/prepend with other usages
  • I don't think it's a good idea to try to equate v-card > header with v-list > v-list-item etc. They are two different things.
  • I don't think this is going to be an issue since it's standardizing the framework
  • Something like prepend-header and append-header?
  • I'm equating v-card to a v-list-item only in terms of interface.
    • v-list-item-content will probably be renamed to v-list-item-header in the future

@nekosaur
Copy link
Member

  • Something like prepend-header and append-header?

yes, something like that

  • I'm equating v-card to a v-list-item only in terms of interface.

I think the markup becomes very weird though

<v-card>
  <v-card-item>
    <v-card-avatar/>
    <v-card-header>
      ...
    </v-card-header>
    <v-card-avatar/>
  </v-card-item>
  <v-card-text/>
</v-card>

vs

<v-card>
  <v-card-header>
    <v-card-avatar/>
    ...
    <v-card-avatar/>
  </v-card-header>
  <v-card-text/>
</v-card>

which to me seems more natural

@johnleider
Copy link
Member Author

The only way to align prepend/append with a title/subtitle is if the latter has a wrapper. The following won't work:

<v-card>
  <v-card-header>
    <v-card-avatar />

    <v-card-title />

    <v-card-subtitle />

    <v-card-avatar />
  </v-card-header>
</v-card>

We need something like this:

<v-card>
  <v-card-header>
    <v-card-avatar />

    <v-card-some-component-name>
      <v-card-title />

      <v-card-subtitle />
    </v-card-some-component-name>

    <v-card-avatar />
  </v-card-header>
</v-card>

@nekosaur
Copy link
Member

The only way to align prepend/append with a title/subtitle is if the latter has a wrapper. The following won't work:

<v-card>
  <v-card-header>
    <v-card-avatar />

    <v-card-title />

    <v-card-subtitle />

    <v-card-avatar />
  </v-card-header>
</v-card>

We need something like this:

<v-card>
  <v-card-header>
    <v-card-avatar />

    <v-card-some-component-name>
      <v-card-title />

      <v-card-subtitle />
    </v-card-some-component-name>

    <v-card-avatar />
  </v-card-header>
</v-card>

<v-card-some-component-name> -> <v-card-header-content> or <v-card-header-text>?

@johnleider johnleider marked this pull request as ready for review May 25, 2021 21:27
@johnleider
Copy link
Member Author

Requesting Final comments from @vuetifyjs/core-team

@johnleider johnleider changed the title feat/v3-card feat(VCard): port to v3 May 26, 2021
@johnleider johnleider merged commit c132009 into next May 26, 2021
Vuetify 3 - Titan automation moved this from In progress to Done May 26, 2021
@johnleider johnleider deleted the feat/v3-card branch May 26, 2021 18:38
johnleider added a commit that referenced this pull request May 26, 2021
Co-authored-by: Elijah Kotyluk <elijah@elijahkotyluk.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VCard VCard T: feature A new feature
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

3 participants