feat: add tab bar navigation for crowded pages

This commit is contained in:
Elias Schneider
2026-07-10 15:33:02 +02:00
parent b2711ced99
commit 28a553f63b
20 changed files with 578 additions and 332 deletions
@@ -1,18 +1,14 @@
<script lang="ts">
import CollapsibleCard from '$lib/components/collapsible-card.svelte';
import * as Alert from '$lib/components/ui/alert';
import * as Card from '$lib/components/ui/card';
import * as Tabs from '$lib/components/ui/tabs';
import { m } from '$lib/paraglide/messages';
import AppConfigService from '$lib/services/app-config-service';
import appConfigStore from '$lib/stores/application-configuration-store';
import type { AllAppConfig } from '$lib/types/application-configuration.type';
import { axiosErrorToast } from '$lib/utils/error-util';
import {
LucideImage,
LucideInfo,
Mail,
SlidersHorizontal,
UserSearch,
Users
LucideInfo
} from '@lucide/svelte';
import { toast } from 'svelte-sonner';
import AppConfigEmailForm from './forms/app-config-email-form.svelte';
@@ -101,57 +97,85 @@
</Alert.Description>
</Alert.Root>
{/if}
<div>
<CollapsibleCard
id="application-configuration-general"
icon={SlidersHorizontal}
title={m.general()}
defaultExpanded
>
<AppConfigGeneralForm {appConfig} callback={updateAppConfig} />
</CollapsibleCard>
</div>
<Tabs.Root value="general" useHash class="gap-4">
<div class="overflow-x-auto pb-1">
<Tabs.List variant="line" class="min-w-max">
<Tabs.Trigger value="general">
{m.general()}
</Tabs.Trigger>
<Tabs.Trigger value="user-creation">
{m.user_creation()}
</Tabs.Trigger>
<Tabs.Trigger value="email">
{m.email()}
</Tabs.Trigger>
<Tabs.Trigger value="ldap">
{m.ldap()}
</Tabs.Trigger>
<Tabs.Trigger value="images">
{m.images()}
</Tabs.Trigger>
</Tabs.List>
</div>
<div>
<CollapsibleCard
id="application-configuration-signup-defaults"
icon={Users}
title={m.user_creation()}
description={m.configure_user_creation()}
>
<AppConfigSignupDefaultsForm {appConfig} callback={updateAppConfig} />
</CollapsibleCard>
</div>
<Tabs.Content value="general" id="application-configuration-general">
<Card.Root>
<Card.Header>
<Card.Title>{m.general()}</Card.Title>
</Card.Header>
<Card.Content>
<AppConfigGeneralForm {appConfig} callback={updateAppConfig} />
</Card.Content>
</Card.Root>
</Tabs.Content>
<div>
<CollapsibleCard
id="application-configuration-email"
icon={Mail}
title={m.email()}
description={m.configure_smtp_to_send_emails()}
>
<AppConfigEmailForm {appConfig} callback={updateAppConfig} />
</CollapsibleCard>
</div>
<Tabs.Content value="user-creation" id="application-configuration-signup-defaults">
<Card.Root>
<Card.Header>
<Card.Title>{m.user_creation()}</Card.Title>
<Card.Description>{m.configure_user_creation()}</Card.Description>
</Card.Header>
<Card.Content>
<AppConfigSignupDefaultsForm {appConfig} callback={updateAppConfig} />
</Card.Content>
</Card.Root>
</Tabs.Content>
<div>
<CollapsibleCard
id="application-configuration-ldap"
icon={UserSearch}
title={m.ldap()}
description={m.configure_ldap_settings_to_sync_users_and_groups_from_an_ldap_server()}
>
<AppConfigLdapForm {appConfig} callback={updateAppConfig} />
</CollapsibleCard>
</div>
<Tabs.Content value="email" id="application-configuration-email">
<Card.Root>
<Card.Header>
<Card.Title>{m.email()}</Card.Title>
<Card.Description>{m.configure_smtp_to_send_emails()}</Card.Description>
</Card.Header>
<Card.Content>
<AppConfigEmailForm {appConfig} callback={updateAppConfig} />
</Card.Content>
</Card.Root>
</Tabs.Content>
<div>
<CollapsibleCard
id="application-configuration-images"
icon={LucideImage}
title={m.images()}
description={m.configure_application_images()}
>
<UpdateApplicationImages callback={updateImages} />
</CollapsibleCard>
</div>
<Tabs.Content value="ldap" id="application-configuration-ldap">
<Card.Root>
<Card.Header>
<Card.Title>{m.ldap()}</Card.Title>
<Card.Description>
{m.configure_ldap_settings_to_sync_users_and_groups_from_an_ldap_server()}
</Card.Description>
</Card.Header>
<Card.Content>
<AppConfigLdapForm {appConfig} callback={updateAppConfig} />
</Card.Content>
</Card.Root>
</Tabs.Content>
<Tabs.Content value="images" id="application-configuration-images">
<Card.Root>
<Card.Header>
<Card.Title>{m.images()}</Card.Title>
<Card.Description>{m.configure_application_images()}</Card.Description>
</Card.Header>
<Card.Content>
<UpdateApplicationImages callback={updateImages} />
</Card.Content>
</Card.Root>
</Tabs.Content>
</Tabs.Root>