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 16 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
128 changes: 89 additions & 39 deletions packages/calcite-components/src/components.d.ts

Large diffs are not rendered by default.

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,40 @@
:host {
@apply flex;
display: flex;
flex-direction: column;
}

:host > .item-wrapper {
display: 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([validation-message][layout="horizontal"]) > .item-wrapper {
--calcite-label-margin-bottom: 0;
}

:host([validation-message][layout="vertical"]) > .item-wrapper > ::slotted(calcite-label:last-child) {
--calcite-label-margin-bottom: 0;
}

@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 All @@ -19,6 +19,9 @@ export const simple = (): string => html`
${boolean("hidden", false)}
layout="${select("layout", ["horizontal", "vertical"], "horizontal")}"
scale="${select("scale", ["s", "m", "l"], "m")}"
status="${select("status", ["idle", "invalid", "valid"], "idle")}"
validation-icon="${select("validation-icon", ["", ...iconNames], "")}"
validation-message="${text("validation-message", "")}"
>
<calcite-label layout="inline">
<calcite-radio-button value="react"></calcite-radio-button>
Expand All @@ -44,13 +47,14 @@ export const darkModeRTL_TestOnly = (): string => html`
class="calcite-mode-dark"
dir="rtl"
name="dark"
${boolean("disabled", false)}
${boolean("hidden", false)}
layout="${select("layout", ["horizontal", "vertical"], "horizontal")}"
scale="${select("scale", ["s", "m", "l"], "m")}"
layout="vertical"
scale="l"
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"></calcite-radio-button>
<calcite-radio-button value="react" checked></calcite-radio-button>
React
</calcite-label>
<calcite-label layout="inline">
Expand All @@ -69,3 +73,85 @@ export const darkModeRTL_TestOnly = (): string => html`
`;

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
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
:host {
@apply flex flex-col;
}

.item-wrapper {
@apply bg-foreground-1 flex;
inline-size: fit-content;
outline: 1px solid var(--calcite-color-border-input);
outline-offset: -1px;
}

:host([appearance="outline"]) {
:host([appearance="outline"]) > .item-wrapper {
@apply bg-transparent;
}

@include disabled();

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

// segmented control width for full

:host([width="full"]) {
:host([width="full"]) > .item-wrapper {
@apply w-full;
min-inline-size: fit-content;

::slotted(calcite-segmented-control-item) {
@apply flex-auto;
}
}

:host([width="full"][layout="vertical"]) ::slotted(calcite-segmented-control-item) {
@apply justify-start;
:host([width="full"][layout="vertical"]) > .item-wrapper {
::slotted(calcite-segmented-control-item) {
@apply justify-start;
}
}

@include form-validation-message();
@include hidden-form-input();
@include base-component();
Loading
Loading