From cf2b6abe7d0a70660a398d7bea7fde88366ba64a Mon Sep 17 00:00:00 2001 From: SHYAKA Davis <87414827+shyakadavis@users.noreply.github.com> Date: Wed, 17 Jul 2024 00:17:58 +0200 Subject: [PATCH] components: add Avatar (#6) * components: add `Avatar` * . * simplify and more * oops * read somewhere to stick to undefined instead of null --------- Co-authored-by: Davis SHYAKA <87414827+davis-shyaka@users.noreply.github.com> --- .vscode/settings.json | 14 ++- package.json | 1 + pnpm-lock.yaml | 83 ++++++++++++++ src/lib/assets/icons/chevron-left.svg | 3 + src/lib/assets/icons/chevron-right.svg | 4 +- src/lib/assets/icons/index.ts | 10 +- src/lib/assets/icons/logo-bitbucket-color.svg | 10 ++ src/lib/assets/icons/logo-github.svg | 10 ++ src/lib/assets/icons/logo-gitlab.svg | 13 +++ src/lib/components/shared/demo.svelte | 102 +++++++++--------- src/lib/components/shared/page-wrapper.svelte | 2 +- .../ui/avatar/avatar-fallback.svelte | 16 +++ .../components/ui/avatar/avatar-group.svelte | 79 ++++++++++++++ .../components/ui/avatar/avatar-image.svelte | 18 ++++ src/lib/components/ui/avatar/avatar.svelte | 31 ++++++ src/lib/components/ui/avatar/index.ts | 6 ++ src/lib/components/ui/badge/badge.svelte | 8 +- src/lib/components/ui/badge/index.ts | 6 +- src/routes/+page.svelte | 4 +- src/routes/avatar/+page.svelte | 30 +++++- src/routes/avatar/+page.ts | 22 ++++ src/routes/avatar/group.svelte | 37 +++++++ src/routes/avatar/placeholder.svelte | 5 + src/routes/avatar/with-icons.svelte | 19 ++++ src/routes/badge/+page.svelte | 5 + src/routes/footer.svelte | 82 ++++++++++---- src/routes/introduction-link.svelte | 2 +- src/routes/sitemap.ts | 4 +- 28 files changed, 536 insertions(+), 90 deletions(-) create mode 100644 src/lib/assets/icons/chevron-left.svg create mode 100644 src/lib/assets/icons/logo-bitbucket-color.svg create mode 100644 src/lib/assets/icons/logo-github.svg create mode 100644 src/lib/assets/icons/logo-gitlab.svg create mode 100644 src/lib/components/ui/avatar/avatar-fallback.svelte create mode 100644 src/lib/components/ui/avatar/avatar-group.svelte create mode 100644 src/lib/components/ui/avatar/avatar-image.svelte create mode 100644 src/lib/components/ui/avatar/avatar.svelte create mode 100644 src/lib/components/ui/avatar/index.ts create mode 100644 src/routes/avatar/+page.ts create mode 100644 src/routes/avatar/group.svelte create mode 100644 src/routes/avatar/placeholder.svelte create mode 100644 src/routes/avatar/with-icons.svelte diff --git a/.vscode/settings.json b/.vscode/settings.json index 56be484..ce292bc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,26 @@ { "cSpell.words": [ + "anatolzak", + "benmccann", "Choicebox", + "ciscoheat", "Combobox", - "exmarkdown", + "Conduitry", + "dummdidumm", "geist", + "geoffrich", + "Gonz", + "huntabyte", + "lukeed", "nums", + "ollema", "Paperclip", "poppanator", "shadcn", "shiki", + "shyakadavis", + "techniq", + "trueadm", "Turborepo", "WAAPI" ] diff --git a/package.json b/package.json index 55a9cdc..075ed42 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ }, "type": "module", "dependencies": { + "bits-ui": "^0.21.12", "clsx": "^2.1.1", "tailwind-merge": "^2.4.0", "tailwind-variants": "^0.2.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 699509c..b243d81 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + bits-ui: + specifier: ^0.21.12 + version: 0.21.12(svelte@4.2.18) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -233,12 +236,24 @@ packages: cpu: [x64] os: [win32] + '@floating-ui/core@1.6.4': + resolution: {integrity: sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==} + + '@floating-ui/dom@1.6.7': + resolution: {integrity: sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==} + + '@floating-ui/utils@0.2.4': + resolution: {integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==} + '@fontsource/geist-mono@5.0.3': resolution: {integrity: sha512-ekY5FNiK7aMxan/c6lgVQa/rIwQ/AMEJZJWY7768jBrLVdkrCxfEfCe1ePpe7C3JnySy7c9R6HC4Xh4ksfjTaw==} '@fontsource/geist-sans@5.0.3': resolution: {integrity: sha512-oGwoSIqNPMvjtCwj1lZaEr47MeiG27XPhypwkF643u1TQduvwbm3V3hYB01JekeaT34SAGP4I1h+WCdRpJkcwA==} + '@internationalized/date@3.5.4': + resolution: {integrity: sha512-qoVJVro+O0rBaw+8HPjUB1iH8Ihf8oziEnqMnvhJUSuVIrHOuZ6eNLHNvzXJKUvAtaDiqMnRlg8Z2mgh09BlUw==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -261,6 +276,11 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@melt-ui/svelte@0.76.2': + resolution: {integrity: sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==} + peerDependencies: + svelte: '>=3 <5' + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -408,6 +428,9 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 + '@swc/helpers@0.5.12': + resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} + '@tailwindcss/typography@0.5.13': resolution: {integrity: sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==} peerDependencies: @@ -486,6 +509,11 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bits-ui@0.21.12: + resolution: {integrity: sha512-Cf0iB+ZKwA0ZjkpixrhrZK9PC6pGPFleW/65Xc/z0lpGvWaFtdOhiYEntCHHxZ0VihP3aJaG0OBhUBIbmAePaA==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.118 + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -667,6 +695,9 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + focus-trap@7.5.4: + resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==} + foreground-child@3.2.1: resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} engines: {node: '>=14'} @@ -857,6 +888,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.0.7: + resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==} + engines: {node: ^18 || >=20} + hasBin: true + node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} @@ -1191,6 +1227,9 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tailwind-merge@2.4.0: resolution: {integrity: sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==} @@ -1381,10 +1420,25 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true + '@floating-ui/core@1.6.4': + dependencies: + '@floating-ui/utils': 0.2.4 + + '@floating-ui/dom@1.6.7': + dependencies: + '@floating-ui/core': 1.6.4 + '@floating-ui/utils': 0.2.4 + + '@floating-ui/utils@0.2.4': {} + '@fontsource/geist-mono@5.0.3': {} '@fontsource/geist-sans@5.0.3': {} + '@internationalized/date@3.5.4': + dependencies: + '@swc/helpers': 0.5.12 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -1411,6 +1465,16 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@melt-ui/svelte@0.76.2(svelte@4.2.18)': + dependencies: + '@floating-ui/core': 1.6.4 + '@floating-ui/dom': 1.6.7 + '@internationalized/date': 3.5.4 + dequal: 2.0.3 + focus-trap: 7.5.4 + nanoid: 5.0.7 + svelte: 4.2.18 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1542,6 +1606,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@swc/helpers@0.5.12': + dependencies: + tslib: 2.6.3 + '@tailwindcss/typography@0.5.13(tailwindcss@3.4.4)': dependencies: lodash.castarray: 4.4.0 @@ -1612,6 +1680,13 @@ snapshots: binary-extensions@2.3.0: {} + bits-ui@0.21.12(svelte@4.2.18): + dependencies: + '@internationalized/date': 3.5.4 + '@melt-ui/svelte': 0.76.2(svelte@4.2.18) + nanoid: 5.0.7 + svelte: 4.2.18 + boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -1806,6 +1881,10 @@ snapshots: dependencies: to-regex-range: 5.0.1 + focus-trap@7.5.4: + dependencies: + tabbable: 6.2.0 + foreground-child@3.2.1: dependencies: cross-spawn: 7.0.3 @@ -1968,6 +2047,8 @@ snapshots: nanoid@3.3.7: {} + nanoid@5.0.7: {} + node-releases@2.0.14: {} normalize-path@3.0.0: {} @@ -2268,6 +2349,8 @@ snapshots: csso: 5.0.5 picocolors: 1.0.1 + tabbable@6.2.0: {} + tailwind-merge@2.4.0: {} tailwind-variants@0.2.1(tailwindcss@3.4.4): diff --git a/src/lib/assets/icons/chevron-left.svg b/src/lib/assets/icons/chevron-left.svg new file mode 100644 index 0000000..491bee6 --- /dev/null +++ b/src/lib/assets/icons/chevron-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/lib/assets/icons/chevron-right.svg b/src/lib/assets/icons/chevron-right.svg index 9b52b78..e200313 100644 --- a/src/lib/assets/icons/chevron-right.svg +++ b/src/lib/assets/icons/chevron-right.svg @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/src/lib/assets/icons/index.ts b/src/lib/assets/icons/index.ts index 2c0067b..a7377ad 100644 --- a/src/lib/assets/icons/index.ts +++ b/src/lib/assets/icons/index.ts @@ -4,6 +4,7 @@ import BrandAssets from './brand-assets.svg?component'; import CharBarMiddle from './chart-bar-middle.svg?component'; import CharTrendingDown from './chart-trending-down.svg?component'; import Check from './check.svg?component'; +import ChevronLeft from './chevron-left.svg?component'; import ChevronRightSmall from './chevron-right-small.svg?component'; import ChevronRight from './chevron-right.svg?component'; import ClockDashed from './clock-dashed.svg?component'; @@ -21,7 +22,10 @@ import GridSquare from './grid-square.svg?component'; import Inbox from './inbox.svg?component'; import Key from './key.svg?component'; import Link from './link.svg?component'; -import LogoGeist from './logo-geist.svg'; +import LogoBitbucketColor from './logo-bitbucket-color.svg?component'; +import LogoGeist from './logo-geist.svg?component'; +import LogoGithub from './logo-github.svg?component'; +import LogoGitlab from './logo-gitlab.svg?component'; import LogoNext from './logo-next.svg?component'; import LogoTurborepo from './logo-turborepo.svg?component'; import LogoV0 from './logo-v0.svg?component'; @@ -44,6 +48,7 @@ export const Icons = { CharBarMiddle, CharTrendingDown, Check, + ChevronLeft, ChevronRightSmall, ChevronRight, ClockDashed, @@ -61,7 +66,10 @@ export const Icons = { Inbox, Key, Link, + LogoBitbucketColor, LogoGeist, + LogoGithub, + LogoGitlab, LogoNext, LogoTurborepo, LogoV0, diff --git a/src/lib/assets/icons/logo-bitbucket-color.svg b/src/lib/assets/icons/logo-bitbucket-color.svg new file mode 100644 index 0000000..d24b2cf --- /dev/null +++ b/src/lib/assets/icons/logo-bitbucket-color.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/lib/assets/icons/logo-github.svg b/src/lib/assets/icons/logo-github.svg new file mode 100644 index 0000000..461ee69 --- /dev/null +++ b/src/lib/assets/icons/logo-github.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/lib/assets/icons/logo-gitlab.svg b/src/lib/assets/icons/logo-gitlab.svg new file mode 100644 index 0000000..914ae30 --- /dev/null +++ b/src/lib/assets/icons/logo-gitlab.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/lib/components/shared/demo.svelte b/src/lib/components/shared/demo.svelte index f4e3b82..cda6be2 100644 --- a/src/lib/components/shared/demo.svelte +++ b/src/lib/components/shared/demo.svelte @@ -45,7 +45,7 @@ } - + - - - - - - + + + + + + + + Show code + + + Hide code + + + + + {@html highlighted_code} + + - - - - Show code - - + + Copied + + {:else} + - Hide code - - - - - {@html highlighted_code} - - - {#if copied} - - - Copied - - {:else} - - - Copy code - - {/if} - - - - + + Copy code + + {/if} + + + - + diff --git a/src/lib/components/shared/page-wrapper.svelte b/src/lib/components/shared/page-wrapper.svelte index e17281c..5604bf7 100644 --- a/src/lib/components/shared/page-wrapper.svelte +++ b/src/lib/components/shared/page-wrapper.svelte @@ -14,7 +14,7 @@ )} > - + diff --git a/src/lib/components/ui/avatar/avatar-fallback.svelte b/src/lib/components/ui/avatar/avatar-fallback.svelte new file mode 100644 index 0000000..14f6593 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-fallback.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/avatar/avatar-group.svelte b/src/lib/components/ui/avatar/avatar-group.svelte new file mode 100644 index 0000000..1edf6d5 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-group.svelte @@ -0,0 +1,79 @@ + + + + {#each visible_avatars as { src, alt }} + + + + + {alt + ?.split(' ') + ?.map((word) => word[0]) + ?.join('') + ?.toUpperCase()} + + + + {/each} + {#if hidden_avatars.length > 0} + + + +{hidden_avatars.length} + + + {/if} + diff --git a/src/lib/components/ui/avatar/avatar-image.svelte b/src/lib/components/ui/avatar/avatar-image.svelte new file mode 100644 index 0000000..12c1bd8 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-image.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/lib/components/ui/avatar/avatar.svelte b/src/lib/components/ui/avatar/avatar.svelte new file mode 100644 index 0000000..77b1f6b --- /dev/null +++ b/src/lib/components/ui/avatar/avatar.svelte @@ -0,0 +1,31 @@ + + + + + + + {#if icon} + + {/if} + diff --git a/src/lib/components/ui/avatar/index.ts b/src/lib/components/ui/avatar/index.ts new file mode 100644 index 0000000..025d1ed --- /dev/null +++ b/src/lib/components/ui/avatar/index.ts @@ -0,0 +1,6 @@ +import Fallback from './avatar-fallback.svelte'; +import Group from './avatar-group.svelte'; +import Image from './avatar-image.svelte'; +import Root from './avatar.svelte'; + +export { Root as Avatar, Fallback as AvatarFallback, Group as AvatarGroup, Image as AvatarImage }; diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte index d48e588..73d92cd 100644 --- a/src/lib/components/ui/badge/badge.svelte +++ b/src/lib/components/ui/badge/badge.svelte @@ -1,21 +1,21 @@ {#if icon} diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts index 5191e84..f627d31 100644 --- a/src/lib/components/ui/badge/index.ts +++ b/src/lib/components/ui/badge/index.ts @@ -2,7 +2,7 @@ import type { Icons } from '$lib/assets/icons'; import { type VariantProps, tv } from 'tailwind-variants'; export { default as Badge } from './badge.svelte'; -export const badgeVariants = tv({ +export const badge_variants = tv({ base: 'inline-flex select-none items-center justify-center shrink-0 rounded-full font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-focus-color focus:ring-offset-2 capitalize whitespace-nowrap tabular-nums hover:cursor-text', variants: { variant: { @@ -37,8 +37,8 @@ export const badgeVariants = tv({ } }); -type Variant = VariantProps['variant']; -type Size = VariantProps['size']; +type Variant = VariantProps['variant']; +type Size = VariantProps['size']; export type Props = { variant: Variant; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index ac57d76..b0c2706 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -47,7 +47,7 @@ title="Geist Design System" description="Vercel design system for building consistent web experiences." > - + - + diff --git a/src/routes/avatar/+page.svelte b/src/routes/avatar/+page.svelte index f0dc4e4..23462dc 100644 --- a/src/routes/avatar/+page.svelte +++ b/src/routes/avatar/+page.svelte @@ -1 +1,29 @@ -avatar + + + + + + + + + + + + + + + + + + diff --git a/src/routes/avatar/+page.ts b/src/routes/avatar/+page.ts new file mode 100644 index 0000000..265fc75 --- /dev/null +++ b/src/routes/avatar/+page.ts @@ -0,0 +1,22 @@ +import type { MetaTagsProps } from 'svelte-meta-tags'; + +export function load() { + const title = 'Avatar'; + const description = + 'Avatars represent a user or a team. Stacked avatars represent a group of people'; + + const pageMetaTags = Object.freeze({ + title, + description, + openGraph: { + title, + description + } + }) satisfies MetaTagsProps; + + return { + pageMetaTags, + title, + description + }; +} diff --git a/src/routes/avatar/group.svelte b/src/routes/avatar/group.svelte new file mode 100644 index 0000000..978a2b3 --- /dev/null +++ b/src/routes/avatar/group.svelte @@ -0,0 +1,37 @@ + + + + + + + diff --git a/src/routes/avatar/placeholder.svelte b/src/routes/avatar/placeholder.svelte new file mode 100644 index 0000000..31631d7 --- /dev/null +++ b/src/routes/avatar/placeholder.svelte @@ -0,0 +1,5 @@ + + + diff --git a/src/routes/avatar/with-icons.svelte b/src/routes/avatar/with-icons.svelte new file mode 100644 index 0000000..5604eb9 --- /dev/null +++ b/src/routes/avatar/with-icons.svelte @@ -0,0 +1,19 @@ + + + + + RH + + + + + DG + + + + + SH + diff --git a/src/routes/badge/+page.svelte b/src/routes/badge/+page.svelte index bd65392..a094fc8 100644 --- a/src/routes/badge/+page.svelte +++ b/src/routes/badge/+page.svelte @@ -1,6 +1,7 @@ - - - - - Next - - + + {#if prev} + + + + + Previous + - {next_title} + {prev.title} + + + + {/if} + + {#if next} + + + + Next - - + + {next.title} - + + - - + {/if} + diff --git a/src/routes/introduction-link.svelte b/src/routes/introduction-link.svelte index a9db128..42452c9 100644 --- a/src/routes/introduction-link.svelte +++ b/src/routes/introduction-link.svelte @@ -14,7 +14,7 @@
+ + Show code + + + Hide code + +
- - Show code - - + + Copied +
+ + Previous + - {next_title} + {prev.title} + +
+ + Next - - + + {next.title} -