| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| |
| <script lang="ts"> |
| import { twMerge } from 'tailwind-merge'; |
| import type { iconType } from '$lib/components/Icon.svelte'; |
| import Icon from '$lib/components/Icon.svelte'; |
| |
| import { typedRoute } from '$lib/types/appRoutes'; |
| import { page } from '$app/state'; |
| import { resolve } from '$app/paths'; |
| interface Props { |
| actions?: import('svelte').Snippet; |
| children?: import('svelte').Snippet; |
| } |
| |
| let { actions, children }: Props = $props(); |
| |
| type Tabs = 'server' | 'users' | 'webUI' | 'terminal'; |
| |
| let activeTab = $derived(page.url.pathname.split('/').slice(-1)[0]); |
| |
| const tabs = [ |
| { |
| tab: 'server', |
| icon: 'adjustments', |
| name: 'Server', |
| path: typedRoute('/dashboard/settings/server') |
| }, |
| { |
| tab: 'webUI', |
| icon: 'settings', |
| name: 'Web UI', |
| path: typedRoute('/dashboard/settings/webUI') |
| }, |
| { |
| tab: 'users', |
| icon: 'usersGroup', |
| name: 'Users', |
| path: typedRoute('/dashboard/settings/users') |
| } |
| ] satisfies { tab: Tabs; name: string; icon: iconType; path: string }[]; |
| </script> |
| |
| <div class="flex justify-between items-center px-10"> |
| <h1 class="font-semibold text-3xl text-color my-10">Settings</h1> |
| |
| {@render actions?.()} |
| </div> |
| |
| <div class="flex gap-12 border-b px-10"> |
| {#each tabs as { icon, name, path }, idx (idx)} |
| {@const isActive = activeTab === path.split('/').slice(-1)[0]} |
| <a |
| href={resolve(path)} |
| class={twMerge('pb-3 relative group flex items-center justify-start gap-2 text-color')} |
| > |
| <Icon name={icon} class="w-[15px] h-[15px]" /> |
| |
| <span> |
| {name} |
| </span> |
| |
| <div |
| class={twMerge( |
| 'absolute left-0 right-0 top-full h-[2px] -translate-y-full rounded-tl-md rounded-tr-md transition-colors duration-200', |
| isActive |
| ? 'dark:bg-white bg-black' |
| : 'group-hover:bg-shade-l600 dark:group-hover:bg-shade-d300' |
| )} |
| ></div> |
| </a> |
| {/each} |
| </div> |
| |
| {@render children?.()} |