avatar component
asd
This commit is contained in:
parent
40bf33a9e5
commit
f374c3aa4d
5 changed files with 146 additions and 18 deletions
56
src/lib/components/Datadisplay/Avatar.stories.svelte
Normal file
56
src/lib/components/Datadisplay/Avatar.stories.svelte
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<script module lang="ts">
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import Avatar from './Avatar.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Data display/Avatar',
|
||||
component: Avatar,
|
||||
argTypes: {
|
||||
img: {
|
||||
control: 'text',
|
||||
},
|
||||
placeholder: {
|
||||
control: 'text',
|
||||
},
|
||||
presence: {
|
||||
control: 'select',
|
||||
options: [undefined, 'online', 'offline'],
|
||||
},
|
||||
ring: {
|
||||
control: 'select',
|
||||
options: [
|
||||
undefined,
|
||||
'neutral',
|
||||
'primary',
|
||||
'secondary',
|
||||
'accent',
|
||||
'info',
|
||||
'success',
|
||||
'warning',
|
||||
'error',
|
||||
],
|
||||
},
|
||||
shape: {
|
||||
control: 'select',
|
||||
options: ['square', 'circle'],
|
||||
},
|
||||
size: {
|
||||
control: 'select',
|
||||
options: ['xs', 'sm', 'md', 'lg'],
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
{#snippet template(props: ComponentProps<typeof Avatar>)}
|
||||
<Avatar {...props} />
|
||||
{/snippet}
|
||||
|
||||
<Story
|
||||
name="Default"
|
||||
args={{
|
||||
img: 'https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp',
|
||||
}}
|
||||
children={template}
|
||||
/>
|
||||
62
src/lib/components/Datadisplay/Avatar.svelte
Normal file
62
src/lib/components/Datadisplay/Avatar.svelte
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<script lang="ts">
|
||||
import type { DaisyColor, DaisySize } from '$lib/types';
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
img?: string;
|
||||
placeholder: string;
|
||||
presence?: 'online' | 'offline';
|
||||
ring?: Exclude<DaisyColor, 'ghost'>;
|
||||
shape?: 'square' | 'circle';
|
||||
size?: DaisySize | 'md';
|
||||
} & Omit<SvelteHTMLElements['div'], 'children'>;
|
||||
|
||||
let {
|
||||
class: className,
|
||||
img,
|
||||
placeholder,
|
||||
presence,
|
||||
ring,
|
||||
shape = 'circle',
|
||||
size = 'md',
|
||||
...props
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<div {...props} class={twMerge('avatar', presence, clsx(className))} class:placeholder>
|
||||
<div
|
||||
class={twMerge(
|
||||
'rounded-xl',
|
||||
clsx({
|
||||
'rounded-xl': shape === 'square',
|
||||
'rounded-full': shape === 'circle',
|
||||
'w-12': size === 'xs',
|
||||
'w-16': size === 'sm',
|
||||
'w-20': size === 'md',
|
||||
'w-32': size === 'lg',
|
||||
'avatar-ring ring ring-offset-2 ring-offset-base-100': !!ring,
|
||||
})
|
||||
)}
|
||||
class:bg-neutral={placeholder}
|
||||
class:ring-neutral={ring === 'neutral'}
|
||||
class:ring-primary={ring === 'primary'}
|
||||
class:ring-secondary={ring === 'secondary'}
|
||||
class:ring-accent={ring === 'accent'}
|
||||
class:ring-info={ring === 'info'}
|
||||
class:ring-success={ring === 'success'}
|
||||
class:ring-warning={ring === 'warning'}
|
||||
class:ring-error={ring === 'error'}
|
||||
>
|
||||
{#if img}
|
||||
<img src={img} alt={placeholder} />
|
||||
{:else}
|
||||
<span
|
||||
class:text-3xl={size === 'lg'}
|
||||
class:text-xl={size === 'md'}
|
||||
class:text-xs={size === 'xs'}>{placeholder}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
1
src/lib/components/Datadisplay/index.ts
Normal file
1
src/lib/components/Datadisplay/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as Avatar } from './Avatar.svelte';
|
||||
|
|
@ -5,17 +5,15 @@
|
|||
import { messages } from '$lib/i18n';
|
||||
import 'clerk-sveltekit/client';
|
||||
import SignOutButton from 'clerk-sveltekit/client/SignOutButton.svelte';
|
||||
import { Cog, LogOut, MessageCircleMore, UsersRound } from 'lucide-svelte';
|
||||
import { Cog, LogOut, Menu, MessageCircleMore, UsersRound } from 'lucide-svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import type { LayoutData } from './$types';
|
||||
|
||||
type Props = {
|
||||
children: Snippet;
|
||||
data: LayoutData;
|
||||
};
|
||||
|
||||
let { children, data }: Props = $props();
|
||||
let { children }: Props = $props();
|
||||
|
||||
let clerk;
|
||||
|
||||
|
|
@ -45,22 +43,17 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
let message = $derived(messages.nav_greeting({ name: data.user.name }));
|
||||
</script>
|
||||
|
||||
{#snippet userMenu()}
|
||||
<div class="dropdown dropdown-end">
|
||||
<div tabindex="0" role="button" class="btn btn-circle btn-primary btn-sm ring">
|
||||
<div class="avatar placeholder online">
|
||||
<div class="w-8 rounded-full">
|
||||
{#if data.user.hasImage}
|
||||
<img src={data.user.imageUrl} alt="Avatar" />
|
||||
{:else}
|
||||
<span>{data.user.name.at(0)}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
tabindex={0}
|
||||
role="button"
|
||||
class="btn btn-primary btn-md flex items-center gap-2 text-lg"
|
||||
>
|
||||
<Menu />
|
||||
Menu
|
||||
</div>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
||||
<ul
|
||||
|
|
@ -106,8 +99,7 @@
|
|||
<h1 class="prose prose-2xl">Svelte</h1>
|
||||
{/snippet}
|
||||
{#snippet end()}
|
||||
<div class="flex items-center gap-3">
|
||||
<p class="prose prose-lg">{message}</p>
|
||||
<div class="flex items-center gap-4 pr-2">
|
||||
{@render userMenu()}
|
||||
</div>
|
||||
{/snippet}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { Avatar } from '$lib/components/Datadisplay';
|
||||
import { messages } from '$lib/i18n';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
type Props = {
|
||||
data: PageData;
|
||||
};
|
||||
|
||||
let { data }: Props = $props();
|
||||
|
||||
let message = $derived(messages.nav_greeting({ name: data.user.name }));
|
||||
let initials = $derived(data.user.name.split(' ').reduce((col, name) => col + name.at(0), ''));
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<Avatar img={data.user.imageUrl} placeholder={initials} size="sm" ring="primary" />
|
||||
<h1 class="prose prose-2xl">{message}</h1>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue