mirror of
				https://github.com/Blah-IM/Weblah.git
				synced 2025-11-04 03:41:37 +00:00 
			
		
		
		
	feat: basic settings layout
This commit is contained in:
		
							parent
							
								
									5c82a79b9c
								
							
						
					
					
						commit
						3097b8a9dd
					
				
					 8 changed files with 118 additions and 15 deletions
				
			
		
							
								
								
									
										4
									
								
								src/lib/components/GroupedList.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/lib/components/GroupedList.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					import GroupedListItem from './GroupedList/GroupedListItem.svelte';
 | 
				
			||||||
 | 
					import GroupedListSection from './GroupedList/GroupedListSection.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { GroupedListItem, GroupedListSection };
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/lib/components/GroupedList/GroupedListItem.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/lib/components/GroupedList/GroupedListItem.svelte
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						import { Icon, type IconSource } from 'svelte-hero-icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						export let href: string | undefined = undefined;
 | 
				
			||||||
 | 
						export let icon: IconSource | undefined = undefined;
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<svelte:element
 | 
				
			||||||
 | 
						this={href ? 'a' : 'div'}
 | 
				
			||||||
 | 
						{href}
 | 
				
			||||||
 | 
						class="flex items-center gap-2 px-4 py-3 font-medium text-sf-primary"
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						{#if icon}
 | 
				
			||||||
 | 
							<Icon src={icon} class="size-5 text-sf-secondary" mini />
 | 
				
			||||||
 | 
						{/if}
 | 
				
			||||||
 | 
						<slot />
 | 
				
			||||||
 | 
					</svelte:element>
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/lib/components/GroupedList/GroupedListSection.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/lib/components/GroupedList/GroupedListSection.svelte
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					<section class="my-4 px-4">
 | 
				
			||||||
 | 
						{#if $$slots.header}
 | 
				
			||||||
 | 
							<h3 class="mb-1 truncate text-sm font-medium uppercase text-sf-secondary">
 | 
				
			||||||
 | 
								<slot name="header" />
 | 
				
			||||||
 | 
							</h3>
 | 
				
			||||||
 | 
						{/if}
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							class="divide-y-[0.5px] divide-ss-secondary rounded-lg border-[0.5px] border-ss-secondary bg-sb-primary shadow-sm"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<slot />
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						{#if $$slots.footer}
 | 
				
			||||||
 | 
							<div class="mt-1 text-sm font-medium uppercase text-sf-secondary">
 | 
				
			||||||
 | 
								<slot name="footer" />
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						{/if}
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@
 | 
				
			||||||
{:else}
 | 
					{:else}
 | 
				
			||||||
	<div
 | 
						<div
 | 
				
			||||||
		class="box-border size-[--weblah-profile-pic-size] rounded-full border-2 border-dashed border-ss-primary"
 | 
							class="box-border size-[--weblah-profile-pic-size] rounded-full border-2 border-dashed border-ss-primary"
 | 
				
			||||||
		style:--weblah-profile-pic-size={`${size - 2}px`}
 | 
							style:--weblah-profile-pic-size={`${size}px`}
 | 
				
			||||||
		aria-hidden
 | 
							aria-hidden
 | 
				
			||||||
	/>
 | 
						/>
 | 
				
			||||||
	<span class="sr-only">Account Unavailable</span>
 | 
						<span class="sr-only">Account Unavailable</span>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,9 +15,10 @@
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$: isSettings = $page.route.id?.startsWith('/settings');
 | 
						$: isSettings = $page.route.id?.startsWith('/(app)/settings');
 | 
				
			||||||
	$: mainVisible =
 | 
						$: mainVisible =
 | 
				
			||||||
		!!$page.params.chatId || (isSettings && !$page.route.id?.startsWith('/settings/_mobile_empty'));
 | 
							!!$page.params.chatId ||
 | 
				
			||||||
 | 
							(isSettings && !$page.route.id?.startsWith('/(app)/settings/_mobile_empty'));
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div
 | 
					<div
 | 
				
			||||||
| 
						 | 
					@ -29,7 +30,7 @@
 | 
				
			||||||
	>
 | 
						>
 | 
				
			||||||
		<ChatList />
 | 
							<ChatList />
 | 
				
			||||||
		{#if isSettings}
 | 
							{#if isSettings}
 | 
				
			||||||
			<SettingsList />
 | 
								<SettingsList class="absolute inset-0 z-10 size-full [view-transition-name:settings-list]" />
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	</aside>
 | 
						</aside>
 | 
				
			||||||
	{#if mainVisible}
 | 
						{#if mainVisible}
 | 
				
			||||||
| 
						 | 
					@ -61,6 +62,27 @@
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@keyframes float-in {
 | 
				
			||||||
 | 
							from {
 | 
				
			||||||
 | 
								transform: scale(0.9);
 | 
				
			||||||
 | 
								opacity: 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							to {
 | 
				
			||||||
 | 
								transform: scale(1);
 | 
				
			||||||
 | 
								opacity: 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						@keyframes float-out {
 | 
				
			||||||
 | 
							from {
 | 
				
			||||||
 | 
								transform: scale(1);
 | 
				
			||||||
 | 
								opacity: 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							to {
 | 
				
			||||||
 | 
								transform: scale(0.9);
 | 
				
			||||||
 | 
								opacity: 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	:root::view-transition-old(root),
 | 
						:root::view-transition-old(root),
 | 
				
			||||||
	:root::view-transition-new(root) {
 | 
						:root::view-transition-new(root) {
 | 
				
			||||||
		animation-duration: 250ms;
 | 
							animation-duration: 250ms;
 | 
				
			||||||
| 
						 | 
					@ -71,4 +93,14 @@
 | 
				
			||||||
	:root::view-transition-new(main) {
 | 
						:root::view-transition-new(main) {
 | 
				
			||||||
		animation: 250ms ease-out slide-in;
 | 
							animation: 250ms ease-out slide-in;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						:root::view-transition-old(settings-list),
 | 
				
			||||||
 | 
						:root::view-transition-new(settings-list) {
 | 
				
			||||||
 | 
							transform-origin: top left;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						:root::view-transition-old(settings-list) {
 | 
				
			||||||
 | 
							animation: 250ms ease-out float-out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						:root::view-transition-new(settings-list) {
 | 
				
			||||||
 | 
							animation: 250ms ease-out float-in;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,8 @@
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#await getAccount($currentAccountStore) then currentAccount}
 | 
					{#await getAccount($currentAccountStore)}
 | 
				
			||||||
 | 
						<ProfilePicture account={undefined} />
 | 
				
			||||||
 | 
					{:then currentAccount}
 | 
				
			||||||
	<ProfilePicture account={currentAccount} {size} />
 | 
						<ProfilePicture account={currentAccount} {size} />
 | 
				
			||||||
{/await}
 | 
					{/await}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
	import { formatUnreadCount } from '$lib/formatters';
 | 
						import { formatUnreadCount } from '$lib/formatters';
 | 
				
			||||||
	import type { Chat } from '$lib/types';
 | 
						import type { Chat } from '$lib/types';
 | 
				
			||||||
	import { AvatarBeam } from 'svelte-boring-avatars';
 | 
						import { AvatarBeam } from 'svelte-boring-avatars';
 | 
				
			||||||
 | 
						import { ChevronLeft, Icon } from 'svelte-hero-icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let info: Chat;
 | 
						export let info: Chat;
 | 
				
			||||||
	export let outsideUnreadCount = 0;
 | 
						export let outsideUnreadCount = 0;
 | 
				
			||||||
| 
						 | 
					@ -12,16 +13,7 @@
 | 
				
			||||||
	class="relative z-10 box-border flex min-h-[calc(3rem+1px)] w-full items-center gap-2 border-b border-ss-secondary bg-sb-primary p-2 shadow-sm"
 | 
						class="relative z-10 box-border flex min-h-[calc(3rem+1px)] w-full items-center gap-2 border-b border-ss-secondary bg-sb-primary p-2 shadow-sm"
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
	<Button href="/" class="rounded-full sm:hidden">
 | 
						<Button href="/" class="rounded-full sm:hidden">
 | 
				
			||||||
		<svg
 | 
							<Icon src={ChevronLeft} />
 | 
				
			||||||
			xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
			stroke-width="1.5"
 | 
					 | 
				
			||||||
			stroke="currentColor"
 | 
					 | 
				
			||||||
			class="-me-0.5 -ms-1 size-5"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" />
 | 
					 | 
				
			||||||
		</svg>
 | 
					 | 
				
			||||||
		{#if outsideUnreadCount}
 | 
							{#if outsideUnreadCount}
 | 
				
			||||||
			<span class="text-xs text-sf-tertiary">{formatUnreadCount(outsideUnreadCount)}</span>
 | 
								<span class="text-xs text-sf-tertiary">{formatUnreadCount(outsideUnreadCount)}</span>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,39 @@
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						import Button from '$lib/components/Button.svelte';
 | 
				
			||||||
 | 
						import { GroupedListSection, GroupedListItem } from '$lib/components/GroupedList';
 | 
				
			||||||
 | 
						import { tw } from '$lib/tw';
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							Bell,
 | 
				
			||||||
 | 
							Cog,
 | 
				
			||||||
 | 
							DevicePhoneMobile,
 | 
				
			||||||
 | 
							InformationCircle,
 | 
				
			||||||
 | 
							LockClosed,
 | 
				
			||||||
 | 
							QuestionMarkCircle,
 | 
				
			||||||
 | 
							UserPlus
 | 
				
			||||||
 | 
						} from 'svelte-hero-icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let className = '';
 | 
				
			||||||
 | 
						export { className as class };
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class={tw('flex flex-col bg-sb-secondary shadow-md', className)}>
 | 
				
			||||||
 | 
						<div class="flex items-center border-b border-ss-secondary bg-sb-primary p-2 shadow-sm">
 | 
				
			||||||
 | 
							<Button href="/">Done</Button>
 | 
				
			||||||
 | 
							<h2 class="flex-1 truncate text-center font-semibold text-sf-primary">Settings</h2>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<div class="flex-1 overflow-y-scroll">
 | 
				
			||||||
 | 
							<GroupedListSection>
 | 
				
			||||||
 | 
								<GroupedListItem icon={UserPlus}>Add Account</GroupedListItem>
 | 
				
			||||||
 | 
							</GroupedListSection>
 | 
				
			||||||
 | 
							<GroupedListSection>
 | 
				
			||||||
 | 
								<GroupedListItem icon={Cog}>General</GroupedListItem>
 | 
				
			||||||
 | 
								<GroupedListItem icon={Bell}>Notifications</GroupedListItem>
 | 
				
			||||||
 | 
								<GroupedListItem icon={LockClosed}>Privacy and Security</GroupedListItem>
 | 
				
			||||||
 | 
								<GroupedListItem icon={DevicePhoneMobile}>Devices</GroupedListItem>
 | 
				
			||||||
 | 
							</GroupedListSection>
 | 
				
			||||||
 | 
							<GroupedListSection>
 | 
				
			||||||
 | 
								<GroupedListItem icon={InformationCircle}>About Blah & Weblah</GroupedListItem>
 | 
				
			||||||
 | 
								<GroupedListItem icon={QuestionMarkCircle}>Ask a Question</GroupedListItem>
 | 
				
			||||||
 | 
							</GroupedListSection>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue