@mohasinac/appkit 4.52.1 → 4.52.3

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.
Files changed (53) hide show
  1. package/dist/.build-stamp.json +4 -4
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -4
  3. package/dist/_internal/server/features/products/list-public.js +37 -1
  4. package/dist/features/about/components/PolicyPageView.js +1 -1
  5. package/dist/features/auctions/components/MarketplaceAuctionCard.js +2 -2
  6. package/dist/features/auth/components/SocialAuthButtons.js +1 -1
  7. package/dist/features/categories/components/CategoryBundlesListing.js +1 -1
  8. package/dist/features/categories/components/CategoryDetailPageView.js +8 -7
  9. package/dist/features/checkout/components/CheckoutStepper.js +1 -1
  10. package/dist/features/faq/components/FAQAccordion.js +1 -1
  11. package/dist/features/filters/FilterFacetSection.js +1 -1
  12. package/dist/features/filters/RangeFilter.js +1 -1
  13. package/dist/features/filters/SwitchFilter.js +1 -1
  14. package/dist/features/homepage/components/BeforeAfterCard.js +2 -2
  15. package/dist/features/homepage/components/CharacterHotspot.js +1 -1
  16. package/dist/features/homepage/components/FAQSection.js +1 -1
  17. package/dist/features/homepage/components/HeroBanner.js +1 -1
  18. package/dist/features/homepage/components/HeroCarousel.js +4 -4
  19. package/dist/features/homepage/components/HowItWorksSection.js +1 -1
  20. package/dist/features/homepage/components/SectionCarousel.js +1 -1
  21. package/dist/features/homepage/components/SecurityHighlightsSection.js +1 -1
  22. package/dist/features/homepage/components/TrustBadges.js +1 -1
  23. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  24. package/dist/features/layout/AppLayoutShell.js +8 -1
  25. package/dist/features/layout/BackToTop.js +2 -2
  26. package/dist/features/layout/BottomActions.js +20 -5
  27. package/dist/features/layout/BottomChrome.d.ts +0 -29
  28. package/dist/features/layout/BottomChrome.js +72 -7
  29. package/dist/features/live/components/LiveItemDetailPageView.js +1 -1
  30. package/dist/features/products/components/ProductFeaturesSelector.d.ts +38 -1
  31. package/dist/features/products/components/ProductFeaturesSelector.js +133 -34
  32. package/dist/features/products/hooks/useProducts.js +18 -1
  33. package/dist/features/reviews/components/ReviewDetailShell.js +2 -1
  34. package/dist/features/reviews/components/ReviewSummary.js +1 -1
  35. package/dist/features/tester/seed-data/_happy-path.js +1 -1
  36. package/dist/features/tester/seed-data/authored/admin__catalog-listings.js +1 -1
  37. package/dist/features/tester/seed-data/authored/content-discovery__category-brand-relations.js +3 -3
  38. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.d.ts +2 -0
  39. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +152 -0
  40. package/dist/features/tester/seed-data/authored/design-ux__action-bar-placement.d.ts +2 -0
  41. package/dist/features/tester/seed-data/authored/design-ux__action-bar-placement.js +89 -0
  42. package/dist/features/tester/seed-data/authored/design-ux__feature-badge-picker.d.ts +2 -0
  43. package/dist/features/tester/seed-data/authored/design-ux__feature-badge-picker.js +82 -0
  44. package/dist/features/tester/seed-data/authored/design-ux__rich-text-readability.d.ts +2 -0
  45. package/dist/features/tester/seed-data/authored/design-ux__rich-text-readability.js +84 -0
  46. package/dist/features/tester/seed-data/authored/index.js +8 -0
  47. package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +2 -2
  48. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +157 -3
  49. package/dist/styles.css +74 -1
  50. package/dist/tailwind-utilities.css +1 -1
  51. package/dist/ui/components/RichTextEditor.js +1 -1
  52. package/dist/ui/rich-text/RichText.style.css +73 -0
  53. package/package.json +1 -1
@@ -3119,6 +3119,43 @@ const rawTesterChecklistItems = [
3119
3119
  { key: "seller-description-lists-parts", label: "A listing under a model leaf gets a Parts line in its filled description, and a non-Beyblade category gets no empty one" },
3120
3120
  ],
3121
3121
  },
