@immich/ui 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@
17
17
  const sidebar = $derived(getChildSnippet(ChildKey.AppShellSidebar));
18
18
  </script>
19
19
 
20
- <div class={cleanClass('flex h-screen flex-col overflow-hidden', className)}>
20
+ <div class={cleanClass('flex h-dvh flex-col overflow-hidden', className)}>
21
21
  {#if header}
22
22
  <header class="border-b">
23
23
  {@render header?.snippet()}
@@ -1,8 +1,11 @@
1
1
  <script lang="ts">
2
+ import { afterNavigate } from '$app/navigation';
3
+ import IconButton from '../IconButton/IconButton.svelte';
4
+ import Scrollable from '../Scrollable/Scrollable.svelte';
2
5
  import { ChildKey } from '../../constants.js';
3
6
  import Child from '../../internal/Child.svelte';
4
7
  import { cleanClass } from '../../utils.js';
5
- import Scrollable from '../Scrollable/Scrollable.svelte';
8
+ import { mdiClose, mdiMenu } from '@mdi/js';
6
9
  import type { Snippet } from 'svelte';
7
10
 
8
11
  type Props = {
@@ -12,11 +15,34 @@
12
15
  };
13
16
 
14
17
  let { class: className, children, noBorder = false }: Props = $props();
18
+
19
+ afterNavigate(() => {
20
+ if (!hidden) {
21
+ hidden = true;
22
+ }
23
+ });
24
+
25
+ let hidden = $state(true);
15
26
  </script>
16
27
 
17
28
  <Child for={ChildKey.AppShell} as={ChildKey.AppShellSidebar}>
29
+ <IconButton
30
+ size="giant"
31
+ onclick={() => (hidden = !hidden)}
32
+ icon={hidden ? mdiMenu : mdiClose}
33
+ shape="round"
34
+ color={hidden ? 'primary' : 'secondary'}
35
+ variant="filled"
36
+ class="absolute bottom-2 right-4 z-[100] m-2 opacity-100 md:hidden"
37
+ />
18
38
  <Scrollable
19
- class={cleanClass('hidden h-full w-min shrink-0 lg:block', className, noBorder || 'border-r')}
39
+ class={cleanClass(
40
+ 'z-[90] h-dvh w-full shrink-0 bg-light pb-16 text-dark md:relative md:block md:w-min md:pb-0',
41
+
42
+ hidden ? 'hidden' : '',
43
+ className,
44
+ noBorder || 'border-r',
45
+ )}
20
46
  >
21
47
  {@render children?.()}
22
48
  </Scrollable>
@@ -36,14 +36,14 @@
36
36
  },
37
37
 
38
38
  filled: {
39
- true: 'rounded px-2 py-1',
39
+ true: 'rounded-lg p-3',
40
40
  false: '',
41
41
  },
42
42
 
