GithubHelp home page GithubHelp logo

kirby-template-attributes's Introduction

Kirby Template Attributes

Better attribute API for snippets and templates

This plugin brings Vue.js/Laravel-Blade-like attribute composition to the templates of your Kirby project. This is an exploration in search of better HTML attribute handling for nested snippets and components.

Requirements

  • Kirby 4.0+ (use version 1.x for Kirby 3 installations)
  • PHP 8.1 (because of Enumeration support)

Installation

The recommended is installation via composer.

composer require fabianmichael/kirby-template-attributes

Alternatively, you can also download the plugin and install it manually by copying it to the site/plugins/ folder of your website.

Usage

Basic usage

Use the attributes() helper for generating a string of attributes:

<button <?= attributes([
  'role' => 'button',
  'aria-expanded' => 'false',
]) ?>>[…]</button>

You can also use named arguments if you prefer a leaner syntax. Be aware, that this only works as long as you don’t have dashes in your attribute names:

<img <?= attributes(
  class: 'icon',
  width: 16,
  height: 16,
  src: $image->url(),
	alt: 'The funniest donkey ever!',
) ?>>

Or if all you have is an attributes string, you can also feed the that to the attributes() helper:

<?php

// get image dimensions as height="yyy" width="xxx" 
$src  = 'img.png';
$size = getimagesize($src)[3];

?>

<img <?= attributes($size)->merge([
	'src' => $src,
	'alt' => '',
]) ?>>

⚠️ If you need XML-compatible attributes, always call $attributes->toXml() instead of just echoing the Attributes object, because otherwise all attributes will be converted to lower-case.

In many cases, you need to set different classes. The classes() helper is a nice shortcut for improved readability:

<button <?= classes([
  'button',
  'button--red' => $color === 'red', // class will only appear in class attribute, if condition is true
]) ?>>[…]</button>

The classes() helper is pretty flexible and also accepts multiple paramaters, each of those can eithe be a string or array (but please ensure to write readible code anyways):

<button <?= classes('button', [
  'button--red' => $color === 'red',
], 'absolute', 'top-0 left-0') ?>>[…]</button>

Merging attributes

# site/snippets/button.php

<button <?= attributes([
  'class' => 'button',
  'role' => 'button',
  'aria-expanded' => 'false',
  'style' => '--foo: bar',
])->merge($attr ?? []) ?>>[…]</button>

# site/templates/default.php

<?php snippet('button', [
  'attr' => [
    'role' => 'unicorn', // attributes can be overridden
    'onclick' => 'alert("everyone likes alerts!!!")',
    'class' => 'absolute top-0 left-0
      md:left-4
      xl:left-8', // classes are automatically appended to the existing attribute value and surplus whitespace is trimmed
    'style' => '--bar: foo', // style attribute value is also appended to the original value
  ],
]) ?>

Before/After

You can set $before and $after, just like for Kirby’s Html::attr() helper by using the corresponding methods:

attributes(class: 'foo')->before(' ');
attributes(class: 'foo')->after(' ');

Examples

A button component exists as a snippet in site/snippets/button.php:

<button class="button"><?= html($text ?? 'Button text') ?></button>

A common situation would be the requirement to add attributes when calling the snippet('button') helper class, e.g. class, data-*, title, aria-* etc. Developers cannot handly every possible attribute for each component. The previous attributes() helper could help here:

<button <?= attributes($attr ?? []) ?> class="button"><?= html($text ?? 'Button text') ?></button>

This works better, but we still cannot extend the class attribute easily. Enter the new attributes() helper:

<button <?= attributes([
    'class' => 'button',
])->merge($attr ?? []) ?>><?= html($text ?? 'Button text') ?></button>

Even shorter:

<button <?= classes('button')->merge($attr ?? []) ?>><?= html($text ?? 'Button text') ?></button>

This becomes even cooler, because the classes can be assigned conditionally as an array:

<?php

$text ??= 'Button text';
$size ??= 'normal';
$theme ??= null;
$attr ??= [];

?>
<button <?= attributes([
    'role' => 'button',
    'style' => [
      'font-size: 2rem;' => ($size === 'large'),
    ],
])->class([
    'button',
    "button--{$size}",
    "button--{$theme}" => $theme, // will only be merged, if $theme is trueish
])->merge($attr) ?>><?= html($text) ?></button>

This is already cool and makes working with attributes for snippets much easier, e.g. is we use the button in site/snippets/menu.php:

<nav class="menu">
    […]
    <?php snippet('button', [
        'text' => 'Toggle Menu',
        'attr' => [
            'class' => 'menu__button',
            'aria-controls' => 'menu-popup',
            'aria-expanded' => false,
            'role' => 'teapot', // overrrides the default attribute
        ],
    ]) ?>
</nav>

License

MIT (but you are highly encouraged to ❤️ sponsor me, if this piece of software helps you to pay your bills).

kirby-template-attributes's People

Contributors

fabianmichael avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

kirby-template-attributes's Issues

Add own serializer for attributes

The current serializer for attributes relies on Kirby’s Toolkit. But that one converts everything to lowercase, which does not follow spec and currently makes it impossible to generate SVG code, that relies on case-sensitive attributes.

See: getkirby/kirby#4908

Allow empty attributes

Right now empty attributes are only added if they don't have a value:

attributes(['alt']);

Would be great if this also works (but it seems to be filtered out):

attributes(['alt' => '']);

I prefer the first syntax, but in some cases I can only use the second (e.g. auto-generated attributes that have to be an associative array).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.