test contracts

This commit is contained in:
2026-02-26 19:40:00 +03:00
parent 81d62c1345
commit 36173c0880
35 changed files with 1811 additions and 759 deletions

View File

@@ -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}