Skip to content

Commit

Permalink
feat: navbar (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrasm91 authored Dec 20, 2024
1 parent 3320317 commit 2ec90ae
Show file tree
Hide file tree
Showing 17 changed files with 133 additions and 53 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"devDependencies": {
"@sveltejs/adapter-static": "^3.0.6",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/kit": "^2.13.0",
"@sveltejs/package": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^5.0.2",
"@types/eslint": "^9.6.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
--immich-danger: 180 0 0;
--immich-warning: 255 170 0;
--immich-info: 14 165 233;
--immich-gray: 246 246 246;
}

.dark {
Expand All @@ -23,5 +24,6 @@
--immich-danger: 239 68 68;
--immich-warning: 255 170 0;
--immich-info: 14 165 233;
--immich-gray: 33 33 33;
}
}
2 changes: 1 addition & 1 deletion src/docs/components/ExampleLayout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<div class="flex h-full flex-col">
<!-- TODO replace with breadcrumb component -->
<nav
class="flex shrink-0 justify-between border-b border-gray-300 bg-light px-8 py-2 text-dark dark:border-gray-700"
class="flex shrink-0 justify-between border-b border-gray-300 bg-light p-4 text-dark dark:border-gray-700"
>
<div class="flex items-center gap-2">
<a href="/" class="underline">Home</a>
Expand Down
14 changes: 8 additions & 6 deletions src/docs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import {
mdiCardOutline,
mdiCheckboxMarked,
mdiCloseCircle,
mdiCreditCardOutline,
mdiDotsCircle,
mdiFormatHeaderPound,
mdiFormTextbox,
mdiFormTextboxPassword,
mdiHomeCircle,
mdiImage,
mdiLink,
mdiListBoxOutline,
mdiMenu,
mdiNumeric,
mdiPartyPopper,
mdiViewSequential,
Expand Down Expand Up @@ -40,29 +41,30 @@ export type ExampleCardProps = ExampleItem & { theme: Theme };

export const componentGroups = [
{
name: 'Layout',
title: 'Layout',
components: [
{ name: 'Alert', icon: mdiAlertCircleOutline },
{ name: 'AppShell', icon: mdiApplicationOutline },
{ name: 'Card', icon: mdiCardOutline },
{ name: 'Navbar', icon: mdiMenu },
{ name: 'Stack', icon: mdiViewSequential },
],
},
{
name: 'Forms',
title: 'Forms',
components: [
{ name: 'Button', icon: mdiButtonCursor },
{ name: 'IconButton', icon: mdiHomeCircle },
{ name: 'Checkbox', icon: mdiCheckboxMarked },
{ name: 'CloseButton', icon: mdiCloseCircle },
{ name: 'Field', icon: mdiListBoxOutline },
{ name: 'Input', icon: mdiFormTextbox },
{ name: 'LoadingSpinner', icon: mdiCreditCardOutline },
{ name: 'LoadingSpinner', icon: mdiDotsCircle },
{ name: 'PasswordInput', icon: mdiFormTextboxPassword },
],
},
{
name: 'Text',
title: 'Text',
components: [
{ name: 'Text', icon: mdiFormatHeaderPound },
{ name: 'Heading', icon: mdiFormTextbox },
Expand All @@ -71,7 +73,7 @@ export const componentGroups = [
],
},
{
name: 'Immich',
title: 'Immich',
components: [
{ name: 'Logo', icon: mdiImage },
{ name: 'SupporterBadge', icon: mdiPartyPopper },
Expand Down
6 changes: 4 additions & 2 deletions src/lib/components/AppShell/AppShellSidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
type Props = {
class?: string;
children: Snippet;
noBorder?: boolean;
};
let { class: className, children }: Props = $props();
let { class: className, children, noBorder = false }: Props = $props();
</script>

<Child for={ChildKey.AppShell} as={ChildKey.AppShellSidebar}>
<Scrollable
class={cleanClass(
'hidden h-full shrink-0 border-r border-gray-200 dark:border-gray-700 lg:block',
'hidden h-full shrink-0 border-gray-200 dark:border-gray-700 lg:block',
className,
noBorder || 'border-r',
)}
>
{@render children?.()}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/AppShell/PageLayout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<section class="relative">
{#if title || buttons}
<div
class="dark:border-immich-dark-gray dark:text-immich-dark-fg absolute flex h-16 w-full place-items-center justify-between border-b p-4"
class="dark:border-immich-neutral dark:text-immich-dark-fg absolute flex h-16 w-full place-items-center justify-between border-b p-4"
>
<div class="flex items-center gap-2">
{#if title}
Expand Down
12 changes: 12 additions & 0 deletions src/lib/components/Navbar/NavbarGroup.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
type Props = {
title: string;
};
let { title }: Props = $props();
</script>

<div class="text-xs transition-all duration-200">
<p class="hidden px-6 py-4 uppercase group-hover:sm:block md:block">{title}</p>
<hr class="mx-4 mb-[31px] mt-8 block group-hover:sm:hidden md:hidden" />
</div>
31 changes: 31 additions & 0 deletions src/lib/components/Navbar/NavbarItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import Icon from '$lib/components/Icon/Icon.svelte';
import type { IconProps } from '$lib/types.js';
import { tv } from 'tailwind-variants';
type Props = {
title: string;
active?: boolean;
href: string;
} & IconProps;
let { href, title, active = false, ...iconProps }: Props = $props();
const styles = tv({
base: 'hover:bg-neutral hover:text-primary flex w-full place-items-center gap-4 rounded-r-full py-3 transition-[padding] delay-100 duration-100 pl-5 group-hover:sm:px-5 md:px-5',
variants: {
active: {
true: 'bg-primary/10 text-primary',
false: '',
},
},
});
</script>

<a {href} draggable="false" aria-current={active ? 'page' : undefined} class={styles({ active })}>
<div class="flex w-full place-items-center gap-4 overflow-hidden truncate">
<Icon size="1.5em" class="shrink-0" aria-hidden={true} {...iconProps} />
<span class="text-sm font-medium">{title}</span>
</div>
<div></div>
</a>
2 changes: 2 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export { default as IconButton } from '$lib/components/IconButton/IconButton.sve
export { default as Link } from '$lib/components/Link/Link.svelte';
export { default as LoadingSpinner } from '$lib/components/LoadingSpinner/LoadingSpinner.svelte';
export { default as Logo } from '$lib/components/Logo/Logo.svelte';
export { default as NavbarGroup } from '$lib/components/Navbar/NavbarGroup.svelte';
export { default as NavbarItem } from '$lib/components/Navbar/NavbarItem.svelte';
export { default as Scrollable } from '$lib/components/Scrollable/Scrollable.svelte';
export { default as HStack } from '$lib/components/Stack/HStack.svelte';
export { default as Stack } from '$lib/components/Stack/Stack.svelte';
Expand Down
28 changes: 14 additions & 14 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { page } from '$app/state';
import Navbar from '$docs/components/Navbar.svelte';
import { componentGroups, Theme } from '$docs/constants.js';
import { asComponentHref } from '$docs/utilities.js';
Expand All @@ -7,19 +8,20 @@
AppShell,
AppShellHeader,
AppShellSidebar,
Heading,
IconButton,
Link,
Stack,
NavbarGroup,
NavbarItem,
} from '@immich/ui';
import { mdiWeatherNight, mdiWeatherSunny } from '@mdi/js';
import { mdiHome, mdiWeatherNight, mdiWeatherSunny } from '@mdi/js';
import '../app.css';
let { children } = $props();
const handleToggleTheme = () =>
(theme.value = theme.value === Theme.Dark ? Theme.Light : Theme.Dark);
const themeIcon = $derived(theme.value === Theme.Light ? mdiWeatherSunny : mdiWeatherNight);
const isActive = (path: string) => path === page.url.pathname;
</script>

<AppShell class="{theme.value} bg-light text-dark">
Expand All @@ -36,17 +38,15 @@
</Navbar>
</AppShellHeader>

<AppShellSidebar class="p-4">
<Stack class="min-w-[200px]">
{#each componentGroups as group}
<Heading size="tiny">{group.name}</Heading>
<Stack class="pl-4">
{#each group.components as component}
<Link href={asComponentHref(component.name)}>{component.name}</Link>
{/each}
</Stack>
<AppShellSidebar class="min-w-[225px] py-4 pr-4">
<NavbarItem active={isActive('/')} title="Home" icon={mdiHome} href="/" />
{#each componentGroups as group}
<NavbarGroup title={group.title} />
{#each group.components as component}
{@const href = asComponentHref(component.name)}
<NavbarItem active={isActive(href)} title={component.name} icon={component.icon} {href} />
{/each}
</Stack>
{/each}
</AppShellSidebar>

<div class="h-full">
Expand Down
2 changes: 1 addition & 1 deletion src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<Stack gap={8}>
{#each componentGroups as group}
<Stack>
<Heading size="medium">{group.name}</Heading>
<Heading size="medium">{group.title}</Heading>
<Grid>
{#each group.components as component}
<ComponentCard {component} />
Expand Down
40 changes: 17 additions & 23 deletions src/routes/components/app-shell/BasicExample.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<script lang="ts">
import DecorativeBlock from '$docs/components/DecorativeBlock.svelte';
import { AppShell, AppShellHeader, AppShellSidebar, Heading, Stack } from '@immich/ui';
import {
AppShell,
AppShellHeader,
AppShellSidebar,
Heading,
NavbarItem,
Stack,
} from '@immich/ui';
import { mdiHome } from '@mdi/js';
</script>

<Stack>
Expand Down Expand Up @@ -46,30 +53,17 @@
</div>
</AppShellHeader>

<AppShellSidebar>
<div class="p-4">
<Heading size="tiny">Sidebar Overflow</Heading>
<Stack>
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
</Stack>
</div>
<AppShellSidebar noBorder class="pt-2">
<Stack>
<NavbarItem icon={mdiHome} title="Home" href="/" active />
<NavbarItem icon={mdiHome} title="Home" href="/" />
<NavbarItem icon={mdiHome} title="Home" href="/" />
<NavbarItem icon={mdiHome} title="Home" href="/" />
</Stack>
</AppShellSidebar>

<div class="p-4">
<Heading size="tiny">Content Overflow</Heading>
<Stack>
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
<DecorativeBlock />
</Stack>
<Heading size="tiny">Content</Heading>
</div>
</AppShell>
</div>
Expand Down
14 changes: 14 additions & 0 deletions src/routes/components/navbar/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
import ExampleLayout from '$docs/components/ExampleLayout.svelte';
import BasicExample from './BasicExample.svelte';
import basicExample from './BasicExample.svelte?raw';
import GroupExample from './GroupExample.svelte';
import groupExample from './GroupExample.svelte?raw';
const examples = [
{ title: 'Basic', code: basicExample, component: BasicExample },
{ title: 'Group', code: groupExample, component: GroupExample },
];
</script>

<ExampleLayout name="Basic" {examples} />
8 changes: 8 additions & 0 deletions src/routes/components/navbar/BasicExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script lang="ts">
import { NavbarItem } from '@immich/ui';
import { mdiHome } from '@mdi/js';
</script>

<div class="w-[200px]">
<NavbarItem icon={mdiHome} title="Home" href="#" active />
</div>
12 changes: 12 additions & 0 deletions src/routes/components/navbar/GroupExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import NavbarGroup from '$lib/components/Navbar/NavbarGroup.svelte';
import { NavbarItem } from '@immich/ui';
import { mdiButtonPointer, mdiCardOutline, mdiHome } from '@mdi/js';
</script>

<div class="w-[200px]">
<NavbarItem icon={mdiHome} title="Home" href="#" active />
<NavbarGroup title="Components" />
<NavbarItem icon={mdiButtonPointer} title="Button" href="#" />
<NavbarItem icon={mdiCardOutline} title="Card" href="#" />
</div>
1 change: 1 addition & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
danger: 'rgb(var(--immich-danger) / <alpha-value>)',
warning: 'rgb(var(--immich-warning) / <alpha-value>)',
info: 'rgb(var(--immich-info) / <alpha-value>)',
neutral: 'rgb(var(--immich-gray) / <alpha-value>)',
},
},
},
Expand Down

0 comments on commit 2ec90ae

Please sign in to comment.