/**
* Proto-Blocks Styling Knowledge Module
* Complete documentation for styling approaches
*/
export function getStylingKnowledge(approach) {
if (approach === 'vanilla-css') {
return getVanillaCssGuide();
}
if (approach === 'tailwind-inline') {
return getTailwindInlineGuide();
}
if (approach === 'tailwind-apply') {
return getTailwindApplyGuide();
}
return `# Proto-Blocks Styling: Complete Guide
Proto-Blocks supports three styling approaches. Choose based on your project needs and preferences.
---
## Styling Approaches Overview
| Approach | Best For | Complexity | File |
|----------|----------|------------|------|
| Vanilla CSS | Traditional styling | Low | \`style.css\` |
| Tailwind Inline | Rapid prototyping | Medium | Template |
| Tailwind @apply | Component-based | Medium | \`style.css\` |
---
## 1. Vanilla CSS
Traditional CSS in a separate \`style.css\` file.
### Setup
\`\`\`json
{
"protoBlocks": {
"useTailwind": false
}
}
\`\`\`
### style.css
\`\`\`css
.my-block {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 2rem;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.my-block__title {
margin: 0;
font-size: 1.5rem;
font-weight: 600;
color: #1a1a1a;
}
.my-block__content {
font-size: 1rem;
line-height: 1.6;
color: #4a4a4a;
}
/* Responsive */
@media (min-width: 768px) {
.my-block {
flex-direction: row;
padding: 3rem;
}
}
\`\`\`
### Pros & Cons
**Pros:**
- No build step
- Full CSS control
- Familiar to all developers
- Smaller file sizes
**Cons:**
- More verbose
- Manual responsive utilities
- No utility classes
---
## 2. Tailwind CSS Inline
Utility classes directly in the PHP template.
### Setup
\`\`\`json
{
"protoBlocks": {
"useTailwind": true
}
}
\`\`\`
### Template
\`\`\`php
<?php
$wrapper_attributes = get_block_wrapper_attributes([
'class' => 'flex flex-col gap-4 p-8 bg-white rounded-lg shadow-md',
]);
?>
<div <?php echo $wrapper_attributes; ?>>
<h2 class="m-0 text-2xl font-semibold text-gray-900" data-proto-field="title">
<?php echo esc_html($title); ?>
</h2>
<div class="text-base leading-relaxed text-gray-600" data-proto-field="content">
<?php echo wp_kses_post($content); ?>
</div>
</div>
\`\`\`
### Pros & Cons
**Pros:**
- Rapid development
- No context switching
- Easy responsive design
- No naming conventions needed
**Cons:**
- Verbose HTML
- Learning curve for Tailwind
- Can be hard to maintain
---
## 3. Tailwind with @apply
Use Tailwind utilities in CSS with @apply directive.
### Setup
\`\`\`json
{
"protoBlocks": {
"useTailwind": true
}
}
\`\`\`
### style.css
\`\`\`css
.my-block {
@apply flex flex-col gap-4 p-8 bg-white rounded-lg shadow-md;
}
.my-block__title {
@apply m-0 text-2xl font-semibold text-gray-900;
}
.my-block__content {
@apply text-base leading-relaxed text-gray-600;
}
/* Responsive with @apply */
@screen md {
.my-block {
@apply flex-row p-12;
}
}
/* Or using standard media query */
@media (min-width: 768px) {
.my-block {
@apply p-12;
}
}
\`\`\`
### Template
\`\`\`php
<?php
$wrapper_attributes = get_block_wrapper_attributes([
'class' => 'my-block',
]);
?>
<div <?php echo $wrapper_attributes; ?>>
<h2 class="my-block__title" data-proto-field="title">
<?php echo esc_html($title); ?>
</h2>
</div>
\`\`\`
### Pros & Cons
**Pros:**
- Clean HTML
- Tailwind speed
- BEM-compatible
- Best of both worlds
**Cons:**
- Build step required
- Larger CSS output
- Two places for styles
---
## Theme Colors
Proto-Blocks Tailwind includes themed color scales:
### Available Colors
| Name | Shades | Usage |
|------|--------|-------|
| \`primary\` | 50-950 | Brand primary color |
| \`secondary\` | 50-950 | Brand secondary color |
| \`accent\` | 50-950 | Accent/highlight color |
### Using in Tailwind
\`\`\`html
<div class="bg-primary-600 text-white">
Primary background
</div>
<span class="text-secondary-500">
Secondary text
</span>
<button class="bg-accent-600 hover:bg-accent-700">
Accent button
</button>
\`\`\`
### CSS Variables
Access theme colors via CSS variables:
\`\`\`css
.custom-element {
background-color: var(--tw-color-primary-600);
border-color: var(--tw-color-secondary-300);
color: var(--tw-color-accent-700);
}
\`\`\`
---
## Editor Styles
Proto-Blocks automatically applies styles to the block editor.
### Automatic Behavior
- \`style.css\` is loaded in both editor and frontend
- Tailwind CSS is compiled and injected in editor
- WordPress block supports are applied
### Editor-Specific Styles
\`\`\`css
/* Target editor only */
.editor-styles-wrapper .my-block {
outline: 1px dashed rgba(0, 0, 0, 0.1);
}
/* Placeholder styling */
.my-block__title:empty::before {
content: 'Enter title...';
color: #999;
}
/* Make empty elements clickable */
.my-block__image--empty {
min-height: 150px;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
cursor: pointer;
}
\`\`\`
---
## Responsive Design
### Vanilla CSS
\`\`\`css
.my-block {
padding: 1rem;
}
@media (min-width: 640px) {
.my-block {
padding: 1.5rem;
}
}
@media (min-width: 768px) {
.my-block {
padding: 2rem;
}
}
@media (min-width: 1024px) {
.my-block {
padding: 3rem;
}
}
\`\`\`
### Tailwind Inline
\`\`\`php
<div class="p-4 sm:p-6 md:p-8 lg:p-12">
Content
</div>
\`\`\`
### Tailwind Breakpoints
| Prefix | Min-width | CSS |
|--------|-----------|-----|
| (none) | 0 | Default |
| \`sm:\` | 640px | \`@media (min-width: 640px)\` |
| \`md:\` | 768px | \`@media (min-width: 768px)\` |
| \`lg:\` | 1024px | \`@media (min-width: 1024px)\` |
| \`xl:\` | 1280px | \`@media (min-width: 1280px)\` |
| \`2xl:\` | 1536px | \`@media (min-width: 1536px)\` |
---
## Dynamic Styling from Controls
### Using Control Values
\`\`\`php
<?php
$layout = $attributes['layout'] ?? 'vertical';
$columns = $attributes['columns'] ?? 3;
$gap = $attributes['gap'] ?? 16;
$wrapper_attributes = get_block_wrapper_attributes([
'class' => "my-grid my-grid--{$layout}",
'style' => "--columns: {$columns}; --gap: {$gap}px;",
]);
?>
<div <?php echo $wrapper_attributes; ?>>
<!-- Content -->
</div>
\`\`\`
\`\`\`css
.my-grid {
display: grid;
grid-template-columns: repeat(var(--columns, 3), 1fr);
gap: var(--gap, 16px);
}
.my-grid--vertical {
grid-template-columns: 1fr;
}
.my-grid--horizontal {
grid-auto-flow: column;
}
\`\`\`
### Color Controls
\`\`\`php
<?php
$bg_color = $attributes['backgroundColor'] ?? '#ffffff';
$text_color = $attributes['textColor'] ?? '#000000';
?>
<div style="background-color: <?php echo esc_attr($bg_color); ?>; color: <?php echo esc_attr($text_color); ?>;">
Content
</div>
\`\`\`
---
## Best Practices
1. **Choose One Approach**: Don't mix vanilla and Tailwind randomly
2. **Use CSS Variables**: For dynamic values from controls
3. **Mobile-First**: Start with mobile styles, add breakpoints up
4. **Keep It Simple**: Avoid over-engineering styles
5. **Test Both Views**: Verify editor and frontend appearance
6. **Empty States**: Style placeholder/empty elements for editor
7. **Use BEM**: If using vanilla CSS, follow naming conventions
8. **Leverage WordPress**: Use \`get_block_wrapper_attributes()\` for supports
`;
}
function getVanillaCssGuide() {
return `# Vanilla CSS Styling Guide
Traditional CSS styling for Proto-Blocks without Tailwind.
## Setup
\`\`\`json
{
"protoBlocks": {
"useTailwind": false,
"template": "template.php"
}
}
\`\`\`
## File Structure
\`\`\`
my-block/
├── block.json
├── template.php
└── style.css ← Your styles go here
\`\`\`
## Complete Example
### block.json
\`\`\`json
{
"name": "proto-blocks/feature-card",
"title": "Feature Card",
"protoBlocks": {
"useTailwind": false,
"fields": {
"icon": { "type": "image" },
"title": { "type": "text", "tagName": "h3" },
"description": { "type": "wysiwyg" }
},
"controls": {
"layout": {
"type": "select",
"default": "vertical",
"options": [
{ "key": "vertical", "label": "Vertical" },
{ "key": "horizontal", "label": "Horizontal" }
]
}
}
}
}
\`\`\`
### template.php
\`\`\`php
<?php
$icon = $attributes['icon'] ?? null;
$title = $attributes['title'] ?? '';
$description = $attributes['description'] ?? '';
$layout = $attributes['layout'] ?? 'vertical';
$wrapper_attributes = get_block_wrapper_attributes([
'class' => "feature-card feature-card--{$layout}",
]);
?>
<article <?php echo $wrapper_attributes; ?>>
<div class="feature-card__icon" data-proto-field="icon">
<?php if ($icon && !empty($icon['url'])) : ?>
<img src="<?php echo esc_url($icon['url']); ?>" alt="" />
<?php else : ?>
<span class="feature-card__icon-placeholder">+</span>
<?php endif; ?>
</div>
<div class="feature-card__content">
<h3 class="feature-card__title" data-proto-field="title">
<?php echo esc_html($title); ?>
</h3>
<div class="feature-card__description" data-proto-field="description">
<?php echo wp_kses_post($description); ?>
</div>
</div>
</article>
\`\`\`
### style.css
\`\`\`css
/* ==========================================================================
Feature Card Block
========================================================================== */
.feature-card {
display: flex;
padding: 1.5rem;
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
transition: box-shadow 0.2s ease;
}
.feature-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* Layout Variants
========================================================================== */
.feature-card--vertical {
flex-direction: column;
align-items: center;
text-align: center;
}
.feature-card--horizontal {
flex-direction: row;
align-items: flex-start;
gap: 1.5rem;
}
/* Icon
========================================================================== */
.feature-card__icon {
flex-shrink: 0;
width: 64px;
height: 64px;
margin-bottom: 1rem;
}
.feature-card--horizontal .feature-card__icon {
margin-bottom: 0;
}
.feature-card__icon img {
width: 100%;
height: 100%;
object-fit: contain;
}
.feature-card__icon-placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: #f3f4f6;
border: 2px dashed #d1d5db;
border-radius: 0.5rem;
font-size: 1.5rem;
color: #9ca3af;
cursor: pointer;
}
/* Content
========================================================================== */
.feature-card__content {
flex: 1;
}
.feature-card__title {
margin: 0 0 0.5rem;
font-size: 1.25rem;
font-weight: 600;
color: #111827;
}
.feature-card__title:empty::before {
content: 'Enter title...';
color: #9ca3af;
}
.feature-card__description {
font-size: 0.9375rem;
line-height: 1.6;
color: #6b7280;
}
.feature-card__description p:last-child {
margin-bottom: 0;
}
/* Responsive
========================================================================== */
@media (max-width: 640px) {
.feature-card--horizontal {
flex-direction: column;
text-align: center;
}
.feature-card--horizontal .feature-card__icon {
margin-bottom: 1rem;
}
}
\`\`\`
## BEM Naming Convention
Proto-Blocks recommends BEM (Block Element Modifier):
\`\`\`css
/* Block */
.feature-card { }
/* Element */
.feature-card__title { }
.feature-card__icon { }
.feature-card__content { }
/* Modifier */
.feature-card--horizontal { }
.feature-card--vertical { }
.feature-card--highlighted { }
\`\`\`
## CSS Custom Properties
Use CSS variables for dynamic values:
\`\`\`css
.feature-card {
--card-padding: 1.5rem;
--card-radius: 0.5rem;
--card-bg: #ffffff;
--card-border: #e5e7eb;
padding: var(--card-padding);
border-radius: var(--card-radius);
background: var(--card-bg);
border: 1px solid var(--card-border);
}
/* Override with controls */
.feature-card[style*="--card-bg"] {
/* Custom background from control */
}
\`\`\`
`;
}
function getTailwindInlineGuide() {
return `# Tailwind Inline Styling Guide
Use Tailwind utility classes directly in PHP templates.
## Setup
\`\`\`json
{
"protoBlocks": {
"useTailwind": true,
"template": "template.php"
}
}
\`\`\`
## Complete Example
### template.php
\`\`\`php
<?php
$icon = $attributes['icon'] ?? null;
$title = $attributes['title'] ?? '';
$description = $attributes['description'] ?? '';
$layout = $attributes['layout'] ?? 'vertical';
$layout_classes = [
'vertical' => 'flex-col items-center text-center',
'horizontal' => 'flex-row items-start gap-6',
];
$wrapper_attributes = get_block_wrapper_attributes([
'class' => 'flex p-6 bg-white border border-gray-200 rounded-lg transition-shadow hover:shadow-lg ' . ($layout_classes[$layout] ?? $layout_classes['vertical']),
]);
?>
<article <?php echo $wrapper_attributes; ?>>
<div
class="flex-shrink-0 w-16 h-16 mb-4 <?php echo $layout === 'horizontal' ? 'mb-0' : ''; ?>"
data-proto-field="icon"
>
<?php if ($icon && !empty($icon['url'])) : ?>
<img
src="<?php echo esc_url($icon['url']); ?>"
alt=""
class="w-full h-full object-contain"
/>
<?php else : ?>
<span class="flex items-center justify-center w-full h-full bg-gray-100 border-2 border-dashed border-gray-300 rounded-lg text-2xl text-gray-400 cursor-pointer">
+
</span>
<?php endif; ?>
</div>
<div class="flex-1">
<h3
class="m-0 mb-2 text-xl font-semibold text-gray-900 empty:before:content-['Enter_title...'] empty:before:text-gray-400"
data-proto-field="title"
>
<?php echo esc_html($title); ?>
</h3>
<div
class="text-base leading-relaxed text-gray-600 [&>p:last-child]:mb-0"
data-proto-field="description"
>
<?php echo wp_kses_post($description); ?>
</div>
</div>
</article>
\`\`\`
## Common Patterns
### Responsive Classes
\`\`\`php
<div class="
flex flex-col
sm:flex-row
gap-4 sm:gap-6 md:gap-8
p-4 sm:p-6 md:p-8
text-sm sm:text-base md:text-lg
">
\`\`\`
### State Variants
\`\`\`php
<button class="
bg-primary-600 text-white
hover:bg-primary-700
focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
active:bg-primary-800
disabled:opacity-50 disabled:cursor-not-allowed
">
Click me
</button>
\`\`\`
### Dynamic Classes
\`\`\`php
<?php
$size_classes = [
'small' => 'p-3 text-sm',
'medium' => 'p-4 text-base',
'large' => 'p-6 text-lg',
];
$size = $attributes['size'] ?? 'medium';
?>
<div class="<?php echo esc_attr($size_classes[$size]); ?>">
Content
</div>
\`\`\`
### Conditional Classes
\`\`\`php
<?php
$is_featured = $attributes['isFeatured'] ?? false;
?>
<article class="
p-6 rounded-lg border
<?php echo $is_featured ? 'border-primary-500 bg-primary-50' : 'border-gray-200 bg-white'; ?>
">
\`\`\`
## Arbitrary Values
\`\`\`php
<!-- Custom values with brackets -->
<div class="w-[350px] h-[200px] bg-[#ff6b6b] text-[14px]">
Custom dimensions and colors
</div>
<!-- CSS variables -->
<div style="--my-color: <?php echo esc_attr($color); ?>;" class="bg-[var(--my-color)]">
Dynamic color
</div>
\`\`\`
## Theme Colors
\`\`\`php
<!-- Primary -->
<div class="bg-primary-600 text-primary-50 hover:bg-primary-700">
Primary button
</div>
<!-- Secondary -->
<div class="bg-secondary-100 text-secondary-800 border-secondary-200">
Secondary card
</div>
<!-- Accent -->
<span class="text-accent-600 font-semibold">
Highlighted text
</span>
\`\`\`
`;
}
function getTailwindApplyGuide() {
return `# Tailwind @apply Styling Guide
Use Tailwind utilities in CSS with @apply for cleaner HTML.
## Setup
\`\`\`json
{
"protoBlocks": {
"useTailwind": true,
"template": "template.php"
}
}
\`\`\`
## File Structure
\`\`\`
my-block/
├── block.json
├── template.php
└── style.css ← Tailwind @apply here
\`\`\`
## Complete Example
### template.php
\`\`\`php
<?php
$icon = $attributes['icon'] ?? null;
$title = $attributes['title'] ?? '';
$description = $attributes['description'] ?? '';
$layout = $attributes['layout'] ?? 'vertical';
$wrapper_attributes = get_block_wrapper_attributes([
'class' => "feature-card feature-card--{$layout}",
]);
?>
<article <?php echo $wrapper_attributes; ?>>
<div class="feature-card__icon" data-proto-field="icon">
<?php if ($icon && !empty($icon['url'])) : ?>
<img src="<?php echo esc_url($icon['url']); ?>" alt="" />
<?php else : ?>
<span class="feature-card__icon-placeholder">+</span>
<?php endif; ?>
</div>
<div class="feature-card__content">
<h3 class="feature-card__title" data-proto-field="title">
<?php echo esc_html($title); ?>
</h3>
<div class="feature-card__description" data-proto-field="description">
<?php echo wp_kses_post($description); ?>
</div>
</div>
</article>
\`\`\`
### style.css
\`\`\`css
/* ==========================================================================
Feature Card - Tailwind @apply
========================================================================== */
.feature-card {
@apply flex p-6 bg-white border border-gray-200 rounded-lg;
@apply transition-shadow hover:shadow-lg;
}
/* Layout Variants */
.feature-card--vertical {
@apply flex-col items-center text-center;
}
.feature-card--horizontal {
@apply flex-row items-start gap-6;
}
/* Icon */
.feature-card__icon {
@apply flex-shrink-0 w-16 h-16 mb-4;
}
.feature-card--horizontal .feature-card__icon {
@apply mb-0;
}
.feature-card__icon img {
@apply w-full h-full object-contain;
}
.feature-card__icon-placeholder {
@apply flex items-center justify-center w-full h-full;
@apply bg-gray-100 border-2 border-dashed border-gray-300 rounded-lg;
@apply text-2xl text-gray-400 cursor-pointer;
}
/* Content */
.feature-card__content {
@apply flex-1;
}
.feature-card__title {
@apply m-0 mb-2 text-xl font-semibold text-gray-900;
}
.feature-card__title:empty::before {
content: 'Enter title...';
@apply text-gray-400;
}
.feature-card__description {
@apply text-base leading-relaxed text-gray-600;
}
.feature-card__description p:last-child {
@apply mb-0;
}
/* Responsive */
@screen sm {
.feature-card--horizontal {
@apply flex-col text-center;
}
.feature-card--horizontal .feature-card__icon {
@apply mb-4;
}
}
\`\`\`
## @screen Directive
Use @screen for responsive styles:
\`\`\`css
.element {
@apply text-sm;
}
@screen sm {
.element {
@apply text-base;
}
}
@screen md {
.element {
@apply text-lg;
}
}
@screen lg {
.element {
@apply text-xl;
}
}
\`\`\`
## Mixing @apply with Regular CSS
\`\`\`css
.complex-element {
/* Tailwind utilities */
@apply flex items-center gap-4 p-4;
/* Custom CSS */
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
/* CSS variables */
--element-spacing: theme('spacing.4');
}
\`\`\`
## Theme Function
Access Tailwind config values:
\`\`\`css
.element {
padding: theme('spacing.4');
color: theme('colors.primary.600');
font-size: theme('fontSize.lg');
border-radius: theme('borderRadius.lg');
box-shadow: theme('boxShadow.md');
}
\`\`\`
## Best Practices
1. **Group Related Utilities**: Keep @apply statements organized
2. **Use BEM Classes**: Maintain semantic class names
3. **Leverage @screen**: For cleaner responsive code
4. **Mix When Needed**: Combine @apply with custom CSS
5. **Avoid Overuse**: Don't @apply everything—use inline for one-offs
`;
}