定制 fabianmichael/kirby-template-attributes 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

fabianmichael/kirby-template-attributes

Composer 安装命令:

composer require fabianmichael/kirby-template-attributes

包简介

Better HTML attribute handling for your snippets and templates.

README 文档

README

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.

Note

This plugin is completely free and published under the MIT license. However, if you are using it in a commercial project and want to help me keep up with maintenance, please consider to ❤️ sponsor me for securing the continued development of the plugin.

Requirements

  • Kirby 4/5 (use version 1.x for Kirby 3 installations)
  • PHP 8.3 (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
  ],
]) ?>

You can also use magic invoke method by calling the Attributes object like a function. This is basically syntactic sugar for passing-down attributes the snipept include chain:

<?php

// some parameter passed to the base button snippet for
// overriding the button type
$attr = attributes([
	'type' => 'submit' 
]);

?>

<button <?= $attr([
	'type' =>  'button'
]) ?>>[…]</button>

This is the same as:

<?php

$attr = attributes([
	'class' => 'submit'
]);

?>

<button <?= attributes([
	'type' =>  'button'
])->merge($attr) ?>>[…]</button>

Output is:

<button type="submit">[…]</button>

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>

Custom Snippet component

It makes a lot of sense to standardize the usage of this plugin across your project and to reduce boilerplate code. A custom snippet component can help with that by ensuring that the $attr variable is always available:

<?php

use Kirby\Cms\App;
use Kirby\Template\Snippet;

App::plugin('my/site', [
	'components' => [
		'snippet' => function (
			App $kirby,
			string $name,
			array $data = [],
			bool $slots = false
		): Snippet|string {
			// ensure that `$attr` is always available
			$data['attr'] = attributes($data['attr'] ?? []);

			return $kirby->nativeComponent('snippet')(
				$kirby,
				$name,
				$data,
				$slots
			);
		},
	],
]);

No longer do your snippets have to include something like $attr ??= [] at the top:

# site/snippets/components/button.php

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

You can event take this a step further by invoking $attr() as a function, which ist a shortcut for attributes([…])->merge($attr):

# site/snippets/components/button.php

<button <?= $attr([
  'class' => 'button',
]) ?>>
  [...]
</button>

License

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

统计信息

  • 总下载量: 8.12k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 23
  • 点击次数: 0
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 23
  • Watchers: 2
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-11-29

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固