tailwindlabs / discuss

A place to ask questions, get help, or share what you've built with Tailwind CSS.
MIT License
171 stars 9 forks source link

How would you approach this- change layout on click- need ideas #383

Open nezaboravi opened 4 years ago

nezaboravi commented 4 years ago

I am using Vue and Tailwind. Love both. I am wondering how could i achieve following. Currently i am having nice and beautiful page where i am displaying items as card boxes. I have a card component, and items are nicely sorted:

Screenshot 2019-11-19 18 31 14

Visitor click on List view and get items on list sorted as list. :D Visitor clicks on Card view and get items sorted in card boxes. Any pseudo code or code example would help. Something like this photo:

Screenshot 2019-11-19 18 28 54

Thanks :)

Forgot to add the code :D :D This is my Ads.vue component

<template>
    <div class="flex flex-col flex-1">
        <div class="hidden lg:flex justify-between w-84 self-end">
            <div class="uppercase text-a4a-dark-grey pr-4">View</div>
            <div>
                <svg width="29px" height="23px" viewBox="0 0 29 23" version="1.1" xmlns="http://www.w3.org/2000/svg"
                     xmlns:xlink="http://www.w3.org/1999/xlink">
                    <g id="list-view-icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
                        <g id="Group" transform="translate(0.000000, 0.000000)" fill="#545454">
                            <path
                                d="M1.99004762,19.0744476 C0.939714286,19.0744476 -5.40012479e-13,19.9594 -5.40012479e-13,21.0097333 C-5.40012479e-13,22.0600667 0.939714286,22.999781 1.99004762,22.999781 C3.04038095,22.999781 3.92533333,22.0600667 3.92533333,21.0097333 C3.92533333,19.9594 3.04038095,19.0744476 1.99004762,19.0744476"
                                id="Fill-3"></path>
                            <path
                                d="M1.99004762,9.56493333 C0.939714286,9.56493333 -5.40012479e-13,10.4498857 -5.40012479e-13,11.500219 C-5.40012479e-13,12.5505524 0.939714286,13.4355048 1.99004762,13.4355048 C3.04038095,13.4355048 3.92533333,12.5505524 3.92533333,11.500219 C3.92533333,10.4498857 3.04038095,9.56493333 1.99004762,9.56493333"
                                id="Fill-4"></path>
                            <path
                                d="M9.06692857,3.75962381 L25.8196905,3.75962381 C26.8141667,3.75962381 27.6443571,2.98529048 27.6443571,1.99081429 C27.6443571,0.995242857 26.8141667,0.166147619 25.8196905,0.166147619 L9.06692857,0.166147619 C8.07135714,0.166147619 7.2422619,0.995242857 7.2422619,1.99081429 C7.2422619,2.98529048 8.07135714,3.75962381 9.06692857,3.75962381"
                                id="Fill-5"></path>
                            <path
                                d="M1.99004762,1.43662859e-13 C0.939714286,1.43662859e-13 -5.40012479e-13,0.939714286 -5.40012479e-13,1.99004762 C-5.40012479e-13,3.04038095 0.939714286,3.92533333 1.99004762,3.92533333 C3.04038095,3.92533333 3.92533333,3.04038095 3.92533333,1.99004762 C3.92533333,0.939714286 3.04038095,1.43662859e-13 1.99004762,1.43662859e-13"
                                id="Fill-6"></path>
                            <path
                                d="M25.8194714,9.67533333 L9.06670952,9.67533333 C8.07223333,9.67533333 7.24204286,10.5044286 7.24204286,11.5 C7.24204286,12.4955714 8.07223333,13.3246667 9.06670952,13.3246667 L25.8194714,13.3246667 C26.8150429,13.3246667 27.6441381,12.4955714 27.6441381,11.5 C27.6441381,10.5044286 26.8150429,9.67533333 25.8194714,9.67533333"
                                id="Fill-7"></path>
                            <path
                                d="M25.8194714,19.1851762 L9.06670952,19.1851762 C8.07223333,19.1851762 7.24204286,20.0142714 7.24204286,21.0098429 C7.24204286,22.004319 8.07223333,22.8345095 9.06670952,22.8345095 L25.8194714,22.8345095 C26.8150429,22.8345095 27.6441381,22.004319 27.6441381,21.0098429 C27.6441381,20.0142714 26.8150429,19.1851762 25.8194714,19.1851762"
                                id="Fill-8"></path>
                        </g>
                    </g>
                </svg>
            </div>
            <div>
                <svg width="23px" height="23px" viewBox="0 0 23 23" version="1.1" xmlns="http://www.w3.org/2000/svg"
                     xmlns:xlink="http://www.w3.org/1999/xlink">
                    <g id="card-view-icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
                        <g id="Group-9" fill="#545454">
                            <polygon id="Fill-9"
                                     points="-2.84217094e-14 22.9989048 9.27009524 22.9989048 9.27009524 13.6061429 -2.84217094e-14 13.6061429"></polygon>
                            <polygon id="Fill-10"
                                     points="13.0782381 22.9989048 22.3483333 22.9989048 22.3483333 13.6061429 13.0782381 13.6061429"></polygon>
                            <polygon id="Fill-11"
                                     points="-2.84217094e-14 9.3927619 9.27009524 9.3927619 9.27009524 1.0658141e-14 -2.84217094e-14 1.0658141e-14"></polygon>
                            <polygon id="Fill-12"
                                     points="13.0782381 9.3927619 22.3483333 9.3927619 22.3483333 1.0658141e-14 13.0782381 1.0658141e-14"></polygon>
                        </g>
                    </g>
                </svg>
            </div>
            <div class="flex ml-4">
                <span class="uppercase text-a4a-dark-grey">Sort by </span>
                <span>
                    <select name="" id="" class="border-0 bg-white focus:outline-none">
                        <option value="relevance" selected>Relevance</option>
                        <option value="">Other thing</option>
                        <option value="">Something</option>
                    </select>
                </span>
            </div>
        </div>
        <div class="flex flex-col flex-wrap mt-16 px-1 justify-between items-start">
            <div v-if="this.$store.state.ads.length < 1" class="flex flex-wrap px-1 justify-between">
                Sorry, there is nothing to be found by your filters.
            </div>
            <transition-group name="fade" tag="ul" class="flex flex-wrap px-1 justify-between">
                <li v-for="(ad, key) in this.$store.state.ads" :key="ad.id">
                    <div v-if="key===3"
                         class="w-full sm:w-card-horizontal lg:w-card-vertical lg:h-card-height-horizontal p-2 mb-8 m-1 border-1 bg-green-800 text-white items-center border-a4a-light-grey"
                         style="min-width:300px; min-height:409px">
                        <span>FERGUSON AD</span>
                    </div>
                    <ad v-else :item='ad'></ad>
                </li>
            </transition-group>
        </div>
        <button v-if="this.$store.state.ads.length > 10" class="w-32 h-8 rounded-full text-white bg-a4a-orange self-center mb-2">Load more
        </button>
    </div>
