From b9d0197fb7ae3c777ea3e3ec82f11287a5f59761 Mon Sep 17 00:00:00 2001 From: vicky-comeau <110498164+vicky-comeau@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:11:46 -0500 Subject: [PATCH] Fix: [IGL-130] Option button inconsistencies (#730) --- .changeset/odd-ducks-cry.md | 5 + .../OptionButton/src/OptionButton.stories.tsx | 38 ++++++ packages/OptionButton/src/OptionButton.tsx | 48 +++++-- .../__snapshots__/OptionButton.test.tsx.snap | 11 +- packages/OptionButton/src/option-button.scss | 90 +++++++------- packages/OptionButton/src/svgs.tsx | 117 ++++++++++++++---- 6 files changed, 226 insertions(+), 83 deletions(-) create mode 100644 .changeset/odd-ducks-cry.md diff --git a/.changeset/odd-ducks-cry.md b/.changeset/odd-ducks-cry.md new file mode 100644 index 00000000..beb643b2 --- /dev/null +++ b/.changeset/odd-ducks-cry.md @@ -0,0 +1,5 @@ +--- +"@igloo-ui/option-button": patch +--- + +Fixed Optionbutton style for Workleap brand. Also updated its icons and added a checked disabled look. diff --git a/packages/OptionButton/src/OptionButton.stories.tsx b/packages/OptionButton/src/OptionButton.stories.tsx index 06e8f258..fc7a48d8 100644 --- a/packages/OptionButton/src/OptionButton.stories.tsx +++ b/packages/OptionButton/src/OptionButton.stories.tsx @@ -146,6 +146,44 @@ export const CheckedStates = () => { ); }; +export const CheckedDisabledStates = () => { + const [checkedId, setCheckedId] = React.useState('radio-2'); + + const handleOnChange = (event: React.ChangeEvent): void => { + setCheckedId(event.target.id); + }; + + return ( +
+ + Unchecked Button + + + Checked + +
+ ); +}; + export const Description = () => (
diff --git a/packages/OptionButton/src/OptionButton.tsx b/packages/OptionButton/src/OptionButton.tsx index 7e7ff9a1..e26b8113 100644 --- a/packages/OptionButton/src/OptionButton.tsx +++ b/packages/OptionButton/src/OptionButton.tsx @@ -2,6 +2,10 @@ import * as React from "react"; import cx from "classnames"; import { + LegacyTextIcon, + LegacyOptionScaleIcon, + LegacyMultipleChoiceIcon, + LegacyLikertIcon, TextIcon, OptionScaleIcon, MultipleChoiceIcon, @@ -40,6 +44,10 @@ export interface OptionButtonProps extends React.ComponentProps<"input"> { unchecked?: boolean; } +const getBrand = (): string => { + return document.documentElement.getAttribute("data-brand") ?? "igloo"; +}; + const OptionButton: React.FunctionComponent = ({ buttonType = "text", checked, @@ -58,41 +66,55 @@ const OptionButton: React.FunctionComponent = ({ if (icon) { return icon; } - let disabledClass = ""; - if (disabled || unchecked) { - disabledClass = "disabled"; + + const isWorkleap = getBrand() === "workleap"; + let OptionScale = LegacyOptionScaleIcon; + let MultipleChoice = LegacyMultipleChoiceIcon; + let Likert = LegacyLikertIcon; + let Text = LegacyTextIcon; + if (isWorkleap) { + OptionScale = OptionScaleIcon; + MultipleChoice = MultipleChoiceIcon; + Likert = LikertIcon; + Text = TextIcon; } + switch (buttonType) { case "optionScale": return ( - ); case "multipleChoice": return ( - ); case "likert": return ( - ); default: return ( - ); } }; const classes = cx("ids-option-button", className, { - "ids-option-button--unchecked": unchecked + "ids-option-button--unchecked": unchecked, + "ids-option-button--checked": checked, + "ids-option-button--disabled": disabled }); return ( diff --git a/packages/OptionButton/src/__snapshots__/OptionButton.test.tsx.snap b/packages/OptionButton/src/__snapshots__/OptionButton.test.tsx.snap index 27c6eb7f..a6d23c54 100644 --- a/packages/OptionButton/src/__snapshots__/OptionButton.test.tsx.snap +++ b/packages/OptionButton/src/__snapshots__/OptionButton.test.tsx.snap @@ -19,7 +19,8 @@ exports[`OptionButton It should render a snapshot 1`] = ` class="ids-option-button__icon-container" > diff --git a/packages/OptionButton/src/option-button.scss b/packages/OptionButton/src/option-button.scss index 25ac56f2..d426a2f6 100644 --- a/packages/OptionButton/src/option-button.scss +++ b/packages/OptionButton/src/option-button.scss @@ -29,19 +29,19 @@ --ids-option-button-icon-container-disabled-background: #{tokens.$grey-200}; --ids-option-button-border-color-disabled: #{tokens.$grey-400}; --ids-option-button-background-color-disabled: transparent; + --ids-option-button-text-color-disabled: #{tokens.$grey-600}; /* Icon */ --ids-option-button-icon-container-background: #{tokens.$electric-blue-50}; --ids-option-button-icon-container-height: 5.6rem; --ids-option-button-icon-container-width: 6.2rem; + --ids-option-button-icon-background: #{tokens.$sky-100}; --ids-option-button-icon-background-disabled: #{tokens.$grey-300}; + --ids-option-button-icon-background-hover: #{tokens.$sky-100}; + --ids-option-button-icon-color: #{tokens.$grey-800}; + --ids-option-button-icon-color-disabled: #{tokens.$grey-600}; --ids-option-button-icon-width: auto; --ids-option-button-icon-height: auto; - --ids-option-button-icon-circle-fill: #{tokens.$sky-100}; - --ids-option-button-icon-path-fill: #{tokens.$grey-800}; - --ids-option-button-icon-stroke: #{tokens.$grey-800}; - --ids-option-button-icon-circle-fill-hover: #{tokens.$sky-100}; - --ids-option-button-icon-circle-fill-disabled: #{tokens.$sky-100}; /* Text */ --ids-option-button-text-container-padding: #{tokens.$space-1} #{tokens.$space-3}; @@ -67,12 +67,12 @@ /* Hover */ --ids-option-button-hover-border-color: var(--hop-neutral-border-hover); - --ids-option-button-hover-background-color: var(--hop-neutral-surface-weak-hover); + --ids-option-button-hover-background-color: var(--hop-neutral-surface-hover); /* Checked */ --ids-option-button-checked-box-shadow: none; --ids-option-button-checked-border-color: var(--hop-neutral-border-active); - --ids-option-button-checked-background-color: var(--hop-neutral-surface-weak-hover); + --ids-option-button-checked-background-color: var(--hop-neutral-surface-weak-active); --ids-option-button-checked-outline: 0.125rem solid var(--hop-neutral-border-active); --ids-option-button-checked-outline-offset: -0.125rem; @@ -80,19 +80,19 @@ --ids-option-button-icon-container-disabled-background: transparent; --ids-option-button-border-color-disabled: var(--hop-neutral-border-disabled); --ids-option-button-background-color-disabled: var(--hop-neutral-surface-disabled); + --ids-option-button-text-color-disabled: var(--hop-neutral-text-disabled); /* Icon */ --ids-option-button-icon-container-background: transparent; --ids-option-button-icon-container-height: 3.5rem; --ids-option-button-icon-container-width: 2.5rem; + --ids-option-button-icon-background: var(--hop-decorative-option7-surface); --ids-option-button-icon-background-disabled: transparent; + --ids-option-button-icon-background-hover: var(--hop-decorative-option7-surface-hover); + --ids-option-button-icon-color: var(--hop-decorative-option7-icon); + --ids-option-button-icon-color-disabled: var(--hop-neutral-icon-disabled); --ids-option-button-icon-width: 2.5rem; --ids-option-button-icon-height: 2.5rem; - --ids-option-button-icon-circle-fill: #F0EAE3; // will be decorative-option7-surface - --ids-option-button-icon-path-fill: #2A2620; // will be decorative-option7-icon - --ids-option-button-icon-stroke: #2A2620; // will be decorative-option7-icon - --ids-option-button-icon-circle-fill-hover: #E5DED6; // will be decorative-option7-surface-strong - --ids-option-button-icon-circle-fill-disabled: transparent; /* Text */ --ids-option-button-text-container-padding: var(--hop-space-inset-sm) var(--hop-space-inset-lg) var(--hop-space-inset-sm) var(--hop-space-inset-sm); @@ -149,20 +149,16 @@ padding: var(--ids-option-button-padding); } - &__radio:hover:not(:disabled) ~ &__label { + &:hover:not(.ids-option-button--disabled, .ids-option-button--checked) &__label { border-color: var(--ids-option-button-hover-border-color); background-color: var(--ids-option-button-hover-background-color); } - &__radio:hover:not(:disabled) ~ &__label &__icon-circle { - fill: var(--ids-option-button-icon-circle-fill-hover); - } - &__radio:focus ~ &__label { box-shadow: var(--ids-option-focus); } - &__radio:checked ~ &__label { + &--checked &__label { background-color: var(--ids-option-button-checked-background-color); border: var(--ids-option-button-border-dimension) solid var(--ids-option-button-checked-border-color); box-shadow: var(--ids-option-button-checked-box-shadow); @@ -171,11 +167,7 @@ outline-offset: var(--ids-option-button-checked-outline-offset); } - &__radio:checked ~ &__label &__icon-circle { - fill: var(--ids-option-button-icon-circle-fill-hover); - } - - &__radio:disabled ~ &__label { + &--disabled &__label { border: var(--ids-option-button-border-dimension) solid var(--ids-option-button-border-color-disabled); box-shadow: none; cursor: not-allowed; @@ -183,11 +175,14 @@ background-color: var(--ids-option-button-background-color-disabled); } - &__radio:disabled ~ &__label &__icon-circle { - fill: var(--ids-option-button-icon-circle-fill-disabled); + &--checked.ids-option-button--disabled &__label { + border: var(--ids-option-button-border-dimension) solid var(--ids-option-button-checked-border-color); + box-shadow: var(--ids-option-button-checked-box-shadow); + outline: var(--ids-option-button-checked-outline); + outline-offset: var(--ids-option-button-checked-outline-offset); } - &--unchecked &__radio:checked ~ &__label { + &--unchecked.ids-option-button--checked &__label { box-shadow: none; } @@ -204,40 +199,43 @@ width: var(--ids-option-button-icon-container-width); } - &__icon-circle { - fill: var(--ids-option-button-icon-circle-fill); + &--unchecked &__icon-container { + @extend %disabled-icon-container; } - &__icon-path { - fill: var(--ids-option-button-icon-path-fill); + &--checked &__icon-container { + @extend %active-icon-container; } - &__icon-stroke { - stroke: var(--ids-option-button-icon-stroke); + &--disabled &__icon-container, + &--unchecked.ids-option-button--checked &__icon-container { + @extend %disabled-icon-container; } - &__multiple-choice-icon, - &__text-icon, - &__option-scale-icon, - &__likert-icon { + &__icon { + color: var(--ids-option-button-icon-color); height: var(--ids-option-button-icon-width); width: var(--ids-option-button-icon-width); } - &--unchecked &__icon-container { - @extend %disabled-icon-container; + &--disabled &__icon { + color: var(--ids-option-button-icon-color-disabled); } - &__radio:checked ~ &__label &__icon-container { - @extend %active-icon-container; + &__icon-circle { + fill: var(--ids-option-button-icon-background); } - &__radio:disabled ~ &__label &__icon-container, - &--unchecked &__radio:checked ~ &__label &__icon-container { - @extend %disabled-icon-container; + &:hover:not(.ids-option-button--disabled, .ids-option-button--checked) &__icon-circle { + fill: var(--ids-option-button-icon-background-hover); + } + + &--checked &__icon-circle { + fill: var(--ids-option-button-icon-background-hover); } - &__icon-container svg.disabled [fill$='#{tokens.$sky-100}'] { + + &--disabled &__icon-circle { fill: var(--ids-option-button-icon-background-disabled); } @@ -254,6 +252,10 @@ line-height: var(--ids-option-button-text-line-height); @extend %ellipsis; + + .ids-option-button--disabled & { + color: var(--ids-option-button-text-color-disabled); + } } &__desc { diff --git a/packages/OptionButton/src/svgs.tsx b/packages/OptionButton/src/svgs.tsx index c6c7c3a7..7a3cf189 100644 --- a/packages/OptionButton/src/svgs.tsx +++ b/packages/OptionButton/src/svgs.tsx @@ -2,7 +2,7 @@ /* If SVGs are updated, remember to keep props. */ import React from "react"; -export const TextIcon: React.FunctionComponent> = ( +export const LegacyTextIcon: React.FunctionComponent> = ( props: React.ComponentProps<"svg"> ) => ( > = ( fillRule="evenodd" clipRule="evenodd" d="M15.5358 11.2583C13.4703 11.2877 11.5563 11.3885 11.1234 11.4607C10.7148 11.5288 10.3284 11.2527 10.2603 10.8442C10.1922 10.4356 10.4682 10.0492 10.8768 9.98107C11.4439 9.88655 13.48 9.78738 15.5144 9.75844C16.5465 9.74375 17.6038 9.74678 18.5082 9.77915C19.3876 9.81064 20.1947 9.87143 20.682 9.99325C21.0839 10.0937 21.3282 10.5009 21.2277 10.9028C21.1273 11.3046 20.7201 11.5489 20.3182 11.4485C20.0055 11.3703 19.3501 11.3103 18.4545 11.2782C17.584 11.247 16.5537 11.2438 15.5358 11.2583Z" - className="ids-option-button__icon-path" + fill="currentColor" /> @@ -52,7 +52,7 @@ export const TextIcon: React.FunctionComponent> = ( ); -export const OptionScaleIcon: React.FunctionComponent< +export const LegacyOptionScaleIcon: React.FunctionComponent< React.ComponentProps<"svg"> > = (props: React.ComponentProps<"svg">) => ( /> @@ -96,7 +96,7 @@ React.ComponentProps<"svg"> ); -export const MultipleChoiceIcon: React.FunctionComponent< +export const LegacyMultipleChoiceIcon: React.FunctionComponent< React.ComponentProps<"svg"> > = (props: React.ComponentProps<"svg">) => ( fillRule="evenodd" clipRule="evenodd" d="M17.7988 10.258C16.9085 10.2861 16.0918 10.3826 15.6234 10.4607C15.2148 10.5288 14.8284 10.2528 14.7603 9.84418C14.6922 9.4356 14.9682 9.04918 15.3768 8.98109C15.9085 8.89248 16.7918 8.78902 17.7515 8.75875C18.7013 8.7288 19.7823 8.76834 20.682 8.99327C21.0839 9.09374 21.3282 9.50094 21.2277 9.90278C21.1273 10.3046 20.7201 10.549 20.3182 10.4485C19.6179 10.2734 18.6989 10.2296 17.7988 10.258Z" - className="ids-option-button__icon-path" + fill="currentColor" /> @@ -164,7 +164,7 @@ React.ComponentProps<"svg"> ); -export const LikertIcon: React.FunctionComponent< +export const LegacyLikertIcon: React.FunctionComponent< React.ComponentProps<"svg"> > = (props: React.ComponentProps<"svg">) => ( /> @@ -203,3 +203,78 @@ React.ComponentProps<"svg"> ); + + +export const TextIcon: React.FunctionComponent> = ( + props: React.ComponentProps<"svg"> +) => ( + + + + + + +); + +export const OptionScaleIcon: React.FunctionComponent< +React.ComponentProps<"svg"> +> = (props: React.ComponentProps<"svg">) => ( + + + + + + + +); + +export const MultipleChoiceIcon: React.FunctionComponent< +React.ComponentProps<"svg"> +> = (props: React.ComponentProps<"svg">) => ( + + + + + + +); + +export const LikertIcon: React.FunctionComponent< +React.ComponentProps<"svg"> +> = (props: React.ComponentProps<"svg">) => ( + + + + + + + +); \ No newline at end of file