Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/tender-chairs-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@scouterna/ui-react": patch
"@scouterna/ui-webc": patch
---

Align all input components
6 changes: 6 additions & 0 deletions .changeset/wicked-books-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@scouterna/ui-react": minor
"@scouterna/ui-webc": minor
---

Add radio button component
25 changes: 25 additions & 0 deletions packages/storybook/src/stories/radio-button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ScoutRadioButton } from "@scouterna/ui-react";
import preview from "#.storybook/preview";

const meta = preview.meta({
title: "Interaction/Radio Button",
component: ScoutRadioButton,
parameters: {
layout: "centered",
},
});

export default meta;

export const BasicExample = meta.story({
args: {
name: "my-radio-group",
},
render: (args) => (
<div style={{ display: "flex", gap: "1rem" }}>
<ScoutRadioButton {...args} />
<ScoutRadioButton {...args} />
<ScoutRadioButton {...args} />
</div>
),
});
27 changes: 24 additions & 3 deletions packages/ui-react/lib/components/stencil-generated/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/* eslint-disable */

import { type ScoutCheckboxCustomEvent, type ScoutInputCustomEvent, type ScoutLinkCustomEvent, type ScoutSelectCustomEvent, type ScoutSwitchCustomEvent } from "@scouterna/ui-webc";
import { type ScoutCheckboxCustomEvent, type ScoutInputCustomEvent, type ScoutLinkCustomEvent, type ScoutRadioButtonCustomEvent, type ScoutSelectCustomEvent, type ScoutSwitchCustomEvent } from "@scouterna/ui-webc";
import { ScoutBottomBarItem as ScoutBottomBarItemElement, defineCustomElement as defineScoutBottomBarItem } from "@scouterna/ui-webc/dist/components/scout-bottom-bar-item.js";
import { ScoutBottomBar as ScoutBottomBarElement, defineCustomElement as defineScoutBottomBar } from "@scouterna/ui-webc/dist/components/scout-bottom-bar.js";
import { ScoutButton as ScoutButtonElement, defineCustomElement as defineScoutButton } from "@scouterna/ui-webc/dist/components/scout-button.js";
Expand All @@ -21,6 +21,7 @@ import { ScoutListViewItem as ScoutListViewItemElement, defineCustomElement as d
import { ScoutListViewSubheader as ScoutListViewSubheaderElement, defineCustomElement as defineScoutListViewSubheader } from "@scouterna/ui-webc/dist/components/scout-list-view-subheader.js";
import { ScoutListView as ScoutListViewElement, defineCustomElement as defineScoutListView } from "@scouterna/ui-webc/dist/components/scout-list-view.js";
import { ScoutLoader as ScoutLoaderElement, defineCustomElement as defineScoutLoader } from "@scouterna/ui-webc/dist/components/scout-loader.js";
import { ScoutRadioButton as ScoutRadioButtonElement, defineCustomElement as defineScoutRadioButton } from "@scouterna/ui-webc/dist/components/scout-radio-button.js";
import { ScoutSelect as ScoutSelectElement, defineCustomElement as defineScoutSelect } from "@scouterna/ui-webc/dist/components/scout-select.js";
import { ScoutStack as ScoutStackElement, defineCustomElement as defineScoutStack } from "@scouterna/ui-webc/dist/components/scout-stack.js";
import { ScoutSwitch as ScoutSwitchElement, defineCustomElement as defineScoutSwitch } from "@scouterna/ui-webc/dist/components/scout-switch.js";
Expand Down Expand Up @@ -73,7 +74,7 @@ export const ScoutCard: StencilReactComponent<ScoutCardElement, ScoutCardEvents>
});