</template>
<script>
    import Ad from './Ad';

    export default {
        name: 'Ads',
        components: { Ad },
        props: ['category'],
        methods: {
            setAds() {
                this.$store.dispatch('setAds', this.category.id);
            },
        },
        mounted() {
            this.setAds();
        },

    };
</script>

And here is my Ad component:

<template>
    <transition name="fade">
    <div class="sm:w-card-horizontal lg:w-card-vertical lg:h-card-height-horizontal p-2 mb-8 m-1 border-1 border-a4a-light-grey">
        <div class="flex lg:flex-col lg:justify-center">
            <div class="flex flex-col w-1/3 lg:w-full content-between justify-between">
                <div class="flex flex-col flex-grow">
                    <img class="w-full cursor-pointer lg:-mt-5 shadow-2xl mb-2 border-2 border-transparent  md:hover:-mt-8 hover:border-2 hover:block hover:border-transparent" :src="'https://picsum.photos/200/150?random='+ item.id">
                    <span class="hidden md:flex opacity-50 border border-transparent hover:border-transparent md:relative lg:w-24 lg:h-8 items-center px-2 justify-between -mt-4 lg:-mt-10 ml-2 text-xs bg-black  text-white">
                        <svg class="w-4 h-4 fill-current text-white" viewBox="0 0 20 20">
                            <path d="M10,6.536c-2.263,0-4.099,1.836-4.099,4.098S7.737,14.732,10,14.732s4.099-1.836,4.099-4.098S12.263,6.536,10,6.536M10,13.871c-1.784,0-3.235-1.453-3.235-3.237S8.216,7.399,10,7.399c1.784,0,3.235,1.452,3.235,3.235S11.784,13.871,10,13.871M17.118,5.672l-3.237,0.014L12.52,3.697c-0.082-0.105-0.209-0.168-0.343-0.168H7.824c-0.134,0-0.261,0.062-0.343,0.168L6.12,5.686H2.882c-0.951,0-1.726,0.748-1.726,1.699v7.362c0,0.951,0.774,1.725,1.726,1.725h14.236c0.951,0,1.726-0.773,1.726-1.725V7.195C18.844,6.244,18.069,5.672,17.118,5.672 M17.98,14.746c0,0.477-0.386,0.861-0.862,0.861H2.882c-0.477,0-0.863-0.385-0.863-0.861V7.384c0-0.477,0.386-0.85,0.863-0.85l3.451,0.014c0.134,0,0.261-0.062,0.343-0.168l1.361-1.989h3.926l1.361,1.989c0.082,0.105,0.209,0.168,0.343,0.168l3.451-0.014c0.477,0,0.862,0.184,0.862,0.661V14.746z"></path>
                        </svg>
                        <span>10 Photos</span>
                    </span>
                </div>
                <div class="flex justify-between md:hidden h-8 md:h-12 bottom-0 mb-0 items-end">
                        <img class="rounded-full border-2 border-a4a-form-border h-12 w-12 flex items-center justify-center bg-gray-200"
                             :src="'https://lorempixel.com/44/50/technics/' +  item.id" alt="">
                    <wishlist  :item="item"></wishlist>
                </div>
            </div>
            <div class="flex w-2/3 lg:w-full flex-col px-2 lg:py-4">
                <div class="flex justify-between items-center lg:h-16">
                    <div class="text-light text-xs h-8">
                        Equipment | Tractor
                    </div>
                    <div class="hidden md:block">
                        <img class="rounded-full h-16 w-16 flex border-2 border-a4a-form-border items-center bg-gray-200"
                             :src="'https://lorempixel.com/44/50/technics/' +  item.id" alt="">
                    </div>
                </div>
                <div class="flex flex-col flex-grow lg:py-5">
                    <div class="flex font-medium lg:text-2xl h-12 lg:h-16">{{ item.currency }} {{ formatMoney(item.price) }}</div>
                    <div class="flex font-medium text-sm md:text-lg text-a4a-equipment-red leading-none h-12 lg:h-16 two-lines">{{ item.description }}</div>
                </div>
                <div class="flex justify-between h-8 md:h-16 bottom-0 mb-0 lg:px-2">
                    <div class="flex items-center justify-start">
                    <span>
                        <svg width="15px" height="20px" viewBox="0 0 15 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
                            <g id="map-pin-icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
                                <path d="M7.06989324,9.496 C5.66089324,9.496 4.51289324,8.35 4.51289324,6.939 C4.51289324,5.53 5.66089324,4.383 7.06989324,4.383 C8.47889324,4.383 9.62689324,5.53 9.62689324,6.939 C9.62689324,8.35 8.47889324,9.496 7.06989324,9.496 M11.9578932,2.052 C10.6348932,0.728 8.87589324,0 7.00589324,0 C5.13389324,0 3.37589324,0.728 2.05189324,2.052 C-0.396106764,4.5 -0.701106764,9.105 1.39289324,11.895 L7.00589324,20 L12.6078932,11.907 C14.7108932,9.105 14.4058932,4.5 11.9578932,2.052" id="Fill-13" fill="#545454"></path>
                            </g>
                        </svg>
                    </span>
                    <span class="font-normal items-end text-sm p-2 w-32 truncate ...">
                        {{ item.city }}, {{ item.country }}
                    </span>
                    </div>
                </div>
                <div class="flex justify-between h-8 md:h-16 bottom-0 lg:pt-3 items-end">
                    <div class="flex justify-between w-full items-center h-8 lg:h-8 border-t-2 lg:border-b-2 border-gray-100 bottom-0 mb-0 px-2">
                        <div><span class="text-xs lg:text-sm font-medium">REF#</span> <span class="font-light text-xs">{{ item.id.split("-").pop().toUpperCase()}}</span></div>
                        <div><span class="text-xs lg:text-sm font-medium">Views:</span><span class="text-sm font-light"> {{ item.views ? item.views :  Math.floor(Math.random() * 100)}}</span></div>
                    </div>
                </div>
                <div class="hidden lg:flex justify-between h-16 pt-3">
                    <!-- visible on big screen -->
                    <button class="border border-a4a-equipment-red w-32 h-8 text-red-600 text-center rounded-full">View Ad</button>
                    <span class="hidden md:block"><wishlist :item="item"></wishlist></span>
                </div>
            </div>
        </div>
    </div>
    </transition>
</template>
<script>
    import Wishlist from '../Utils/Wishlist';
    export default {
        name: 'Ad',
        components: { Wishlist },
        props: ['item'],
    };
</script>

<style scoped>
    .two-lines{
        word-break: break-word;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        line-height: 16px; /* fallback */
        max-height: 32px; /* fallback */
        -webkit-line-clamp: 2; /* number of lines to show */
        -webkit-box-orient: vertical;
    }
</style>
dtparks commented 4 years ago

What I've done in the past is have some data or prop like "view" that can have either the value "table" or "card". Then, in the parent or wherever you control this piece of state you can toggle the values on a button click. In your component where you actually render the cards or the boxes, just have a v-if="view==='card'" and a second portion v-if="view==='table'" and handle the styling differently.

Edit: One other way to handle it would be to forego having multiple v-ifs and conditionally bind your classes based on that data value. Ex. <div :class="[view === 'card' ? 'w-96 ...' : 'w-full']> You get the idea.

nezaboravi commented 4 years ago

Thanks @dtparks . Second idea i like more. Will see where it will lead me :) Thanks :)