test contracts
This commit is contained in:
@@ -12,6 +12,20 @@
|
||||
* @UX_STATE: Toggling -> Animation plays for 200ms
|
||||
* @UX_FEEDBACK: Active item highlighted with different background
|
||||
* @UX_RECOVERY: Click outside on mobile closes overlay
|
||||
*
|
||||
* @TEST_CONTRACT Component_Sidebar ->
|
||||
* {
|
||||
* required_props: {},
|
||||
* optional_props: {},
|
||||
* invariants: [
|
||||
* "Highlights active category and sub-item based on current page URL",
|
||||
* "Toggles sidebar via toggleSidebar store action",
|
||||
* "Closes mobile overlay on click outside"
|
||||
* ]
|
||||
* }
|
||||
* @TEST_FIXTURE idle_state -> {}
|
||||
* @TEST_EDGE mobile_open -> shows mobile overlay mask
|
||||
* @TEST_INVARIANT navigation -> verifies: [idle_state]
|
||||
*/
|
||||
|
||||
import { onMount } from "svelte";
|
||||
@@ -30,56 +44,52 @@
|
||||
return [
|
||||
{
|
||||
id: "dashboards",
|
||||
label: $t.nav?.dashboards ,
|
||||
label: $t.nav?.dashboards,
|
||||
icon: "dashboard",
|
||||
tone: "from-sky-100 to-sky-200 text-sky-700 ring-sky-200",
|
||||
path: "/dashboards",
|
||||
subItems: [
|
||||
{ label: $t.nav?.overview , path: "/dashboards" },
|
||||
],
|
||||
subItems: [{ label: $t.nav?.overview, path: "/dashboards" }],
|
||||
},
|
||||
{
|
||||
id: "datasets",
|
||||
label: $t.nav?.datasets ,
|
||||
label: $t.nav?.datasets,
|
||||
icon: "database",
|
||||
tone: "from-emerald-100 to-emerald-200 text-emerald-700 ring-emerald-200",
|
||||
path: "/datasets",
|
||||
subItems: [
|
||||
{ label: $t.nav?.all_datasets , path: "/datasets" },
|
||||
],
|
||||
subItems: [{ label: $t.nav?.all_datasets, path: "/datasets" }],
|
||||
},
|
||||
{
|
||||
id: "storage",
|
||||
label: $t.nav?.storage ,
|
||||
label: $t.nav?.storage,
|
||||
icon: "storage",
|
||||
tone: "from-amber-100 to-amber-200 text-amber-800 ring-amber-200",
|
||||
path: "/storage",
|
||||
subItems: [
|
||||
{ label: $t.nav?.backups , path: "/storage/backups" },
|
||||
{ label: $t.nav?.backups, path: "/storage/backups" },
|
||||
{
|
||||
label: $t.nav?.repositories ,
|
||||
label: $t.nav?.repositories,
|
||||
path: "/storage/repos",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "reports",
|
||||
label: $t.nav?.reports ,
|
||||
label: $t.nav?.reports,
|
||||
icon: "reports",
|
||||
tone: "from-violet-100 to-fuchsia-100 text-violet-700 ring-violet-200",
|
||||
path: "/reports",
|
||||
subItems: [{ label: $t.nav?.reports , path: "/reports" }],
|
||||
subItems: [{ label: $t.nav?.reports, path: "/reports" }],
|
||||
},
|
||||
{
|
||||
id: "admin",
|
||||
label: $t.nav?.admin ,
|
||||
label: $t.nav?.admin,
|
||||
icon: "admin",
|
||||
tone: "from-rose-100 to-rose-200 text-rose-700 ring-rose-200",
|
||||
path: "/admin",
|
||||
subItems: [
|
||||
{ label: $t.nav?.admin_users , path: "/admin/users" },
|
||||
{ label: $t.nav?.admin_roles , path: "/admin/roles" },
|
||||
{ label: $t.nav?.settings , path: "/settings" },
|
||||
{ label: $t.nav?.admin_users, path: "/admin/users" },
|
||||
{ label: $t.nav?.admin_roles, path: "/admin/roles" },
|
||||
{ label: $t.nav?.settings, path: "/settings" },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -198,10 +208,12 @@
|
||||
>
|
||||
{#if isExpanded}
|
||||
<span class="font-semibold text-gray-800 flex items-center gap-2">
|
||||
<span class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-slate-100 to-slate-200 text-slate-700 ring-1 ring-slate-200">
|
||||
<span
|
||||
class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-slate-100 to-slate-200 text-slate-700 ring-1 ring-slate-200"
|
||||
>
|
||||
<Icon name="layers" size={14} />
|
||||
</span>
|
||||
{$t.nav?.menu }
|
||||
{$t.nav?.menu}
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-xs text-gray-500">M</span>
|
||||
@@ -228,7 +240,9 @@
|
||||
aria-expanded={expandedCategories.has(category.id)}
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<span class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br ring-1 transition-all {category.tone}">
|
||||
<span
|
||||
class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br ring-1 transition-all {category.tone}"
|
||||
>
|
||||
<Icon name={category.icon} size={16} strokeWidth={2} />
|
||||
</span>
|
||||
{#if isExpanded}
|
||||
@@ -282,10 +296,12 @@
|
||||
class="flex items-center justify-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
on:click={handleToggleClick}
|
||||
>
|
||||
<span class="mr-2 inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-100 text-slate-600">
|
||||
<span
|
||||
class="mr-2 inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-100 text-slate-600"
|
||||
>
|
||||
<Icon name="chevronLeft" size={14} />
|
||||
</span>
|
||||
{$t.nav?.collapse }
|
||||
{$t.nav?.collapse}
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
@@ -293,10 +309,10 @@
|
||||
<button
|
||||
class="flex items-center justify-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
on:click={handleToggleClick}
|
||||
aria-label={$t.nav?.expand_sidebar }
|
||||
aria-label={$t.nav?.expand_sidebar}
|
||||
>
|
||||
<Icon name="chevronRight" size={16} />
|
||||
<span class="ml-2">{$t.nav?.expand }</span>
|
||||
<span class="ml-2">{$t.nav?.expand}</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user