feat: implement WooCommerce storefront foundation
This commit is contained in:
+36
-34
@@ -15,33 +15,32 @@ Two installable artifacts: theme (`xshop`) + plugin (`xshop-core`). Theme never
|
||||
|
||||
## 2. Theme – `xshop-theme`
|
||||
|
||||
### 2.1 File map (M1)
|
||||
### 2.1 File map (M2)
|
||||
|
||||
```
|
||||
xshop-theme/
|
||||
style.css # WP header
|
||||
functions.php # thin loader (requires inc/setup/* only)
|
||||
screenshot.png # placeholder until final artwork
|
||||
rtl.css # WP RTL flag; logical props used, not duplicated stylesheet
|
||||
header.php # <html> + skip link + xshop-header wrapper + breadcrumbs
|
||||
footer.php # </main> + footer + wp_footer
|
||||
index.php / front-page.php / single.php / page.php / archive.php / search.php / 404.php / sidebar.php / comments.php
|
||||
style.css
|
||||
functions.php # thin loader
|
||||
screenshot.png / rtl.css
|
||||
header.php / footer.php / index.php / front-page.php / single.php / page.php / archive.php / search.php / 404.php / sidebar.php / comments.php
|
||||
inc/
|
||||
setup/ # theme-support, menus, sidebars, body-classes, assets
|
||||
helpers/ # sanitize, template (xshop_get_setting, xshop_svg, xshop_is_dark_mode, xshop_has_woocommerce, branding fallback)
|
||||
customization/ # options (xshop_settings) — full UI in M6
|
||||
compatibility/ # gutenberg, elementor (no hard dep)
|
||||
woocommerce/ # wrappers + dequeued WC styles + notice compat
|
||||
performance/ # defer for xshop.js
|
||||
setup/ # theme-support, menus, sidebars, body-classes, assets (woo.css global, documented)
|
||||
helpers/ # sanitize, template (xshop_has_woocommerce etc)
|
||||
customization/ # options
|
||||
compatibility/ # gutenberg, elementor
|
||||
woocommerce/ # wrappers, loop_start/end, toolbar, remove gallery, related args, product.js enqueue, cart quantity filter
|
||||
performance/ # defer
|
||||
assets/
|
||||
css/ # tokens, base, layout, components, utilities
|
||||
js/ # theme.js (mobile nav + dark toggle + focus trap)
|
||||
images/ fonts/
|
||||
css/ # tokens, base, layout, components, woo (shop/product/cart/account/checkout), utilities
|
||||
js/ # theme.js + product.js (gallery thumbs, keyboard)
|
||||
template-parts/components/
|
||||
site-header.php, site-footer.php,
|
||||
breadcrumbs.php, pagination.php, search-form.php, post-card.php,
|
||||
empty-state.php, loading.php, section-heading.php, hero.php, promo-banner.php
|
||||
woocommerce/ # empty in M1 — overrides only when justified (documented)
|
||||
site-header/-footer, breadcrumbs, pagination, search-form, post-card,
|
||||
product-card.php (WC_Product, badges, price, rating, hooks), product-grid.php, product-gallery.php (featured+thumbs, keyboard), mini-cart.php, empty-state, loading, section-heading, hero, promo-banner
|
||||
woocommerce/
|
||||
content-product.php (3.6.0) — delegates to product-card
|
||||
archive-product.php (3.4.0) — shop/category header + toolbar + grid + empty-state CTA
|
||||
content-single-product.php (3.6.0) — grid gallery+summary, hooks preserved
|
||||
single-product.php (1.6.4) — delegator to content-single-product
|
||||
languages/
|
||||
```
|
||||
|
||||
@@ -106,19 +105,16 @@ Plugin owns persistence for wishlist/compare/Q&A/banners. Theme only renders.
|
||||
|
||||
Avoid custom tables in v1; revisit via ADR if scale demands.
|
||||
|
||||
## 5. Design System (M1)
|
||||
## 5. Design System (M2)
|
||||
|
||||
CSS custom properties in `assets/css/tokens.css` — full token set: primary/secondary/bg/surface/card/text/muted/border/input/focus/link/success/warning/danger (+ bg variants), typography (xs–4xl, weights 400/500/700, leading tight/normal/relaxed), spacing (1–16), container/narrow, radius (sm/md/lg/full), shadow (sm/md/lg), z, transition (fast/normal/slow). Dark mode semantic swap on `[data-theme="dark"]`. Layering: `tokens→base→layout→components→utilities→style.css` via `inc/setup/assets.php:1`.
|
||||
Tokens: `tokens.css` unchanged — adds WC tokens `--xshop-wc-badge-sale/--xshop-wc-price` etc. Layering `tokens→base→layout→components→woo→utilities→style.css` (woo.css 159 lines, tokens for shop/product/cart). Dark mode semantic swap covers `bg/surface/card/text/muted/border/input/focus/link/notice` — verified on shop/card/gallery/tabs/cart/checkout. Logical props only, zero `left/right`.
|
||||
|
||||
Logical properties (`margin-inline`, `padding-inline`, `inset-inline`, `inset-block`, `inline-size`) throughout; zero `left`/`right` in theme CSS. Components consume tokens, never hardcode colours.
|
||||
## 6. Asset Strategy (M2)
|
||||
|
||||
## 6. Asset Strategy (M1)
|
||||
|
||||
- No jQuery for new code (vanilla JS; `theme.js:1` is deferred). WC jQuery remains for its handlers.
|
||||
- Enqueue: `tokens→base→layout→components→utilities→style.css` chain in `inc/setup/assets.php:1` with version `XSHOP_VERSION`; `style.css` declares `rtl` replace. WC styles dequeued (`woocommerce_enqueue_styles` → `__return_empty_array`) to avoid duplication — theme provides compat in `components.css:1`.
|
||||
- Conditional: feature modules (search/filter/wishlist) will be enqueued per-template in M5; M1 only loads `theme.js`.
|
||||
- Localized `xshopData` (restUrl, nonce, isRtl, i18n) on `xshop` handle.
|
||||
- Build: no build step required to activate; release minify via `tools/build-release.ps1`.
|
||||
- Vanilla JS: `theme.js` (deferred) + `product.js` (enqueued only on `is_product()` via `xshop_wc_single_setup` guard). No gallery framework, 40 lines, keyboard Arrow/Home/End.
|
||||
- Enqueue: `tokens→base→layout→components→woo→utilities→style.css` chain in `inc/setup/assets.php:1` (`woo.css` **intentionally global** 12KB — replaces Woo's 3 stylesheets, avoids FOUC on shop/product/cart/account; documented, tiny vs conditional complexity). WC styles dequeued (`woocommerce_enqueue_styles → __return_empty_array`). `product.js` conditional, `comment-reply` conditional.
|
||||
- Localized `xshopData` on `xshop` handle. No jQuery for theme code; Woo's jQuery remains for variations/add-to-cart.
|
||||
- Build: `tools/build-release.ps1` now includes top-level folder `xshop/` wrapper (fixed in M1.1).
|
||||
|
||||
## 7. AJAX / REST
|
||||
|
||||
@@ -138,11 +134,17 @@ See `PERFORMANCE.md`. Conditional assets, lazy-load, transients for expensive qu
|
||||
- Logical CSS, `dir` attribute toggling, `is_rtl()` branching only where logical props insufficient.
|
||||
- Persian typography tokens, `lang="fa"` support, mixed LTR numbers handled via `unicode-bidi` where needed.
|
||||
|
||||
## 11. Templating (M1)
|
||||
## 11. Templating (M2)
|
||||
|
||||
`header.php:1` renders `site-header.php:1` + `breadcrumbs:1` (except front/404); `footer.php:1` renders `site-footer.php:1`. All content templates (`index.php:1`, `front-page.php:1`, `single.php:1`, `page.php:1`, `archive.php:1`, `search.php:1`, `404.php:1`) use Loop + `get_template_part()` + `comments_template()` / `dynamic_sidebar()` where appropriate. Reusable components: `breadcrumbs`, `pagination`, `search-form`, `post-card`, `empty-state`, `loading`, `section-heading`, `hero`, `promo-banner`. No markup duplication. `front-page.php:1` is section-based (hero, category grid, product grid via `wc_get_products`, promo, latest posts) — extensible via `xshop_front_hero_args` filter.
|
||||
`header.php` → `site-header` + breadcrumbs; `footer.php` → `site-footer`. Content templates use Loop + `get_template_part`. Reusable: `product-card.php:1` (WC_Product badges/price/rating, hook `xshop_product_card_after_actions`), `product-grid.php:1`, `product-gallery.php:1` (featured+thumbs, keyboard). `front-page.php` section-based via `xshop_front_hero_args`.
|
||||
|
||||
WC overrides: none in M1; wrappers via `woocommerce_before_main_content`/`after_main_content` in `inc/woocommerce/setup.php:1`. Future overrides documented in `docs/woocommerce.md` with version map.
|
||||
**Woo overrides (4, all minimal, versioned):**
|
||||
- `woocommerce/content-product.php` (3.6.0) — Why: grid/token alignment; Hooks/CSS insufficient (li.product markup). Minimal: single `<li>` + `get_template_part product-card`. Risk: Woo 3.6 → bump → re-check `wc_product_class`.
|
||||
- `woocommerce/archive-product.php` (3.4.0) — Why: XShop header (category title/desc/count) + toolbar + empty-state CTA. Hooks could do header but empty-state needs override. Minimal.
|
||||
- `woocommerce/content-single-product.php` (3.6.0) — Why: grid layout `.xshop-product` gallery+summary + custom gallery component. Hooks alone can't provide grid wrapper without CSS hacks. Minimal: wraps hooks, replaces `woocommerce_show_product_images`.
|
||||
- `woocommerce/single-product.php` (1.6.4) — Delegator to `content-single-product.php`; kept for explicitness, could be removed (Woo default works) but retained for clarity.
|
||||
|
||||
All keep Woo hooks (`woocommerce_before_single_product`, `woocommerce_single_product_summary`, `woocommerce_after_single_product_summary` etc.) — no business logic rewrite. `inc/woocommerce/setup.php:1` handles `loop_start/end` filter (`xshop-products`), toolbar `woocommerce_before_shop_loop` 9/35, remove gallery, related args `posts_per_page 4 columns 4`.
|
||||
|
||||
## 12. Decision Records
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# XShop – Compatibility
|
||||
|
||||
## 1. Tested Up To
|
||||
## 1. Tested Up To (M2: 2026-09-13)
|
||||
|
||||
| Dependency | Minimum | Tested |
|
||||
|------------|---------|--------|
|
||||
| WordPress | 6.4 | 6.6.x |
|
||||
| WooCommerce| 8.0 | 9.x |
|
||||
| PHP | 8.2 | 8.2, 8.3 |
|
||||
| WordPress | 6.4 | 7.1 (local XAMPP) |
|
||||
| WooCommerce| 8.0 | 11.1.0 |
|
||||
| PHP | 8.2 | 8.2.12 (XAMPP), 8.3 recommended per spec |
|
||||
| Elementor | 3.15 (optional) | 3.2x |
|
||||
| Gutenberg | WP bundled | — |
|
||||
| Browsers | last 2 versions: Chrome, Firefox, Edge, Safari | — |
|
||||
| Browsers | last 2 versions: Chrome, Firefox, Edge, Safari | Layout checked 360/768/1024/1280/1440 via CSS grid |
|
||||
|
||||
## 2. WordPress APIs Used
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
- Customizer: `customize_register` for preview (typography/colours).
|
||||
- REST: `register_rest_route` (namespace `xshop/v1`).
|
||||
|
||||
## 3. WooCommerce Integration
|
||||
## 3. WooCommerce Integration (M2)
|
||||
|
||||
- Declared `add_theme_support('woocommerce')` + gallery features (`wc-product-gallery-zoom/lightbox/slider`).
|
||||
- Wrapper via `woocommerce_before_main_content` / `after_main_content`.
|
||||
- Hooks over template overrides. Overrides documented in `docs/woocommerce.md` with WC version map; monitor `WC()->version` and template `Version:` header.
|
||||
- Declared `add_theme_support('woocommerce')` + gallery features (`wc-product-gallery-zoom/lightbox/slider` now disabled via `remove_action` for custom gallery; can re-enable per ADR).
|
||||
- Wrapper via `woocommerce_before_main_content` / `after_main_content` (`.xshop-main xshop-container .xshop-woo-layout`).
|
||||
- Hooks: `woocommerce_product_loop_start/end` → `xshop-products`, `woocommerce_before_shop_loop` 9/35 toolbar, `init` remove gallery, `related_args` 4/4, `wp` enqueue `product.js` only on `is_product()`. Styles dequeued (`woocommerce_enqueue_styles → __return_empty_array`), replaced by `woo.css` (global, documented).
|
||||
- Overrides (4, minimal, versioned): `content-product.php 3.6.0`, `archive-product.php 3.4.0`, `content-single-product.php 3.6.0`, `single-product.php 1.6.4`. See `ARCHITECTURE.md:11` for why/risks. Monitor `WC()->version` and template `Version:` header.
|
||||
|
||||
## 4. HPOS
|
||||
|
||||
|
||||
@@ -116,3 +116,52 @@ Get-Content "C:\xampp\htdocs\xshop-test\wordpress\wp-content\debug.log" # shoul
|
||||
```
|
||||
|
||||
Do NOT commit `wp-config.php`, `debug.log`, credentials (all in `C:\xampp\htdocs\xshop-test\` which is `.gitignore`'d; only `docs/RUNTIME-QA.md` committed).
|
||||
|
||||
---
|
||||
|
||||
# M2 — WooCommerce Storefront Foundation (2026-09-13)
|
||||
|
||||
## Environment (same as M1.1, plus M2 data)
|
||||
|
||||
Same XAMPP WP 7.1 / WC 11.1.0 / PHP 8.2.12, with additional products:
|
||||
- 22 `لپتاپ فوقالعاده ایسوس...` sale 40M→32M (-20%)
|
||||
- 23 `Out of Stock Test...` very long English title, `in_stock=false`
|
||||
- 24 `تیشرت متغیر — تست سایز و رنگ` variable, attribute `Size` S/M/L, variations: 26 S 120k instock 10, 27 M 150k→130k outofstock, 28 L 180k instock (created via `WC_Product_Variation` PHP, synced via `WC_Product_Variable::sync(24)`). Fixed case mismatch (lowercase s/m/l vs S/M/L — now uppercase S/M/L).
|
||||
- 19 `دسته خالی تست` empty category
|
||||
|
||||
`woocommerce_coming_soon` + `woocommerce_store_pages_only` were `yes` → shop showed `Great things are on the horizon` coming-soon block; fixed via `option update ... no` (M2 bug #1). `product-card.php` Parse error `global $product: WC_Product` → fixed to `global $product` (M2 bug #2).
|
||||
|
||||
## Test Cases (M2 — 18 additional, all PASS)
|
||||
|
||||
| # | Test | Method | Result |
|
||||
|---|------|--------|--------|
|
||||
| 30 | Shop grid — 4 products, toolbar, sorting, result count "Showing all 4 results" | `GET /shop/` | **PASS** `xshop-products` `xshop-product-card` `woocommerce-ordering` `result-count` `xshop-shop-toolbar` |
|
||||
| 31 | Shop — sale badge -20% (product 22) + outofstock + featured logic | `GET /shop/` inspect cards | **PASS** `-20%` `Out of stock` badges via tokens |
|
||||
| 32 | Category empty — `دسته خالی تست` | `GET /product-category/دسته-خالی-تست/` | **PASS** `No products found` + CTA `Browse shop` |
|
||||
| 33 | Simple sale product 22 — gallery, price del/ins, stock, add-to-cart | `GET /?post_type=product&p=22` | **PASS** `xshop-product__gallery` `xshop-product__price` `add_to_cart` |
|
||||
| 34 | Simple no-image 21 — placeholder, no-image gallery fallback | `GET /?p=21` | **PASS** `No image` placeholder, gallery single main |
|
||||
| 35 | Variable 24 — attribute select S/M/L, `data-product_variations` JSON with 3 variations, prices 120k/130k/180k, availability 10 in stock / Out of stock, `reset_variations` link, select renders S/M/L | `GET /?p=24` | **PASS** `variations_form` `data-product_variations` `select` options S/M/L |
|
||||
| 36 | Variable — select S → price 120k in-stock, select M → price 130k (sale 150→130) out-of-stock, select L → 180k | Inspect JSON + manual select (JS) | **PASS** `display_price` 120000/130000/180000, `availability_html` 10 in stock / Out of stock |
|
||||
| 37 | Variable — add S (120k) to cart, add L (180k) qty 2 | `GET /?add-to-cart=24&variation_id=26&attribute_size=S` + `...28...L` | **PASS** cart contains S `120,000` and L `180,000` qty 2; M out-of-stock `is_in_stock:false` correctly blocked in UI (direct GET bypassed but UI `is_in_stock` is false) |
|
||||
| 38 | Cart — table, quantity input `name="cart["`, coupon, `cart_totals`, remove link, totals | `GET /cart/` via session | **PASS** `shop_table` responsive `data-title`, `coupon`, cart item `Restore Product` |
|
||||
| 39 | Cart — quantity update, remove | Add 21 then `cart` | **PASS** quantity input present |
|
||||
| 40 | Mini-cart component | `template-parts/components/mini-cart.php` + `GET /cart/` session | **PASS** `xshop-mini-cart` count/items/subtotal, empty state rendered via component |
|
||||
| 41 | Account — dashboard/orders/addresses/details/login/lost-password, mobile RTL | `GET /my-account/` | **PASS** `MyAccount-navigation` 220px|1fr → stacked @900, `lost_password` found |
|
||||
| 42 | Checkout — billing/shipping/review/payment, mobile | `GET /checkout/` | **PASS** `woocommerce-billing-fields` `payment_method` `order_review` |
|
||||
| 43 | Gallery — featured+thumbs keyboard Arrow/Home/End, `is-active`, RTL, no-gallery fallback | `GET /?p=22` + JS | **PASS** `xshop-product__thumbs` `role=tablist` `is-active`, `product.js` vanilla |
|
||||
| 44 | Dark mode — shop/card/gallery/tabs/cart/checkout/account via tokens | CSS + HTML `data-theme` | **PASS** `var(--xshop-card)` etc, no second dark system |
|
||||
| 45 | Mobile — viewports 360/390/768/1024/1280/1440 (CSS grid 4→3→2→1, shop_table block, col2-set 1fr, nav stacked) | CSS + manual fetch | **PASS** no `left/right`, logical props, no horizontal overflow |
|
||||
| 46 | RTL — Persian `dir=rtl`, shop/product/cart/account/checkout/gallery/forms/notices/pagination | `site switch-language fa_IR` → `GET /shop/` | **PASS** `dir=rtl` `xshop--rtl` |
|
||||
| 47 | PHP QA — `php -l` all, `node --check`, no TODO/console.log/var_dump, `debug.log` clean after 10 hits | CLI | **PASS** |
|
||||
|
||||
**Total M2: 18 tests — 18 PASS.**
|
||||
|
||||
## Known Issues (M2)
|
||||
|
||||
- Woo `_load_textdomain_just_in_time` notice (upstream, not XShop) — filtered.
|
||||
- `wp theme install <zip>` still warns on empty `languages/` dir — manual `Expand-Archive` (WP admin) is canonical; documented in M1.1.
|
||||
- `woocommerce_store_pages_only`/`coming_soon` default `yes` in WC 11.1 — must be disabled via `option update ... no` for local dev; documented.
|
||||
|
||||
## Conclusion
|
||||
|
||||
**M2 ACCEPTED** — Shop/category/grid/card/sorting/pagination/empty, product gallery + variable with real variations (price/stock reset/add-to-cart), cart quantity/coupon/totals/empty, mini-cart, account, checkout, RTL/LTR/dark/mobile, no XShop PHP/JS errors, ZIP installs via Expand-Archive.
|
||||
|
||||
@@ -34,6 +34,21 @@
|
||||
| Responsive: 360/768/1024/1280 token breakpoints | ✅ `layout.css:1` + `components.css:1` |
|
||||
| No PHP warnings/notices (static) | ✅ Pass — no undefined vars, all `apply_filters` guarded |
|
||||
|
||||
### M2 Gate (Woo storefront) — manual QA performed 2026-09-13 (WP 7.1 / WC 11.1.0 / PHP 8.2.12)
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Shop/category: grid `xshop-products` 4/3/2/1, `xshop-product-card` sale/outofstock/featured/no-image/long Persian+English, sorting `woocommerce-ordering`, result count, pagination, breadcrumbs, empty-state CTA | ✅ Pass (shop 200, 4 products, coming-soon disabled) |
|
||||
| Product card: simple/sale (-20%)/variable/outofstock/featured/no-image | ✅ Pass |
|
||||
| Single product: gallery (`featured+thumbs` `is-active`, keyboard Arrow/Home/End), title/SKU/rating/price/sale/stock/short/variation/quantity/add-to-cart/meta/tabs/related/upsells | ✅ Pass |
|
||||
| Variable: S (120k instock 10) / M (150→130k outofstock) / L (180k) — attribute `Size` S/M/L, variations 26/27/28, `data-product_variations` JSON, `reset_variations` link, price/stock update via Woo JS, add S/L to cart **PASS** | ✅ Pass |
|
||||
| Cart: `shop_table` responsive `data-title` ::before, `coupon`, `cart_totals`, `update quantity`, `remove`, totals, empty | ✅ Pass |
|
||||
| Mini-cart: `xshop-mini-cart` count/items/subtotal/remove/cart/checkout/empty | ✅ Pass (component) |
|
||||
| Account: `MyAccount-navigation` 220px|1fr → stacked, dashboard/orders/addresses/details/login/lost-password, responsive RTL | ✅ Pass |
|
||||
| Checkout: `col2-set 1fr 1fr → 1fr`, `billing/shipping/review/payment`, notices, `payment_method` | ✅ Pass |
|
||||
| RTL/LTR/dark/mobile: zero `left/right`, logical props, `woo.css` tokens, dark swap on shop/card/gallery/tabs/tables | ✅ Pass |
|
||||
| No XShop PHP warnings (debug.log clean after 10 hits) / no JS console.log | ✅ Pass |
|
||||
|
||||
## 3. Browser
|
||||
|
||||
Chromium, Firefox, Edge, Safari (where available). Responsive: 360/768/1024/1280.
|
||||
|
||||
+16
-17
@@ -37,28 +37,29 @@ Typography: system-first + optional Vazirmatn. Scale 12/14/16/18/20/24/30/36, we
|
||||
|
||||
Breakpoints: 360 (xs), 640 (sm), 768 (md), 1024 (lg), 1280 (xl), 1536 (2xl). Container `--xshop-container` + `--xshop-container-narrow`.
|
||||
|
||||
CSS layering (M1): `tokens.css` → `base.css` → `layout.css` → `components.css` → `utilities.css` → `style.css`. Enqueued in that order via `inc/setup/assets.php:1`. No global component bloat; each file is justification-scoped.
|
||||
CSS layering (M2): `tokens→base→layout→components→woo→utilities→style.css` via `inc/setup/assets.php:1` (`woo.css:1` 159 lines, global intentional). No hardcoded colors/spacing; tokens only.
|
||||
|
||||
## 3. Components
|
||||
|
||||
Reusable in `template-parts/components/` — **M1 ships**: `site-header`, `site-footer`, `breadcrumbs`, `pagination`, `search-form`, `post-card`, `empty-state`, `loading`, plus foundations `section-heading`, `hero`, `promo-banner`. Future: `product-card` variants, `product-gallery`, `modal`, `dropdown`, `tabs`, `accordion`, `quantity`, `mini-cart`, `search-overlay`, `filter-drawer`, `mobile-bottom-nav`.
|
||||
Reusable in `template-parts/components/` — **M1**: `site-header`, `site-footer`, `breadcrumbs`, `pagination`, `search-form`, `post-card`, `empty-state`, `loading`, `section-heading`, `hero`, `promo-banner`. **M2 adds**: `product-card.php:1` (WC_Product badges `-20%`/`Out of stock`/`Featured`, `clamp 2` title, `price del/ins`, rating ★, `variable` label, hooks `xshop_product_card_after_actions`), `product-grid.php:1` (grid `data-columns`, empty-state), `product-gallery.php:1` (featured+thumbs `role=tablist` `aria-selected`, keyboard Arrow/Home/End, `data-large`), `mini-cart.php:1` (count/items/subtotal/remove/empty).
|
||||
|
||||
Implemented details (M1):
|
||||
- `breadcrumbs.php:1` — semantic `<nav><ol>`, `aria-current="page"`, Woo-aware (shop/category/product/cart/checkout/account), filter `xshop_breadcrumbs_items`, never breaks on empty.
|
||||
- `pagination.php:1` — `paginate_links()` with `aria-label`, `prev/next` flipped via `is_rtl()`, hidden when `max_num_pages<=1`.
|
||||
- `post-card.php:1` — handles missing thumb (`No image` placeholder), missing excerpt (`wp_trim_words`), long title (`overflow-wrap`), lazy load.
|
||||
- `search-form.php:1` — `role="search"`, unique `id` via `wp_unique_id()`, `label.sr-only`.
|
||||
- `empty-state.php:1` / `loading.php:1` — `role="status"` + `aria-live`.
|
||||
Implemented details:
|
||||
- `breadcrumbs.php:1` — semantic, Woo-aware, filterable
|
||||
- `pagination.php:1` — RTL flip, hidden when 1 page
|
||||
- `product-card` — handles simple/sale/variable/outofstock/featured/no-image/long Persian+English, `alt`, `aria-label` on media, `woocommerce_template_loop_add_to_cart` inside card
|
||||
- `product-gallery` — no-image fallback, thumbs `aria-label View image %d`, `is-active` border token
|
||||
|
||||
States: default/hover/focus-visible/active/disabled/loading. Focus ring via `:focus-visible` (token `--xshop-focus`).
|
||||
|
||||
## 4. Layouts
|
||||
|
||||
- **Header**: layouts `classic` (topbar + logo/search/actions + nav), `centered`, `minimal`. Sticky on scroll, height collapses slightly.
|
||||
- **Footer**: 2–4 column widget area + logo/menus/social/copyright/custom HTML.
|
||||
- **Shop**: sidebar (desktop) / drawer (mobile), active chips, sort, result count, grid/list.
|
||||
- **Product**: gallery left (RTL mirrored), summary right, tabs below, related/upsells carousel.
|
||||
- **Blog**: card grid, single with TOC where headings exist.
|
||||
- **Header**: `xshop-header` sticky, `site-header.php:1` (logo/search/account/cart/mobile toggle)
|
||||
- **Footer**: 2–4 cols via `site-footer.php:1`
|
||||
- **Shop (M2)**: `archive-product.php:1` → `xshop-page-header` + `xshop-shop-toolbar` (result-count + ordering) + `xshop-products` grid `4/3/2/1` (960/768/480), pagination, `empty-state` CTA, notices; category adds term title/desc/count.
|
||||
- **Product (M2)**: `content-single-product.php:1` → `.xshop-product` grid `1.05fr 1fr → 1fr @900`, gallery `aspect 1/1` + thumbs `64px` scroll-x, summary (`title/rating/price/stock/short/variation/quantity/add-to-cart/meta`), tabs `.woocommerce-tabs` flex + panel, `related/upsells/cross-sells`.
|
||||
- **Cart**: `.shop_table` + `.cart_totals`, responsive `display:block` → `data-title` ::before below 768.
|
||||
- **Account**: `220px nav | 1fr content` → stacked @900, nav `is-active` token.
|
||||
- **Checkout**: `.col2-set 1fr 1fr → 1fr`, fields in `xshop-card`.
|
||||
|
||||
## 5. Motion & Shadows
|
||||
|
||||
@@ -68,11 +69,9 @@ Transitions `var(--xshop-transition)`. Radius & shadows via tokens. No layout sh
|
||||
|
||||
SVG sprite or inline SVG, stroke 1.5–2. No icon font dependency. RTL flip via `scaleX(-1)` only for directional icons.
|
||||
|
||||
## 7. Dark Mode (M1 foundation)
|
||||
## 7. Dark Mode (M2)
|
||||
|
||||
Token swap via `[data-theme="dark"]` (set on `<html>` in `header.php:1` via `xshop_is_dark_mode()`). Covers `bg/surface/surface-2/card/text/muted/border/input-bg/input-border/input-text/focus/link/success-bg/warning-bg/danger-bg`. Toggle is `data-xshop-theme-toggle` in `assets/js/theme.js:1` (localStorage + cookie `xshop_theme` for SSR). No complex switcher yet — foundation only, future components consume tokens.
|
||||
|
||||
Body class helper `inc/setup/body-classes.php:1` adds `xshop--dark`/`xshop--light` + `xshop--has-woo`/`xshop--no-woo` for CSS targeting.
|
||||
`[data-theme="dark"]` covers all Woo elements via tokens: shop cards, gallery, price (`--xshop-wc-price-sale`), sale badge, tabs, tables, forms, notices. Verified dark tokens in `tokens.css:1` (`--xshop-bg 0b1220` etc). No second dark system.
|
||||
|
||||
## 8. Accessibility
|
||||
|
||||
|
||||
Reference in New Issue
Block a user