@rovela-ai/sdk 0.19.3 → 0.19.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/server/admin-session.d.ts.map +1 -1
- package/dist/admin/server/admin-session.js +7 -0
- package/dist/admin/server/admin-session.js.map +1 -1
- package/dist/auth/server/customer-session.d.ts.map +1 -1
- package/dist/auth/server/customer-session.js +5 -0
- package/dist/auth/server/customer-session.js.map +1 -1
- package/dist/checkout/server/checkout-customer.d.ts.map +1 -1
- package/dist/checkout/server/checkout-customer.js +5 -0
- package/dist/checkout/server/checkout-customer.js.map +1 -1
- package/docs/changelog/README.md +53 -0
- package/docs/changelog/epoch-01-chrome-consent.md +63 -0
- package/docs/changelog/epoch-02-platform-commerce.md +108 -0
- package/docs/changelog/epoch-03-i18n-files.md +72 -0
- package/docs/changelog/epoch-04-emails.md +65 -0
- package/docs/changelog/epoch-05-admin-experience.md +98 -0
- package/docs/changelog/epoch-06-mobile-integrity.md +72 -0
- package/docs/design/admin-ledger-visual-universe.html +1961 -0
- package/docs/design/admin-sidebar-and-band.html +542 -0
- package/package.json +3 -1
- package/templates/store-template/.claude/skills/add-section/SKILL.md +438 -0
- package/templates/store-template/.claude/skills/build-feature/SKILL.md +201 -0
- package/templates/store-template/.claude/skills/customize-theme/SKILL.md +167 -0
- package/templates/store-template/.claude/skills/debug-errors/SKILL.md +68 -0
- package/templates/store-template/.claude/skills/frontend-design/SKILL.md +176 -0
- package/templates/store-template/.claude/skills/generate-images/SKILL.md +115 -0
- package/templates/store-template/.claude/skills/manage-products/SKILL.md +187 -0
- package/templates/store-template/.claude/skills/override-sdk-component/SKILL.md +154 -0
- package/templates/store-template/.env.example +50 -0
- package/templates/store-template/.mcp.json +8 -0
- package/templates/store-template/.rovela/blueprint.example.json +190 -0
- package/templates/store-template/CLAUDE.md +14 -0
- package/templates/store-template/app/LayoutContent.tsx +106 -0
- package/templates/store-template/app/[...path]/page.tsx +79 -0
- package/templates/store-template/app/account/addresses/page.tsx +45 -0
- package/templates/store-template/app/account/layout.tsx +17 -0
- package/templates/store-template/app/account/orders/[id]/invoice/page.tsx +277 -0
- package/templates/store-template/app/account/orders/[id]/page.tsx +725 -0
- package/templates/store-template/app/account/orders/page.tsx +153 -0
- package/templates/store-template/app/account/page.tsx +184 -0
- package/templates/store-template/app/account/profile/page.tsx +434 -0
- package/templates/store-template/app/admin/(dashboard)/account/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/events/page.tsx +14 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/layout.tsx +48 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/analytics/visitors/page.tsx +14 -0
- package/templates/store-template/app/admin/(dashboard)/categories/[id]/page.tsx +38 -0
- package/templates/store-template/app/admin/(dashboard)/categories/new/page.tsx +35 -0
- package/templates/store-template/app/admin/(dashboard)/categories/page.tsx +223 -0
- package/templates/store-template/app/admin/(dashboard)/customers/[id]/page.tsx +26 -0
- package/templates/store-template/app/admin/(dashboard)/customers/page.tsx +33 -0
- package/templates/store-template/app/admin/(dashboard)/discounts/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/emails/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/files/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/layout.tsx +44 -0
- package/templates/store-template/app/admin/(dashboard)/loading.tsx +88 -0
- package/templates/store-template/app/admin/(dashboard)/locations/page.tsx +16 -0
- package/templates/store-template/app/admin/(dashboard)/orders/[id]/page.tsx +66 -0
- package/templates/store-template/app/admin/(dashboard)/orders/page.tsx +26 -0
- package/templates/store-template/app/admin/(dashboard)/page.tsx +146 -0
- package/templates/store-template/app/admin/(dashboard)/payments/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/products/[id]/page.tsx +38 -0
- package/templates/store-template/app/admin/(dashboard)/products/new/page.tsx +35 -0
- package/templates/store-template/app/admin/(dashboard)/products/page.tsx +31 -0
- package/templates/store-template/app/admin/(dashboard)/settings/page.tsx +46 -0
- package/templates/store-template/app/admin/(dashboard)/shipping/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/tax/page.tsx +15 -0
- package/templates/store-template/app/admin/(dashboard)/users/[id]/page.tsx +114 -0
- package/templates/store-template/app/admin/(dashboard)/users/page.tsx +16 -0
- package/templates/store-template/app/admin/accept-invite/page.tsx +36 -0
- package/templates/store-template/app/admin/forgot-password/page.tsx +13 -0
- package/templates/store-template/app/admin/layout.tsx +47 -0
- package/templates/store-template/app/admin/login/page.tsx +528 -0
- package/templates/store-template/app/admin/reset-password/page.tsx +36 -0
- package/templates/store-template/app/api/account/addresses/[id]/route.ts +10 -0
- package/templates/store-template/app/api/account/addresses/route.ts +10 -0
- package/templates/store-template/app/api/account/change-password/route.ts +107 -0
- package/templates/store-template/app/api/account/orders/[id]/refund/route.ts +11 -0
- package/templates/store-template/app/api/account/orders/[id]/return/route.ts +14 -0
- package/templates/store-template/app/api/account/orders/[id]/route.ts +42 -0
- package/templates/store-template/app/api/account/orders/route.ts +29 -0
- package/templates/store-template/app/api/account/profile/route.ts +165 -0
- package/templates/store-template/app/api/admin/accept-invite/route.ts +11 -0
- package/templates/store-template/app/api/admin/analytics/events/route.ts +9 -0
- package/templates/store-template/app/api/admin/analytics/route.ts +10 -0
- package/templates/store-template/app/api/admin/analytics/visitors/route.ts +9 -0
- package/templates/store-template/app/api/admin/branding/favicon/route.ts +9 -0
- package/templates/store-template/app/api/admin/branding/logo/route.ts +9 -0
- package/templates/store-template/app/api/admin/categories/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/categories/route.ts +9 -0
- package/templates/store-template/app/api/admin/check/route.ts +10 -0
- package/templates/store-template/app/api/admin/customer-groups/[id]/route.ts +10 -0
- package/templates/store-template/app/api/admin/customer-groups/route.ts +10 -0
- package/templates/store-template/app/api/admin/customers/[id]/addresses/[addressId]/route.ts +15 -0
- package/templates/store-template/app/api/admin/customers/[id]/addresses/route.ts +15 -0
- package/templates/store-template/app/api/admin/customers/[id]/route.ts +11 -0
- package/templates/store-template/app/api/admin/customers/bulk/route.ts +8 -0
- package/templates/store-template/app/api/admin/customers/route.ts +9 -0
- package/templates/store-template/app/api/admin/discounts/[id]/route.ts +11 -0
- package/templates/store-template/app/api/admin/discounts/route.ts +10 -0
- package/templates/store-template/app/api/admin/emails/preview/route.ts +4 -0
- package/templates/store-template/app/api/admin/emails/route.ts +5 -0
- package/templates/store-template/app/api/admin/emails/test/route.ts +4 -0
- package/templates/store-template/app/api/admin/files/route.ts +8 -0
- package/templates/store-template/app/api/admin/forgot-password/route.ts +7 -0
- package/templates/store-template/app/api/admin/linked-customer/route.ts +11 -0
- package/templates/store-template/app/api/admin/locations/[id]/route.ts +10 -0
- package/templates/store-template/app/api/admin/locations/route.ts +10 -0
- package/templates/store-template/app/api/admin/me/password/route.ts +13 -0
- package/templates/store-template/app/api/admin/me/route.ts +11 -0
- package/templates/store-template/app/api/admin/orders/[id]/refund/route.ts +7 -0
- package/templates/store-template/app/api/admin/orders/[id]/return/approve/route.ts +7 -0
- package/templates/store-template/app/api/admin/orders/[id]/return/reject/route.ts +7 -0
- package/templates/store-template/app/api/admin/orders/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/orders/[id]/ship-with-shippo/route.ts +6 -0
- package/templates/store-template/app/api/admin/orders/[id]/shippo-rates/route.ts +6 -0
- package/templates/store-template/app/api/admin/orders/bulk/route.ts +8 -0
- package/templates/store-template/app/api/admin/orders/route.ts +9 -0
- package/templates/store-template/app/api/admin/payment-methods/[id]/route.ts +10 -0
- package/templates/store-template/app/api/admin/payment-methods/route.ts +10 -0
- package/templates/store-template/app/api/admin/products/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/products/bulk/route.ts +9 -0
- package/templates/store-template/app/api/admin/products/route.ts +9 -0
- package/templates/store-template/app/api/admin/products/stats/route.ts +10 -0
- package/templates/store-template/app/api/admin/reset-password/route.ts +10 -0
- package/templates/store-template/app/api/admin/settings/route.ts +11 -0
- package/templates/store-template/app/api/admin/setup/route.ts +10 -0
- package/templates/store-template/app/api/admin/setup-guide/manual-mark/route.ts +13 -0
- package/templates/store-template/app/api/admin/setup-guide/route.ts +10 -0
- package/templates/store-template/app/api/admin/shipping/carriers/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/carriers/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/rates/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/rates/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/shippo/api-key/route.ts +1 -0
- package/templates/store-template/app/api/admin/shipping/shippo/validate/route.ts +1 -0
- package/templates/store-template/app/api/admin/shipping/zones/[id]/route.ts +9 -0
- package/templates/store-template/app/api/admin/shipping/zones/route.ts +9 -0
- package/templates/store-template/app/api/admin/stats/route.ts +9 -0
- package/templates/store-template/app/api/admin/stripe-status/route.ts +1 -0
- package/templates/store-template/app/api/admin/tax-zones/[id]/route.ts +7 -0
- package/templates/store-template/app/api/admin/tax-zones/route.ts +7 -0
- package/templates/store-template/app/api/admin/users/[id]/route.ts +14 -0
- package/templates/store-template/app/api/admin/users/route.ts +12 -0
- package/templates/store-template/app/api/admin-auth/[...nextauth]/route.ts +17 -0
- package/templates/store-template/app/api/analytics/track/route.ts +12 -0
- package/templates/store-template/app/api/auth/[...nextauth]/route.ts +19 -0
- package/templates/store-template/app/api/auth/forgot-password/route.ts +9 -0
- package/templates/store-template/app/api/auth/register/route.ts +9 -0
- package/templates/store-template/app/api/auth/resend-verification/route.ts +9 -0
- package/templates/store-template/app/api/auth/reset-password/route.ts +10 -0
- package/templates/store-template/app/api/auth/verify-email/route.ts +10 -0
- package/templates/store-template/app/api/categories/route.ts +10 -0
- package/templates/store-template/app/api/checkout/countries/route.ts +7 -0
- package/templates/store-template/app/api/checkout/discount/route.ts +9 -0
- package/templates/store-template/app/api/checkout/manual/route.ts +10 -0
- package/templates/store-template/app/api/checkout/payment-methods/route.ts +8 -0
- package/templates/store-template/app/api/checkout/pickup-locations/route.ts +8 -0
- package/templates/store-template/app/api/checkout/route.ts +10 -0
- package/templates/store-template/app/api/checkout/shipping/route.ts +21 -0
- package/templates/store-template/app/api/checkout/status/route.ts +10 -0
- package/templates/store-template/app/api/contact/route.ts +164 -0
- package/templates/store-template/app/api/media/presign/route.ts +7 -0
- package/templates/store-template/app/api/media/route.ts +7 -0
- package/templates/store-template/app/api/products/[slug]/route.ts +10 -0
- package/templates/store-template/app/api/products/route.ts +10 -0
- package/templates/store-template/app/api/store/settings/route.ts +12 -0
- package/templates/store-template/app/api/webhooks/stripe/route.ts +63 -0
- package/templates/store-template/app/auth/forgot-password/page.tsx +38 -0
- package/templates/store-template/app/auth/layout.tsx +17 -0
- package/templates/store-template/app/auth/reset-password/page.tsx +81 -0
- package/templates/store-template/app/auth/signin/page.tsx +62 -0
- package/templates/store-template/app/auth/signup/page.tsx +38 -0
- package/templates/store-template/app/auth/verify-email/page.tsx +185 -0
- package/templates/store-template/app/cart/page.tsx +137 -0
- package/templates/store-template/app/checkout/page.tsx +88 -0
- package/templates/store-template/app/checkout/success/page.tsx +50 -0
- package/templates/store-template/app/contact/layout.tsx +24 -0
- package/templates/store-template/app/contact/page.tsx +321 -0
- package/templates/store-template/app/faq/page.tsx +153 -0
- package/templates/store-template/app/globals.css +99 -0
- package/templates/store-template/app/layout.tsx +269 -0
- package/templates/store-template/app/not-found.tsx +35 -0
- package/templates/store-template/app/page.tsx +23 -0
- package/templates/store-template/app/privacy/page.tsx +281 -0
- package/templates/store-template/app/products/[slug]/ProductDetailClient.tsx +179 -0
- package/templates/store-template/app/products/[slug]/page.tsx +149 -0
- package/templates/store-template/app/products/layout.tsx +26 -0
- package/templates/store-template/app/products/page.tsx +102 -0
- package/templates/store-template/app/robots.ts +25 -0
- package/templates/store-template/app/sitemap.ts +76 -0
- package/templates/store-template/app/terms/page.tsx +313 -0
- package/templates/store-template/components/PathSyncBridge.tsx +61 -0
- package/templates/store-template/components/Providers.tsx +37 -0
- package/templates/store-template/components/layout/Footer.tsx +150 -0
- package/templates/store-template/components/layout/Header.tsx +162 -0
- package/templates/store-template/components/sections/.gitkeep +7 -0
- package/templates/store-template/components/sections/CTA.tsx +51 -0
- package/templates/store-template/components/sections/Features.tsx +91 -0
- package/templates/store-template/components/sections/Hero.tsx +85 -0
- package/templates/store-template/eslint.config.mjs +18 -0
- package/templates/store-template/lib/store-config.ts +77 -0
- package/templates/store-template/lib/store-policy.ts +68 -0
- package/templates/store-template/lib/utils.ts +21 -0
- package/templates/store-template/next-env.d.ts +6 -0
- package/templates/store-template/next.config.js +105 -0
- package/templates/store-template/package.json +32 -0
- package/templates/store-template/postcss.config.js +6 -0
- package/templates/store-template/proxy.ts +150 -0
- package/templates/store-template/public/rovela-logo.png +0 -0
- package/templates/store-template/tailwind.config.ts +74 -0
- package/templates/store-template/tsconfig.json +41 -0
- package/templates/store-template/types/next-auth.d.ts +32 -0
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
<!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1"><style>:root{color-scheme:light}body{margin:0;padding:0;font:14px -apple-system,BlinkMacSystemFont,sans-serif;background:#faf9f5;color:#141413}img{max-width:100%}</style></head><body>
|
|
2
|
+
<title>Rovela Admin — Sidebar & The Band</title>
|
|
3
|
+
<style>
|
|
4
|
+
:root{
|
|
5
|
+
--pg-bg:#ECE7DE; --pg-card:#F7F3ED; --pg-ink:#262F31; --pg-muted:#657172;
|
|
6
|
+
--pg-subtle:#8C9899; --pg-border:#DCD5C8; --pg-accent:#0CAF7D; --pg-accent-deep:#087C58;
|
|
7
|
+
--pg-red:#B3372C; --frame-edge:#D8D1C3;
|
|
8
|
+
}
|
|
9
|
+
@media (prefers-color-scheme: dark){
|
|
10
|
+
:root{ --pg-bg:#191B1C; --pg-card:#212425; --pg-ink:#E8E6E1; --pg-muted:#9BA3A2;
|
|
11
|
+
--pg-subtle:#6E7877; --pg-border:#343839; --frame-edge:#3A3F40; }
|
|
12
|
+
}
|
|
13
|
+
:root[data-theme="dark"]{ --pg-bg:#191B1C; --pg-card:#212425; --pg-ink:#E8E6E1; --pg-muted:#9BA3A2;
|
|
14
|
+
--pg-subtle:#6E7877; --pg-border:#343839; --frame-edge:#3A3F40; }
|
|
15
|
+
:root[data-theme="light"]{ --pg-bg:#ECE7DE; --pg-card:#F7F3ED; --pg-ink:#262F31; --pg-muted:#657172;
|
|
16
|
+
--pg-subtle:#8C9899; --pg-border:#DCD5C8; --frame-edge:#D8D1C3; }
|
|
17
|
+
|
|
18
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
19
|
+
@media (prefers-reduced-motion: reduce){ *{transition:none!important;animation:none!important} }
|
|
20
|
+
body{background:var(--pg-bg);color:var(--pg-ink);font-family:'Plus Jakarta Sans',ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased}
|
|
21
|
+
.wrap{max-width:1220px;margin:0 auto;padding:0 32px}
|
|
22
|
+
@media(max-width:760px){.wrap{padding:0 16px}}
|
|
23
|
+
|
|
24
|
+
.hero{padding:64px 0 36px}
|
|
25
|
+
.hero .eyebrow{font-size:11px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--pg-accent-deep)}
|
|
26
|
+
@media (prefers-color-scheme: dark){ .hero .eyebrow{color:var(--pg-accent)} }
|
|
27
|
+
:root[data-theme="dark"] .hero .eyebrow{color:var(--pg-accent)}
|
|
28
|
+
.hero h1{font-size:clamp(26px,4vw,40px);font-weight:700;letter-spacing:-0.02em;line-height:1.14;margin:10px 0 12px;text-wrap:balance}
|
|
29
|
+
.hero p{max-width:66ch;color:var(--pg-muted);font-size:15px}
|
|
30
|
+
|
|
31
|
+
section{padding:44px 0 6px}
|
|
32
|
+
.sec-eyebrow{font-size:11px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--pg-subtle)}
|
|
33
|
+
.sec-title{font-size:22px;font-weight:700;letter-spacing:-0.015em;margin:6px 0 8px}
|
|
34
|
+
.sec-note{color:var(--pg-muted);max-width:74ch;margin-bottom:22px}
|
|
35
|
+
|
|
36
|
+
.findings{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px}
|
|
37
|
+
.finding{background:var(--pg-card);border:1px solid var(--pg-border);border-radius:12px;padding:16px 18px}
|
|
38
|
+
.finding .tag{display:inline-flex;font-size:10.5px;font-weight:700;letter-spacing:.06em;border-radius:999px;padding:2px 9px;margin-bottom:8px}
|
|
39
|
+
.tag.p0{background:#FCE5E3;color:#B3372C}
|
|
40
|
+
.tag.p1{background:#FCF0D8;color:#8A6116}
|
|
41
|
+
.tag.p2{background:#E3EFFA;color:#2563A8}
|
|
42
|
+
.finding h3{font-size:13.5px;font-weight:700;margin-bottom:5px}
|
|
43
|
+
.finding p{font-size:12.5px;color:var(--pg-muted);line-height:1.55}
|
|
44
|
+
.finding code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;background:var(--pg-bg);border:1px solid var(--pg-border);border-radius:4px;padding:0 4px}
|
|
45
|
+
|
|
46
|
+
/* boards */
|
|
47
|
+
.frame{border:1px solid var(--frame-edge);border-radius:14px;overflow:hidden;box-shadow:0 2px 14px rgba(0,0,0,.05);margin-bottom:10px}
|
|
48
|
+
.frame-bar{display:flex;align-items:center;gap:8px;background:var(--pg-card);border-bottom:1px solid var(--pg-border);padding:8px 14px}
|
|
49
|
+
.frame-bar .dots{display:flex;gap:5px}
|
|
50
|
+
.frame-bar .dots i{width:9px;height:9px;border-radius:50%;background:var(--pg-border);display:block}
|
|
51
|
+
.frame-bar b{font-size:12px;font-weight:700}
|
|
52
|
+
.frame-bar span.lab{font-size:11.5px;color:var(--pg-subtle)}
|
|
53
|
+
.frame-scroll{overflow-x:auto}
|
|
54
|
+
|
|
55
|
+
.board{
|
|
56
|
+
--bg:#F7F3ED; --card:#fff; --sidebar:#F9F7F4; --side-hover:#EFEBE4;
|
|
57
|
+
--ink:#262F31; --muted:#657172; --subtle:#8C9899; --border:#E5E0D6;
|
|
58
|
+
--accent:#0CAF7D; --accent-deep:#087C58; --accent-tint:#E3F8F0;
|
|
59
|
+
min-width:980px; background:var(--bg); color:var(--ink); font-size:13px;
|
|
60
|
+
display:flex; position:relative; height:470px; overflow:hidden;
|
|
61
|
+
}
|
|
62
|
+
.board *{box-sizing:border-box}
|
|
63
|
+
.b-side{width:240px;flex:none;background:var(--sidebar);border-right:1px solid var(--border);display:flex;flex-direction:column;position:relative}
|
|
64
|
+
.b-main{flex:1;min-width:0;position:relative;display:flex;flex-direction:column}
|
|
65
|
+
|
|
66
|
+
/* nav shared */
|
|
67
|
+
.b-nav{padding:8px;flex:1;overflow:hidden;position:relative}
|
|
68
|
+
.b-eyebrow{font-size:10.5px;font-weight:700;text-transform:uppercase;color:var(--subtle);padding:12px 10px 4px}
|
|
69
|
+
.b-item{display:flex;align-items:center;gap:9px;height:30px;padding:0 10px;border-radius:6px;font-size:13px;font-weight:500;color:var(--muted);cursor:pointer;transition:background .14s,color .14s;position:relative;user-select:none}
|
|
70
|
+
.b-item:hover{background:var(--side-hover);color:var(--ink)}
|
|
71
|
+
.b-item.on{background:var(--accent-tint);color:var(--accent-deep);font-weight:600}
|
|
72
|
+
.b-item svg{width:16px;height:16px;flex:none}
|
|
73
|
+
.b-foot{border-top:1px solid var(--border);padding:8px;font-size:12.5px}
|
|
74
|
+
.b-frow{display:flex;align-items:center;gap:9px;height:28px;padding:0 10px;border-radius:6px;color:var(--muted);cursor:pointer}
|
|
75
|
+
.b-frow:hover{background:var(--side-hover);color:var(--ink)}
|
|
76
|
+
.b-frow svg{width:14px;height:14px}
|
|
77
|
+
.b-user{display:flex;align-items:center;gap:9px;padding:7px 10px;border-radius:6px;cursor:pointer}
|
|
78
|
+
.b-user:hover{background:var(--side-hover)}
|
|
79
|
+
.b-user .av{width:24px;height:24px;border-radius:50%;background:var(--accent-tint);color:var(--accent-deep);font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex:none}
|
|
80
|
+
.b-user b{font-size:12.5px;font-weight:600}
|
|
81
|
+
|
|
82
|
+
/* BEFORE specifics */
|
|
83
|
+
.v1 .b-brand{height:64px;display:flex;align-items:center;gap:10px;padding:0 14px;border-bottom:1px solid var(--border);flex:none}
|
|
84
|
+
.v1 .b-logo-raw{display:flex;flex-direction:column;align-items:center;line-height:1;flex:none}
|
|
85
|
+
.v1 .b-logo-raw .m{display:flex;align-items:center;gap:3px;font-weight:800;font-size:13px;color:#C0392B}
|
|
86
|
+
.v1 .b-logo-raw .m i{width:13px;height:13px;border-radius:50%;background:#C0392B;display:inline-block}
|
|
87
|
+
.v1 .b-logo-raw .t{font-size:4.5px;color:#8a8378;margin-top:2px;white-space:nowrap}
|
|
88
|
+
.v1 .b-item.on::before{content:'';position:absolute;left:0;top:6px;bottom:6px;width:3px;border-radius:2px;background:var(--accent)}
|
|
89
|
+
.v1 .b-item svg{stroke-width:2px !important}
|
|
90
|
+
.v1 .b-phead{padding:24px 24px 20px;background:linear-gradient(to bottom, rgba(12,175,125,.055), transparent);border-bottom:1px solid rgba(38,47,49,.12)}
|
|
91
|
+
.v1 .b-phead h1{font-size:20px;font-weight:700;letter-spacing:-0.01em}
|
|
92
|
+
.v1 .b-phead .sub{font-size:12px;color:var(--muted);margin-top:4px}
|
|
93
|
+
.v1 .b-pow{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--subtle);padding:8px 10px 4px}
|
|
94
|
+
.v1 .b-pow b{color:var(--pg-accent-deep);font-size:11px}
|
|
95
|
+
|
|
96
|
+
/* AFTER specifics — the unified band */
|
|
97
|
+
/* PROPOSED — Shopify's architecture: a 52px identity top bar spanning the
|
|
98
|
+
full width (the ONE hairline; the wash lives here now), then a row of
|
|
99
|
+
nav-only sidebar + content with a QUIET page header. */
|
|
100
|
+
.v3{flex-direction:column}
|
|
101
|
+
.v3 .b-top{height:52px;flex:none;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:0 12px 0 14px;background:linear-gradient(to bottom, rgba(12,175,125,.05), rgba(12,175,125,.012)),#F9F7F4;border-bottom:1px solid rgba(38,47,49,.12);position:relative;z-index:5}
|
|
102
|
+
.v3 .b-top-left{display:flex;align-items:center;gap:10px;min-width:0;cursor:pointer}
|
|
103
|
+
.v3 .b-tile{width:28px;height:28px;border-radius:6px;background:#fff;border:1px solid var(--border);display:flex;align-items:center;justify-content:center;flex:none;box-shadow:0 1px 2px rgba(38,47,49,.04)}
|
|
104
|
+
.v3 .b-tile span{font-weight:800;font-size:12.5px;color:#C0392B}
|
|
105
|
+
.v3 .b-top-left b{font-size:13.5px;font-weight:700;white-space:nowrap}
|
|
106
|
+
.v3 .b-admtag{font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);background:#EFEBE4;border-radius:999px;padding:2px 7px}
|
|
107
|
+
.v3 .b-top-right{display:flex;align-items:center;gap:4px}
|
|
108
|
+
.v3 .b-tbtn{display:inline-flex;align-items:center;gap:6px;height:28px;padding:0 10px;border-radius:6px;border:none;background:transparent;font:inherit;font-size:12.5px;font-weight:600;color:var(--muted);cursor:pointer;transition:background .14s,color .14s}
|
|
109
|
+
.v3 .b-tbtn:hover{background:rgba(38,47,49,.05);color:var(--ink)}
|
|
110
|
+
.v3 .b-tbtn svg{width:14px;height:14px}
|
|
111
|
+
.v3 .b-tdiv{width:1px;height:16px;background:var(--border);margin:0 6px}
|
|
112
|
+
.v3 .b-tuser{display:flex;align-items:center;gap:4px;cursor:pointer;padding:3px 5px 3px 3px;border-radius:999px;transition:background .14s}
|
|
113
|
+
.v3 .b-tuser:hover{background:rgba(38,47,49,.05)}
|
|
114
|
+
.v3 .b-tuser .av{width:26px;height:26px;border-radius:50%;background:var(--accent-tint);color:var(--accent-deep);font-size:10.5px;font-weight:700;display:flex;align-items:center;justify-content:center}
|
|
115
|
+
.v3 .b-tuser .chev{width:12px;height:12px;color:var(--subtle)}
|
|
116
|
+
.v3 .b-row{flex:1;display:flex;min-height:0}
|
|
117
|
+
.v3 .b-side{position:relative}
|
|
118
|
+
.v3 .b-nav{overflow-y:auto;scrollbar-width:none;padding:10px 8px;min-height:0}
|
|
119
|
+
.v3 .b-nav::-webkit-scrollbar{width:0;height:0}
|
|
120
|
+
.v3 .b-item svg{stroke-width:1.5px}
|
|
121
|
+
.v3 .b-eyebrow{letter-spacing:.14em}
|
|
122
|
+
.v3 .b-navfade{position:absolute;left:1px;right:1px;height:34px;pointer-events:none;opacity:0;transition:opacity .2s;z-index:4}
|
|
123
|
+
.v3 .b-navfade.down{bottom:64px;background:linear-gradient(to bottom, rgba(249,247,244,0), #F9F7F4 80%)}
|
|
124
|
+
.v3 .b-navfade.up{top:0;background:linear-gradient(to top, rgba(249,247,244,0), #F9F7F4 80%)}
|
|
125
|
+
.v3 .b-navfade.show{opacity:1}
|
|
126
|
+
.v3 .b-foot{flex:none}
|
|
127
|
+
.v3 .b-pow{display:flex;align-items:center;gap:4px;font-size:10.5px;color:var(--subtle);padding:6px 10px 2px}
|
|
128
|
+
.v3 .b-phead3{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:24px 24px 2px}
|
|
129
|
+
.v3 .b-phead3 h1{font-size:20px;font-weight:700;letter-spacing:-0.01em}
|
|
130
|
+
.v3 .b-phead3 .sub{font-size:12px;color:var(--muted);margin-top:4px}
|
|
131
|
+
.v3 .b-phead3 .acts{display:flex;gap:8px;align-items:center;flex:none}
|
|
132
|
+
.v3 .b-btn{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:6px;font-size:12.5px;font-weight:600;border:1px solid transparent;cursor:pointer}
|
|
133
|
+
.v3 .b-btn.pri{background:var(--accent);color:#fff}
|
|
134
|
+
.v3 .b-btn.sec{background:#fff;border-color:#D8D1C3;color:var(--ink)}
|
|
135
|
+
|
|
136
|
+
/* content hints below band */
|
|
137
|
+
.b-hint{padding:20px 24px;display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
|
|
138
|
+
.b-hintcard{background:var(--card);border:1px solid var(--border);border-radius:10px;height:84px;box-shadow:0 1px 2px rgba(38,47,49,.04);padding:12px}
|
|
139
|
+
.b-hintcard .k{height:8px;width:56px;border-radius:4px;background:#EFEBE4;margin-bottom:12px}
|
|
140
|
+
.b-hintcard .v{height:16px;width:80px;border-radius:4px;background:#E7E2D8}
|
|
141
|
+
|
|
142
|
+
/* annotations */
|
|
143
|
+
.anno{position:absolute;left:0;right:0;pointer-events:none;z-index:20}
|
|
144
|
+
.anno .line{position:absolute;left:0;right:0;border-top:1.5px dashed var(--pg-red);opacity:.85}
|
|
145
|
+
.anno .line.ok{border-color:#0CAF7D}
|
|
146
|
+
.anno .pill{position:absolute;right:10px;transform:translateY(-50%);font-size:10.5px;font-weight:700;background:var(--pg-red);color:#fff;border-radius:999px;padding:2px 9px;white-space:nowrap}
|
|
147
|
+
.anno .pill.ok{background:#087C58}
|
|
148
|
+
|
|
149
|
+
/* flash overlay for the BEFORE demo */
|
|
150
|
+
.flashveil{position:absolute;inset:0;background:#fff;opacity:0;pointer-events:none;z-index:30;transition:opacity 120ms}
|
|
151
|
+
.board.flashing .flashveil{opacity:.92}
|
|
152
|
+
|
|
153
|
+
.demo-note{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 4px}
|
|
154
|
+
.demo-note span{font-size:12px;color:var(--pg-muted);background:var(--pg-card);border:1px solid var(--pg-border);border-radius:999px;padding:4px 12px}
|
|
155
|
+
.demo-note b{color:var(--pg-ink);font-weight:600}
|
|
156
|
+
|
|
157
|
+
/* spec table */
|
|
158
|
+
table.spec{width:100%;border-collapse:collapse;font-size:12.5px;background:var(--pg-card);border:1px solid var(--pg-border);border-radius:12px;overflow:hidden}
|
|
159
|
+
.spec th{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--pg-subtle);text-align:left;padding:10px 14px;border-bottom:1px solid var(--pg-border)}
|
|
160
|
+
.spec td{padding:9px 14px;border-bottom:1px solid var(--pg-border);vertical-align:top}
|
|
161
|
+
.spec tr:last-child td{border-bottom:none}
|
|
162
|
+
.spec td:first-child{font-weight:600;white-space:nowrap}
|
|
163
|
+
.spec code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;background:var(--pg-bg);border:1px solid var(--pg-border);border-radius:4px;padding:0 4px}
|
|
164
|
+
.tablewrap{overflow-x:auto;border-radius:12px}
|
|
165
|
+
|
|
166
|
+
/* plan */
|
|
167
|
+
.plan{display:flex;flex-direction:column;gap:10px}
|
|
168
|
+
.step{display:flex;gap:14px;background:var(--pg-card);border:1px solid var(--pg-border);border-radius:12px;padding:14px 16px}
|
|
169
|
+
.step .n{flex:none;width:26px;height:26px;border-radius:8px;background:var(--pg-ink);color:var(--pg-bg);font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center;margin-top:2px}
|
|
170
|
+
.step h3{font-size:13.5px;font-weight:700;margin-bottom:3px}
|
|
171
|
+
.step h3 .pf{font-size:10.5px;font-weight:700;border-radius:999px;padding:1px 8px;margin-left:8px;vertical-align:1px}
|
|
172
|
+
.pf.p0{background:#FCE5E3;color:#B3372C}
|
|
173
|
+
.pf.p1{background:#FCF0D8;color:#8A6116}
|
|
174
|
+
.pf.p2{background:#E3EFFA;color:#2563A8}
|
|
175
|
+
.step p{font-size:12.5px;color:var(--pg-muted);line-height:1.55}
|
|
176
|
+
.step code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;background:var(--pg-bg);border:1px solid var(--pg-border);border-radius:4px;padding:0 4px}
|
|
177
|
+
|
|
178
|
+
footer{padding:40px 0 56px;color:var(--pg-subtle);font-size:12.5px}
|
|
179
|
+
footer .wrap{border-top:1px solid var(--pg-border);padding-top:22px}
|
|
180
|
+
</style>
|
|
181
|
+
|
|
182
|
+
<svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs>
|
|
183
|
+
<symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10.5 12 3l9 7.5"/><path d="M5.5 8.8V21h13V8.8"/><path d="M9.5 21v-6h5v6"/></symbol>
|
|
184
|
+
<symbol id="i-receipt" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5.5 3h13v18l-2.2-1.4-2.1 1.4-2.2-1.4L9.9 21l-2.2-1.4L5.5 21z"/><path d="M9 8.5h6M9 12.5h6"/></symbol>
|
|
185
|
+
<symbol id="i-box" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 8.2 12 3 3 8.2v7.6L12 21l9-5.2z"/><path d="M3 8.2l9 5.1 9-5.1"/><path d="M12 21v-7.7"/></symbol>
|
|
186
|
+
<symbol id="i-users" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3.4"/><path d="M2.8 20c.4-3.3 3-5.2 6.2-5.2s5.8 1.9 6.2 5.2"/><path d="M15.5 5.2a3.2 3.2 0 0 1 0 6"/><path d="M17.3 15.1c2.4.5 4 2.2 4.3 4.9"/></symbol>
|
|
187
|
+
<symbol id="i-folder" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7.5A2.5 2.5 0 0 1 5.5 5h4l2 2.5h7A2.5 2.5 0 0 1 21 10v7.5a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 17.5z"/></symbol>
|
|
188
|
+
<symbol id="i-tag" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11.8 11.8 3H21v9.2L12.2 21z"/><circle cx="16.2" cy="7.8" r="1.3"/></symbol>
|
|
189
|
+
<symbol id="i-pin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 21.3S5.2 15 5.2 10.2a6.8 6.8 0 0 1 13.6 0C18.8 15 12 21.3 12 21.3z"/><circle cx="12" cy="10" r="2.4"/></symbol>
|
|
190
|
+
<symbol id="i-image" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="8.4" cy="9.6" r="1.5"/><path d="M21 15.5 16 10.5 6.5 19"/></symbol>
|
|
191
|
+
<symbol id="i-mail" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3.5 7.5 8.5 6 8.5-6"/></symbol>
|
|
192
|
+
<symbol id="i-chart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 20v-7M12 20V5M19 20v-10"/></symbol>
|
|
193
|
+
<symbol id="i-card" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2.5" y="5.5" width="19" height="13" rx="2"/><path d="M2.5 10h19"/></symbol>
|
|
194
|
+
<symbol id="i-truck" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6.5H14V17H2.5z"/><path d="M14 9.5h3.8l2.7 3V17H14"/><circle cx="7" cy="17.6" r="1.9"/><circle cx="16.8" cy="17.6" r="1.9"/></symbol>
|
|
195
|
+
<symbol id="i-pct" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19 19 5"/><circle cx="7" cy="7" r="2.4"/><circle cx="17" cy="17" r="2.4"/></symbol>
|
|
196
|
+
<symbol id="i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/><circle cx="9.5" cy="7" r="1.9" fill="#F9F7F4"/><circle cx="15" cy="12" r="1.9" fill="#F9F7F4"/><circle cx="7.5" cy="17" r="1.9" fill="#F9F7F4"/></symbol>
|
|
197
|
+
<symbol id="i-edit" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4.5 19.5.9-3.6L16.6 4.7a2 2 0 0 1 2.8 2.8L8.2 18.7z"/></symbol>
|
|
198
|
+
<symbol id="i-ext" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h6v6M20 4 10.5 13.5M17.5 13.5V20h-13V6.5H11"/></symbol>
|
|
199
|
+
<symbol id="i-chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol>
|
|
200
|
+
<symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></symbol>
|
|
201
|
+
<symbol id="i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 2.7 5.4 6 .9-4.3 4.2 1 6-5.4-2.9L6.6 20l1-6L3.3 9.8l6-.9z"/></symbol>
|
|
202
|
+
<symbol id="i-bag" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5.5 8h13l1 13h-15z"/><path d="M8.5 10.5V7a3.5 3.5 0 0 1 7 0v3.5"/></symbol>
|
|
203
|
+
</defs></svg>
|
|
204
|
+
|
|
205
|
+
<header class="hero">
|
|
206
|
+
<div class="wrap">
|
|
207
|
+
<div class="eyebrow">Rovela Admin · LEDGER · Sidebar Deep-Dive</div>
|
|
208
|
+
<h1>The sidebar, rebuilt<br>on Shopify's architecture.</h1>
|
|
209
|
+
<p>Audit and plan only, nothing implemented. The reason Shopify's bar never feels cramped: their sidebar carries no identity at all. Store, account and store-links live in a slim top bar; the column below is pure navigation. This proposal adopts that architecture — a 52px identity top bar (which dissolves the separator-alignment question into one full-width hairline), a nav-only sidebar that fits without scrolling on any laptop, an elegant fade + auto-hiding scrollbar for stores whose custom pages overflow it, and true SPA navigation underneath so nothing ever flashes.</p>
|
|
210
|
+
</div>
|
|
211
|
+
</header>
|
|
212
|
+
|
|
213
|
+
<!-- ═══════════ AUDIT ═══════════ -->
|
|
214
|
+
<section id="audit">
|
|
215
|
+
<div class="wrap">
|
|
216
|
+
<div class="sec-eyebrow">Section 1</div>
|
|
217
|
+
<h2 class="sec-title">Audit — nine findings, ranked</h2>
|
|
218
|
+
<p class="sec-note">Everything below is verified in code (AdminNav.tsx, AdminUserMenu.tsx, useAdminSession.ts, admin-theme.css) and on the live EasyElec admin.</p>
|
|
219
|
+
<div class="findings">
|
|
220
|
+
<div class="finding"><span class="tag p0">P0 · the flash you saw</span>
|
|
221
|
+
<h3>Every sidebar click is a full page reload</h3>
|
|
222
|
+
<p>Nav items render plain <code><a href></code> — zero <code>next/link</code> in AdminNav. Each click tears down the whole React tree: the session and store-settings refetch from scratch, and while they load the UI paints fallbacks — your name becomes "Admin" for a few hundred ms, then corrects. It also resets scroll, re-runs every fetch, and makes each navigation feel like 2005. This one fix upgrades the entire admin's perceived speed at once.</p>
|
|
223
|
+
</div>
|
|
224
|
+
<div class="finding"><span class="tag p0">P0 · your separator note</span>
|
|
225
|
+
<h3>Two hairlines, two heights</h3>
|
|
226
|
+
<p>The sidebar brand row is fixed at <code>64px</code> with its border there; the page-header band varies between ~70 and ~112px depending on eyebrow and subtitle, so its border floats at a different height on every page. Two competing lines in the same zone read as misalignment because they are.</p>
|
|
227
|
+
</div>
|
|
228
|
+
<div class="finding"><span class="tag p1">P1</span>
|
|
229
|
+
<h3>Wrong-value fallbacks instead of skeletons</h3>
|
|
230
|
+
<p>While loading, the user menu literally renders the string "Admin" and the avatar letter "A"; the store name falls back to "Admin" too. Painting a wrong value and correcting it is the glitch signature. The rule: unknown values render a quiet skeleton, never a placeholder that looks like data.</p>
|
|
231
|
+
</div>
|
|
232
|
+
<div class="finding"><span class="tag p1">P1</span>
|
|
233
|
+
<h3>Raw merchant logo in the brand row</h3>
|
|
234
|
+
<p>The logo image renders untreated at 32px height — EasyElec's mark has a baked-in tagline that turns to mush. Arbitrary merchant logos need a frame: a white 32px tile with a hairline, logo contained inside, ink monogram as fallback (today's fallback badge is emerald-tinted, spending the accent on decoration).</p>
|
|
235
|
+
</div>
|
|
236
|
+
<div class="finding"><span class="tag p1">P1</span>
|
|
237
|
+
<h3>Active item carries a left accent bar</h3>
|
|
238
|
+
<p>The active state is a tint pill AND a 3px accent indicator bar. Double-encoding, and the colored-left-bar is a known template tell. The tint pill alone is the Linear/Polaris answer.</p>
|
|
239
|
+
</div>
|
|
240
|
+
<div class="finding"><span class="tag p1">P1</span>
|
|
241
|
+
<h3>Footer is a five-row stack</h3>
|
|
242
|
+
<p>Settings + Edit store + View store + user menu + Powered by Rovela. It's the heaviest zone of the sidebar and the least used. Settings stays pinned (Shopify's signature), the two store links compact to 28px quiet rows, powered-by drops to a 10.5px single line.</p>
|
|
243
|
+
</div>
|
|
244
|
+
<div class="finding"><span class="tag p2">P2</span>
|
|
245
|
+
<h3>Icons at 2px stroke, 18px box</h3>
|
|
246
|
+
<p>LAW 07 says 15–16px at 1.5px stroke next to 13px labels. Current nav icons are optically heavier than everything else in the system.</p>
|
|
247
|
+
</div>
|
|
248
|
+
<div class="finding"><span class="tag p2">P2</span>
|
|
249
|
+
<h3>Eyebrow tracking differs from the band's</h3>
|
|
250
|
+
<p>Sidebar group labels track at ~0.09em while the page-header eyebrow tracks at 0.14em. One eyebrow spec (11px / 600 / uppercase / 0.14em) everywhere; color stays muted in the sidebar so the accent isn't spent.</p>
|
|
251
|
+
</div>
|
|
252
|
+
<div class="finding"><span class="tag p2">P2</span>
|
|
253
|
+
<h3>Nav clips without a scroll affordance</h3>
|
|
254
|
+
<p>On short viewports the last items (Team, Settings…) sit hidden behind the footer with no cue. The nav area needs <code>overflow-y: auto</code> with a thin scrollbar and soft fade masks top and bottom, so clipped means "scrollable", not "broken". Mobile still needs its drawer — kept as its own later phase.</p>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
</section>
|
|
259
|
+
|
|
260
|
+
<!-- ═══════════ BEFORE / AFTER ═══════════ -->
|
|
261
|
+
<section id="boards">
|
|
262
|
+
<div class="wrap">
|
|
263
|
+
<div class="sec-eyebrow">Section 2</div>
|
|
264
|
+
<h2 class="sec-title">See it — today vs proposed</h2>
|
|
265
|
+
<p class="sec-note">Both boards are interactive. In the first, click any nav item: it simulates today's full-page reload, name flash included. In the second, click around (instant) and scroll the nav (the fade is the scroll indicator). This supersedes the earlier 104px aligned-band idea — you were right that separator alignment isn't worth the vertical budget; moving identity into a top bar dissolves the problem instead of solving it.</p>
|
|
266
|
+
|
|
267
|
+
<!-- BEFORE -->
|
|
268
|
+
<div class="frame">
|
|
269
|
+
<div class="frame-bar"><div class="dots"><i></i><i></i><i></i></div><b>Today</b><span class="lab">· click a nav item to feel the reload</span></div>
|
|
270
|
+
<div class="frame-scroll">
|
|
271
|
+
<div class="board v1" id="board-before">
|
|
272
|
+
<aside class="b-side">
|
|
273
|
+
<div class="b-brand">
|
|
274
|
+
<div class="b-logo-raw"><span class="m"><i></i>EasyElec</span><span class="t">Vente de matériel électrique et appareillages neufs</span></div>
|
|
275
|
+
<div style="min-width:0"><b style="font-size:13px;font-weight:700;display:block;line-height:1.2" class="js-store">EasyElec</b><span style="font-size:11px;color:var(--subtle)">Admin</span></div>
|
|
276
|
+
</div>
|
|
277
|
+
<nav class="b-nav">
|
|
278
|
+
<div class="b-item on nav1" data-l="Home"><svg><use href="#i-home"/></svg>Home</div>
|
|
279
|
+
<div class="b-item nav1" data-l="Orders"><svg><use href="#i-receipt"/></svg>Orders</div>
|
|
280
|
+
<div class="b-item nav1" data-l="Products"><svg><use href="#i-box"/></svg>Products</div>
|
|
281
|
+
<div class="b-item nav1" data-l="Customers"><svg><use href="#i-users"/></svg>Customers</div>
|
|
282
|
+
<div class="b-eyebrow" style="letter-spacing:.09em">Store</div>
|
|
283
|
+
<div class="b-item nav1" data-l="Categories"><svg><use href="#i-folder"/></svg>Categories</div>
|
|
284
|
+
<div class="b-item nav1" data-l="Discounts"><svg><use href="#i-tag"/></svg>Discounts</div>
|
|
285
|
+
<div class="b-item nav1" data-l="Locations"><svg><use href="#i-pin"/></svg>Locations</div>
|
|
286
|
+
<div class="b-item nav1" data-l="Files"><svg><use href="#i-image"/></svg>Files</div>
|
|
287
|
+
<div class="b-item nav1" data-l="Emails"><svg><use href="#i-mail"/></svg>Emails</div>
|
|
288
|
+
<div class="b-item nav1" data-l="Analytics"><svg><use href="#i-chart"/></svg>Analytics</div>
|
|
289
|
+
<div class="b-eyebrow" style="letter-spacing:.09em">Configuration</div>
|
|
290
|
+
<div class="b-item nav1" data-l="Payments"><svg><use href="#i-card"/></svg>Payments</div>
|
|
291
|
+
</nav>
|
|
292
|
+
<div class="b-foot">
|
|
293
|
+
<div class="b-frow"><svg><use href="#i-sliders"/></svg>Settings</div>
|
|
294
|
+
<div class="b-frow"><svg><use href="#i-edit"/></svg>Edit Store</div>
|
|
295
|
+
<div class="b-frow"><svg><use href="#i-ext"/></svg>View Store</div>
|
|
296
|
+
<div class="b-user"><span class="av js-av">GB</span><b class="js-user">Ghali Bennis</b><svg style="width:13px;height:13px;color:var(--subtle);margin-left:auto"><use href="#i-chev"/></svg></div>
|
|
297
|
+
<div class="b-pow">Powered by <b>⟠ Rovela</b></div>
|
|
298
|
+
</div>
|
|
299
|
+
</aside>
|
|
300
|
+
<main class="b-main">
|
|
301
|
+
<div class="b-phead">
|
|
302
|
+
<h1 class="js-title">Home</h1>
|
|
303
|
+
<div class="sub">Good afternoon, Ghali</div>
|
|
304
|
+
</div>
|
|
305
|
+
<div class="b-hint">
|
|
306
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
307
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
308
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
309
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
310
|
+
</div>
|
|
311
|
+
</main>
|
|
312
|
+
<!-- annotations: two misaligned hairlines -->
|
|
313
|
+
<div class="anno">
|
|
314
|
+
<div class="line" style="top:64px;left:0;width:240px;right:auto"></div>
|
|
315
|
+
<span class="pill" style="top:64px;right:auto;left:126px">sidebar line · 64px</span>
|
|
316
|
+
<div class="line" style="top:92px;left:240px"></div>
|
|
317
|
+
<span class="pill" style="top:92px">content line · ~70–112px, varies per page</span>
|
|
318
|
+
</div>
|
|
319
|
+
<div class="flashveil"></div>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
<div class="demo-note">
|
|
324
|
+
<span><b>What you just saw</b> is the simulation of a real full-document reload: white flash, store + user names reset to "Admin", then correct themselves</span>
|
|
325
|
+
<span>two red lines never meet</span>
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
<!-- AFTER -->
|
|
329
|
+
<div class="frame" style="margin-top:26px">
|
|
330
|
+
<div class="frame-bar"><div class="dots"><i></i><i></i><i></i></div><b>Proposed</b><span class="lab">· click around, then scroll the nav — the fade tells you there's more</span></div>
|
|
331
|
+
<div class="frame-scroll">
|
|
332
|
+
<div class="board v3" id="board-after">
|
|
333
|
+
<div class="b-top">
|
|
334
|
+
<div class="b-top-left">
|
|
335
|
+
<div class="b-tile"><span>e</span></div>
|
|
336
|
+
<b>EasyElec</b><span class="b-admtag">Admin</span>
|
|
337
|
+
</div>
|
|
338
|
+
<div class="b-top-right">
|
|
339
|
+
<button class="b-tbtn"><svg><use href="#i-ext"/></svg>View store</button>
|
|
340
|
+
<button class="b-tbtn"><svg><use href="#i-edit"/></svg>Edit store</button>
|
|
341
|
+
<i class="b-tdiv"></i>
|
|
342
|
+
<div class="b-tuser"><span class="av">GB</span><svg class="chev"><use href="#i-chev"/></svg></div>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
<div class="b-row">
|
|
346
|
+
<aside class="b-side">
|
|
347
|
+
<nav class="b-nav" id="nav-scroll">
|
|
348
|
+
<div class="b-item on nav2" data-l="Home" data-s="Good afternoon, Ghali"><svg><use href="#i-home"/></svg>Home</div>
|
|
349
|
+
<div class="b-item nav2" data-l="Orders" data-s="Track, fulfill and refund your customers' orders."><svg><use href="#i-receipt"/></svg>Orders</div>
|
|
350
|
+
<div class="b-item nav2" data-l="Products" data-s="Manage your product catalog."><svg><use href="#i-box"/></svg>Products</div>
|
|
351
|
+
<div class="b-item nav2" data-l="Customers" data-s="Everyone with an account or an order in your store."><svg><use href="#i-users"/></svg>Customers</div>
|
|
352
|
+
<div class="b-eyebrow">Store</div>
|
|
353
|
+
<div class="b-item nav2" data-l="Categories" data-s="Collections your customers browse."><svg><use href="#i-folder"/></svg>Categories</div>
|
|
354
|
+
<div class="b-item nav2" data-l="Discounts" data-s="Codes and automatic promotions."><svg><use href="#i-tag"/></svg>Discounts</div>
|
|
355
|
+
<div class="b-item nav2" data-l="Locations" data-s="Your physical shops."><svg><use href="#i-pin"/></svg>Locations</div>
|
|
356
|
+
<div class="b-item nav2" data-l="Files" data-s="Every image and video your store uses."><svg><use href="#i-image"/></svg>Files</div>
|
|
357
|
+
<div class="b-item nav2" data-l="Emails" data-s="The emails your store sends, styled to your brand."><svg><use href="#i-mail"/></svg>Emails</div>
|
|
358
|
+
<div class="b-item nav2" data-l="Analytics" data-s="Visitors, sessions, and conversion."><svg><use href="#i-chart"/></svg>Analytics</div>
|
|
359
|
+
<div class="b-eyebrow">Configuration</div>
|
|
360
|
+
<div class="b-item nav2" data-l="Payments" data-s="How your store gets paid."><svg><use href="#i-card"/></svg>Payments</div>
|
|
361
|
+
<div class="b-item nav2" data-l="Shipping" data-s="Carriers, zones and rates."><svg><use href="#i-truck"/></svg>Shipping</div>
|
|
362
|
+
<div class="b-item nav2" data-l="Tax" data-s="How tax applies to your prices."><svg><use href="#i-pct"/></svg>Tax</div>
|
|
363
|
+
<div class="b-item nav2" data-l="Team" data-s="The people who can sign in to this admin."><svg><use href="#i-users"/></svg>Team</div>
|
|
364
|
+
<div class="b-eyebrow">Features</div>
|
|
365
|
+
<div class="b-item nav2" data-l="Reviews" data-s="A custom page this merchant added from the Features Store."><svg><use href="#i-star"/></svg>Reviews</div>
|
|
366
|
+
<div class="b-item nav2" data-l="Wholesale" data-s="Another merchant-added page — this is why scroll must exist."><svg><use href="#i-bag"/></svg>Wholesale</div>
|
|
367
|
+
</nav>
|
|
368
|
+
<div class="b-navfade up" id="fade-up"></div>
|
|
369
|
+
<div class="b-navfade down" id="fade-down"></div>
|
|
370
|
+
<div class="b-foot">
|
|
371
|
+
<div class="b-frow"><svg><use href="#i-sliders"/></svg>Settings</div>
|
|
372
|
+
<div class="b-pow">Powered by <b style="color:var(--pg-accent-deep)">⟠ Rovela</b></div>
|
|
373
|
+
</div>
|
|
374
|
+
</aside>
|
|
375
|
+
<main class="b-main">
|
|
376
|
+
<div class="b-phead3">
|
|
377
|
+
<div>
|
|
378
|
+
<h1 class="js-title2">Home</h1>
|
|
379
|
+
<div class="sub js-sub2">Good afternoon, Ghali</div>
|
|
380
|
+
</div>
|
|
381
|
+
<div class="acts">
|
|
382
|
+
<button class="b-btn sec">Last 30 days<svg style="width:12px;height:12px"><use href="#i-chev"/></svg></button>
|
|
383
|
+
<button class="b-btn pri"><svg style="width:13px;height:13px"><use href="#i-plus"/></svg>Add product</button>
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
<div class="b-hint">
|
|
387
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
388
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
389
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
390
|
+
<div class="b-hintcard"><div class="k"></div><div class="v"></div></div>
|
|
391
|
+
</div>
|
|
392
|
+
</main>
|
|
393
|
+
</div>
|
|
394
|
+
<div class="anno">
|
|
395
|
+
<div class="line ok" style="top:52px"></div>
|
|
396
|
+
<span class="pill ok" style="top:52px">the one hairline · full width · 52px top bar carries the wash</span>
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
<div class="demo-note">
|
|
402
|
+
<span><b>Shopify's architecture:</b> identity, store links and your account live in the top bar; the sidebar is pure navigation</span>
|
|
403
|
+
<span>core nav (15 items) fits with no scroll on any laptop; this demo adds a merchant's custom Features pages to force overflow — <b>scroll the nav</b> and watch the fades</span>
|
|
404
|
+
<span>scrollbar is hidden until you scroll; the fade is the indicator</span>
|
|
405
|
+
<span>page header goes quiet: the wash and hairline now live only in the top bar</span>
|
|
406
|
+
<span>View store / Edit store leave the sidebar AND the dashboard header — one home</span>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</section>
|
|
410
|
+
|
|
411
|
+
<!-- ═══════════ SPEC ═══════════ -->
|
|
412
|
+
<section id="spec">
|
|
413
|
+
<div class="wrap">
|
|
414
|
+
<div class="sec-eyebrow">Section 3</div>
|
|
415
|
+
<h2 class="sec-title">The spec, in numbers</h2>
|
|
416
|
+
<p class="sec-note">Everything additive on the existing tokens; no <code>.admin-*</code> class is renamed or removed.</p>
|
|
417
|
+
<div class="tablewrap">
|
|
418
|
+
<table class="spec">
|
|
419
|
+
<thead><tr><th style="width:220px">Element</th><th>Proposed</th><th>Today</th></tr></thead>
|
|
420
|
+
<tbody>
|
|
421
|
+
<tr><td>Top bar (new)</td><td>52px, full width, in the sidebar tone with the accent wash and the single bottom hairline — the identity band, now one element with nothing to align. Left: 28px white logo tile (hairline, radius 6, <code>object-contain</code>, ink monogram fallback) + store name 13.5/700 + uppercase "Admin" chip, linking to <code>/admin</code>. Right: View store + Edit store as ghost buttons, divider, avatar menu (name, email, account, sign out). On mobile it hosts the hamburger later.</td><td>Doesn't exist — identity, user menu and store links all crowd the sidebar column.</td></tr>
|
|
422
|
+
<tr><td>Sidebar</td><td>Pure navigation, 240px: the daily four, Store, Configuration (+ merchant Features group when present). Rows 30px / 13 / icons 16px at 1.5 stroke, tint pill active with no indicator bar, eyebrows at the band spec (11 / 600 / 0.14em, muted). Footer is just Settings pinned + a 10.5px powered-by line. Core nav = ~500px: <b>no scroll on anything taller than a 640px viewport</b>.</td><td>Brand block + nav + five-row footer ≈ 690px; scrolls on ordinary laptops, clips with no cue.</td></tr>
|
|
423
|
+
<tr><td>Page header</td><td>Goes quiet: keeps AdminPageHeader's structure (markup untouched) but drops the wash, full-bleed and bottom border — those now belong to the top bar. Dashboard drops its View/Edit store buttons (they live in the top bar); actions reduce to period + Add product.</td><td>Washed full-bleed band per page whose border height varies 70–112px and competes with the sidebar's 64px line.</td></tr>
|
|
424
|
+
<tr><td>Navigation clicks</td><td><code>next/link</code> for every internal route. External links stay anchors with <code>target="_blank"</code>. Active detection already uses <code>usePathname()</code> — survives soft navigation untouched.</td><td>Plain <code><a href></code> → full reload per click.</td></tr>
|
|
425
|
+
<tr><td>Loading identity</td><td>Skeleton bars while session/settings load — never "Admin"/"A" placeholder text. Module-level session cache paints the real name instantly on remounts.</td><td>Literal "Admin" + "A" fallbacks that flash and correct.</td></tr>
|
|
426
|
+
<tr><td>Scroll affordance</td><td><code>overflow-y: auto</code>; scrollbar hidden until scrolling (thin on hover); 34px directional fades that appear <b>only</b> when content continues in that direction — the fade IS the indicator.</td><td>Items clip behind the footer with no cue.</td></tr>
|
|
427
|
+
<tr><td>Mobile</td><td>Later phase: hamburger in the top bar → 200ms focus-trapped drawer under 768px.</td><td>Sidebar consumes 60% of a phone screen.</td></tr>
|
|
428
|
+
</tbody>
|
|
429
|
+
</table>
|
|
430
|
+
</div>
|
|
431
|
+
</div>
|
|
432
|
+
</section>
|
|
433
|
+
|
|
434
|
+
<!-- ═══════════ PLAN ═══════════ -->
|
|
435
|
+
<section id="plan">
|
|
436
|
+
<div class="wrap">
|
|
437
|
+
<div class="sec-eyebrow">Section 4</div>
|
|
438
|
+
<h2 class="sec-title">Implementation plan — six steps, almost all SDK-side</h2>
|
|
439
|
+
<p class="sec-note">AdminLayout is an SDK component and templates just mount it, so the top bar + slim sidebar ship to both template mirrors automatically with the version bump. The only template file that moves is the dashboard page (dropping its now-duplicate View/Edit store buttons). Each step is independently shippable.</p>
|
|
440
|
+
<div class="plan">
|
|
441
|
+
<div class="step"><span class="n">1</span><div>
|
|
442
|
+
<h3>Kill the reloads (the flash fix)<span class="pf p0">P0</span></h3>
|
|
443
|
+
<p>Convert AdminNav's internal links to <code>next/link</code> — nav items, brand link, Settings. The (dashboard) layout then persists across navigation, so the session and settings never refetch on a click and the flash becomes structurally impossible. Files: <code>AdminNav.tsx</code>. Active states need zero work (already pathname-reactive).</p>
|
|
444
|
+
</div></div>
|
|
445
|
+
<div class="step"><span class="n">2</span><div>
|
|
446
|
+
<h3>Skeletons, never wrong values<span class="pf p0">P0</span></h3>
|
|
447
|
+
<p>Cold loads still fetch once. While loading: skeleton bars, never the literal "Admin"/"A". Module-level last-session cache in <code>useAdminSession</code> so remounts paint the real name instantly. Files: <code>AdminNav.tsx</code>, <code>AdminUserMenu.tsx</code>, <code>useAdminSession.ts</code>.</p>
|
|
448
|
+
</div></div>
|
|
449
|
+
<div class="step"><span class="n">3</span><div>
|
|
450
|
+
<h3>AdminTopBar + slim AdminNav<span class="pf p0">P0</span></h3>
|
|
451
|
+
<p>New <code>AdminTopBar</code> component (logo tile + store name + Admin chip left; View store, Edit store, avatar menu right). <code>AdminLayout</code> restructures to top bar over sidebar + main. <code>AdminNav</code> slims to navigation only: groups + Settings pinned + the one-line powered-by; the user menu and store links move up. All additive classes in <code>admin-theme.css</code>; nothing renamed. Files: <code>AdminTopBar.tsx</code> (new), <code>AdminLayout.tsx</code>, <code>AdminNav.tsx</code>, <code>admin-theme.css</code>.</p>
|
|
452
|
+
</div></div>
|
|
453
|
+
<div class="step"><span class="n">4</span><div>
|
|
454
|
+
<h3>Quiet page headers + dashboard dedupe<span class="pf p1">P1</span></h3>
|
|
455
|
+
<p>The page-header band loses its wash, full-bleed margins and bottom border (CSS only — AdminPageHeader markup and every page we standardized stay untouched). Dashboard actions reduce to period + Add product since View/Edit store live in the top bar. Files: <code>admin-theme.css</code> + dashboard <code>page.tsx</code> in both mirrors.</p>
|
|
456
|
+
</div></div>
|
|
457
|
+
<div class="step"><span class="n">5</span><div>
|
|
458
|
+
<h3>Nav metrics pass<span class="pf p1">P1</span></h3>
|
|
459
|
+
<p>Icons to 16px / 1.5 stroke, remove the active indicator bar, unify eyebrow tracking to 0.14em, ink monogram fallback for the logo tile. Files: <code>AdminNav.tsx</code>, <code>AdminTopBar.tsx</code>, <code>admin-theme.css</code>.</p>
|
|
460
|
+
</div></div>
|
|
461
|
+
<div class="step"><span class="n">6</span><div>
|
|
462
|
+
<h3>Scroll affordance<span class="pf p2">P2</span></h3>
|
|
463
|
+
<p>Nav <code>overflow-y: auto</code>, scrollbar hidden until scrolling, directional 34px fades that appear only when content continues that way (tiny scroll listener toggling two classes). Core nav fits without any of this on ≥640px viewports; it exists for merchant-added Features pages. Files: <code>AdminNav.tsx</code>, <code>admin-theme.css</code>. (Mobile drawer stays its own later phase, hamburger in the top bar.)</p>
|
|
464
|
+
</div></div>
|
|
465
|
+
</div>
|
|
466
|
+
</div>
|
|
467
|
+
</section>
|
|
468
|
+
|
|
469
|
+
<footer>
|
|
470
|
+
<div class="wrap">
|
|
471
|
+
Sidebar & Band proposal · audit and plan only, no code shipped · part of the LEDGER design language · July 10, 2026. Verified against AdminNav.tsx, AdminUserMenu.tsx, useAdminSession.ts and admin-theme.css in the working tree.
|
|
472
|
+
</div>
|
|
473
|
+
</footer>
|
|
474
|
+
|
|
475
|
+
<script>
|
|
476
|
+
(function(){
|
|
477
|
+
// BEFORE: simulate today's full-page reload on nav click
|
|
478
|
+
var before = document.getElementById('board-before');
|
|
479
|
+
var busy = false;
|
|
480
|
+
if(before){
|
|
481
|
+
var store = before.querySelector('.js-store');
|
|
482
|
+
var user = before.querySelector('.js-user');
|
|
483
|
+
var av = before.querySelector('.js-av');
|
|
484
|
+
var title = before.querySelector('.js-title');
|
|
485
|
+
before.querySelectorAll('.nav1').forEach(function(it){
|
|
486
|
+
it.addEventListener('click', function(){
|
|
487
|
+
if(busy) return; busy = true;
|
|
488
|
+
var label = it.dataset.l;
|
|
489
|
+
before.classList.add('flashing');
|
|
490
|
+
setTimeout(function(){
|
|
491
|
+
// "reload": fallbacks paint first
|
|
492
|
+
store.textContent = 'Admin';
|
|
493
|
+
user.textContent = 'Admin';
|
|
494
|
+
av.textContent = 'A';
|
|
495
|
+
title.textContent = label;
|
|
496
|
+
before.querySelectorAll('.nav1').forEach(function(n){ n.classList.remove('on') });
|
|
497
|
+
it.classList.add('on');
|
|
498
|
+
before.classList.remove('flashing');
|
|
499
|
+
// then the fetches resolve and names correct themselves
|
|
500
|
+
setTimeout(function(){
|
|
501
|
+
store.textContent = 'EasyElec';
|
|
502
|
+
user.textContent = 'Ghali Bennis';
|
|
503
|
+
av.textContent = 'GB';
|
|
504
|
+
busy = false;
|
|
505
|
+
}, 480);
|
|
506
|
+
}, 160);
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// AFTER: instant soft navigation
|
|
512
|
+
var after = document.getElementById('board-after');
|
|
513
|
+
if(after){
|
|
514
|
+
var t2 = after.querySelector('.js-title2');
|
|
515
|
+
var s2 = after.querySelector('.js-sub2');
|
|
516
|
+
after.querySelectorAll('.nav2').forEach(function(it){
|
|
517
|
+
it.addEventListener('click', function(){
|
|
518
|
+
after.querySelectorAll('.nav2').forEach(function(n){ n.classList.remove('on') });
|
|
519
|
+
it.classList.add('on');
|
|
520
|
+
t2.textContent = it.dataset.l;
|
|
521
|
+
s2.textContent = it.dataset.s || '';
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// AFTER: directional scroll fades — visible only when content continues
|
|
527
|
+
var nav = document.getElementById('nav-scroll');
|
|
528
|
+
if(nav){
|
|
529
|
+
var fu = document.getElementById('fade-up');
|
|
530
|
+
var fd = document.getElementById('fade-down');
|
|
531
|
+
var syncFade = function(){
|
|
532
|
+
fu.classList.toggle('show', nav.scrollTop > 4);
|
|
533
|
+
fd.classList.toggle('show', nav.scrollTop + nav.clientHeight < nav.scrollHeight - 4);
|
|
534
|
+
};
|
|
535
|
+
nav.addEventListener('scroll', syncFade);
|
|
536
|
+
window.addEventListener('resize', syncFade);
|
|
537
|
+
syncFade();
|
|
538
|
+
}
|
|
539
|
+
})();
|
|
540
|
+
</script>
|
|
541
|
+
|
|
542
|
+
</body></html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rovela-ai/sdk",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.5",
|
|
4
4
|
"description": "Rovela SDK - Pre-built e-commerce components for AI-powered store generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
26
|
+
"docs",
|
|
27
|
+
"templates/store-template",
|
|
26
28
|
"README.md"
|
|
27
29
|
],
|
|
28
30
|
"main": "./dist/index.js",
|