export type ScoutCheckboxEvents = {
onScoutCheckboxChecked: EventName<ScoutCheckboxCustomEvent<{
onScoutChecked: EventName<ScoutCheckboxCustomEvent<{
checked: boolean;
element: HTMLInputElement;
}>>,
Expand All @@ -86,7 +87,7 @@ export const ScoutCheckbox: StencilReactComponent<ScoutCheckboxElement, ScoutChe
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
react: React,
events: {
onScoutCheckboxChecked: 'scoutCheckboxChecked',
onScoutChecked: 'scoutChecked',
on_fieldId: '_fieldId'
} as ScoutCheckboxEvents,
defineCustomElement: defineScoutCheckbox
Expand Down Expand Up @@ -191,6 +192,26 @@ export const ScoutLoader: StencilReactComponent<ScoutLoaderElement, ScoutLoaderE
defineCustomElement: defineScoutLoader
});

export type ScoutRadioButtonEvents = {
onScoutChecked: EventName<ScoutRadioButtonCustomEvent<{
checked: boolean;
element: HTMLInputElement;
}>>,
on_fieldId: EventName<CustomEvent<string>>
};

export const ScoutRadioButton: StencilReactComponent<ScoutRadioButtonElement, ScoutRadioButtonEvents> = /*@__PURE__*/ createComponent<ScoutRadioButtonElement, ScoutRadioButtonEvents>({
tagName: 'scout-radio-button',
elementClass: ScoutRadioButtonElement,
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
react: React,
events: {
onScoutChecked: 'scoutChecked',
on_fieldId: '_fieldId'
} as ScoutRadioButtonEvents,
defineCustomElement: defineScoutRadioButton
});

