From d7daf5b4d92936dde3b19ab024f786ca127a573b Mon Sep 17 00:00:00 2001 From: Ilya Sosidka Date: Sat, 3 Sep 2022 11:53:40 +0300 Subject: [PATCH 1/5] chore: Added types for avatar component --- src/components/Avatar/types.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/components/Avatar/types.ts diff --git a/src/components/Avatar/types.ts b/src/components/Avatar/types.ts new file mode 100644 index 0000000..3c75a55 --- /dev/null +++ b/src/components/Avatar/types.ts @@ -0,0 +1,3 @@ +export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' +export type AvatarStatus = 'away' | 'busy' | 'offline' | 'online' +export type AvatarStatusPosition = 'bottom-left' | 'bottom-right' | 'bottom-center' | 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' From a3e93e1ef1dab56cfdfbaa2179f7742511bb9a92 Mon Sep 17 00:00:00 2001 From: Ilya Sosidka Date: Tue, 6 Sep 2022 13:15:06 +0300 Subject: [PATCH 2/5] feat: Implemented avatar component --- docs/.vitepress/config.ts | 2 +- docs/components/avatar/avatar.md | 91 ++++++++++++++++++- .../avatar/examples/AvatarBorderedExample.vue | 9 ++ .../examples/AvatarDotIndicatorExample.vue | 11 +++ .../AvatarDotIndicatorPositionExample.vue | 15 +++ .../avatar/examples/AvatarExample.vue | 5 +- .../avatar/examples/AvatarSizeExample.vue | 14 +++ src/components/Avatar/Avatar.vue | 29 +++--- .../Avatar/composables/useAvatarClasses.ts | 79 ++++++++++++++++ src/components/Avatar/types.ts | 4 +- 10 files changed, 238 insertions(+), 21 deletions(-) create mode 100644 docs/components/avatar/examples/AvatarBorderedExample.vue create mode 100644 docs/components/avatar/examples/AvatarDotIndicatorExample.vue create mode 100644 docs/components/avatar/examples/AvatarDotIndicatorPositionExample.vue create mode 100644 docs/components/avatar/examples/AvatarSizeExample.vue create mode 100644 src/components/Avatar/composables/useAvatarClasses.ts diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index d81f580..f1b615d 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -35,6 +35,7 @@ function buildSidebar() { function getComponents() { return [ { text: 'Alert', link: '/components/alert/alert.md' }, + { text: 'Avatar', link: 'components/avatar/avatar.md' }, { text: 'Button', link: '/components/button/button.md' }, { text: 'Button Group', link: '/components/buttonGroup/buttonGroup.md' }, { text: 'Dropdown', link: '/components/dropdown/dropdown.md' }, @@ -44,7 +45,6 @@ function getComponents() { { text: 'Toast', link: 'components/toast/toast.md' }, { text: '- Accordion', link: 'components/accordion/accordion.md' }, - { text: '- Avatar', link: 'components/avatar/avatar.md' }, { text: '- Badge', link: 'components/badge/badge.md' }, { text: '- Breadcrumb', link: 'components/breadcrumb/breadcrumb.md' }, { text: '- Card', link: 'components/card/card.md' }, diff --git a/docs/components/avatar/avatar.md b/docs/components/avatar/avatar.md index 63b1c84..2ef1033 100644 --- a/docs/components/avatar/avatar.md +++ b/docs/components/avatar/avatar.md @@ -1,15 +1,102 @@ # Avatar +Use the avatar component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes + +## Default avatar +Use this example to create a circle and rounded avatar on an image element. + + ```vue ``` - +## Bordered +Use this example to create a circle and rounded avatar on an image element. + + + +```vue + + +``` + +## Dot indicator + + + +```vue + + +``` + +## Sizes + + + +```vue + + +``` + +## Dot indicator position + + + +```vue + + +``` diff --git a/docs/components/avatar/examples/AvatarBorderedExample.vue b/docs/components/avatar/examples/AvatarBorderedExample.vue new file mode 100644 index 0000000..1de342b --- /dev/null +++ b/docs/components/avatar/examples/AvatarBorderedExample.vue @@ -0,0 +1,9 @@ + + diff --git a/docs/components/avatar/examples/AvatarDotIndicatorExample.vue b/docs/components/avatar/examples/AvatarDotIndicatorExample.vue new file mode 100644 index 0000000..ca877c0 --- /dev/null +++ b/docs/components/avatar/examples/AvatarDotIndicatorExample.vue @@ -0,0 +1,11 @@ + + diff --git a/docs/components/avatar/examples/AvatarDotIndicatorPositionExample.vue b/docs/components/avatar/examples/AvatarDotIndicatorPositionExample.vue new file mode 100644 index 0000000..5deae90 --- /dev/null +++ b/docs/components/avatar/examples/AvatarDotIndicatorPositionExample.vue @@ -0,0 +1,15 @@ + + diff --git a/docs/components/avatar/examples/AvatarExample.vue b/docs/components/avatar/examples/AvatarExample.vue index 316eb82..a0705b8 100644 --- a/docs/components/avatar/examples/AvatarExample.vue +++ b/docs/components/avatar/examples/AvatarExample.vue @@ -1,6 +1,7 @@ diff --git a/src/components/Avatar/Avatar.vue b/src/components/Avatar/Avatar.vue index b56b350..3826820 100644 --- a/src/components/Avatar/Avatar.vue +++ b/src/components/Avatar/Avatar.vue @@ -1,27 +1,24 @@ diff --git a/src/components/Avatar/composables/useAvatarClasses.ts b/src/components/Avatar/composables/useAvatarClasses.ts new file mode 100644 index 0000000..6766ab6 --- /dev/null +++ b/src/components/Avatar/composables/useAvatarClasses.ts @@ -0,0 +1,79 @@ +import { computed } from 'vue' +import type { Ref } from 'vue' +import classNames from 'classnames' +import type { AvatarSize, AvatarStatus, AvatarStatusPosition, AvatarType, avatarDotIndicatorPositionClasses } from '@/components/Avatar/types' + +const avatarSizeClasses: Record = { + xs: 'w-6 h-6', + sm: 'w-8 h-8', + md: 'w-10 h-10', + lg: 'w-20 h-20', + xl: 'w-36 h-36', +} +const avatarTypeClasses: Record = { + default: 'rounded', + rounded: 'rounded-full', +} +const avatarBorderedClasses = 'ring-2 ring-gray-300 dark:ring-gray-500 p-1' + +const avatarStatusDotDefaultClasses = 'absolute h-3.5 w-3.5 rounded-full border-2 border-white dark:border-gray-800' +const avatarStatusDotClasses: Record = { + away: 'bg-gray-400', + busy: 'bg-yellow-400', + offline: 'bg-red-400', + online: 'bg-green-400', +} +const avatarStatusDotPositionClasses: Record = { + 'top-right-rounded': 'top-0 -right-0.5', + 'top-right-default': '-top-1.5 -right-1.5', + 'top-left-rounded': 'top-0 left-0', + 'top-left-default': 'top-0 left-0 transform -translate-y-1/2 -translate-x-1/2', + 'bottom-right-rounded': 'bottom-0 -right-0.5', + 'bottom-right-default': 'bottom-0 -right-1.5 translate-y-1/2', + 'bottom-left-rounded': 'bottom-0 left-0', + 'bottom-left-default': '-bottom-1.5 left-0 transform -translate-x-1/2 ', +} + +export type UseAvatarClassesProps = { + status: Ref + bordered: Ref + img: Ref + alt: Ref + rounded: Ref + size: Ref + stacked: Ref + statusPosition: Ref +} + +export function useAvatarClasses(props: UseAvatarClassesProps): { + avatarClasses: Ref + avatarDotClasses: Ref +} { + + const avatarClasses = computed(() => { + console.log('border', props.bordered.value) + return classNames( + avatarSizeClasses[props.size.value], + avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'], + props.bordered.value ? avatarBorderedClasses : '', + ) + }) + const avatarDotClasses = computed(() => { + const avatarType = `${props.statusPosition.value}-${props.rounded.value ? 'rounded' : 'default'}` + return classNames( + avatarStatusDotDefaultClasses, + avatarStatusDotClasses[props.status.value], + avatarStatusDotPositionClasses[avatarType as avatarDotIndicatorPositionClasses], + ) + }) + // TODO: Placeholder + // TODO: Stacked avatars + // TODO: Avatar Initials + + return { + avatarClasses, + avatarDotClasses, + } +} + + diff --git a/src/components/Avatar/types.ts b/src/components/Avatar/types.ts index 3c75a55..d9903d0 100644 --- a/src/components/Avatar/types.ts +++ b/src/components/Avatar/types.ts @@ -1,3 +1,5 @@ export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' export type AvatarStatus = 'away' | 'busy' | 'offline' | 'online' -export type AvatarStatusPosition = 'bottom-left' | 'bottom-right' | 'bottom-center' | 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' +export type AvatarStatusPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' +export type AvatarType = 'default' | 'rounded' +export type avatarDotIndicatorPositionClasses = `${AvatarStatusPosition}-${AvatarType}` From 68440bac7faf28c68b18f801c9cb12ff07f4d92b Mon Sep 17 00:00:00 2001 From: Ilya Artamonov Date: Tue, 6 Sep 2022 16:36:58 +0300 Subject: [PATCH 3/5] feat: Added stacked avatars --- docs/components/avatar/avatar.md | 33 +++++++++++++++++++ .../examples/AvatarAlternativeTextExample.vue | 8 +++++ .../avatar/examples/StackedAvatarsExample.vue | 21 ++++++++++++ src/components/Avatar/StackedAvatars.vue | 5 +++ .../Avatar/StackedAvatarsCounter.vue | 15 +++++++++ .../Avatar/composables/useAvatarClasses.ts | 2 +- src/index.ts | 6 ++-- 7 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 docs/components/avatar/examples/AvatarAlternativeTextExample.vue create mode 100644 docs/components/avatar/examples/StackedAvatarsExample.vue create mode 100644 src/components/Avatar/StackedAvatars.vue create mode 100644 src/components/Avatar/StackedAvatarsCounter.vue diff --git a/docs/components/avatar/avatar.md b/docs/components/avatar/avatar.md index 2ef1033..1294e57 100644 --- a/docs/components/avatar/avatar.md +++ b/docs/components/avatar/avatar.md @@ -4,6 +4,9 @@ import AvatarBorderedExample from './examples/AvatarBorderedExample.vue' import AvatarDotIndicatorExample from './examples/AvatarDotIndicatorExample.vue' import AvatarSizeExample from './examples/AvatarSizeExample.vue' import AvatarDotIndicatorPositionExample from './examples/AvatarDotIndicatorPositionExample.vue' +import AvatarAlternativeTextExample from './examples/AvatarAlternativeTextExample.vue' +import StackedAvatarsExample from './examples/StackedAvatarsExample.vue' + # Avatar Use the avatar component to show a visual representation of a user profile using an image element or SVG object based on multiple styles and sizes @@ -100,3 +103,33 @@ import { Avatar } from 'flowbite-vue' ``` +## Alternative text + + + +## Stacked avatars + + + +```vue + + + +``` diff --git a/docs/components/avatar/examples/AvatarAlternativeTextExample.vue b/docs/components/avatar/examples/AvatarAlternativeTextExample.vue new file mode 100644 index 0000000..3b32d2a --- /dev/null +++ b/docs/components/avatar/examples/AvatarAlternativeTextExample.vue @@ -0,0 +1,8 @@ + + diff --git a/docs/components/avatar/examples/StackedAvatarsExample.vue b/docs/components/avatar/examples/StackedAvatarsExample.vue new file mode 100644 index 0000000..60f25f6 --- /dev/null +++ b/docs/components/avatar/examples/StackedAvatarsExample.vue @@ -0,0 +1,21 @@ + + diff --git a/src/components/Avatar/StackedAvatars.vue b/src/components/Avatar/StackedAvatars.vue new file mode 100644 index 0000000..ef4c830 --- /dev/null +++ b/src/components/Avatar/StackedAvatars.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/Avatar/StackedAvatarsCounter.vue b/src/components/Avatar/StackedAvatarsCounter.vue new file mode 100644 index 0000000..521b367 --- /dev/null +++ b/src/components/Avatar/StackedAvatarsCounter.vue @@ -0,0 +1,15 @@ + + diff --git a/src/components/Avatar/composables/useAvatarClasses.ts b/src/components/Avatar/composables/useAvatarClasses.ts index 6766ab6..c172c37 100644 --- a/src/components/Avatar/composables/useAvatarClasses.ts +++ b/src/components/Avatar/composables/useAvatarClasses.ts @@ -56,6 +56,7 @@ export function useAvatarClasses(props: UseAvatarClassesProps): { avatarSizeClasses[props.size.value], avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'], props.bordered.value ? avatarBorderedClasses : '', + props.stacked.value ? 'border-2 border-white dark:border-gray-800' : '', ) }) const avatarDotClasses = computed(() => { @@ -67,7 +68,6 @@ export function useAvatarClasses(props: UseAvatarClassesProps): { ) }) // TODO: Placeholder - // TODO: Stacked avatars // TODO: Avatar Initials return { diff --git a/src/index.ts b/src/index.ts index 64d1910..34a6643 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,9 +7,11 @@ export { default as Tab } from './components/Tabs/components/Tab/Tab.vue' export { default as Dropdown } from './components/Dropdown/Dropdown.vue' export { default as FlowbiteThemable } from './components/utils/FlowbiteThemable/FlowbiteThemable.vue' export { default as FlowbiteThemableChild } from './components/utils/FlowbiteThemable/components/FlowbiteThemableChild/FlowbiteThemableChild.vue' - -export { default as Accordion } from './components/Accordion/Accordion.vue' export { default as Avatar } from './components/Avatar/Avatar.vue' +export { default as StackedAvatars } from './components/Avatar/StackedAvatars.vue' +export { default as StackedAvatarsCounter } from './components/Avatar/StackedAvatarsCounter.vue' +export { default as Accordion } from './components/Accordion/Accordion.vue' + export { default as Badge } from './components/Badge/Badge.vue' export { default as Breadcrumb } from './components/Breadcrumb/Breadcrumb.vue' export { default as Card } from './components/Card/Card.vue' From 1e240f0af4d0e82449da1f96c833f4eec505935a Mon Sep 17 00:00:00 2001 From: Ilya Artamonov Date: Wed, 7 Sep 2022 12:51:48 +0300 Subject: [PATCH 4/5] feat: Added placeholder avatar --- docs/components/avatar/avatar.md | 90 +++++++++++++++---- .../examples/AvatarPlaceholderExample.vue | 9 ++ .../AvatarPlaceholderInitialsExample.vue | 9 ++ src/components/Avatar/Avatar.vue | 14 ++- .../Avatar/composables/useAvatarClasses.ts | 36 +++++++- 5 files changed, 136 insertions(+), 22 deletions(-) create mode 100644 docs/components/avatar/examples/AvatarPlaceholderExample.vue create mode 100644 docs/components/avatar/examples/AvatarPlaceholderInitialsExample.vue diff --git a/docs/components/avatar/avatar.md b/docs/components/avatar/avatar.md index 1294e57..a1b8a7f 100644 --- a/docs/components/avatar/avatar.md +++ b/docs/components/avatar/avatar.md @@ -6,6 +6,8 @@ import AvatarSizeExample from './examples/AvatarSizeExample.vue' import AvatarDotIndicatorPositionExample from './examples/AvatarDotIndicatorPositionExample.vue' import AvatarAlternativeTextExample from './examples/AvatarAlternativeTextExample.vue' import StackedAvatarsExample from './examples/StackedAvatarsExample.vue' +import AvatarPlaceholderExample from './examples/AvatarPlaceholderExample.vue' +import AvatarPlaceholderInitialsExample from './examples/AvatarPlaceholderInitialsExample.vue' # Avatar @@ -46,6 +48,7 @@ import { Avatar } from 'flowbite-vue' ``` ## Dot indicator +Use a dot element relative to the avatar component as an indicator for the user (eg. online or offline status). @@ -63,27 +66,9 @@ import { Avatar } from 'flowbite-vue' ``` -## Sizes - - - -```vue - - -``` - ## Dot indicator position + ```vue @@ -103,11 +88,44 @@ import { Avatar } from 'flowbite-vue' ``` + +## Sizes + +Choose from multiple sizing options for the avatar component from this example. + + + +```vue + + +``` + ## Alternative text +```vue + + + +``` + ## Stacked avatars +Use this example if you want to stack a group of users by overlapping the avatar components. @@ -133,3 +151,37 @@ import { StackedAvatars, Avatar, StackedAvatarsCounter } from 'flowbite-vue' ``` + +## Placeholder icon + + + +```vue + + + +``` + +## Placeholder initials + + + +```vue + + + +``` diff --git a/docs/components/avatar/examples/AvatarPlaceholderExample.vue b/docs/components/avatar/examples/AvatarPlaceholderExample.vue new file mode 100644 index 0000000..e22a835 --- /dev/null +++ b/docs/components/avatar/examples/AvatarPlaceholderExample.vue @@ -0,0 +1,9 @@ + + diff --git a/docs/components/avatar/examples/AvatarPlaceholderInitialsExample.vue b/docs/components/avatar/examples/AvatarPlaceholderInitialsExample.vue new file mode 100644 index 0000000..a53b0f4 --- /dev/null +++ b/docs/components/avatar/examples/AvatarPlaceholderInitialsExample.vue @@ -0,0 +1,9 @@ + + diff --git a/src/components/Avatar/Avatar.vue b/src/components/Avatar/Avatar.vue index 3826820..1d674fe 100644 --- a/src/components/Avatar/Avatar.vue +++ b/src/components/Avatar/Avatar.vue @@ -1,6 +1,12 @@ @@ -43,8 +49,12 @@ const props = defineProps({ type: String as PropType, default: 'top-right', }, + initials: { + type: String, + default: null, + }, }) -const { avatarClasses, avatarDotClasses } = useAvatarClasses(toRefs(props)) +const { avatarClasses, avatarDotClasses, avatarPlaceholderClasses, avatarPlaceholderWrapperClasses, avatarPlaceholderInitialsClasses } = useAvatarClasses(toRefs(props)) diff --git a/src/components/Avatar/composables/useAvatarClasses.ts b/src/components/Avatar/composables/useAvatarClasses.ts index c172c37..bfb5619 100644 --- a/src/components/Avatar/composables/useAvatarClasses.ts +++ b/src/components/Avatar/composables/useAvatarClasses.ts @@ -34,6 +34,17 @@ const avatarStatusDotPositionClasses: Record bordered: Ref @@ -48,6 +59,9 @@ export type UseAvatarClassesProps = { export function useAvatarClasses(props: UseAvatarClassesProps): { avatarClasses: Ref avatarDotClasses: Ref + avatarPlaceholderClasses: Ref + avatarPlaceholderWrapperClasses: Ref + avatarPlaceholderInitialsClasses: Ref } { const avatarClasses = computed(() => { @@ -67,12 +81,32 @@ export function useAvatarClasses(props: UseAvatarClassesProps): { avatarStatusDotPositionClasses[avatarType as avatarDotIndicatorPositionClasses], ) }) - // TODO: Placeholder + const avatarPlaceholderClasses = computed(() => { + return classNames( + avatarPlaceholderDefaultClasses, + avatarPlaceholderSizes[props.size.value], + ) + }) + const avatarPlaceholderWrapperClasses = computed(() => { + return classNames( + avatarPlaceholderWrapperDefaultClasses, + avatarSizeClasses[props.size.value], + avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'], + ) + }) + const avatarPlaceholderInitialsClasses = computed(() => { + return classNames( + avatarPlaceholderInitialsDefaultClasses, + ) + }) // TODO: Avatar Initials return { avatarClasses, avatarDotClasses, + avatarPlaceholderClasses, + avatarPlaceholderWrapperClasses, + avatarPlaceholderInitialsClasses, } } From 4f274a907ee4b659dcb3a81ab00c8ae4c1eb5687 Mon Sep 17 00:00:00 2001 From: Ilya Artamonov Date: Wed, 7 Sep 2022 12:54:04 +0300 Subject: [PATCH 5/5] fix: Fixed offline status in an example component --- docs/components/avatar/examples/AvatarDotIndicatorExample.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/components/avatar/examples/AvatarDotIndicatorExample.vue b/docs/components/avatar/examples/AvatarDotIndicatorExample.vue index ca877c0..ed38dd8 100644 --- a/docs/components/avatar/examples/AvatarDotIndicatorExample.vue +++ b/docs/components/avatar/examples/AvatarDotIndicatorExample.vue @@ -3,7 +3,7 @@ - +