Skip to content

Commit

Permalink
tag component
Browse files Browse the repository at this point in the history
  • Loading branch information
tborychowski committed Sep 23, 2023
1 parent 6d9ca84 commit 0fc3fe2
Show file tree
Hide file tree
Showing 43 changed files with 543 additions and 157 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Changelog
=========

## v9.1.0 *(2023-09-22)*
- New component `InputRating`.
- New components `InputRating`, `Tag`.
- Small bugfixes and improvements.


Expand Down
1 change: 1 addition & 0 deletions docs-src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export { Tree } from './tree';

export { Menu } from './menu';
export { Icon } from './icon';
export { Tag } from './tag';
export { Utils } from './utils';
export { Splitter } from './splitter';
export { ColorPalette } from './color-palette';
1 change: 1 addition & 0 deletions docs-src/components/input/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './input-number';
export * from './input-password';
export * from './input-rating';
export * from './input-search';
export * from './input-tag';
export * from './input-text';
export * from './radio';
export * from './select';
Expand Down
60 changes: 60 additions & 0 deletions docs-src/components/input/input-tag/InputTag.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<h2>Input Tag</h2>


<h3>Normal</h3>
<InputTag bind:value="{val}" />
<p>Input value: {val}</p>

<h3>Disabled</h3>
<InputTag disabled value="disabled value" on:input="{oninput}" />


<h3>Label on the left</h3>
<InputTag label="Label is on the left" labelOnTheLeft="true"/>



<CodeExample html="{exampleHtml}" />

<API props="{apiProps}"/>


<script>
import { InputTag } from '../../../../src';
import { CodeExample } from '../../../code-example';
import { API } from '../../../api-table';
const apiProps = [
{ name: 'class', type: 'string', description: 'Additional css class name to be added to the component.' },
{ name: 'disabled', description: 'Make the input disabled.' },
{ name: 'id', type: 'string', description: 'Assign ID to the underlying input.' },
{ name: 'info', type: 'string', description: 'Show info message above the input.' },
{ name: 'error', type: 'string', description: 'Error message to show above the input.' },
{ name: 'name', type: 'string', description: 'Assign title to the underlying input.' },
{ name: 'label', type: 'string', description: 'Label for the input.' },
{ name: 'labelOnTheLeft', type: ['true', 'false'], default: 'false', description: 'Put label to the left of the input (instead of at the top). Usually in longer forms, to align labels and inputs, hence input also gets <em>width: 100%</em>, as it will be constraint by the form container.' },
{ name: 'placeholder', type: 'string', description: 'Assign placeholder to the underlying input.' },
{ name: 'required', description: 'Mark the input as <i>aria-required</i>. The actual validation must be done in the consumer.' },
{ name: 'title', type: 'string', description: 'Assign title to the underlying input.' },
{ name: 'value', type: ['string', 'number'], description: 'Initial value of the input.' },
{ name: 'bind:element', type: 'element', description: 'Exposes the HTML element of the component.' },
{ name: 'bind:inputElement', type: 'element', description: 'Exposes the HTML element of the underlying input.' },
{ name: 'on:change', type: 'function', description: 'Triggered after the value changes and the focus leaves the input.' },
{ name: 'on:input', type: 'function', description: 'Triggered as soon as the input value changes.' },
];
const exampleHtml = `
<InputTag label="Email" error="Invalid email" value="admin" on:change="{onChange}" />
<script>
function onChange (e) {
console.log('value', e.target.value);
}
&lt;/script>
`;
let val = '';
</script>
1 change: 1 addition & 0 deletions docs-src/components/input/input-tag/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as InputTag } from './InputTag.svelte';
1 change: 1 addition & 0 deletions docs-src/components/tag/Tag.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.panel p { margin: 0; }
63 changes: 63 additions & 0 deletions docs-src/components/tag/Tag.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<h2>Tag</h2>

<h3>Normal</h3>
<Tag>Tag 123</Tag>


<h3>With icon</h3>
<Tag icon="close">Closable tag</Tag>
<Tag icon="plus">Add tag</Tag>


<h3>Colourful</h3>
<Tag color="info">Info</Tag>
<Tag color="warning">Warning</Tag>
<Tag color="danger">Danger</Tag>
<Tag color="success">Success</Tag>
<Tag color="#ac6453">Custom color</Tag>


<h3>Round</h3>
<Tag round>Round tag</Tag>


