@mohasinac/appkit 4.52.3 → 4.52.4
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/.build-stamp.json +3 -3
- package/dist/features/layout/NavbarLayout.js +1 -1
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/tester/seed-data/authored/design-ux__nav-reachability.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__nav-reachability.js +88 -0
- package/dist/features/tester/seed-data/authored/index.js +2 -0
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +43 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/ImageLightbox.js +1 -1
- package/package.json +1 -1
package/dist/.build-stamp.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"stampVersion": 1,
|
|
3
|
-
"version": "4.52.
|
|
4
|
-
"head": "
|
|
3
|
+
"version": "4.52.4",
|
|
4
|
+
"head": "8c2a4fbdf7c75e4d979047ff6bd10114078a2562",
|
|
5
5
|
"branch": "main",
|
|
6
6
|
"dirty": true,
|
|
7
|
-
"builtAt": "2026-10-
|
|
7
|
+
"builtAt": "2026-10-15T02:06:48.669Z"
|
|
8
8
|
}
|
|
@@ -91,5 +91,5 @@ export function NavbarLayout({ items, activeHref, id = "main-navbar", ariaLabel
|
|
|
91
91
|
if (inline) {
|
|
92
92
|
return (_jsx(Ul, { "aria-label": ariaLabel, className: "hidden xl:flex items-center justify-center gap-[var(--appkit-space-0-5)] xl:gap-[var(--appkit-space-1)] w-full", children: items.map((item) => (_jsx(Li, { children: renderItem ? (renderItem(item, isItemActive(item))) : (_jsx(DefaultNavItem, { item: item, isActive: isItemActive(item) })) }, item.href))) }));
|
|
93
93
|
}
|
|
94
|
-
return (_jsx(Nav, { border: "subtle", id: id, "aria-label": ariaLabel, className: "hidden lg:block bg-[var(--appkit-color-bg)]/95 backdrop-blur-md border-b", children: _jsxs(Row, { className: "container mx-auto sm:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)] max-w-[1920px] h-10", padding: "x-md", align: "center", reverse: "hand", children: [_jsxs(Div, { className: `relative flex-1 ${__O.hidden}`, children: [canScrollLeft && (_jsx(NavbarChevron, { direction: "left", onClick: () => scroll("left") })), _jsx(Ul, { ref: scrollRef, className: "flex items-center justify-center gap-[var(--appkit-space-0-5)] lg:gap-[var(--appkit-space-1)] overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: items.map((item) => (_jsx(Li, { className: "shrink-0", children: renderItem ? (renderItem(item, isItemActive(item))) : (_jsx(DefaultNavItem, { item: item, isActive: isItemActive(item) })) }, item.href))) }), canScrollRight && (_jsx(NavbarChevron, { direction: "right", onClick: () => scroll("right") }))] }), rightSlot && _jsx(Div, { className: "shrink-0", children: rightSlot })] }) }));
|
|
94
|
+
return (_jsx(Nav, { border: "subtle", id: id, "aria-label": ariaLabel, className: "hidden lg:block bg-[var(--appkit-color-bg)]/95 backdrop-blur-md border-b", children: _jsxs(Row, { className: "container mx-auto sm:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)] max-w-[1920px] h-10", padding: "x-md", align: "center", reverse: "hand", children: [_jsxs(Div, { className: `relative flex-1 ${__O.hidden}`, children: [canScrollLeft && (_jsx(NavbarChevron, { direction: "left", onClick: () => scroll("left") })), _jsx(Ul, { ref: scrollRef, className: "flex items-center justify-center-safe gap-[var(--appkit-space-0-5)] lg:gap-[var(--appkit-space-1)] overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: items.map((item) => (_jsx(Li, { className: "shrink-0", children: renderItem ? (renderItem(item, isItemActive(item))) : (_jsx(DefaultNavItem, { item: item, isActive: isItemActive(item) })) }, item.href))) }), canScrollRight && (_jsx(NavbarChevron, { direction: "right", onClick: () => scroll("right") }))] }), rightSlot && _jsx(Div, { className: "shrink-0", children: rightSlot })] }) }));
|
|
95
95
|
}
|
|
@@ -67,7 +67,7 @@ export function TitleBarLayout({ onToggleSidebar, sidebarOpen, onSearchToggle, s
|
|
|
67
67
|
// ── Render ───────────────────────────────────────────────────────────────────
|
|
68
68
|
return (_jsxs(BlockHeader, { id: id, className: `sticky top-0 z-50 bg-[var(--appkit-color-bg)]/95 backdrop-blur-md border-b border-[var(--appkit-color-border-subtle)] shadow-sm ${className}`, children: [promoStripText && (_jsx(Section, { color: "inverse", tone: "accent-banner", className: "text-[length:var(--appkit-text-xs)] text-center font-medium", padding: "y-2xs", children: promoStripText })), _jsxs(Div, { paddingX: "x-page", className: "container mx-auto max-w-[1920px]", children: [_jsxs(Row, { justify: "between", gap: "none", reverse: "hand", className: "relative h-14", children: [_jsx(Row, { gap: "3", children: _jsxs(Link, { href: logoHref, "aria-label": brandName, className: "flex items-center gap-[var(--appkit-space-2)] transition-opacity hover:opacity-80", children: [_jsx(Div, { className: "flex md:hidden", children: _jsx(SiteMark, { title: brandShortName ?? brandName, size: "sm" }) }), _jsx(SiteLogo, { title: brandName, size: "md" })] }) }), _jsx(Row, { className: "hidden md:flex absolute inset-y-0 left-1/2 -translate-x-1/2", align: "center", children: _jsx(Link, { href: logoHref, "aria-label": brandName, className: "flex items-center transition-opacity hover:opacity-80", children: _jsx(SiteMark, { src: siteLogoUrl, title: brandName, size: "lg" }) }) }), _jsxs(Row, { gap: "xs", reverse: "hand", children: [devSlot, navSlot, compareEl, notificationSlot, notificationsEl && _jsx(Div, { className: "hidden lg:flex", children: notificationsEl }), messagesEl && _jsx(Div, { className: "hidden lg:flex", children: messagesEl }), wishlistEl && _jsx(Div, { className: "hidden lg:flex", children: wishlistEl }), cartEl && _jsx(Div, { className: "hidden lg:flex", children: cartEl }), user
|
|
69
69
|
? profileEl && _jsx(Div, { className: "hidden lg:flex", children: profileEl })
|
|
70
|
-
: authButtonsEl ?? (profileEl && _jsx(Div, { className: "hidden lg:flex", children: profileEl })), searchBtn, promotionsEl, tourBtn, themeBtn, hamburgerBtn] })] }), hasTb2 && (
|
|
70
|
+
: authButtonsEl ?? (profileEl && _jsx(Div, { className: "hidden lg:flex", children: profileEl })), searchBtn, _jsx(Div, { className: "hidden sm:flex", children: promotionsEl }), _jsx(Div, { className: "hidden sm:flex", children: tourBtn }), themeBtn, hamburgerBtn] })] }), hasTb2 && (
|
|
71
71
|
// `justify="end"` is CORRECT alongside `reverse="hand"` — do not
|
|
72
72
|
// "fix" it to "start". `row-reverse` inverts the main axis, so
|
|
73
73
|
// main-end IS the left edge: flex-end already packs this row left in
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: Authored six-part procedures for the design-ux/nav-reachability page.
|
|
3
|
+
* WHAT: 6 case(s), keyed by full checklist id.
|
|
4
|
+
*
|
|
5
|
+
* @tag domain:tester
|
|
6
|
+
* @tag layer:seed
|
|
7
|
+
* @tag pattern:none
|
|
8
|
+
* @tag access:server-only
|
|
9
|
+
* @tag consumers:seed-data/authored/index.ts
|
|
10
|
+
* @tag sideEffects:none
|
|
11
|
+
*/
|
|
12
|
+
export const authored = {
|
|
13
|
+
"checklist-design-ux-nav-reachability-main-nav-first-items-reachable": {
|
|
14
|
+
roles: ["guest"],
|
|
15
|
+
startPage: "/products",
|
|
16
|
+
steps: [
|
|
17
|
+
"Set the browser window to roughly 1024 pixels wide.",
|
|
18
|
+
"Open /products and look at the horizontal navigation strip under the header.",
|
|
19
|
+
"Read the FIRST item at the left edge of the strip.",
|
|
20
|
+
"Scroll the strip to the right as far as it goes and read the LAST item.",
|
|
21
|
+
],
|
|
22
|
+
expectedBehaviour: "The strip centres its items while they fit and falls back to starting at the left edge as soon as they would overflow, so nothing is ever pushed past the leading edge where scrolling cannot reach it.",
|
|
23
|
+
expectedUiState: "'Home' is the first item visible at the left edge of the strip, followed by 'Products'. Scrolling right reaches 'About Us' at the far end. The prior symptom was the strip opening mid-list with 'Home' and 'Products' already cut off past the left edge and no way to bring them back.",
|
|
24
|
+
endResult: "Nothing persists. Reloading at the same width shows 'Home' first again — the strip is not remembering a scroll position, it genuinely starts at the beginning.",
|
|
25
|
+
},
|
|
26
|
+
"checklist-design-ux-nav-reachability-main-nav-left-chevron-works": {
|
|
27
|
+
roles: ["guest"],
|
|
28
|
+
startPage: "/products",
|
|
29
|
+
steps: [
|
|
30
|
+
"At roughly 1024 pixels wide, scroll the navigation strip to the right (drag it, or use the right chevron).",
|
|
31
|
+
"Look at the left end of the strip for a left-pointing chevron.",
|
|
32
|
+
"Click the left chevron.",
|
|
33
|
+
],
|
|
34
|
+
expectedBehaviour: "The left chevron is shown when the strip has been scrolled away from its start. That condition could never be true while the centring pinned the scroll position at 0, so the control existed and never appeared.",
|
|
35
|
+
expectedUiState: "After scrolling right, a left chevron is visible at the left end of the strip. Clicking it scrolls the strip back towards the start, and continuing to click eventually brings 'Home' into view and the chevron disappears again.",
|
|
36
|
+
endResult: "The strip can be scrolled to either end and back as many times as wanted. No state is saved.",
|
|
37
|
+
},
|
|
38
|
+
"checklist-design-ux-nav-reachability-header-hamburger-reachable-at-320": {
|
|
39
|
+
roles: ["guest"],
|
|
40
|
+
startPage: "/products",
|
|
41
|
+
steps: [
|
|
42
|
+
"Set the browser window to 320 pixels wide, or choose an iPhone SE device profile.",
|
|
43
|
+
"Look at the right-hand end of the top header row.",
|
|
44
|
+
"Tap the hamburger (menu) control.",
|
|
45
|
+
],
|
|
46
|
+
expectedBehaviour: "The header row must fit inside the viewport at the narrowest supported width. The app shell clips horizontal overflow rather than scrolling it, so anything past the edge is unreachable — not merely out of sight.",
|
|
47
|
+
expectedUiState: "The hamburger is FULLY visible at the end of the header row, not half-cut and not missing, and tapping it opens the menu. The theme toggle immediately before it is also whole. The prior symptom was the hamburger sitting entirely beyond the right edge and the theme toggle sliced in half.",
|
|
48
|
+
endResult: "The menu opens and closes normally. Nothing persists.",
|
|
49
|
+
},
|
|
50
|
+
"checklist-design-ux-nav-reachability-header-demotes-optional-controls": {
|
|
51
|
+
roles: ["guest"],
|
|
52
|
+
startPage: "/products",
|
|
53
|
+
steps: [
|
|
54
|
+
"At 320 pixels wide, read every icon in the top header row.",
|
|
55
|
+
"Widen the window past about 640 pixels.",
|
|
56
|
+
"Read the header row again.",
|
|
57
|
+
"At 320 pixels again, open the hamburger menu and look for the deals and tour entries.",
|
|
58
|
+
],
|
|
59
|
+
expectedBehaviour: "Room for the hamburger is made by demoting the two most discretionary controls at the narrowest width, rather than by letting the most important one fall off the end. Neither is removed from the product — only from the header row at that width.",
|
|
60
|
+
expectedUiState: "At 320px the 'Today's Deals' and product-tour icons are NOT in the header. Above ~640px both are back. At 320px their destinations are still reachable from the menu, so nothing has become unavailable.",
|
|
61
|
+
endResult: "Purely responsive; no state is written. Resizing back and forth shows them disappear and reappear at the same point each time.",
|
|
62
|
+
},
|
|
63
|
+
"checklist-design-ux-nav-reachability-no-horizontal-page-scroll": {
|
|
64
|
+
roles: ["guest"],
|
|
65
|
+
startPage: "/",
|
|
66
|
+
steps: [
|
|
67
|
+
"Set the browser window to 320 pixels wide.",
|
|
68
|
+
"Visit each of: /, /products, any product detail page, /categories, /cart.",
|
|
69
|
+
"On each page, try to drag the page sideways and look for a horizontal scrollbar at the bottom of the window.",
|
|
70
|
+
],
|
|
71
|
+
expectedBehaviour: "No layout should be wider than the viewport at the narrowest supported width. A sideways-scrolling page is the clearest single symptom of a broken responsive layout.",
|
|
72
|
+
expectedUiState: "On all five pages the content does not move horizontally and no horizontal scrollbar appears. Report the page and the element if any one of them scrolls — this case is per-page, so a single failure is still a finding even if the other four pass.",
|
|
73
|
+
endResult: "Nothing persists. This is a pure layout check at one width.",
|
|
74
|
+
},
|
|
75
|
+
"checklist-design-ux-nav-reachability-lightbox-thumbnails-reachable": {
|
|
76
|
+
roles: ["guest"],
|
|
77
|
+
startPage: "/products",
|
|
78
|
+
steps: [
|
|
79
|
+
"Open a product that has several images — the Beyblade X UX-03 WizardRod and the video-demo fixtures all carry multiple.",
|
|
80
|
+
"Click the main product image to open the lightbox.",
|
|
81
|
+
"Look at the thumbnail strip below the enlarged image.",
|
|
82
|
+
"Scroll the strip to both ends.",
|
|
83
|
+
],
|
|
84
|
+
expectedBehaviour: "The thumbnail strip is a horizontal scroller and had the same centring defect as the navbar, so with enough images its first thumbnails were off the leading edge with no scroll position that could reach them.",
|
|
85
|
+
expectedUiState: "The strip begins at the FIRST image, and every thumbnail can be reached by scrolling. No thumbnail is stranded past the left edge. Clicking any thumbnail switches the enlarged image to it.",
|
|
86
|
+
endResult: "Closing the lightbox returns to the product page with no change. Reopening starts the strip at the first image again.",
|
|
87
|
+
},
|
|
88
|
+
};
|
|
@@ -88,6 +88,7 @@ import { authored as a_cta_layout__product_bottom_bar } from "./cta-layout__prod
|
|
|
88
88
|
import { authored as a_design_ux__back_to_top_button } from "./design-ux__back-to-top-button.js";
|
|
89
89
|
import { authored as a_design_ux__rich_text_readability } from "./design-ux__rich-text-readability.js";
|
|
90
90
|
import { authored as a_design_ux__action_bar_placement } from "./design-ux__action-bar-placement.js";
|
|
91
|
+
import { authored as a_design_ux__nav_reachability } from "./design-ux__nav-reachability.js";
|
|
91
92
|
import { authored as a_design_ux__feature_badge_picker } from "./design-ux__feature-badge-picker.js";
|
|
92
93
|
import { authored as a_design_ux__dashboard_layout } from "./design-ux__dashboard-layout.js";
|
|
93
94
|
import { authored as a_design_ux__footer_theme } from "./design-ux__footer-theme.js";
|
|
@@ -213,6 +214,7 @@ export const AUTHORED_CASES = {
|
|
|
213
214
|
...a_design_ux__back_to_top_button,
|
|
214
215
|
...a_design_ux__rich_text_readability,
|
|
215
216
|
...a_design_ux__action_bar_placement,
|
|
217
|
+
...a_design_ux__nav_reachability,
|
|
216
218
|
...a_design_ux__feature_badge_picker,
|
|
217
219
|
...a_design_ux__dashboard_layout,
|
|
218
220
|
...a_design_ux__footer_theme,
|
|
@@ -3892,6 +3892,49 @@ const rawTesterChecklistItems = [
|
|
|
3892
3892
|
},
|
|
3893
3893
|
],
|
|
3894
3894
|
},
|
|
3895
|
+
{
|
|
3896
|
+
pageKey: "nav-reachability",
|
|
3897
|
+
pageLabel: "Navigation — Every Item Reachable at Every Width",
|
|
3898
|
+
href: "/products",
|
|
3899
|
+
cases: [
|
|
3900
|
+
{
|
|
3901
|
+
key: "main-nav-first-items-reachable",
|
|
3902
|
+
label: "At a ~1024px window the main navbar still reaches 'Home' and 'Products' — they are not cut off past the left edge",
|
|
3903
|
+
description: "Fixed 2026-10-15. BEFORE: the nav strip was a horizontal scroller centred with `justify-center`. When flex content overflows a centred container the overflow splits across BOTH ends, and the leading half cannot be scrolled to because scrollLeft stops at 0. Measured at 1024px: 14 items needing 1245px in a 990px strip put 'Home' at x=-238 and 'Products' at x=-148, with scrollLeft already 0 — permanently unreachable. AFTER: set the window to roughly 1024px wide and look at the navbar. 'Home' must be the first visible item at the left edge. Scroll the strip right and confirm 'About Us' is reachable too.",
|
|
3904
|
+
href: "/products",
|
|
3905
|
+
},
|
|
3906
|
+
{
|
|
3907
|
+
key: "main-nav-left-chevron-works",
|
|
3908
|
+
label: "After scrolling the navbar right, the left chevron appears and scrolls it back to 'Home'",
|
|
3909
|
+
description: "The chevron existed before the fix but could never appear: it is shown when scrollLeft > 0, and scrollLeft was pinned at 0 by the centring — so the control built for exactly this problem was disabled by the problem. Scroll the nav strip to the right, confirm a left chevron appears, click it, and confirm the strip scrolls back and 'Home' becomes visible.",
|
|
3910
|
+
href: "/products",
|
|
3911
|
+
},
|
|
3912
|
+
{
|
|
3913
|
+
key: "header-hamburger-reachable-at-320",
|
|
3914
|
+
label: "At a 320px-wide window the hamburger (Open menu) is fully visible and tappable in the header",
|
|
3915
|
+
description: "Fixed 2026-10-15. BEFORE: the header action row ran 64px past a 320px viewport and the app shell clips horizontal overflow, so the excess was not scrollable — it was gone. 'Open menu' sat entirely off-screen and the theme toggle was sliced in half. AFTER: narrow the window to 320px (or use an iPhone SE profile). The hamburger must be fully visible at the end of the header row and must open the menu when tapped. The theme toggle beside it must also be whole, not clipped.",
|
|
3916
|
+
href: "/products",
|
|
3917
|
+
},
|
|
3918
|
+
{
|
|
3919
|
+
key: "header-demotes-optional-controls",
|
|
3920
|
+
label: "At 320px the 'Today's Deals' and product-tour icons are hidden from the header, and both reappear on a wider screen",
|
|
3921
|
+
description: "This is how the hamburger was given room — the two most discretionary controls step aside at the narrowest width rather than the most important one falling off. At 320px confirm neither icon is in the header. Widen past ~640px and confirm both come back. Neither is lost at 320px: both remain reachable from the menu the hamburger opens.",
|
|
3922
|
+
href: "/products",
|
|
3923
|
+
},
|
|
3924
|
+
{
|
|
3925
|
+
key: "no-horizontal-page-scroll",
|
|
3926
|
+
label: "No page scrolls sideways at 320px — the whole layout fits the viewport width",
|
|
3927
|
+
description: "A horizontal scrollbar on a phone is the single clearest sign of a broken responsive layout. At 320px, visit the homepage, /products, a product detail page, /categories and /cart. On each, try to drag the page sideways: nothing should move, and no horizontal scrollbar should appear at the bottom of the window.",
|
|
3928
|
+
href: "/",
|
|
3929
|
+
},
|
|
3930
|
+
{
|
|
3931
|
+
key: "lightbox-thumbnails-reachable",
|
|
3932
|
+
label: "In the image lightbox, the FIRST thumbnail is reachable when a gallery has many images",
|
|
3933
|
+
description: "Same defect as the navbar, same fix — the thumbnail strip was a centred flex scroller, so with enough images the leading thumbnails were off the left edge with no way to scroll to them. Open a product with several images, click the main image to open the lightbox, and confirm the thumbnail strip starts at its first image and that every thumbnail can be reached by scrolling the strip.",
|
|
3934
|
+
href: "/products",
|
|
3935
|
+
},
|
|
3936
|
+
],
|
|
3937
|
+
},
|
|
3895
3938
|
{
|
|
3896
3939
|
pageKey: "action-bar-placement",
|
|
3897
3940
|
pageLabel: "Action Bar & Back-to-Top — Desktop vs Mobile",
|