Merge pull request #85 from AhnafAhamed/card-component
implement card component [ issue#54 ]
This commit is contained in:
@@ -1,15 +1,65 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import CardExample from './examples/CardExample.vue'
|
import CardDefaultExample from './examples/CardDefaultExample.vue'
|
||||||
|
import CardImageExample from './examples/CardImageExample.vue'
|
||||||
|
import CardHorizontalExample from './examples/CardHorizontalExample.vue'
|
||||||
</script>
|
</script>
|
||||||
# Vue Card Components - Flowbite
|
# Vue Card Components - Flowbite
|
||||||
|
|
||||||
|
#### Get started with a large variety of Tailwind CSS card examples for your web project
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Original reference: [https://flowbite.com/docs/components/card/](https://flowbite.com/docs/components/card/)
|
||||||
|
:::
|
||||||
|
|
||||||
|
Use these responsive card components to show data entries and information to your users in multiple forms and contexts such as for your blog, application, user profiles, and more.
|
||||||
|
|
||||||
|
## Prop - default
|
||||||
|
|
||||||
|
<CardDefaultExample />
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Card } from 'flowbite-vue'
|
import { TheCard } from 'flowbite-vue'
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Card></Card>
|
<the-card href="#"/>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
<CardExample />
|
## Prop - image
|
||||||
|
|
||||||
|
<CardImageExample />
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { TheCard } from 'flowbite-vue'
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<the-card
|
||||||
|
variant="image"
|
||||||
|
href="#"
|
||||||
|
img-src="./images/blog/image-1.jpg"
|
||||||
|
img-alt="Image"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prop - horizontal
|
||||||
|
|
||||||
|
<CardHorizontalExample />
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { TheCard } from 'flowbite-vue'
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<the-card
|
||||||
|
variant="horizontal"
|
||||||
|
href="#"
|
||||||
|
img-src="./images/blog/image-4.jpg"
|
||||||
|
img-alt="Image"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|||||||
12
docs/components/card/examples/CardDefaultExample.vue
Normal file
12
docs/components/card/examples/CardDefaultExample.vue
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vp-raw inline-flex align-center gap-2 flex-wrap">
|
||||||
|
<the-card href="#">
|
||||||
|
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Noteworthy technology acquisitions 2021</h5>
|
||||||
|
<p class="font-normal text-gray-700 dark:text-gray-400">Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.</p>
|
||||||
|
</the-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { TheCard } from '../../../../src/index'
|
||||||
|
</script>
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="vp-raw flex flex-col">
|
|
||||||
<Card></Card>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { Card } from '../../../../src/index'
|
|
||||||
</script>
|
|
||||||
11
docs/components/card/examples/CardHorizontalExample.vue
Normal file
11
docs/components/card/examples/CardHorizontalExample.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vp-raw inline-flex align-center gap-2 flex-wrap">
|
||||||
|
<the-card href="#" variant="horizontal" img-src="https://flowbite.com/docs/images/blog/image-4.jpg" img-alt="Desk">
|
||||||
|
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Noteworthy technology acquisitions 2021</h5>
|
||||||
|
<p class="font-normal text-gray-700 dark:text-gray-400">Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.</p>
|
||||||
|
</the-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { TheCard } from '../../../../src/index'
|
||||||
|
</script>
|
||||||
11
docs/components/card/examples/CardImageExample.vue
Normal file
11
docs/components/card/examples/CardImageExample.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vp-raw inline-flex align-center gap-2 flex-wrap">
|
||||||
|
<the-card variant="image" img-src="https://flowbite.com/docs/images/blog/image-1.jpg" img-alt="Desk">
|
||||||
|
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Noteworthy technology acquisitions 2021</h5>
|
||||||
|
<p class="font-normal text-gray-700 dark:text-gray-400">Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.</p>
|
||||||
|
</the-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { TheCard } from '../../../../src/index'
|
||||||
|
</script>
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a href="#" class="block p-6 max-w-sm bg-white rounded-lg border border-gray-200 shadow-md hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
|
|
||||||
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Noteworthy technology acquisitions 2021</h5>
|
|
||||||
<p class="font-normal text-gray-700 dark:text-gray-400">Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.</p>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, toRefs } from 'vue'
|
|
||||||
import type { PropType } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
horizontal: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
href: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
imgAlt: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
imgSrc: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
37
src/components/Card/TheCard.vue
Normal file
37
src/components/Card/TheCard.vue
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
<component :is="wrapperType" :href="href" :class="cardClasses">
|
||||||
|
<img v-if="imgSrc" class="rounded-t-lg" :class="horizontalImageClasses" :src="imgSrc" :alt="imgAlt"/>
|
||||||
|
<div class="p-6">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, toRefs } from 'vue'
|
||||||
|
import type { PropType } from 'vue'
|
||||||
|
import { useCardsClasses } from './composables/useCardClasses'
|
||||||
|
import type { CardsVariant } from './types'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
href: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
imgAlt: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
imgSrc: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
type: String as PropType<CardsVariant>,
|
||||||
|
default: 'default',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { cardClasses, horizontalImageClasses } = useCardsClasses(toRefs(props))
|
||||||
|
const wrapperType = computed(() => props.href ? 'a' : 'div')
|
||||||
|
|
||||||
|
</script>
|
||||||
34
src/components/Card/composables/useCardClasses.ts
Normal file
34
src/components/Card/composables/useCardClasses.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import type { Ref } from 'vue'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import type { CardsVariant } from '../types'
|
||||||
|
|
||||||
|
export type UseCardsClassesProps = {
|
||||||
|
variant: Ref<CardsVariant>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useCardsClasses(props: UseCardsClassesProps): {
|
||||||
|
cardClasses: Ref<string>,
|
||||||
|
horizontalImageClasses: Ref<string>
|
||||||
|
} {
|
||||||
|
const cardClasses = computed(() => {
|
||||||
|
if(props.variant.value === 'default')
|
||||||
|
return 'block max-w-sm bg-white rounded-lg border border-gray-200 shadow-md hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700'
|
||||||
|
else if(props.variant.value === 'image')
|
||||||
|
return 'max-w-sm bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700'
|
||||||
|
else if(props.variant.value === 'horizontal')
|
||||||
|
return 'flex flex-col items-center bg-white rounded-lg border shadow-md md:flex-row md:max-w-xl hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700'
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const horizontalImageClasses = computed(() => {
|
||||||
|
if(props.variant.value === 'horizontal')
|
||||||
|
return 'object-cover w-full h-96 rounded-t-lg md:h-auto md:w-48 md:rounded-none md:rounded-l-lg'
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
cardClasses,
|
||||||
|
horizontalImageClasses,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
0
src/components/Card/tests/Card.specs.ts
Normal file
0
src/components/Card/tests/Card.specs.ts
Normal file
1
src/components/Card/types.ts
Normal file
1
src/components/Card/types.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export type CardsVariant = 'default' | 'image' | 'horizontal'
|
||||||
@@ -13,9 +13,8 @@ export { default as Avatar } from './components/Avatar/Avatar.vue'
|
|||||||
export { default as StackedAvatars } from './components/Avatar/StackedAvatars.vue'
|
export { default as StackedAvatars } from './components/Avatar/StackedAvatars.vue'
|
||||||
export { default as StackedAvatarsCounter } from './components/Avatar/StackedAvatarsCounter.vue'
|
export { default as StackedAvatarsCounter } from './components/Avatar/StackedAvatarsCounter.vue'
|
||||||
export { default as Accordion } from './components/Accordion/Accordion.vue'
|
export { default as Accordion } from './components/Accordion/Accordion.vue'
|
||||||
|
|
||||||
export { default as Badge } from './components/Badge/Badge.vue'
|
export { default as Badge } from './components/Badge/Badge.vue'
|
||||||
export { default as Card } from './components/Card/Card.vue'
|
export { default as TheCard } from './components/Card/TheCard.vue'
|
||||||
export { default as Carousel } from './components/Carousel/Carousel.vue'
|
export { default as Carousel } from './components/Carousel/Carousel.vue'
|
||||||
export { default as Footer } from './components/Footer/Footer.vue'
|
export { default as Footer } from './components/Footer/Footer.vue'
|
||||||
export { default as ListGroup } from './components/ListGroup/ListGroup.vue'
|
export { default as ListGroup } from './components/ListGroup/ListGroup.vue'
|
||||||
|
|||||||
Reference in New Issue
Block a user