3122
+ {
3123
+ /*
3124
+ * The categories index, the franchise unit and the bundle collage —
3125
+ * 2026-10-14.
3126
+ *
3127
+ * 🛑 Every case here compares two things or counts an exact number,
3128
+ * because every defect this work already produced rendered a perfectly
3129
+ * plausible page:
3130
+ *
3131
+ * 1. The index rendered all 1,185 rows flat. Nothing errored; it just
3132
+ * buried the six roots under 752 part leaves.
3133
+ * 2. The Parts tab first matched 772 rows — it also caught the 20
3134
+ * classification NODES, whose own parentIds pass through a
3135
+ * `*-parts` node. A tab mixing "Attack Rings" with the attack rings
3136
+ * inside it looks entirely reasonable.
3137
+ * 3. Seven franchises have NO stock. Seeded active they would each be
3138
+ * a card opening an empty shop; omitted entirely, seventeen
3139
+ * CharacterHotspot links stay 404. Both failure modes look fine
3140
+ * from one page.
3141
+ * 4. Every bundle carries a placeholder cover image, so a collage
3142
+ * checked AFTER the cover would never render — and a card showing
3143
+ * one grey tile is not visibly broken.
3144
+ */
3145
+ pageKey: "category-tabs-franchise-bundles",
3146
+ pageLabel: "Categories index tabs, the franchise unit and the bundle collage",
3147
+ href: "/categories",
3148
+ cases: [
3149
+ { key: "index-shows-roots-only", label: "The Categories tab lists the six roots and NO deeper category" },
3150
+ { key: "five-tabs-no-all", label: "There are exactly five tabs and none of them is 'All'" },
3151
+ { key: "parts-tab-is-leaves-only", label: "The Parts tab lists part leaves and NOT the 20 classification nodes" },
3152
+ { key: "tabs-do-not-overlap", label: "No single row appears on two tabs" },
3153
+ { key: "franchise-index-hides-unstocked", label: "The franchise index shows only stocked franchises, not all eight" },
3154
+ { key: "unstocked-franchise-page-resolves", label: "An unstocked franchise page loads and says so, rather than 404ing or showing an empty grid" },
3155
+ { key: "franchise-detail-lists-its-products", label: "The Beyblade franchise page lists its listings, with a nonsense slug as the control" },
3156
+ { key: "bundle-card-shows-a-collage", label: "A bundle card shows a collage of its members, not its placeholder cover" },
3157
+ ],
3158
+ },
3122
3159
  {
3123
3160
  /*
3124
3161
  * Store reviews. The endpoint answered 200 with zero reviews for EVERY
@@ -3450,13 +3487,13 @@ const rawTesterChecklistItems = [
3450
3487
  cases: [
3451
3488
  {
3452
3489
  key: "tier-depth-reachable",
3453
- label: "The category tree is four tiers deep and every tier is reachable by clicking down from a root",
3454
- description: "Two roots exist — Spinning Tops and Living Collectibles. Walk one of them all the way to a leaf without typing a URL.",
3490
+ label: "The category tree is five tiers deep and every tier is reachable by clicking down from a root",
3491
+ description: "Six roots exist — Spinning Tops, Trading Cards, Collectible Figures, Hot Wheels, Model Kits, Living Collectibles. Walk one of them all the way to a leaf without typing a URL.",
3455
3492
  href: "/categories",
3456
3493
  },
3457
3494
  {
3458
3495
  key: "second-root-reachable",
3459
- label: "Both category roots appear on the categories index, not just the Beyblade one",
3496
+ label: "Every category root appears on the categories index, not just the Beyblade one",
3460
3497
  description: "BEFORE: the tree had ONE root and TWO tiers, so the live-item listings carried no category at all and were unreachable from every category and brand page.",
3461
3498
  href: "/categories",
3462
3499
  },
@@ -3855,6 +3892,123 @@ const rawTesterChecklistItems = [
3855
3892
  },
3856
3893
  ],
3857
3894
  },
3895
+ {
3896
+ pageKey: "action-bar-placement",
3897
+ pageLabel: "Action Bar & Back-to-Top — Desktop vs Mobile",
3898
+ href: "/products",
3899
+ cases: [
3900
+ {
3901
+ key: "back-to-top-dismiss-visible",
3902
+ label: "The small ✕ beside the back-to-top button actually shows a ✕ — not an empty outlined pill",
3903
+ description: "Fixed 2026-10-15. BEFORE: the dismiss control was a `<Button size=\"sm\">` forced to 24px wide, but that size carries 12px of padding on each side — so the content box was exactly 0px and the ✕ glyph shrank to nothing. The button was there and clickable; the icon was invisible. AFTER: scroll any long page past ~400px. Two round controls appear in the corner: a large one with an up-chevron, and a small one with a clearly visible ✕. Clicking the ✕ hides both until you navigate to another page.",
3904
+ href: "/products",
3905
+ },
3906
+ {
3907
+ key: "action-bar-top-on-desktop",
3908
+ label: "ON DESKTOP (window wider than ~1024px): the page action bar sits directly UNDER the header, not welded to the bottom of the window",
3909
+ description: "Changed 2026-10-15. BEFORE: the same full-width bar was pinned to the bottom edge on every screen size — a mobile pattern on a desktop window, where it reads as a browser download bar and sits as far from the content as possible. AFTER: maximise the window and open a product detail page (or any admin list and tick a row to enter bulk mode). The bar must appear immediately below the site header, full width, with its shadow falling DOWNWARD onto the page.",
3910
+ href: "/products",
3911
+ },
3912
+ {
3913
+ key: "action-bar-bottom-on-mobile",
3914
+ label: "ON MOBILE (narrow window): the same action bar is still at the BOTTOM, stacked directly above the bottom tab bar",
3915
+ description: "The other half of the change, and the real regression risk — the two layouts share one component. Narrow the browser to phone width (or use device emulation) on the same page. The bar must be at the bottom, immediately above the bottom navigation, with its shadow falling UPWARD. Resize the window slowly across the ~1024px line both ways: the bar must move cleanly between the two positions and never appear in both places or in neither.",
3916
+ href: "/products",
3917
+ },
3918
+ {
3919
+ key: "action-bar-no-content-overlap",
3920
+ label: "ON DESKTOP: the top action bar never covers the first rows of page content, and leaves no empty gap when it is absent",
3921
+ description: "The bar is fixed, so the page reserves space for it. Two checks. (1) With the bar showing, the first heading/row of content must be fully readable, not hidden behind it. (2) On a page with NO action bar, there must be no blank band under the header — the reservation collapses to zero when nothing is published.",
3922
+ href: "/products",
3923
+ },
3924
+ {
3925
+ key: "action-bar-panels-open-into-screen",
3926
+ label: "Expandable panels on the action bar open INTO the screen — downward on desktop, upward on mobile",
3927
+ description: "On desktop, open an admin list, tick two rows to enter bulk mode, then open the action-type picker: it must expand DOWNWARD over the page. Repeat at phone width: it must expand UPWARD. A panel that opens off-screen is unusable, and the direction has to follow whichever edge the bar is attached to.",
3928
+ href: "/admin/products",
3929
+ },
3930
+ {
3931
+ key: "back-to-top-clears-the-bar",
3932
+ label: "The back-to-top button never overlaps the action bar or the bottom tab bar at any window width",
3933
+ description: "On mobile the button floats above whatever is stacked at the bottom edge; on desktop the bar is at the top so the button should sit lower. Scroll a long page at phone width with an action bar showing — the button must sit clear above it. Widen to desktop: the button must move down as the bottom tier empties, with no overlap at any point during the resize.",
3934
+ href: "/products",
3935
+ },
3936
+ ],
3937
+ },
3938
+ {
3939
+ pageKey: "feature-badge-picker",
3940
+ pageLabel: "Feature Badges — Searchable Picker",
3941
+ href: "/store/products",
3942
+ cases: [
3943
+ {
3944
+ key: "features-are-searchable",
3945
+ label: "The product form's Feature badges control is a SEARCHABLE dropdown, not a long grid of checkboxes",
3946
+ description: "Changed 2026-10-15. BEFORE: every eligible badge rendered as a bordered checkbox tile in a two-column grid — a wall a seller had to read end-to-end, which grew every time an admin added a badge. AFTER: as a seller, open any product for editing and find 'Feature badges'. It must be a single control that opens a searchable list. Type part of a badge name and confirm the list narrows.",
3947
+ href: "/store/products",
3948
+ },
3949
+ {
3950
+ key: "features-search-matches-description",
3951
+ label: "Searching the badge picker matches a badge's DESCRIPTION, not only its name",
3952
+ description: "The description is folded into each option so it stays searchable. Open the picker and type a word that appears only in a badge's description (e.g. 'factory', which is in Sealed's description but not its label). That badge must still appear in the filtered list.",
3953
+ href: "/store/products",
3954
+ },
3955
+ {
3956
+ key: "features-scope-is-visible",
3957
+ label: "Each badge option says whether it is a platform badge or one of your own store's",
3958
+ description: "The old grid showed two separate headings. A flat searchable list has none, so the scope rides in the option text — every option must end with '(platform)' or '(your store)', and the selected chips must keep that distinction too.",
3959
+ href: "/store/products",
3960
+ },
3961
+ {
3962
+ key: "features-respects-the-cap",
3963
+ label: "Selecting more than the allowed number of badges is prevented, and an over-limit product loads without blocking save",
3964
+ description: "Select badges until you hit the stated limit ('Selected: N of 24'), then try to select one more — the selection must not exceed the cap. This replaced a mechanism that disabled every unticked checkbox at the limit, so confirm the control still communicates that you are full rather than silently ignoring clicks.",
3965
+ href: "/store/products",
3966
+ },
3967
+ {
3968
+ key: "features-inline-create",
3969
+ label: "A seller can create a NEW store badge from inside the picker, and it is immediately selectable",
3970
+ description: "Added 2026-10-15. As a seller, open the badge picker and use 'Create a badge for my store'. Fill in a label and icon and submit. The drawer must close, the new badge must appear as a selected chip, and reopening the picker must list it as a real option marked '(your store)' — not a one-off chip that disappears on reload. Reload the page and confirm it persisted.",
3971
+ href: "/store/products",
3972
+ },
3973
+ ],
3974
+ },
3975
+ {
3976
+ pageKey: "rich-text-readability",
3977
+ pageLabel: "Admin-Authored Rich Text — Readability in Both Themes",
3978
+ href: "/categories/category-spinning-tops",
3979
+ cases: [
3980
+ {
3981
+ key: "prose-body-readable-dark",
3982
+ label: "IN DARK MODE: the paragraphs of a category's own write-up are clearly readable — not a dim grey that disappears into the page background",
3983
+ description: "Fixed 2026-10-15. BEFORE: every rich-text block on the site rendered the LIGHT-theme prose palette in dark mode — body text at gray-700 — because `dark:prose-invert` has never compiled in this project (the consumer Tailwind build is told `@source not \"../../appkit\"`, and appkit's own build has no typography plugin). AFTER: switch to DARK mode, open /categories/category-spinning-tops and read the four-paragraph write-up under the hero. Every sentence must be comfortably readable at arm's length. A paragraph you have to lean in for is still a bug.",
3984
+ href: "/categories/category-spinning-tops",
3985
+ },
3986
+ {
3987
+ key: "prose-links-visible-dark",
3988
+ label: "IN DARK MODE: links inside that write-up (Beyblade Original, Metal Fight, Burst, Beyblade X, Accessories) are visibly a different colour from the surrounding text and are obviously clickable",
3989
+ description: "The worst half of the same bug, and the one a reader notices first. BEFORE: prose links resolved to gray-900 — near-black on a dark page — so they were effectively invisible; you could only find them by sweeping the mouse for the cursor change. AFTER: each link must read as a link WITHOUT hovering. Check all five in the body copy. Underline alone is not enough: the text colour must differ from the paragraph around it.",
3990
+ href: "/categories/category-spinning-tops",
3991
+ },
3992
+ {
3993
+ key: "prose-readable-light-regression",
3994
+ label: "IN LIGHT MODE: the same write-up and its links are still correct — fixing dark mode must not have broken light mode",
3995
+ description: "A real risk, not a formality: the fix rebinds the prose colour palette to theme tokens, so both themes now come from one place and a mistake affects both. Toggle light/dark a few times on this page. Headings must stay darker than body text, and links must stay distinguishable in BOTH.",
3996
+ href: "/categories/category-spinning-tops",
3997
+ },
3998
+ {
3999
+ key: "prose-readable-across-surfaces",
4000
+ label: "The same readability holds on every other admin-authored rich-text surface — a blog post, a policy page, an FAQ answer and a product description",
4001
+ description: "This was never a category-page bug; ~25 surfaces share one renderer. In DARK mode check: a post under /blog, /terms (or /privacy), an expanded answer on /faqs, and the Description tab of any product. Each must have readable body copy and visible links. One unreadable surface here means the shared fix did not reach it.",
4002
+ href: "/blog",
4003
+ },
4004
+ {
4005
+ key: "prose-follows-custom-theme",
4006
+ label: "Rich-text body copy follows an admin-authored CUSTOM theme, not a fixed grey",
4007
+ description: "Added with the 2026-10-15 fix, and only possible because of it: the old prose palette was hardcoded Tailwind greys that no theme could reach. As admin, open Site Settings → Themes, switch the active theme (e.g. to Cobalt Night or Sunset), then reload a category page with a write-up. The paragraph and link colours must shift with the theme rather than staying the same grey.",
4008
+ href: "/admin/site",
4009
+ },
4010
+ ],
4011
+ },
3858
4012
  {
3859
4013
  pageKey: "status-badge-legibility",
3860
4014
  pageLabel: "Listing Tags & Status Chips — Light vs Dark Mode",