export type ScoutSelectEvents = {
onScoutInputChange: EventName<ScoutSelectCustomEvent<{
value: string;
Expand Down
82 changes: 80 additions & 2 deletions packages/ui-webc/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ export namespace Components {
*/
"disabled": boolean;
"label": string;
"name": string;
"value": string;
}
interface ScoutDivider {
}
Expand All @@ -114,6 +116,7 @@ export namespace Components {
* Input mode hints for devices with dynamic keyboards.
*/
"inputmode"?: InputMode;
"name": string;
/**
* Regex pattern for input validation.
*/
Expand Down Expand Up @@ -186,12 +189,30 @@ export namespace Components {
"size"?: "xs" | "sm" | "base" | "lg" | "xl";
"text"?: string;
}
interface ScoutRadioButton {
/**
* Use this prop if you need to connect your radio button with another element describing its use, other than the property label.
*/
"ariaLabelledby": string;
/**
* @default false
*/
"checked": boolean;
/**
* @default false
*/
"disabled": boolean;
"label": string;
"name": string;
"value": string;
}
interface ScoutSelect {
/**
* Whether the select is disabled. Disabled selects are not editable, excluded from tab order and are not validated.
* @default false
*/
"disabled": boolean;
"name": string;
/**
* Custom validation function run on top of the implicit validation performed by the browser. Return a string with the validation message to mark the select as invalid, or null to mark it as valid.
*/
Expand Down Expand Up @@ -255,6 +276,10 @@ export interface ScoutListViewItemCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLScoutListViewItemElement;
}
export interface ScoutRadioButtonCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLScoutRadioButtonElement;
}
export interface ScoutSelectCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLScoutSelectElement;
Expand Down Expand Up @@ -325,7 +350,7 @@ declare global {
new (): HTMLScoutCardElement;
};
interface HTMLScoutCheckboxElementEventMap {
"scoutCheckboxChecked": {
"scoutChecked": {
checked: boolean;
element: HTMLInputElement;
};
Expand Down Expand Up @@ -431,6 +456,27 @@ declare global {
prototype: HTMLScoutLoaderElement;
new (): HTMLScoutLoaderElement;
};
interface HTMLScoutRadioButtonElementEventMap {
"scoutChecked": {
checked: boolean;
element: HTMLInputElement;
};
"_fieldId": string;
}
interface HTMLScoutRadioButtonElement extends Components.ScoutRadioButton, HTMLStencilElement {
addEventListener<K extends keyof HTMLScoutRadioButtonElementEventMap>(type: K, listener: (this: HTMLScoutRadioButtonElement, ev: ScoutRadioButtonCustomEvent<HTMLScoutRadioButtonElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLScoutRadioButtonElementEventMap>(type: K, listener: (this: HTMLScoutRadioButtonElement, ev: ScoutRadioButtonCustomEvent<HTMLScoutRadioButtonElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLScoutRadioButtonElement: {
prototype: HTMLScoutRadioButtonElement;
new (): HTMLScoutRadioButtonElement;
};
interface HTMLScoutSelectElementEventMap {
"scoutInputChange": {
value: string;
Expand Down Expand Up @@ -494,6 +540,7 @@ declare global {
"scout-list-view-item": HTMLScoutListViewItemElement;
"scout-list-view-subheader": HTMLScoutListViewSubheaderElement;
"scout-loader": HTMLScoutLoaderElement;
"scout-radio-button": HTMLScoutRadioButtonElement;
"scout-select": HTMLScoutSelectElement;
"scout-stack": HTMLScoutStackElement;
"scout-switch": HTMLScoutSwitchElement;
Expand Down Expand Up @@ -577,14 +624,16 @@ declare namespace LocalJSX {
*/
"disabled"?: boolean;
"label"?: string;
"onScoutCheckboxChecked"?: (event: ScoutCheckboxCustomEvent<{
"name"?: string;
"onScoutChecked"?: (event: ScoutCheckboxCustomEvent<{
checked: boolean;
element: HTMLInputElement;
}>) => void;
/**
* Internal event used for form field association.
*/
"on_fieldId"?: (event: ScoutCheckboxCustomEvent<string>) => void;
"value"?: string;
}
interface ScoutDivider {
}
Expand All @@ -608,6 +657,7 @@ declare namespace LocalJSX {
* Input mode hints for devices with dynamic keyboards.
*/
"inputmode"?: InputMode;
"name"?: string;
"onScoutBlur"?: (event: ScoutInputCustomEvent<void>) => void;
"onScoutInputChange"?: (event: ScoutInputCustomEvent<{
value: string;
Expand Down Expand Up @@ -694,12 +744,38 @@ declare namespace LocalJSX {
"size"?: "xs" | "sm" | "base" | "lg" | "xl";
"text"?: string;
}
interface ScoutRadioButton {
/**
* Use this prop if you need to connect your radio button with another element describing its use, other than the property label.
*/
"ariaLabelledby"?: string;
/**
* @default false
*/
"checked"?: boolean;
/**
* @default false
*/
"disabled"?: boolean;
"label"?: string;
"name"?: string;
"onScoutChecked"?: (event: ScoutRadioButtonCustomEvent<{
checked: boolean;
element: HTMLInputElement;
}>) => void;
/**
* Internal event used for form field association.
*/
"on_fieldId"?: (event: ScoutRadioButtonCustomEvent<string>) => void;
"value"?: string;
}
interface ScoutSelect {
/**
* Whether the select is disabled. Disabled selects are not editable, excluded from tab order and are not validated.
* @default false
*/
"disabled"?: boolean;
"name"?: string;
"onScoutBlur"?: (event: ScoutSelectCustomEvent<void>) => void;
"onScoutInputChange"?: (event: ScoutSelectCustomEvent<{
value: string;
Expand Down Expand Up @@ -769,6 +845,7 @@ declare namespace LocalJSX {
"scout-list-view-item": ScoutListViewItem;
"scout-list-view-subheader": ScoutListViewSubheader;
"scout-loader": ScoutLoader;
"scout-radio-button": ScoutRadioButton;
"scout-select": ScoutSelect;
"scout-stack": ScoutStack;
"scout-switch": ScoutSwitch;
Expand Down Expand Up @@ -805,6 +882,7 @@ declare module "@stencil/core" {
"scout-list-view-item": LocalJSX.ScoutListViewItem & JSXBase.HTMLAttributes<HTMLScoutListViewItemElement>;
"scout-list-view-subheader": LocalJSX.ScoutListViewSubheader & JSXBase.HTMLAttributes<HTMLScoutListViewSubheaderElement>;
"scout-loader": LocalJSX.ScoutLoader & JSXBase.HTMLAttributes<HTMLScoutLoaderElement>;
"scout-radio-button": LocalJSX.ScoutRadioButton & JSXBase.HTMLAttributes<HTMLScoutRadioButtonElement>;
"scout-select": LocalJSX.ScoutSelect & JSXBase.HTMLAttributes<HTMLScoutSelectElement>;
"scout-stack": LocalJSX.ScoutStack & JSXBase.HTMLAttributes<HTMLScoutStackElement>;
"scout-switch": LocalJSX.ScoutSwitch & JSXBase.HTMLAttributes<HTMLScoutSwitchElement>;
Expand Down
8 changes: 2 additions & 6 deletions packages/ui-webc/src/components/checkbox/checkbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

.checkbox:checked:hover {
background-color: var(--color-background-brand-hovered);
border: 2px solid var(--color-background-brand-hovered);
border-color: var(--color-background-brand-hovered);
box-shadow: none;
}

Expand Down Expand Up @@ -67,12 +67,8 @@

label {
display: flex;
flex-direction: row-reverse;
align-items: center;
gap: var(--spacing-2);
font: var(--type-label-base);
color: var(--color-text-base);
}

.inlineDivider {
width: var(--spacing-2);
}
27 changes: 13 additions & 14 deletions packages/ui-webc/src/components/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ export class ScoutCheckbox {

@Prop() label: string;

@Prop() value: string;

@Prop() name: string;

@State() ariaId: string;

@Event() scoutCheckboxChecked: EventEmitter<{
@Event() scoutChecked: EventEmitter<{
checked: boolean;
element: HTMLInputElement;
}>;
Expand All @@ -41,38 +45,33 @@ export class ScoutCheckbox {
this._fieldId.emit(this.ariaId);
}

onClick(event: Event) {
onChange(event: Event) {
const checkbox = event.target as HTMLInputElement;
console.log("checkbox", checkbox.checked);

this.scoutCheckboxChecked.emit({
this.scoutChecked.emit({
checked: checkbox.checked,
element: checkbox,
});
}
/*
todo:
- Wrap checkbox with label if used.
- make sure it works with field nicely with label.
*/

render() {
const Tag = this.label?.length ? "label" : "div";
return (
<Tag>
{this.label}
<span class="inlineDivider"></span>
<input
id={this.ariaId}
type="checkbox"
value={this.value}
name={this.name}
class="checkbox"
onChange={(event) => this.onClick(event)}
style={{ "--icon-checkbox": `url(${checkIcon})` }}
type="checkbox"
id={this.ariaId}
aria-labelledby={this.ariaLabelledby}
aria-disabled={this.disabled}
disabled={this.disabled}
checked={this.checked}
onChange={(event) => this.onChange(event)}
/>
{this.label}
</Tag>
);
}
Expand Down
10 changes: 6 additions & 4 deletions packages/ui-webc/src/components/checkbox/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
| `checked` | `checked` | | `boolean` | `false` |
| `disabled` | `disabled` | | `boolean` | `false` |
| `label` | `label` | | `string` | `undefined` |
| `name` | `name` | | `string` | `undefined` |
| `value` | `value` | | `string` | `undefined` |


## Events

| Event | Description | Type |
| ---------------------- | ----------------------------------------------- | --------------------------------------------------------------- |
| `_fieldId` | Internal event used for form field association. | `CustomEvent<string>` |
| `scoutCheckboxChecked` | | `CustomEvent<{ checked: boolean; element: HTMLInputElement; }>` |
| Event | Description | Type |
| -------------- | ----------------------------------------------- | --------------------------------------------------------------- |
| `_fieldId` | Internal event used for form field association. | `CustomEvent<string>` |
| `scoutChecked` | | `CustomEvent<{ checked: boolean; element: HTMLInputElement; }>` |


----------------------------------------------
Expand Down
Loading