Skip to content

Commit

Permalink
feat: web components for textbox and checkbox
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbert committed Aug 9, 2021
1 parent 6dd7431 commit 51b92d8
Show file tree
Hide file tree
Showing 9 changed files with 359 additions and 0 deletions.
44 changes: 44 additions & 0 deletions components/checkbox/stencil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

import { Component, Event, EventEmitter, Prop, State, h } from "@stencil/core";
import clsx from "clsx";

@Component({
tag: "utrecht-checkbox",
styleUrl: "bem.css",
shadow: true,
})
export class Checkbox {
@Prop({ reflect: true }) disabled: boolean = false;
@Prop({ attribute: "readonly", reflect: true }) readOnly: boolean = false;
@State() checked: boolean = false;
@State() value: string = "";
@Event() utrechtBlur: EventEmitter;
@Event() utrechtChange: EventEmitter;
@Event() utrechtFocus: EventEmitter;
@Event() utrechtInput: EventEmitter;

render() {
const { checked, disabled, value } = this;

return (
<input
class={clsx("utrecht-checkbox")}
type="checkbox"
checked={checked}
disabled={disabled}
value={value}
onBlur={(evt) => this.utrechtBlur.emit(evt)}
onChange={(evt) => this.utrechtChange.emit(evt)}
onFocus={(evt) => this.utrechtFocus.emit(evt)}
onInput={(evt) => {
this.checked = (evt.target as HTMLInputElement).checked;
this.utrechtInput.emit(evt);
}}
/>
);
}
}
8 changes: 8 additions & 0 deletions components/form-field-checkbox/stencil.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

@import "./bem";
@import "../form-label/bem";
@import "../checkbox/bem";
54 changes: 54 additions & 0 deletions components/form-field-checkbox/stencil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

import { Component, Event, EventEmitter, Prop, State, h } from "@stencil/core";
import clsx from "clsx";

@Component({
tag: "utrecht-form-field-checkbox",
styleUrl: "stencil.scss",
shadow: true,
})
export class FormFieldCheckbox {
@Prop() label: boolean = false;
@Prop({ reflect: true }) disabled: boolean = false;
@Prop({ attribute: "readonly", reflect: true }) readOnly: boolean = false;
@State() checked: boolean = false;
@State() value: string = "";
@Event() utrechtBlur: EventEmitter;
@Event() utrechtChange: EventEmitter;
@Event() utrechtFocus: EventEmitter;
@Event() utrechtInput: EventEmitter;

render() {
const { checked, disabled, value } = this;

return (
<div class="utrecht-form-field-checkbox">
<input
id="input"
class={clsx("utrecht-checkbox")}
type="checkbox"
checked={checked}
disabled={disabled}
value={value}
onBlur={(evt) => this.utrechtBlur.emit(evt)}
onChange={(evt) => this.utrechtChange.emit(evt)}
onFocus={(evt) => this.utrechtFocus.emit(evt)}
onInput={(evt) => {
this.checked = (evt.target as HTMLInputElement).checked;
this.utrechtInput.emit(evt);
}}
/>
<label
class={clsx("utrecht-form-field-checkbox__label", "utrecht-form-label", "utrecht-form-label--checkbox")}
htmlFor="input"
>
<slot></slot>
</label>
</div>
);
}
}
8 changes: 8 additions & 0 deletions components/form-field-textbox/bem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

.utrecht-form-field-textbox {
font-family: var(--utrecht-document-font-family, inherit);
}
8 changes: 8 additions & 0 deletions components/form-field-textbox/stencil.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

@import "./bem";
@import "../form-label/bem";
@import "../textbox/bem";
57 changes: 57 additions & 0 deletions components/form-field-textbox/stencil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

import { Component, Event, EventEmitter, Prop, State, h } from "@stencil/core";
import clsx from "clsx";

@Component({
tag: "utrecht-form-field-textbox",
styleUrl: "stencil.scss",
shadow: true,
})
export class FormFieldTextbox {
@Prop({ reflect: true }) disabled: boolean = false;
@Prop({ reflect: true }) invalid: boolean = false;
@Prop({ attribute: "readonly", reflect: true }) readOnly: boolean = false;
@Prop() placeholder: string = "";
@State() value: string = "";
@Event() utrechtBlur: EventEmitter;
@Event() utrechtChange: EventEmitter;
@Event() utrechtFocus: EventEmitter;
@Event() utrechtInput: EventEmitter;

render() {
const { disabled, invalid, placeholder, readOnly, value } = this;

return (
<div class="utrecht-form-field-textbox">
<input
id="input"
class={clsx(
"utrecht-textbox",
disabled && "utrecht-textbox--disabled",
invalid && "utrecht-textbox--invalid",
readOnly && "utrecht-textbox--readonly"
)}
type="text"
disabled={disabled}
placeholder={placeholder || null}
readonly={readOnly}
value={value}
onBlur={(evt) => this.utrechtBlur.emit(evt)}
onChange={(evt) => this.utrechtChange.emit(evt)}
onFocus={(evt) => this.utrechtFocus.emit(evt)}
onInput={(evt) => {
this.value = (evt.target as HTMLInputElement).value;
this.utrechtInput.emit(evt);
}}
/>
<label class="utrecht-form-field-textbox__label utrecht-form-label" htmlFor="input">
<slot></slot>
</label>
</div>
);
}
}
121 changes: 121 additions & 0 deletions components/textbox/stencil.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!--
@license EUPL-1.2
Copyright (c) 2021 Robbert Broersma
-->

