Skip to content

Latest commit

 

History

History
645 lines (483 loc) · 13 KB

File metadata and controls

645 lines (483 loc) · 13 KB

Customization Guide

Overview

The Premium Theme is designed to be highly customizable while maintaining code quality and performance. This guide covers advanced customization techniques beyond the basic settings available in the admin interface.


CSS Customization

Understanding the CSS Architecture

The theme uses a modular CSS architecture with Tailwind CSS:

styles/src/
├── main.css              # Entry point
├── base/
│   ├── variables.css     # CSS custom properties
│   └── reset.css         # Normalizations
├── components/
│   ├── buttons.css       # Button styles
│   ├── cards.css         # Card components
│   ├── forms.css         # Form elements
│   ├── navigation.css    # Navigation styles
│   └── article.css       # Article-specific
├── layouts/
│   ├── containers.css    # Container system
│   └── grid.css          # Grid layouts
└── utilities/
    ├── typography.css    # Text utilities
    └── spacing.css       # Spacing helpers

Method 1: CSS Custom Properties

The easiest way to customize colors, fonts, and spacing is through CSS custom properties (variables).

Add to Custom CSS field in admin:

:root {
  /* Override primary hue */
  --primary-hue: 200; /* Custom blue */
  
  /* Override spacing */
  --space-4: 1.25rem; /* Increase base spacing */
  
  /* Override fonts */
  --user-font-heading: 'Playfair Display', serif;
  --user-fonT-body: 'Source Sans Pro', sans-serif;
  
  /* Override border radius */
  --radius-md: 0.5rem;
  --radius-lg: 1rem;
}

Method 2: Component Overrides

Override specific component styles:

/* Customize article cards */
.article-card {
  border: 2px solid var(--color-primary-200);
  border-radius: var(--radius-xl);
}

.article-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-xl);
}

/* Customize buttons */
.btn-primary {
  background: linear-gradient(135deg, 
    hsl(var(--primary-hue), 70%, 50%), 
    hsl(var(--primary-hue), 70%, 40%)
  );
}

/* Customize navigation */
.main-nav {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
}

Method 3: Dark Mode Customization

Customize dark mode specifically:

[data-theme="dark"] {
  /* Override dark mode colors */
  --color-bg: hsl(220, 25%, 8%);
  --color-bg-secondary: hsl(220, 25%, 12%);
  
  /* Custom dark mode shadows */
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
}

[data-theme="dark"] .article-card {
  border-color: hsl(var(--primary-hue), 30%, 25%);
}

Method 4: Responsive Customization

Add responsive breakpoint-specific styles:

/* Mobile */
@media (max-width: 767px) {
  .article-card__title {
    font-size: 1.25rem;
  }
}

/* Tablet */
@media (min-width: 768px) and (max-width: 1023px) {
  .article-card {
    padding: 1.5rem;
  }
}

/* Desktop */
@media (min-width: 1024px) {
  .container {
    max-width: 1200px;
  }
}

Template Customization

Template Override System

To customize templates without modifying core files:

  1. Copy the template from plugins/themes/premium/templates/ to your custom location
  2. Modify as needed
  3. Register custom template path in PremiumThemePlugin.php

Example: Custom Article Template

  1. Copy templates/frontend/pages/article.tpl to templates/custom/article.tpl

  2. Modify PremiumThemePlugin.php:

public function init(): void
{
    parent::init();
    
    // Register custom template directory
    $this->addTemplateDirectory('custom');
}

Common Template Customizations

Custom Article Layout

{* templates/custom/article.tpl *}
{include file="frontend/components/header.tpl"}

<div class="custom-article-layout">
    {* Your custom layout *}
    <div class="article-sidebar">
        {* Custom sidebar content *}
    </div>
    
    <div class="article-main">
        {* Article content *}
        <h1>{$article->getLocalizedTitle()|escape}</h1>
        {* ... *}
    </div>
</div>

{include file="frontend/components/footer.tpl"}

Custom Homepage Sections

