Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(radio-button-group, segmented control): add validationMessage, validationIcon, and status properties #8561

Merged
merged 22 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1f8f1b0
feat(radio-button-group): add validationMessage, validationIcon, and …
benelan Jan 5, 2024
66e39b2
feat(segmented-control): add validationMessage, validationIcon, and s…
benelan Jan 9, 2024
a2c0786
chore: cleanup
benelan Jan 9, 2024
fb698ef
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 9, 2024
25dd6c8
chore: cleanup
benelan Jan 9, 2024
d5dfd37
chore: cleanup
benelan Jan 9, 2024
3f41180
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 9, 2024
2c1f9c3
test: add properties to defaults/reflects
benelan Jan 10, 2024
51bccc8
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 10, 2024
1e83a36
chore: clean
benelan Jan 10, 2024
8a3914b
Merge branch 'main' into benelan/radio-validation-message
benelan Jan 10, 2024
a563d5f
chore: cleanup
benelan Jan 10, 2024
3158a55
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 10, 2024
9cf25c1
chore: cleanup segmented-control styling
benelan Jan 11, 2024
a4a0687
fix(radio-group): spacing above validation message
benelan Jan 11, 2024
8be513b
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 11, 2024
0bdf838
test(radio-button-group): separate validation-message into a NoTest s…
benelan Jan 11, 2024
829acbd
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 11, 2024
2e8bfce
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 12, 2024
2dfb355
chore: cleanup
benelan Jan 13, 2024
f3c3955
chore: cleanup
benelan Jan 13, 2024
b3ebd59
Merge remote-tracking branch 'origin/main' into benelan/radio-validat…
benelan Jan 13, 2024
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
48 changes: 48 additions & 0 deletions packages/calcite-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3796,6 +3796,18 @@ export namespace Components {
* Sets focus on the fist focusable `calcite-radio-button` element in the component.
*/
"setFocus": () => Promise<void>;
/**
* Specifies the status of the validation message.
*/
"status": Status;
/**
* Specifies the validation icon to display under the component.
*/
"validationIcon": string | boolean;
/**
* Specifies the validation message to display under the component.
*/
"validationMessage": string;
}
interface CalciteRating {
/**
Expand Down Expand Up @@ -3903,6 +3915,18 @@ export namespace Components {
* Sets focus on the component.
*/
"setFocus": () => Promise<void>;
/**
* Specifies the status of the validation message.
*/
"status": Status;
/**
* Specifies the validation icon to display under the component.
*/
"validationIcon": string | boolean;
/**
* Specifies the validation message to display under the component.
*/
"validationMessage": string;
/**
* The component's `selectedItem` value.
*/
Expand Down Expand Up @@ -11250,6 +11274,18 @@ declare namespace LocalJSX {
* @readonly
*/
"selectedItem"?: HTMLCalciteRadioButtonElement;
/**
* Specifies the status of the validation message.
*/
"status"?: Status;
/**
* Specifies the validation icon to display under the component.
*/
"validationIcon"?: string | boolean;
/**
* Specifies the validation message to display under the component.
*/
"validationMessage"?: string;
}
interface CalciteRating {
/**
Expand Down Expand Up @@ -11357,6 +11393,18 @@ declare namespace LocalJSX {
* @readonly
*/
"selectedItem"?: HTMLCalciteSegmentedControlItemElement;
/**
* Specifies the status of the validation message.
*/
"status"?: Status;
/**
* Specifies the validation icon to display under the component.
*/
"validationIcon"?: string | boolean;
/**
* Specifies the validation message to display under the component.
*/
"validationMessage"?: string;
/**
* The component's `selectedItem` value.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ describe("calcite-radio-button-group", () => {
defaults("calcite-radio-button-group", [
{ propertyName: "layout", defaultValue: "horizontal" },
{ propertyName: "scale", defaultValue: "m" },
{ propertyName: "status", defaultValue: "idle" },
{ propertyName: "validationIcon", defaultValue: undefined },
{ propertyName: "validationMessage", defaultValue: undefined },
]);
});

Expand Down Expand Up @@ -108,6 +111,8 @@ describe("calcite-radio-button-group", () => {
{ propertyName: "name", value: "reflects-name" },
{ propertyName: "required", value: true },
{ propertyName: "scale", value: "m" },
{ propertyName: "status", value: "invalid" },
{ propertyName: "validationIcon", value: true },
]);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
:host {
@apply flex flex-col;
}

:host > .item-wrapper {
@apply flex;
max-inline-size: 100vw;
}
:host([layout="horizontal"]) {

:host([layout="horizontal"]) > .item-wrapper {
@apply flex-row flex-wrap;
}
:host([layout="horizontal"][scale="s"]) {
@apply gap-4;

:host([layout="horizontal"][scale="s"]) > .item-wrapper {
@apply gap-x-4;
}
:host([layout="horizontal"][scale="m"]) {
@apply gap-5;

:host([layout="horizontal"][scale="m"]) > .item-wrapper {
@apply gap-x-5;
}
:host([layout="horizontal"][scale="l"]) {
@apply gap-6;

:host([layout="horizontal"][scale="l"]) > .item-wrapper {
@apply gap-x-6;
}
:host([layout="vertical"]) {

:host([layout="vertical"]) > .item-wrapper {
@apply flex-col;
}

:host([scale="s"]) calcite-input-message {
--calcite-input-message-spacing-value: calc(var(--calcite-spacing-xxs) * -1);
}

:host([scale="m"]) calcite-input-message {
--calcite-input-message-spacing-value: calc(var(--calcite-spacing-sm) * -1);
}

:host([scale="l"]) calcite-input-message {
--calcite-input-message-spacing-value: calc(var(--calcite-spacing-md) * -1);
}

@include form-validation-message();
@include base-component();
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { select } from "@storybook/addon-knobs";
import { boolean, storyFilters } from "../../../.storybook/helpers";
import { select, text } from "@storybook/addon-knobs";
import { boolean, iconNames, storyFilters } from "../../../.storybook/helpers";
import { modesDarkDefault } from "../../../.storybook/utils";
import readme from "./readme.md";
import { html } from "../../../support/formatting";
import readme from "./readme.md";

export default {
title: "Components/Controls/Radio/Radio Button Group",
Expand Down Expand Up @@ -39,15 +39,20 @@ export const simple = (): string => html`
</calcite-radio-button-group>
`;

export const darkModeRTL_TestOnly = (): string => html`
// We created a separate story for validation-message because it is not possible
// to set a text knob's value to undefined. Unfortunately, this makes the CSS
// attribute selector truthy, which sets "--calcite-label-margin-bottom: 0;",
// causing a Chromatic diff. See calcite-radio-button-group.scss.
export const validationMessage_NoTest = (): string => html`
<calcite-radio-button-group
class="calcite-mode-dark"
dir="rtl"
name="dark"
name="simple"
${boolean("disabled", false)}
${boolean("hidden", false)}
layout="${select("layout", ["horizontal", "vertical"], "horizontal")}"
scale="${select("scale", ["s", "m", "l"], "m")}"
status="${select("status", ["idle", "invalid", "valid"], "invalid")}"
validation-icon="${select("validation-icon", ["", ...iconNames], "")}"
validation-message="${text("validation-message", "Please fill out this field.")}"
>
<calcite-label layout="inline">
<calcite-radio-button value="react"></calcite-radio-button>
Expand All @@ -68,4 +73,115 @@ export const darkModeRTL_TestOnly = (): string => html`
</calcite-radio-button-group>
`;

export const darkModeRTL_TestOnly = (): string => html`
<calcite-radio-button-group
class="calcite-mode-dark"
dir="rtl"
name="dark"
layout="vertical"
status="valid"
validation-icon
validation-message="Thanks for not selecting Ember"
>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭🔥

<calcite-label layout="inline">
<calcite-radio-button value="react" checked></calcite-radio-button>
React
</calcite-label>
<calcite-label layout="inline">
<calcite-radio-button value="ember"></calcite-radio-button>
Ember
</calcite-label>
<calcite-label layout="inline">
<calcite-radio-button value="angular"></calcite-radio-button>
Angular
</calcite-label>
<calcite-label layout="inline">
<calcite-radio-button value="vue"></calcite-radio-button>
Vue
</calcite-label>
</calcite-radio-button-group>
`;

darkModeRTL_TestOnly.parameters = { modes: modesDarkDefault };

export const validationMessage_TestOnly = (): string => html`
<style>
.container {
display: flex;
flex-direction: column;
width: 400px;
height: 200px;
gap: 20px;
}
</style>
<div class="container">
<calcite-radio-button-group
layout="horizontal"
name="validation"
required
scale="s"
status="invalid"
validation-icon
validation-message="Please select an option."
>
<calcite-label layout="inline" scale="s">
<calcite-radio-button value="one" scale="s"></calcite-radio-button>
One
</calcite-label>
<calcite-label layout="inline" scale="s">
<calcite-radio-button value="two" scale="s"></calcite-radio-button>
Two
</calcite-label>
<calcite-label layout="inline" scale="s">
<calcite-radio-button value="three" scale="s"></calcite-radio-button>
Three
</calcite-label>
</calcite-radio-button-group>

<calcite-radio-button-group
layout="horizontal"
name="validation"
required
scale="m"
status="invalid"
validation-icon
validation-message="Please select an option."
>
<calcite-label layout="inline" scale="m">
<calcite-radio-button value="one" scale="m"></calcite-radio-button>
One
</calcite-label>
<calcite-label layout="inline" scale="m">
<calcite-radio-button value="two" scale="m"></calcite-radio-button>
Two
</calcite-label>
<calcite-label layout="inline" scale="m">
<calcite-radio-button value="three" scale="m"></calcite-radio-button>
Three
</calcite-label>
</calcite-radio-button-group>

<calcite-radio-button-group
layout="horizontal"
name="validation"
required
scale="l"
status="invalid"
validation-icon
validation-message="Please select an option."
>
<calcite-label layout="inline" scale="l">
<calcite-radio-button value="one" scale="l"></calcite-radio-button>
One
</calcite-label>
<calcite-label layout="inline" scale="l">
<calcite-radio-button value="two" scale="l"></calcite-radio-button>
Two
</calcite-label>
<calcite-label layout="inline" scale="l">
<calcite-radio-button value="three" scale="l"></calcite-radio-button>
Three
</calcite-label>
</calcite-radio-button-group>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import {
Watch,
} from "@stencil/core";
import { createObserver } from "../../utils/observers";
import { Layout, Scale } from "../interfaces";
import { Layout, Scale, Status } from "../interfaces";
import {
componentFocusable,
LoadableComponent,
setComponentLoaded,
setUpLoadableComponent,
} from "../../utils/loadable";
import { Validation } from "../functional/Validation";
import { CSS } from "./resources";

/**
* @slot - A slot for adding `calcite-radio-button`s.
Expand Down Expand Up @@ -76,6 +78,15 @@ export class RadioButtonGroup implements LoadableComponent {
/** Specifies the size of the component. */
@Prop({ reflect: true }) scale: Scale = "m";

/** Specifies the status of the validation message. */
@Prop({ reflect: true }) status: Status = "idle";

/** Specifies the validation message to display under the component. */
@Prop() validationMessage: string;

/** Specifies the validation icon to display under the component. */
@Prop({ reflect: true }) validationIcon: string | boolean;

@Watch("scale")
onScaleChange(): void {
this.passPropsToRadioButtons();
Expand Down Expand Up @@ -191,7 +202,17 @@ export class RadioButtonGroup implements LoadableComponent {
render(): VNode {
return (
<Host role="radiogroup">
<slot />
<div class={CSS.itemWrapper}>
<slot />
</div>
{this.validationMessage ? (
<Validation
icon={this.validationIcon}
message={this.validationMessage}
scale={this.scale}
status={this.status}
/>
) : null}
</Host>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const CSS = {
itemWrapper: "item-wrapper",
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const CSS = {
itemWrapper: "item-wrapper",
};
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ describe("calcite-segmented-control", () => {
propertyName: "width",
defaultValue: "auto",
},
{
propertyName: "status",
defaultValue: "idle",
},
{
propertyName: "validationIcon",
defaultValue: undefined,
},
{
propertyName: "validationMessage",
defaultValue: undefined,
},
]);
});

Expand All @@ -52,6 +64,14 @@ describe("calcite-segmented-control", () => {
propertyName: "width",
value: "auto",
},
{
propertyName: "status",
value: "invalid",
},
{
propertyName: "validationIcon",
value: true,
},
]);
});

Expand Down
Loading
Loading