Skip to content

Commit 8ec621c

Browse files
authored
IBX-7899: Chip component (#57)
1 parent 7350356 commit 8ec621c

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Base } from '../partials';
2+
3+
interface ChipConfig {
4+
onDelete?: (event: MouseEvent) => void;
5+
}
6+
7+
export default class Chip extends Base {
8+
private deleteButton: HTMLButtonElement | null;
9+
private onDelete?: (event: MouseEvent) => void;
10+
11+
constructor(container: HTMLDivElement, config: ChipConfig = {}) {
12+
super(container);
13+
14+
this.deleteButton = this._container.querySelector('.ids-chip__delete');
15+
this.onDelete = config.onDelete;
16+
}
17+
18+
protected handleDelete(event: MouseEvent): void {
19+
event.stopPropagation();
20+
21+
if (this.onDelete) {
22+
this.onDelete(event);
23+
}
24+
}
25+
26+
protected initDeleteButton(): void {
27+
if (this.deleteButton) {
28+
this.deleteButton.addEventListener('click', this.handleDelete.bind(this));
29+
}
30+
}
31+
32+
public init(): void {
33+
super.init();
34+
this.initDeleteButton();
35+
}
36+
}

src/bundle/Resources/translations/ibexa_design_system_twig.en.xliff

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
77
</header>
88
<body>
9+
<trans-unit id="09975764bd5f4def61682516d7430651e5b8779e" resname="ibexa.chip.delete-btn.label">
10+
<source>Delete</source>
11+
<target state="new">Delete</target>
12+
<note>key: ibexa.chip.delete-btn.label</note>
13+
</trans-unit>
914
<trans-unit id="61c7070a29f932eb0b1a343509d049aa52c92c09" resname="ibexa.clear-btn.label">
1015
<source>Clear</source>
1116
<target state="new">Clear</target>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{% trans_default_domain 'ibexa_design_system_twig' %}
2+
3+
{% set chip_classes =
4+
html_classes(
5+
'ids-chip',
6+
{
7+
'ids-chip--error': error,
8+
'ids-chip--disabled': disabled,
9+
},
10+
attributes.render('class') ?? ''
11+
)
12+
%}
13+
{% set delete_msg = 'ibexa.chip.delete-btn.label'|trans|desc('Delete') %}
14+
15+
<div tabIndex={{ disabled ? -1 : 0 }} class="{{ chip_classes }}" aria-disabled="{{ disabled ? 'true' : 'false' }}" {{ attributes }}>
16+
<div class="ids-chip__content">
17+
{{ block('content') }}
18+
</div>
19+
{% if is_deletable %}
20+
<twig:ibexa:button
21+
type="tertiary-alt"
22+
size="small"
23+
icon="discard"
24+
class="ids-chip__delete"
25+
disabled="{{ disabled }}"
26+
:aria-label="delete_msg"
27+
/>
28+
{% endif %}
29+
</div>

src/lib/Twig/Components/Chip.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\DesignSystemTwig\Twig\Components;
10+
11+
use Symfony\Component\OptionsResolver\OptionsResolver;
12+
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
13+
use Symfony\UX\TwigComponent\Attribute\ExposeInTemplate;
14+
use Symfony\UX\TwigComponent\Attribute\PreMount;
15+
16+
#[AsTwigComponent('ibexa:chip')]
17+
final class Chip
18+
{
19+
public bool $error = false;
20+
21+
#[ExposeInTemplate('is_deletable')]
22+
public bool $isDeletable = true;
23+
24+
public bool $disabled = false;
25+
26+
/**
27+
* @param array<string, mixed> $props
28+
*
29+
* @return array<string, mixed>
30+
*/
31+
#[PreMount]
32+
public function validate(array $props): array
33+
{
34+
$resolver = new OptionsResolver();
35+
$resolver->setIgnoreUndefined();
36+
$resolver
37+
->define('error')
38+
->allowedTypes('bool')
39+
->default(false);
40+
$resolver
41+
->define('isDeletable')
42+
->allowedTypes('bool')
43+
->default(true);
44+
$resolver
45+
->define('disabled')
46+
->allowedTypes('bool')
47+
->default(false);
48+
49+
return $resolver->resolve($props) + $props;
50+
}
51+
}

0 commit comments

Comments
 (0)