{* Add custom section to indexJournal.tpl *}
<section class="featured-authors section-padding">
    <div class="container">
        <h2>Featured Authors</h2>
        {* Custom author showcase *}
    </div>
</section>

JavaScript Customization

Adding Custom Scripts

Method 1: Via Custom JavaScript Field

Add scripts through the admin interface:

// Add Google Analytics
(function() {
  var ga = document.createElement('script');
  ga.src = 'https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID';
  document.head.appendChild(ga);
  
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'GA_MEASUREMENT_ID');
})();

Method 2: Create Custom Module

Create a new JavaScript module:

// js/src/modules/customFeature.js
export class CustomFeature {
  init() {
    console.log('Custom feature initialized');
    this.setupEventListeners();
  }
  
  setupEventListeners() {
    document.querySelectorAll('.custom-trigger').forEach(el => {
      el.addEventListener('click', () => this.handleClick());
    });
  }
  
  handleClick() {
    // Custom functionality
  }
}

Register in main.js:

import { CustomFeature } from './modules/customFeature.js';

// In bootstrap()
this.modules.set('customFeature', new CustomFeature());

Extending Existing Modules

Access and extend theme modules:

// Wait for theme to initialize
document.addEventListener('DOMContentLoaded', () => {
  const themeApp = window.PremiumTheme;
  
  // Get navigation module
  const nav = themeApp.getModule('navigation');
  
  // Add custom behavior
  document.addEventListener('scroll', () => {
    // Custom scroll behavior
  });
});

Advanced PHP Customization

Creating Custom Settings

Add new theme options:

// In PremiumThemePlugin.php init()
$this->addOption('customFeature', 'FieldOptions', [
    'type' => 'radio',
    'label' => 'plugins.themes.premium.option.customFeature.label',
    'default' => 'enabled',
    'options' => [
        'enabled' => 'plugins.themes.premium.option.customFeature.enabled',
        'disabled' => 'plugins.themes.premium.option.customFeature.disabled',
    ]
]);

Custom Template Variables

Pass custom data to templates:

public function addCustomStyles($hookName, $args): bool
{
    $templateMgr = $args[0];
    
    // Get your custom data
    $customData = $this->getCustomData();
    
    // Pass to template
    $templateMgr->assign([
        'customVariable' => $customData,
    ]);
    
    return false;
}

Use in templates:

{if $customVariable}
    <div class="custom-content">
        {$customVariable|escape}
    </div>
{/if}

Color Scheme Customization

Creating Custom Color Schemes

Add your own preset to ColorSchemeManager.php:

public function getPresetSchemes(): array
{
    return [
        // Existing schemes...
        'custom' => ['hue' => 180, 'name' => 'Custom Teal'],
        'brand' => ['hue' => 275, 'name' => 'Brand Purple'],
    ];
}

Register in PremiumThemePlugin.php:

$this->addOption('colorScheme', 'FieldOptions', [
    'options' => [
        // Existing...
        'custom' => 'plugins.themes.premium.option.colorScheme.custom',
        'brand' => 'plugins.themes.premium.option.colorScheme.brand',
    ]
]);

Dynamic Color Generation

Generate colors programmatically:

$colorManager = new ColorSchemeManager();
$scheme = $colorManager->generateScheme('#00BFA5'); // Teal

// Returns array with all shades
// ['primary-50', 'primary-100', ..., 'primary-900']

Layout Customization

Creating Custom Layouts

  1. Define layout in CSS:
/* styles/src/layouts/custom.css */
.layout-custom {
  display: grid;
  grid-template-columns: 200px 1fr 300px;
  gap: 2rem;
}

@media (max-width: 1023px) {
  .layout-custom {
    grid-template-columns: 1fr;
  }
}
  1. Add option to theme:
$this->addOption('layout', 'FieldOptions', [
    'options' => [
        // Existing...
        'custom' => 'plugins.themes.premium.option.layout.custom',
    ]
]);
  1. Use in templates:
<div class="layout-{$premiumLayout|default:'custom'}">
    {* Template content *}