import { Meta, Story, Canvas } from "@storybook/addon-docs";

<!-- Import Docs -->

import README from "./README.md";

export const Template = ({ disabled = false, invalid = false, placeholder = "", readOnly = false, value = "" }) =>
`<utrecht-textbox disabled="${disabled}" invalid="${invalid}" placeholder="${placeholder}" readonly="${readOnly}" value="${value}"></utrecht-textbox>`;

<Meta
title="Web Component/Textbox"
argTypes={{
disabled: {
description: "Disabled",
control: "boolean",
},
invalid: {
description: "Invalid",
control: "boolean",
},
placeholder: {
description: "Placeholder",
control: "string",
},
readOnly: {
description: "Read-only",
control: "boolean",
},
value: {
description: "Value",
control: "string",
},
}}
parameters={{
docs: {
transformSource: (_src, { args }) => Template(args),
},
status: {
type: "WORK IN PROGRESS",
},
notes: {
UX: README,
},
}}
/>

# Textbox

<Canvas>
<Story
name="Textbox"
args={{
value: "Example value",
}}
>
{Template.bind({})}
</Story>
</Canvas>

## States

### Invalid

<Canvas>
<Story
name="Invalid text box"
args={{
invalid: true,
value: "Example value",
}}
>
{Template.bind({})}
</Story>
</Canvas>

### Disabled

<Canvas>
<Story
name="Disabled text box"
args={{
disabled: true,
value: "Example value",
}}
>
{Template.bind({})}
</Story>
</Canvas>

### Read-only

<Canvas>
<Story
name="Read-only text box"
args={{
readOnly: true,
value: "Example value",
}}
>
{Template.bind({})}
</Story>
</Canvas>

## Placeholder

<Canvas>
<Story
name="Text box with placeholder"
args={{
placeholder: "Example placeholder",
value: "",
}}
>
{Template.bind({})}
</Story>
</Canvas>
51 changes: 51 additions & 0 deletions components/textbox/stencil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @license EUPL-1.2
* Copyright (c) 2021 Robbert Broersma
*/

import { Component, Event, EventEmitter, Prop, State, h } from "@stencil/core";
import clsx from "clsx";

@Component({
tag: "utrecht-textbox",
styleUrl: "bem.scss",
shadow: true,
})
export class Textbox {
@Prop({ reflect: true }) disabled: boolean = false;
@Prop({ reflect: true }) invalid: boolean = false;
@Prop({ attribute: "readonly", reflect: true }) readOnly: boolean = false;
@Prop() placeholder: string = "";
@State() value: string = "";
@Event() utrechtBlur: EventEmitter;
@Event() utrechtChange: EventEmitter;
@Event() utrechtFocus: EventEmitter;
@Event() utrechtInput: EventEmitter;

render() {
const { disabled, invalid, placeholder, readOnly, value } = this;

return (
<input
class={clsx(
"utrecht-textbox",
disabled && "utrecht-textbox--disabled",
invalid && "utrecht-textbox--invalid",
readOnly && "utrecht-textbox--readonly"
)}
type="text"
disabled={disabled}
placeholder={placeholder || null}
readOnly={readOnly}
value={value}
onBlur={(evt) => this.utrechtBlur.emit(evt)}
onChange={(evt) => this.utrechtChange.emit(evt)}
onFocus={(evt) => this.utrechtFocus.emit(evt)}
onInput={(evt) => {
this.value = (evt.target as HTMLInputElement).value;
this.utrechtInput.emit(evt);
}}
/>
);
}
}
8 changes: 8 additions & 0 deletions packages/web-component-library-angular/src/index.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
UtrechtBadgeStatus,
UtrechtBreadcrumb,
UtrechtButton,
UtrechtCheckbox,
UtrechtDocument,
UtrechtFormFieldCheckbox,
UtrechtFormFieldTextbox,
UtrechtHeading,
UtrechtHeading1,
UtrechtHeading2,
Expand All @@ -26,6 +29,7 @@ import {
UtrechtParagraph,
UtrechtSeparator,
UtrechtSidenav,
UtrechtTextbox,
} from './directives/proxies';

// This array is maintained manually, so it might miss the latest components.
Expand All @@ -37,7 +41,10 @@ const components = [
UtrechtBadgeStatus,
UtrechtBreadcrumb,
UtrechtButton,
UtrechtCheckbox,
UtrechtDocument,
UtrechtFormFieldCheckbox,
UtrechtFormFieldTextbox,
UtrechtHeading,
UtrechtHeading1,
UtrechtHeading2,
Expand All @@ -57,6 +64,7 @@ const components = [
UtrechtParagraph,
UtrechtSeparator,
UtrechtSidenav,
UtrechtTextbox,
];

@NgModule({
Expand Down

0 comments on commit 51b92d8

Please sign in to comment.