Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The Vite dev server auto-detects DDEV/Docker environments for proper HMR configu
│ └── views/ # Blade templates (128 files)
│ └── woocommerce/ # Full WooCommerce template overrides
├── languages/ # Translations (text domain: %theme_name%)
├── theme.json # WordPress design tokens (generated by Vite)
├── theme.json # Base settings; the build adds the design tokens
├── vite.config.js # Build configuration
└── routes.php # Theme routes (optional)
```
Expand All @@ -61,6 +61,26 @@ The Vite dev server auto-detects DDEV/Docker environments for proper HMR configu
- **Accessibility**: Semantic HTML, ARIA labels, keyboard navigation
- **i18n**: Fully translatable (French included)

## Design tokens

The design lives in the `@theme static` block of `resources/assets/css/app.css`:
colours, type scale, fonts and radii, with concrete values. `npm run build`
writes them into the `theme.json` the editor reads
(`public/build/theme/<slug>/assets/theme.json`), so the page and the editor
always offer the same palette and sizes.

- Change a token in `app.css`, not in `theme.json`: the root `theme.json` is
only the base (layout, editor settings), and a slug defined there wins over
`@theme`.
- To keep a value out of Tailwind, define that slug in `theme.json`, or turn a
whole family off in `vite.config.js` (`disableTailwindColors`,
`disableTailwindFontSizes`, `disableTailwindFonts`,
`disableTailwindBorderRadius`).
- Spacing and layout widths are not generated: set them in `theme.json`.

See [Theme.json and Vite Build Integration](https://pollora.dev/theming/theme-structure/)
for the details.

## Configuration

All theme behavior is driven by config files in `config/`:
Expand Down
15 changes: 6 additions & 9 deletions bin/tests/e2e/editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,15 @@ async function canvasColor(admin: { createNewPost: () => Promise<void> }, editor
);
}

test("the theme's palette reaches the editor canvas", async ({ admin, editor }) => {
expect(await canvasColor(admin, editor, 'red-500'), 'a scale colour of theme.json').not.toBe('');
test("the theme's palette reaches the editor canvas, and Tailwind's scale does not", async ({ admin, editor }) => {
expect(await canvasColor(admin, editor, 'surface'), 'a colour of the theme').not.toBe('');
// The palette once held Tailwind's whole default scale, some 290 colours, offered to authors.
expect(await canvasColor(admin, editor, 'red-500'), 'a colour of the Tailwind scale').toBe('');
});

test('the semantic colours of the palette have a value', async ({ admin, editor }) => {
// Known defect: theme.json declares primary as var(--wp--preset--color--primary, #1f2937),
// a variable defined as itself, which CSS discards as a cycle. The same holds for accent,
// foreground, muted, subtle, surface, surface-alt, outline, ring and primary-hover: a block
// coloured "Primary" gets a transparent background, in the editor and on the page.
// This passes, and is reported as such, once the palette resolves.
test.fail(true, 'theme.json semantic colours reference themselves');

// theme.json once declared primary as var(--wp--preset--color--primary, #1f2937), a variable
// defined as itself, which CSS discards as a cycle: a block coloured "Primary" was transparent.
expect(await canvasColor(admin, editor, 'primary')).not.toBe('');
});

Expand Down
68 changes: 55 additions & 13 deletions resources/assets/css/app.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import "tailwindcss" theme(static);
@import "tailwindcss";
@plugin "@tailwindcss/typography";

@source "../../views";
Expand All @@ -22,23 +22,23 @@
display: none !important;
}

@theme {
@theme static {
/* Primary action color — buttons, links, active states */
--color-primary: var(--wp--preset--color--primary, #1f2937);
--color-primary-hover: var(--wp--preset--color--primary-hover, #111827);
--color-primary: #1f2937;
--color-primary-hover: #111827;
/* Secondary color — accents, badges, highlights */
--color-secondary: var(--wp--preset--color--secondary, #92400e);
--color-accent: var(--wp--preset--color--accent, #fbbf24);
--color-secondary: #92400e;
--color-accent: #fbbf24;
/* Text hierarchy */
--color-foreground: var(--wp--preset--color--foreground, #1f2937);
--color-muted: var(--wp--preset--color--muted, #6b7280);
--color-subtle: var(--wp--preset--color--subtle, #9ca3af);
--color-foreground: #1f2937;
--color-muted: #6b7280;
--color-subtle: #9ca3af;
/* Surfaces */
--color-surface: var(--wp--preset--color--surface, #f9fafb);
--color-surface-alt: var(--wp--preset--color--surface-alt, #f3f4f6);
--color-surface: #f9fafb;
--color-surface-alt: #f3f4f6;
/* Borders */
--color-outline: var(--wp--preset--color--outline, #e5e7eb);
--color-ring: var(--wp--preset--color--ring, #6b7280);
--color-outline: #e5e7eb;
--color-ring: #6b7280;
/* Feedback states */
--color-success: #16a34a;
--color-success-light: #f0fdf4;
Expand All @@ -48,6 +48,25 @@
--color-warning-light: #fffbeb;
--color-info: #2563eb;
--color-info-light: #eff6ff;
/* Typography — the font and the type scale offered in the editor */
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
--text-5xl: 3rem;
/* Corner radii */
--radius-xs: 0.125rem;
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--radius-2xl: 1rem;
/* Animations */
--animate-fade-in-down: fade-in-down 0.3s ease-out;
--animate-fade-out-up: fade-out-up 0.2s ease-in forwards;
Expand All @@ -62,6 +81,29 @@
to { opacity: 0; transform: translateX(-50%) translateY(-0.5rem); }
}

/*
* The build copies the @theme colours above into the theme.json palette. They are
* `static`, so each one reaches it even when no utility uses it, and concrete: a
* preset defined through its own variable is a cycle, and CSS drops it. The
* utilities then read the WordPress presets, so a palette edited in the Site
* Editor still reaches the theme.
*/
@layer base {
:root {
--color-primary: var(--wp--preset--color--primary, #1f2937);
--color-primary-hover: var(--wp--preset--color--primary-hover, #111827);
--color-secondary: var(--wp--preset--color--secondary, #92400e);
--color-accent: var(--wp--preset--color--accent, #fbbf24);
--color-foreground: var(--wp--preset--color--foreground, #1f2937);
--color-muted: var(--wp--preset--color--muted, #6b7280);
--color-subtle: var(--wp--preset--color--subtle, #9ca3af);
--color-surface: var(--wp--preset--color--surface, #f9fafb);
--color-surface-alt: var(--wp--preset--color--surface-alt, #f3f4f6);
--color-outline: var(--wp--preset--color--outline, #e5e7eb);
--color-ring: var(--wp--preset--color--ring, #6b7280);
}
}

/*
* Override WordPress core rule `a:where(:not(.wp-element-button))` which forces
* underline on all links regardless of Tailwind utilities.
Expand Down
2 changes: 1 addition & 1 deletion resources/assets/css/frontend/components/privacy-text.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.woocommerce-privacy-policy-text {
@apply text-sm text-gray-500 mt-5;
@apply text-sm text-muted mt-5;
}
6 changes: 3 additions & 3 deletions resources/assets/css/frontend/components/wpgb.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.product-grid-controls .wpgb-facet .wpgb-result-count,
.product-grid-controls .wpgb-facet .wpgb-facet-title,
.product-facets .wpgb-facet .wpgb-facet-title {
@apply block text-sm font-medium text-gray-900;
@apply block text-sm font-medium text-foreground;
}

.product-facets .wpgb-facet {
Expand All @@ -12,7 +12,7 @@
.product-facets .wpgb-facet .wpgb-rating-label,
.product-facets .wpgb-facet .wpgb-checkbox-label,
.product-facets .wpgb-facet .wpgb-range-facet .wpgb-range-values {
@apply ml-3 text-sm text-gray-600;
@apply ml-3 text-sm text-muted;
}

.product-grid-controls .wpgb-facet.sort-product {
Expand All @@ -34,7 +34,7 @@


.product-grid-controls .wpgb-facet select.wpgb-select:not([multiple]) {
@apply pt-0.5 pb-0.5 h-auto text-sm font-medium text-gray-900;
@apply pt-0.5 pb-0.5 h-auto text-sm font-medium text-foreground;
min-height: 35px;
line-height: 1;
}
4 changes: 2 additions & 2 deletions resources/views/woocommerce/global/rating-stars.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<div class="flex items-center gap-0.5">
@for($i=1;$i<=5;$i++)
@if ($rating >= $i)
<svg class="text-yellow-400 h-4 w-4 shrink-0" x-state-description="undefined: &quot;text-yellow-400&quot;, undefined: &quot;text-subtle&quot;" x-description="Heroicon name: solid/star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<svg class="text-accent h-4 w-4 shrink-0" x-state-description="undefined: &quot;text-accent&quot;, undefined: &quot;text-subtle&quot;" x-description="Heroicon name: solid/star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
@else
<svg class="text-subtle h-4 w-4 shrink-0" x-state-description="undefined: &quot;text-yellow-400&quot;, undefined: &quot;text-subtle&quot;" x-description="Heroicon name: solid/star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<svg class="text-subtle h-4 w-4 shrink-0" x-state-description="undefined: &quot;text-accent&quot;, undefined: &quot;text-subtle&quot;" x-description="Heroicon name: solid/star" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
@endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
aria-hidden="true"
:title="star.label"
class="rounded-xs text-subtle fill-current focus:outline-hidden focus:shadow-outline p-1 w-5 m-0 cursor-pointer"
:class="{'text-yellow-400': hoverRating >= star.amount, 'text-yellow-400': rating >= star.amount && hoverRating >= star.amount}">
:class="{'text-accent': hoverRating >= star.amount, 'text-accent': rating >= star.amount && hoverRating >= star.amount}">
<svg class="w-5 transition duration-150" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
Expand Down
Loading
Loading