<h3>With click action</h3>
<Tag on:click="{onclick}">Click me</Tag>


<CodeExample html="{exampleHtml}" />
<API props="{apiProps}"/>


<script>
import { Tag } from '../../../src';
import { API } from '../../api-table';
import { CodeExample } from '../../code-example';
const apiProps = [
{ name: 'class', type: 'string', description: 'Additional css class name to be added to the component.' },
{ name: 'color', type: 'string', description: 'Tag color. Standard variations are included (info, warning, danger, success). A color hash or name can also be provided.' },
{ name: 'icon', type: 'string', description: 'Icon name to display in the tag.' },
{ name: 'bind:element', type: 'element', description: 'Exposes the HTML element of the component.' },
{ name: 'on:click', type: 'function', description: 'Triggered when the tag is clicked.' },
];
const exampleHtml = `
<Tag icon="close">Closable tag</Tag>
<Tag color="success">Success</Tag>
<Tag color="#132231">Custom color</Tag>
<Tag on:click="{onclick}">Click me</Tag>
<script>
function onclick () {
alert('Clicked!');
}
&lt;/script>
`;
function onclick () {
alert('Clicked!');
}
</script>
1 change: 1 addition & 0 deletions docs-src/components/tag/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Tag } from './Tag.svelte';
2 changes: 1 addition & 1 deletion docs-src/nav/Nav.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ aside {
padding: 0 1rem calc(100lvh - 100svh);

overscroll-behavior: contain;
z-index: 60;
}