43
43
  filledColor: {
44
44
  false: '',
45
45
  muted: 'bg-gray-600 text-light dark:bg-gray-800',
46
- primary: 'bg-gray-200 text-primary dark:bg-gray-700',
46
+ primary: 'bg-gray-200 text-primary dark:bg-primary/20 dark:text-gray-200',
47
47
  secondary: 'bg-gray-700 text-light dark:bg-gray-200',
48
48
  success: 'bg-success text-light',
49
49
  danger: 'bg-danger text-light',
@@ -56,7 +56,7 @@
56
56
 
57
57
  <Dialog.Root bind:open {...restProps}>
58
58
  <Dialog.Portal>
59
- <Dialog.Overlay class="absolute left-0 top-0 flex h-screen w-screen backdrop-blur" />
59
+ <Dialog.Overlay class="absolute left-0 top-0 flex h-dvh w-screen backdrop-blur" />
60
60
  <Dialog.Content
61
61
  class={cleanClass(
62
62
  'absolute left-0 top-0 flex h-dvh w-screen items-center justify-center overflow-hidden sm:p-4',
@@ -6,7 +6,6 @@
6
6
  let { title }: Props = $props();
7
7
  </script>
8
8
 
9
- <div class="text-xs transition-all duration-200">
10
- <p class="hidden px-6 py-4 uppercase group-hover:sm:block md:block">{title}</p>
11
- <hr class="mx-4 mb-[31px] mt-8 block group-hover:sm:hidden md:hidden" />
9
+ <div class="text-sm transition-all duration-200 md:text-sm">
10
+ <p class="py-2 pl-4 uppercase">{title}</p>
12
11
  </div>
@@ -7,24 +7,42 @@
7
7
  title: string;
8
8
  active?: boolean;
9
9
  href: string;
10
- } & IconProps;
10
+ variant?: 'compact';
11
+ } & { icon?: string & Omit<IconProps, 'icon'> };
11
12
 
12
- let { href, title, active = false, ...iconProps }: Props = $props();
13
+ let { href, title, variant, active = false, ...iconProps }: Props = $props();
13
14
 
14
15
  const styles = tv({
15
- base: 'flex w-full place-items-center gap-4 rounded-r-full py-3 pl-5 transition-[padding] delay-100 duration-100 hover:bg-subtle hover:text-primary group-hover:sm:px-5 md:px-5',
16
+ base: 'flex w-full place-items-center gap-4 transition-[padding] delay-100 duration-100 hover:bg-subtle hover:text-primary group-hover:sm:px-5 md:rounded-r-full md:px-5',
16
17
  variants: {
17
18
  active: {
18
19
  true: 'bg-primary/10 text-primary',
19
20
  false: '',
20
21
  },
22
+ variant: {
23
+ default: 'py-3 pl-5',
24
+ compact: 'py-2 pl-3',
25
+ },
21
26
  },
22
27
  });
23
28
  </script>
24
29
 
25
- <a {href} draggable="false" aria-current={active ? 'page' : undefined} class={styles({ active })}>
30
+ <a
31
+ {href}
32
+ draggable="false"
33
+ aria-current={active ? 'page' : undefined}
34
+ class={styles({ active, variant: variant ?? 'default' })}
35
+ >
26
36
  <div class="flex w-full place-items-center gap-4 overflow-hidden truncate">
27
- <Icon size="1.5em" class="shrink-0" aria-hidden={true} {...iconProps} />
37
+ {#if iconProps.icon}
38
+ <Icon
39
+ size="1.375em"
40
+ class="shrink-0"
41
+ aria-hidden={true}
42
+ {...iconProps}
43
+ icon={iconProps.icon}
44
+ />
45
+ {/if}
28
46
  <span class="text-sm font-medium">{title}</span>
29
47
  </div>
30
48
  </a>
@@ -3,5 +3,8 @@ declare const NavbarItem: import("svelte").Component<{
3
3
  title: string;
4
4
  active?: boolean;
5
5
  href: string;
6
- } & IconProps, {}, "">;
6
+ variant?: "compact";
7
+ } & {
8
+ icon?: string & Omit<IconProps, "icon">;
9
+ }, {}, "">;
7
10
  export default NavbarItem;
@@ -5,6 +5,7 @@
5
5
  type Props = {
6
6
  class?: string;
7
7
  children?: Snippet;
8
+ transition?: TransitionEvent;
8
9
  };
9
10
 
10
11
  const { class: className, children }: Props = $props();
@@ -2,5 +2,6 @@ import type { Snippet } from 'svelte';
2
2
  declare const Scrollable: import("svelte").Component<{
3
3
  class?: string;
4
4
  children?: Snippet;
5
+ transition?: TransitionEvent;
5
6
  }, {}, "">;
6
7
  export default Scrollable;
@@ -46,8 +46,8 @@
46
46
  base: 'my-2 h-3 w-12 rounded-full border border-transparent',
47
47
  variants: {
48
48
  fillColor: {
49
- default: 'bg-gray-400',
50
- primary: 'bg-primary/50',
49
+ default: 'bg-gray-300 dark:bg-gray-400',
50
+ primary: 'bg-primary/60',
51
51
  secondary: 'bg-dark/50',
52
52
  success: 'bg-success/50',
53
53
  danger: 'bg-danger/50',
@@ -61,11 +61,11 @@
61
61
  base: 'absolute h-6 w-6 rounded-full transition-transform duration-[400ms]',
62
62
  variants: {
63
63
  checked: {
64
- true: 'translate-x-6',
64
+ true: 'translate-x-6 border border-gray-500/10 shadow-sm dark:border-gray-800/50',
65
65
  false: '',
66
66
  },
67
67
  fillColor: {
68
- default: 'bg-gray-600',
68
+ default: 'bg-gray-400 dark:bg-gray-500',
69
69
  primary: 'bg-primary',
70
70
  secondary: 'bg-dark',
71
71
  success: 'bg-success',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immich/ui",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "license": "GNU Affero General Public License version 3",
5
5
  "scripts": {
6
6
  "create": "node scripts/create.js",