</div>

Widget/Block Customization

Creating Custom Sidebar Blocks

{* templates/frontend/components/custom-block.tpl *}
<div class="sidebar-block custom-block">
    <h3 class="sidebar-block__title">
        {translate key="plugins.themes.premium.customBlock.title"}
    </h3>
    <div class="custom-block__content">
        {* Your custom content *}
        <ul>
            <li><a href="#">Custom Link 1</a></li>
            <li><a href="#">Custom Link 2</a></li>
        </ul>
    </div>
</div>

Include in sidebar:

{* In indexJournal.tpl sidebar *}
<aside class="sidebar">
    {include file="frontend/components/custom-block.tpl"}
</aside>

Performance Optimization

CSS Optimization

  1. Use PurgeCSS - Already configured, but you can add safelist:
// tailwind.config.js
safelist: [
  'custom-class',
  'another-class',
  {
    pattern: /^custom-/,
  },
],
  1. Critical CSS - Inline critical styles:
// In template head
<style>
  <?php echo file_get_contents('path/to/critical.css'); ?>
</style>

JavaScript Optimization

  1. Lazy load modules:
// Load module only when needed
document.querySelector('.trigger').addEventListener('click', async () => {
  const { HeavyModule } = await import('./modules/heavyModule.js');
  const module = new HeavyModule();
  module.init();
});
  1. Debounce expensive operations:
function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

const expensiveOp = debounce(() => {
  // Expensive operation
}, 300);

window.addEventListener('scroll', expensiveOp);

Best Practices

1. Don't Modify Core Files

  • Always use custom CSS field or template overrides
  • Create child themes if extensive modifications needed
  • Document all customizations

2. Maintain Accessibility

  • Keep ARIA labels
  • Maintain keyboard navigation
  • Test with screen readers
  • Check color contrast (4.5:1 minimum)

3. Test Responsively

  • Test on mobile, tablet, desktop
  • Check different browsers
  • Validate dark mode
  • Test RTL languages if applicable

4. Performance Considerations

  • Minimize custom CSS/JS
  • Use CSS custom properties over hardcoded values
  • Lazy load images and heavy scripts
  • Monitor Lighthouse scores

5. Update Compatibility

  • Test customizations after theme updates
  • Keep custom code separate from core
  • Document custom code thoroughly
  • Version control your customizations

Troubleshooting Custom Code

CSS Not Applying

  1. Check CSS specificity
  2. Clear browser cache (hard refresh)
  3. Verify custom CSS is loaded (inspect element)
  4. Check for syntax errors in browser console

JavaScript Errors

  1. Open browser console (F12)
  2. Check for errors in red
  3. Verify module imports
  4. Test in isolation

Template Not Rendering

  1. Clear OJS cache (cache/ directory)
  2. Check template syntax
  3. Verify file permissions
  4. Check OJS error logs

Getting Help


Example: Complete Custom Feature

Here's a complete example of adding a "Reading Time" feature to articles:

1. CSS

.reading-time {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: var(--color-primary-50);
  color: var(--color-primary-700);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
}

2. JavaScript

// js/src/modules/readingTime.js
export class ReadingTime {
  init() {
    this.calculateReadingTime();
  }
  
  calculateReadingTime() {
    const article = document.querySelector('.article-content');
    if (!article) return;
    
    const text = article.textContent;
    const wordCount = text.split(/\s+/).length;
    const readingTime = Math.ceil(wordCount / 200); // 200 words per minute
    
    this.displayReadingTime(readingTime);
  }
  
  displayReadingTime(minutes) {
    const element = document.createElement('div');
    element.className = 'reading-time';
    element.innerHTML = `
      <svg>...</svg>
      <span>${minutes} min read</span>
    `;
    
    const target = document.querySelector('.article-header');
    target.appendChild(element);
  }
}

3. Register Module

// In main.js
import { ReadingTime } from './modules/readingTime.js';
this.modules.set('readingTime', new ReadingTime());

4. Rebuild

npm run build

Done! Reading time now appears on all articles.