menu {
Expand Down Expand Up @@ -75,6 +74,7 @@ menu a.active { background-color: var(--ui-color-highlight); }
aside {
box-shadow: 2px 1px 10px #0006;
transform: translateX(calc(var(--sidebar-width) * -1));
z-index: 60;

--sidebar-elastic-padding: 80px;
width: calc(var(--sidebar-width) + var(--sidebar-elastic-padding));
Expand Down
2 changes: 2 additions & 0 deletions docs-src/nav/Nav.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<NavItem name="Input Password" {active} />
<NavItem name="Input Rating" {active} />
<NavItem name="Input Search" {active} />
<NavItem name="Input Tag" {active} />
<NavItem name="Input Text" {active} />
<NavItem name="Radio" {active} />
<NavItem name="Select" {active} />
Expand All @@ -50,6 +51,7 @@

<h3>Generic</h3>
<NavItem name="Menu" {active} />
<NavItem name="Tag" {active} />
<NavItem name="Icon" {active} />
<NavItem name="Utils" {active} />
<!-- <NavItem name="Splitter" {active} /> -->
Expand Down
2 changes: 1 addition & 1 deletion docs-src/pages/changelog.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1>Changelog</h1>
<h2>v9.1.0 <em>(2023-09-22)</em></h2>
<ul>
<li>New component <code>InputRating</code>.</li>
<li>New components <code>InputRating</code>, <code>Tag</code>.</li>
<li>Small bugfixes and improvements.</li>
</ul>
<h2>v9.0.5 <em>(2023-09-22)</em></h2>
Expand Down
2 changes: 1 addition & 1 deletion docs/docs.css

Large diffs are not rendered by default.

233 changes: 126 additions & 107 deletions docs/docs.js

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions docs/docs.js.map

This file was deleted.

2 changes: 1 addition & 1 deletion docs/ui.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"url": "https://github.com/perfect-things/ui.git"
},
"scripts": {
"test-coverage": "jest --coverage",
"test-coverage": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-vm-modules jest --coverage",
"test": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-vm-modules jest",
"changelog": "marked --gfm -i CHANGELOG.md -o docs-src/pages/changelog.svelte",
"lint": "gulp lint",
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export * from './popover/index.js';
export * from './push-button/index.js';
export * from './splitter/index.js';
export * from './table/index.js';
export * from './tag/index.js';
export * from './tooltip/index.js';
export * from './tree/index.js';
export * from './utils.js';
Expand Down
1 change: 1 addition & 0 deletions src/input/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './input-number';
export * from './input-password';
export * from './input-rating';
export * from './input-search';
export * from './input-tag';
export * from './input-text';
export * from './label';
export * from './radio';
Expand Down
12 changes: 12 additions & 0 deletions src/input/input-tag/InputTag.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.input-search input {
padding-left: calc(2rem + 6px);
padding-right: 2rem;
appearance: none;
-webkit-appearance: none;
}
::-webkit-search-cancel-button { display: none; }

.input-search .input-row>.icon { top: 1px; }

.input-search-button { display: none; }
.input-search-button.visible { display: inline-flex; }
80 changes: 80 additions & 0 deletions src/input/input-tag/InputTag.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<div
class="input input-search {className}"
class:has-error="{error}"
class:has-value="{value !== ''}"
class:label-on-the-left="{labelOnTheLeft === true || labelOnTheLeft === 'true'}"
bind:this="{element}">

<Label {label} {disabled} for="{_id}"/>
<Info msg="{info}" />

<div class="input-inner" class:disabled>
<InputError id="{errorMessageId}" msg="{error}" />

<div class="input-row">
<Icon name="tag"/>

<input
autocomplete="off"
type="text"
{...props}
{disabled}
id="{_id}"
aria-invalid="{error}"
aria-errormessage="{error ? errorMessageId : undefined}"
aria-required="{required}"
bind:this="{inputElement}"
bind:value="{value}"
on:input
on:keydown="{onkeydown}"
on:change
on:focus
on:blur>

<Button link
icon="close"
class="input-search-button {value !== '' && !disabled ? 'visible' : ''}"
on:click="{clear}"/>
</div>
</div>
</div>

<script>
import { pluck, guid } from '../../utils';
import { Button } from '../../button';
import { Icon } from '../../icon';
import { Info } from '../../info-bar';
import { InputError } from '../input-error';
import { Label } from '../label';
$:props = pluck($$props, ['title', 'name', 'placeholder']);
let className = '';
export { className as class };
export let id = '';
export let required = undefined;
export let disabled = false;
export let value = '';
export let label = '';
export let error = undefined;
export let info = undefined;
export let labelOnTheLeft = false;
export let element = undefined;
export let inputElement = undefined;
$:_id = id || name || guid();
const errorMessageId = guid();
function clear () {
value = '';
}
function onkeydown (event) {
if (event.key === 'Escape') clear();
}
</script>
1 change: 1 addition & 0 deletions src/input/input-tag/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as InputTag } from './InputTag.svelte';
34 changes: 34 additions & 0 deletions src/tag/Tag.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.ui-tag {
border: 1px solid var(--ui-color-border);
background: var(--ui-color-secondary);
border-radius: var(--ui-border-radius);
padding: 0.2rem 0.5rem;
display: inline-flex;
align-items: center;
gap: 0.1rem;
height: 1.6rem;
cursor: default;
color: var(--ui-color-text);
}

.ui-tag .icon { width: 1.2rem; height: 1.2rem; }

.ui-tag:focus-visible {
border-color: var(--ui-color-accent);
box-shadow: var(--ui-shadow-focus);
outline: 1px solid transparent;
}

.ui-tag.dark { color: #fff; }

.ui-tag.round { border-radius: var(--ui-border-radius-xl); }

.ui-tag.info { background-color: var(--ui-color-info); }
.ui-tag.success { background-color: var(--ui-color-success); }
.ui-tag.danger { background-color: var(--ui-color-danger); }
.ui-tag.warning { background-color: var(--ui-color-warning); }

.ui-tag.info,
.ui-tag.success,
.ui-tag.danger,
.ui-tag.warning { color: var(--ui-color-text); }
36 changes: 36 additions & 0 deletions src/tag/Tag.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="ui-tag {className} {colorClass}"
class:round
class:dark="{color && isColorDark(color)}"
style="{color ? `background-color: ${color};` : ''}"
role="button"
tabindex="0"
bind:this="{element}"
on:click="{onclick}">
{#if icon}
<Icon name="{icon}"/>
{/if}
<slot/>
</div>

<script>
import { createEventDispatcher } from 'svelte';
import { Icon } from '../icon';
import { isColorDark } from '../utils';
const dispatch = createEventDispatcher();
let className = '';
export { className as class };
export let round = false;
export let icon = undefined;
export let color = undefined;
export let element = undefined;
$: colorClass = (['info', 'warning', 'danger', 'success'].includes(color) ? color : '');
function onclick () {
dispatch('click', { target: element });
}
</script>
1 change: 1 addition & 0 deletions src/tag/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Tag } from './Tag.svelte';
Loading

0 comments on commit 0fc3fe2

Please sign in to comment.