Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d9fbc3aed | ||
|
|
14fd9ca2ec | ||
|
|
93c4dd1e64 | ||
|
|
61eaa62406 | ||
|
|
bcd97f20a3 | ||
|
|
9c1c0c1ba1 | ||
|
|
42fcaef53c | ||
|
|
beeeb2bf50 | ||
|
|
f0c19dad5e | ||
|
|
62e279e0c9 | ||
|
|
f6f3c64f25 | ||
|
|
b7a3f273a3 | ||
|
|
03e2e39185 | ||
|
|
9141e21a02 | ||
|
|
b25bbfd33c | ||
|
|
eebd38d17f | ||
|
|
2a7230298e | ||
|
|
ebc73e1b24 | ||
|
|
6883382420 | ||
|
|
fc9161b2d8 | ||
|
|
623fc60af2 |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,6 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## [X.X.X] - XXXX-XX-XX
|
||||
## [1.1.0] - 2025-11-13
|
||||
- Add new badge colours
|
||||
- Tweak error message
|
||||
|
||||
## [1.0.0] - 2025-02-26
|
||||
- Add label attribute to set badge text
|
||||
- Rename `Badge` enum to `BadgeColour`
|
||||
- Pass misc attributes to badge template
|
||||
- Update documentation and docblocks
|
||||
|
||||
## [0.1.1] - 2024-09-18
|
||||
- Fixed black badge text colour not being black
|
||||
|
||||
8
LICENSE
8
LICENSE
@@ -1 +1,7 @@
|
||||
License
|
||||
Copyright © 2025-present PCM Systems
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
16
Makefile
16
Makefile
@@ -1,16 +0,0 @@
|
||||
PHP = docker compose run php
|
||||
|
||||
.PHONY: composer_install composer_update static_analysis tests
|
||||
|
||||
composer_install:
|
||||
@$(PHP) composer install
|
||||
|
||||
composer_update:
|
||||
@$(PHP) composer update
|
||||
|
||||
static_analysis:
|
||||
@$(PHP) vendor/bin/psalm
|
||||
|
||||
tests:
|
||||
@$(PHP) rm -rf var/cache
|
||||
@$(PHP) vendor/bin/phpunit
|
||||
29
README.md
29
README.md
@@ -16,30 +16,30 @@ Create badges from objects or as standalone elements.
|
||||
|
||||
<br>
|
||||
|
||||
# Badgeable interface
|
||||
# Creating badges with `BadgeableInterface`
|
||||
|
||||
Any object that you would like to be able to be turned into a badge must implement `BadgeableInterface`.
|
||||
|
||||
This interface specifies a single method `getBadgeColour()` and is used to determine what colour the badge should be rendered as.
|
||||
This interface specifies a single method `getBadgeColour()` which expects an instance of the enum `BadgeColour` to be returned and is used to determine the colour of the rendered badge.
|
||||
|
||||
This method can contain as much logic in it as you'd like to return different colours of badge under different circumstances. EG:
|
||||
|
||||
```php
|
||||
// Job.php
|
||||
|
||||
public function getBadgeColour(): Badge
|
||||
public function getBadgeColour(): BadgeColour
|
||||
{
|
||||
return match ($this->getKind()) {
|
||||
JobKind::Investigation => Badge::BLUE,
|
||||
JobKind::Interrogation => Badge::RED,
|
||||
JobKind::Shootout => Badge::BLACK,
|
||||
JobKind::SipWhiskey => Badge::FOREST,
|
||||
default => Badge::GREY
|
||||
JobKind::Investigation => BadgeColour::BLUE,
|
||||
JobKind::Interrogation => BadgeColour::RED,
|
||||
JobKind::Shootout => BadgeColour::BLACK,
|
||||
JobKind::SipWhiskey => BadgeColour::FOREST,
|
||||
default => BadgeColour::GREY
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
You then specify the object using the `obj` prop when rendering the badge:
|
||||
You then specify the object using the `:obj` prop when rendering the badge:
|
||||
|
||||
```twig
|
||||
{# job.html.twig #}
|
||||
@@ -74,7 +74,16 @@ obj="{{ job.kind }}"
|
||||
|
||||
`outline` - A boolean attribute that changes the style of the badge to an outline.
|
||||
|
||||
`class` - Extra classes you want to add to the badge element. These will override the base classes in case of conflicts.
|
||||
`class` - Extra classes you want to add to the badge element. These are merged with the badge base classes taking priority in case of conflicts.
|
||||
|
||||
`label` - Badge label text. Content inside the content block will be prioritised over the label attribute if present.
|
||||
```php
|
||||
{# Both of these render the same markup. #}
|
||||
|
||||
<twig:Pcm:Badge colour="red" label="Warning!" />
|
||||
|
||||
<twig:Pcm:Badge colour="red">Warning!<twig:Pcm:Badge>
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<div class="{{ this.finalClasses }}">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<div {{ attributes }} class="{{ this.finalClasses }}">
|
||||
{% if block('content') is not empty %}
|
||||
{% block content %}{% endblock %}
|
||||
{% else %}
|
||||
{{- this.label -}}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
15
justfile
Normal file
15
justfile
Normal file
@@ -0,0 +1,15 @@
|
||||
php := "docker compose run php"
|
||||
|
||||
composer_install:
|
||||
@{{php}} composer install
|
||||
|
||||
composer_update:
|
||||
@{{php}} composer update
|
||||
|
||||
static_analysis:
|
||||
@{{php}} vendor/bin/psalm
|
||||
|
||||
tests:
|
||||
@{{php}} rm -rf var/cache
|
||||
@{{php}} vendor/bin/phpunit
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pcm\BadgeBundle\Enum;
|
||||
|
||||
use Pcm\BadgeBundle\Model\BadgePalette;
|
||||
|
||||
enum Badge
|
||||
{
|
||||
case AMBER;
|
||||
case BLACK;
|
||||
case BLUE;
|
||||
case DEFAULT;
|
||||
case FOREST;
|
||||
case GREEN;
|
||||
case GREY;
|
||||
case MAROON;
|
||||
case OCHRE;
|
||||
case ORANGE;
|
||||
case RED;
|
||||
case ROSE;
|
||||
case STRIPE;
|
||||
case YELLOW;
|
||||
|
||||
public function getPalette(): BadgePalette
|
||||
{
|
||||
return match ($this) {
|
||||
$this::RED => new BadgePalette('text-red-600', 'border-red-600', 'bg-red-600'),
|
||||
$this::MAROON => new BadgePalette('text-red-900', 'border-red-900', 'bg-red-900'),
|
||||
$this::BLUE => new BadgePalette('text-sky-700', 'border-sky-700', 'bg-sky-700'),
|
||||
$this::FOREST => new BadgePalette('text-green-800', 'border-green-800', 'bg-green-800'),
|
||||
$this::GREEN => new BadgePalette('text-green-600', 'border-green-600', 'bg-green-600'),
|
||||
$this::OCHRE => new BadgePalette('text-yellow-800', 'border-yellow-800', 'bg-yellow-800'),
|
||||
$this::ORANGE => new BadgePalette('text-orange-500', 'border-orange-500', 'bg-orange-500'),
|
||||
$this::AMBER => new BadgePalette('text-amber-500', 'border-amber-500', 'bg-amber-500'),
|
||||
$this::ROSE => new BadgePalette('text-rose-600', 'border-rose-600', 'bg-rose-600'),
|
||||
$this::GREY => new BadgePalette('text-neutral-400', 'border-neutral-400', 'bg-neutral-400'),
|
||||
$this::YELLOW => new BadgePalette('text-yellow-500', 'border-yellow-500', 'bg-yellow-500'),
|
||||
$this::STRIPE => new BadgePalette('text-indigo-500', 'border-indigo-500', 'bg-indigo-500'),
|
||||
$this::BLACK => new BadgePalette('text-zinc-900', 'border-zinc-900', 'bg-zinc-900'),
|
||||
$this::DEFAULT => new BadgePalette('text-primary', 'border-primary', 'bg-primary'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
66
src/Enum/BadgeColour.php
Normal file
66
src/Enum/BadgeColour.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pcm\BadgeBundle\Enum;
|
||||
|
||||
use Pcm\BadgeBundle\Model\BadgePalette;
|
||||
|
||||
enum BadgeColour
|
||||
{
|
||||
case ACCENT;
|
||||
case AMBER;
|
||||
case BLACK;
|
||||
case BLUE;
|
||||
case BROWN;
|
||||
case DEFAULT;
|
||||
case EMERALD;
|
||||
case FOREST;
|
||||
case FUCHSIA;
|
||||
case GOLD;
|
||||
case GREEN;
|
||||
case GREY;
|
||||
case LIME;
|
||||
case RED;
|
||||
case ROSE;
|
||||
case SKY;
|
||||
case MAROON;
|
||||
case NAVY;
|
||||
case OCHRE;
|
||||
case ORANGE;
|
||||
case PINK;
|
||||
case STRIPE;
|
||||
case YELLOW;
|
||||
case ZINC;
|
||||
|
||||
public function getPalette(): BadgePalette
|
||||
{
|
||||
return match ($this) {
|
||||
$this::ACCENT => new BadgePalette('text-accent', 'border-accent', 'bg-accent'),
|
||||
$this::AMBER => new BadgePalette('text-amber-500', 'border-amber-500', 'bg-amber-500'),
|
||||
$this::BLACK => new BadgePalette('text-zinc-900', 'border-zinc-900', 'bg-zinc-900'),
|
||||
$this::BLUE => new BadgePalette('text-sky-700', 'border-sky-700', 'bg-sky-700'),
|
||||
$this::BROWN => new BadgePalette('text-orange-900', 'border-orange-900', 'bg-orange-900'),
|
||||
$this::DEFAULT => new BadgePalette('text-primary', 'border-primary', 'bg-primary'),
|
||||
$this::EMERALD => new BadgePalette('text-emerald-600', 'border-emerald-600', 'bg-emerald-600'),
|
||||
$this::FOREST => new BadgePalette('text-green-800', 'border-green-800', 'bg-green-800'),
|
||||
$this::FUCHSIA => new BadgePalette('text-fuchsia-500', 'border-fuchsia-500', 'bg-fuchsia-500'),
|
||||
$this::GOLD => new BadgePalette('text-yellow-600', 'border-yellow-600', 'bg-yellow-600'),
|
||||
$this::GREEN => new BadgePalette('text-green-600', 'border-green-600', 'bg-green-600'),
|
||||
$this::GREY => new BadgePalette('text-neutral-400', 'border-neutral-400', 'bg-neutral-400'),
|
||||
$this::LIME => new BadgePalette('text-lime-600', 'border-lime-600', 'bg-lime-600'),
|
||||
$this::RED => new BadgePalette('text-red-600', 'border-red-600', 'bg-red-600'),
|
||||
$this::ROSE => new BadgePalette('text-rose-600', 'border-rose-600', 'bg-rose-600'),
|
||||
$this::SKY => new BadgePalette('text-sky-500', 'border-sky-500', 'bg-sky-500'),
|
||||
$this::MAROON => new BadgePalette('text-red-900', 'border-red-900', 'bg-red-900'),
|
||||
$this::NAVY => new BadgePalette('text-blue-900', 'border-blue-900', 'bg-blue-900'),
|
||||
$this::OCHRE => new BadgePalette('text-yellow-800', 'border-yellow-800', 'bg-yellow-800'),
|
||||
$this::ORANGE => new BadgePalette('text-orange-500', 'border-orange-500', 'bg-orange-500'),
|
||||
$this::PINK => new BadgePalette('text-pink-400', 'border-pink-400', 'bg-pink-400'),
|
||||
$this::STRIPE => new BadgePalette('text-indigo-500', 'border-indigo-500', 'bg-indigo-500'),
|
||||
$this::YELLOW => new BadgePalette('text-yellow-500', 'border-yellow-500', 'bg-yellow-500'),
|
||||
$this::ZINC => new BadgePalette('text-zinc-500', 'border-zinc-500', 'bg-zinc-500'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace Pcm\BadgeBundle\Interface;
|
||||
|
||||
use Pcm\BadgeBundle\Enum\Badge;
|
||||
use Pcm\BadgeBundle\Enum\BadgeColour;
|
||||
|
||||
/**
|
||||
* Enables this class to be rendered as a badge using the Badge and BadgeOutline Twig components.
|
||||
* Allows rendering the implementing class as a badge using the PCM Badge twig component.
|
||||
*/
|
||||
interface BadgeableInterface
|
||||
{
|
||||
public function getBadgeColour(): Badge;
|
||||
/**
|
||||
* Get the badge colour that should be used when rendering this object as a badge.
|
||||
*
|
||||
* @return BadgeColour Colour of badge to render
|
||||
*/
|
||||
public function getBadgeColour(): BadgeColour;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,5 +15,7 @@ final readonly class BadgePalette
|
||||
* @param string $backgroundColourClass Background colour Tailwind class
|
||||
*/
|
||||
public function __construct(public string $textColourClass, public string $borderColourClass, public string $backgroundColourClass)
|
||||
{}
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,36 +4,39 @@ declare(strict_types=1);
|
||||
|
||||
namespace Pcm\BadgeBundle\Twig\Component;
|
||||
|
||||
use Pcm\BadgeBundle\Enum\Badge as EnumBadge;
|
||||
use Pcm\BadgeBundle\Enum\BadgeColour;
|
||||
use Pcm\BadgeBundle\Interface\BadgeableInterface;
|
||||
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
|
||||
use TailwindMerge\TailwindMerge;
|
||||
|
||||
#[AsTwigComponent(name: 'Pcm:Badge', template: "@PcmBadge/Badge.html.twig")]
|
||||
#[AsTwigComponent(name: 'Pcm:Badge', template: '@PcmBadge/Badge.html.twig')]
|
||||
final class Badge
|
||||
{
|
||||
public string $finalClasses;
|
||||
public ?string $label = null;
|
||||
|
||||
public function __construct(private string $baseClasses)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ?BadgeableInterface $obj The object to be converted into a badge.
|
||||
* @param ?BadgeableInterface $obj the object to be converted into a badge
|
||||
* @param ?string $class Extra classes to add to the badge element.
|
||||
* These will override the base classes in case
|
||||
* of conflicts.
|
||||
* @param ?string $colour Specify the colour of an objectless badge.
|
||||
* @param bool $outline If the badge should be rendered as an outline.
|
||||
* @param ?string $colour specify the colour of an objectless badge
|
||||
* @param bool $outline if the badge should be rendered as an outline
|
||||
*/
|
||||
public function mount(?BadgeableInterface $obj = null, ?string $class = null, string $colour = null, bool $outline = false): void
|
||||
public function mount(?BadgeableInterface $obj = null, ?string $class = null, ?string $colour = null, ?string $label = null, bool $outline = false): void
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
if (!$obj && !$colour) {
|
||||
throw new \RuntimeException(sprintf("You must specify either a colour an instance of \"%s\".", BadgeableInterface::class));
|
||||
throw new \RuntimeException(sprintf('You must specify either a colour an instance of "%s".', BadgeableInterface::class));
|
||||
}
|
||||
|
||||
if ($obj && $colour) {
|
||||
throw new \RuntimeException(sprintf("You have specified both the colour \"%s\" and an instance of \"%s\". Please use one or the other.", $colour, $obj::class));
|
||||
throw new \RuntimeException(sprintf('You have specified both the colour "%s" and an instance of "%s". Please use one or the other.', $colour, $obj::class));
|
||||
}
|
||||
|
||||
if ($obj) {
|
||||
@@ -41,15 +44,15 @@ final class Badge
|
||||
}
|
||||
|
||||
if ($colour) {
|
||||
$cases = array_map(fn(EnumBadge $b) => strtolower($b->name), EnumBadge::cases());
|
||||
$cases = array_map(fn (BadgeColour $b) => strtolower($b->name), BadgeColour::cases());
|
||||
|
||||
if (!in_array($colour, $cases)) {
|
||||
$formattedCases = implode(", ", array_map(fn(string $s) => '"'.$s.'"', $cases));
|
||||
throw new \RuntimeException(sprintf('"%s" is not a valid Badge colour. Available options are: %s', $colour, $formattedCases));
|
||||
$formattedCases = implode(', ', array_map(fn (string $s) => '"'.$s.'"', $cases));
|
||||
throw new \RuntimeException(sprintf('"%s" is not a valid badge colour. Available options are: %s.', $colour, $formattedCases));
|
||||
}
|
||||
|
||||
$colour = strtoupper($colour);
|
||||
$palette = EnumBadge::{$colour}->getPalette();
|
||||
$colour = strtoupper($colour);
|
||||
$palette = BadgeColour::{$colour}->getPalette();
|
||||
}
|
||||
|
||||
$merger = TailwindMerge::instance();
|
||||
|
||||
Reference in New Issue
Block a user