diff --git a/README.md b/README.md index 3c3e607..d4456f7 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,26 @@ composer create-project pollora/pollora my-project php artisan pollora:make-theme my-theme ``` +## Design tokens + +The design lives in the `@theme static` block of `resources/assets/css/app.css`: +colours, type scale and radii, with concrete values. `npm run build` writes +them into the `theme.json` the editor reads +(`public/build/theme//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, fonts, block styles), and a slug defined there wins + over `@theme`. +- The font is the exception: Inter needs a `fontFace` declaration, which only + `theme.json` can hold, so fonts are declared there and `vite.config.js` turns + their generation off (`disableTailwindFonts`). The same option exists for + colours, font sizes and radii. +- 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. + ## Contributing ### Development Setup diff --git a/resources/assets/css/app.css b/resources/assets/css/app.css index c21ffcd..49a4c60 100644 --- a/resources/assets/css/app.css +++ b/resources/assets/css/app.css @@ -2,16 +2,57 @@ @source "../../views"; -@theme { - --color-primary: var(--wp--preset--color--primary, #ff5334); - --color-primary-vivid: var(--wp--preset--color--primary-vivid, #fb196d); - --color-secondary: var(--wp--preset--color--secondary, #ff8c12); - --color-accent: var(--wp--preset--color--accent, #feb017); - --color-foreground: var(--wp--preset--color--foreground, #1d142a); - --color-muted: var(--wp--preset--color--muted, #6b7280); - --color-surface: var(--wp--preset--color--surface, #fafafa); - --color-surface-alt: var(--wp--preset--color--surface-alt, #f5f3ff); - --color-border: var(--wp--preset--color--border, #e5e7eb); +@theme static { + --color-primary: #ff5334; + --color-primary-vivid: #fb196d; + --color-secondary: #ff8c12; + --color-accent: #feb017; + --color-foreground: #1d142a; + --color-muted: #6b7280; + --color-surface: #fafafa; + --color-surface-alt: #f5f3ff; + --color-background: #ffffff; + --color-border: #e5e7eb; + /* Type scale offered in the editor */ + --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; + --text-6xl: 3.75rem; + --text-7xl: 4.5rem; + /* Corner radii */ + --radius-sm: 0.25rem; + --radius-md: 0.375rem; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --radius-2xl: 1rem; +} + +/* + * The build copies the @theme colours, sizes and radii above into theme.json. + * 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 colour presets, so a palette edited + * in the Site Editor still reaches the theme. + */ +@layer base { + :root { + --color-primary: var(--wp--preset--color--primary, #ff5334); + --color-primary-vivid: var(--wp--preset--color--primary-vivid, #fb196d); + --color-secondary: var(--wp--preset--color--secondary, #ff8c12); + --color-accent: var(--wp--preset--color--accent, #feb017); + --color-foreground: var(--wp--preset--color--foreground, #1d142a); + --color-muted: var(--wp--preset--color--muted, #6b7280); + --color-surface: var(--wp--preset--color--surface, #fafafa); + --color-surface-alt: var(--wp--preset--color--surface-alt, #f5f3ff); + --color-background: var(--wp--preset--color--background, #ffffff); + --color-border: var(--wp--preset--color--border, #e5e7eb); + } } /* WordPress content blocks */ diff --git a/theme.json b/theme.json index 3ecf6da..e227d4e 100644 --- a/theme.json +++ b/theme.json @@ -4,60 +4,6 @@ "customTemplates": [], "settings": { "appearanceTools": true, - "color": { - "palette": [ - { - "slug": "primary", - "color": "#ff5334", - "name": "Primary" - }, - { - "slug": "primary-vivid", - "color": "#fb196d", - "name": "Primary Vivid" - }, - { - "slug": "secondary", - "color": "#ff8c12", - "name": "Secondary" - }, - { - "slug": "accent", - "color": "#feb017", - "name": "Accent" - }, - { - "slug": "foreground", - "color": "#1d142a", - "name": "Foreground" - }, - { - "slug": "muted", - "color": "#6b7280", - "name": "Muted" - }, - { - "slug": "surface", - "color": "#fafafa", - "name": "Surface" - }, - { - "slug": "surface-alt", - "color": "#f5f3ff", - "name": "Surface Alt" - }, - { - "slug": "background", - "color": "#ffffff", - "name": "Background" - }, - { - "slug": "border", - "color": "#e5e7eb", - "name": "Border" - } - ] - }, "custom": { "spacing": { "small": "max(1.25rem, 5vw)", @@ -108,24 +54,6 @@ } ] } - ], - "fontSizes": [ - { - "size": "var(--text-sm)", - "slug": "small" - }, - { - "size": "var(--text-base)", - "slug": "medium" - }, - { - "size": "var(--text-4xl)", - "slug": "large" - }, - { - "size": "var(--text-5xl)", - "slug": "x-large" - } ] }, "layout": { diff --git a/vite.config.js b/vite.config.js index 6b2b01b..286f2aa 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,6 +1,6 @@ import { defineConfig } from "vite"; import laravel, { refreshPaths } from 'laravel-vite-plugin'; -import { wordpressPlugin } from '@roots/vite-plugin'; +import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin'; import { globSync } from 'glob'; import path from 'path'; import tailwindcss from '@tailwindcss/vite'; @@ -93,6 +93,31 @@ export default defineConfig({ plugins: [ tailwindcss(), laravel(getThemeConfig()), + wordpressThemeJson({ + baseThemeJsonPath: './theme.json', + // Inter needs its @font-face, which only theme.json can declare + disableTailwindFonts: true, + fontSizeLabels: { + xs: 'Extra Small', + sm: 'Small', + base: 'Medium', + lg: 'Large', + xl: 'Extra Large', + '2xl': '2X Large', + '3xl': '3X Large', + '4xl': '4X Large', + '5xl': '5X Large', + '6xl': '6X Large', + '7xl': '7X Large', + }, + borderRadiusLabels: { + sm: 'Small', + md: 'Medium', + lg: 'Large', + xl: 'Extra Large', + '2xl': '2X Large', + }, + }), ...(hasBlocks ? [wordpressPlugin()] : []), { name: "blade",