From ae06f306b6071209d05ed67367a111e2fdb305ba Mon Sep 17 00:00:00 2001 From: Miki Date: Sun, 4 Aug 2024 23:25:27 -0700 Subject: [PATCH] Add display type and color to OuiSwitch Signed-off-by: Miki --- CHANGELOG.md | 8 +- src/components/form/switch/_switch.scss | 102 +++++++++++++++++- src/components/form/switch/index.ts | 2 + src/components/form/switch/switch.tsx | 44 +++++++- src/global_styling/variables/_form.scss | 14 +++ .../global_styling/variables/_form.scss | 14 +++ 6 files changed, 180 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 834f54652a..6ba0f8c922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,11 +20,17 @@ ### 🔩 Tests -## [`1.8.2`](https://github.com/opensearch-project/oui/tree/1.8.1) +## [`1.9.0`](https://github.com/opensearch-project/oui/tree/1.8.1) + +### 📈 Features/Enhancements + +- Add display type and color to OuiSwitch ([#1332](https://github.com/opensearch-project/oui/pull/1332)) ### 🐛 Bug Fixes - Fix the availability of OuiCompressedSuperDatePicker ([#1325](https://github.com/opensearch-project/oui/pull/1325)) +- Fix now button to be secondary in SuperDatePicker ([#1320](https://github.com/opensearch-project/oui/pull/1320)) + ## [`1.8.1`](https://github.com/opensearch-project/oui/tree/1.8.1) diff --git a/src/components/form/switch/_switch.scss b/src/components/form/switch/_switch.scss index 85b4b6a47b..f68725b668 100644 --- a/src/components/form/switch/_switch.scss +++ b/src/components/form/switch/_switch.scss @@ -81,7 +81,6 @@ pointer-events: none; width: $ouiSwitchWidth; height: $ouiSwitchHeight; - background-color: $ouiColorPrimary; display: inline-block; position: relative; border-radius: $ouiSwitchHeight; @@ -214,4 +213,105 @@ } } } + + &.ouiSwitch--base { + border: solid 1px transparent; + cursor: pointer; + height: $ouiButtonHeight; + line-height: $ouiButtonHeight; + vertical-align: middle; + align-items: stretch; + border-radius: $ouiBorderRadius; + padding: 0 $euiSize - $euiSizeXS; + + .ouiSwitch__label { + // sass-lint:disable-block no-important + line-height: $ouiFormControlLayoutGroupInputHeight !important; + } + + &.ouiSwitch--compressed, + &.ouiSwitch--mini { + height: $ouiButtonHeightSmall; + line-height: $ouiButtonHeightSmall; + + .ouiSwitch__label { + // sass-lint:disable-block no-important + line-height: $ouiFormControlLayoutGroupInputCompressedHeight !important; + } + } + + &.ouiSwitch-isDisabled { + border-color: $ouiButtonColorDisabled; + cursor: not-allowed; + + &:hover, + &:focus, + &:focus-within { + @include ouiSlightShadow; + } + } + } +} + +// sass-lint:disable-block nesting-depth +@each $name, $color in $ouiSwitchColors { + .ouiSwitch--#{$name} { + &.ouiSwitch--base { + @include ouiSlightShadow; + @include ouiButtonFocus; + + border-color: $color; + + @if ($name == 'ghost') { + // Ghost is unique and ALWAYS sits against a dark background. + color: $color; + } @else if ($name == 'text') { + // The default color is lighter than the normal text color, make the it the text color + color: $ouiTextColor; + } @else { + // Other colors need to check their contrast against the page background color. + color: makeHighContrastColor($color, $ouiPageBackgroundColor); + } + + &:not([class*='isDisabled']) { + $shadowColor: $ouiShadowColor; + @if ($name == 'ghost') { + $shadowColor: $ouiColorInk; + } @else if (lightness($ouiTextColor) < 50) { + // Only if this is the light theme do we use the button variant color to colorize the shadow + $shadowColor: desaturate($color, 60%); + } + + @include ouiSlightShadow($shadowColor); + + &:hover, + &:focus, + &:focus-within { + @include ouiSlightShadowHover($shadowColor); + background-color: transparentize($color, .9); + } + + &:active { + @include ouiSlightShadowActive($color); + } + } + } + + .ouiSwitch__body { + background-color: $color; + } + + .ouiSwitch__icon--checked { + &.ouiSwitch--compressed, + &.ouiSwitch--mini { + .ouiSwitch__button[aria-checked='true'] { + .ouiSwitch__thumb { + border-color: $color; + } + } + } + } + } } + + diff --git a/src/components/form/switch/index.ts b/src/components/form/switch/index.ts index 6518ec9f01..4b8c9477d9 100644 --- a/src/components/form/switch/index.ts +++ b/src/components/form/switch/index.ts @@ -31,6 +31,8 @@ export { OuiSwitch, OuiSwitchProps, + OuiSwitchColor, + OuiSwitchDisplay, OuiSwitchEvent, OuiCompressedSwitch, OuiCompressedSwitchProps, diff --git a/src/components/form/switch/switch.tsx b/src/components/form/switch/switch.tsx index bfeddde9a2..415943cb27 100644 --- a/src/components/form/switch/switch.tsx +++ b/src/components/form/switch/switch.tsx @@ -38,10 +38,34 @@ import React, { } from 'react'; import classNames from 'classnames'; -import { CommonProps } from '../../common'; +import { CommonProps, keysOf } from '../../common'; import { htmlIdGenerator } from '../../../services/accessibility'; import { OuiIcon } from '../../icon'; +const baseClassName = 'ouiSwitch'; + +const colorToClassNameMap = { + primary: `${baseClassName}--primary`, + accent: `${baseClassName}--accent`, + secondary: `${baseClassName}--secondary`, + success: `${baseClassName}--success`, + warning: `${baseClassName}--warning`, + danger: `${baseClassName}--danger`, + ghost: `${baseClassName}--ghost`, + text: `${baseClassName}--text`, +}; + +export const COLORS = keysOf(colorToClassNameMap); +export type OuiSwitchColor = keyof typeof colorToClassNameMap; + +const displayToClassNameMap = { + base: `${baseClassName}--base`, + empty: null, +}; + +export const DISPLAYS = keysOf(displayToClassNameMap); +export type OuiSwitchDisplay = keyof typeof displayToClassNameMap; + export type OuiSwitchEvent = React.BaseSyntheticEvent< React.MouseEvent, HTMLButtonElement, @@ -56,7 +80,7 @@ export type OuiSwitchProps = CommonProps & 'onChange' | 'type' | 'disabled' > & { /** - * Whether to render the render the text label + * Whether to render the text label */ showLabel?: boolean; /** @@ -65,6 +89,11 @@ export type OuiSwitchProps = CommonProps & label: ReactNode | string; checked: boolean; onChange: (event: OuiSwitchEvent) => void; + /** + * Any of the named color palette options. + * **`subdued` set to be DEPRECATED, use `text` instead** + */ + color?: OuiSwitchColor; disabled?: boolean; compressed?: boolean; type?: 'submit' | 'reset' | 'button'; @@ -72,6 +101,12 @@ export type OuiSwitchProps = CommonProps & * Object of props passed to the label's */ labelProps?: CommonProps & HTMLAttributes; + /** + * Sets the display style for matching other OuiButton types. + * `base` is equivalent to a typical OuiButton + * `empty` (default) is equivalent to an OuiButtonEmpty + */ + display?: OuiSwitchDisplay; }; export const OuiSwitch: FunctionComponent = ({ @@ -85,6 +120,8 @@ export const OuiSwitch: FunctionComponent = ({ showLabel = true, type = 'button', labelProps, + color = 'primary', + display = 'empty', ...rest }) => { const [switchId] = useState(id || htmlIdGenerator()()); @@ -105,8 +142,11 @@ export const OuiSwitch: FunctionComponent = ({ const classes = classNames( 'ouiSwitch', + color && colorToClassNameMap[color], + display && displayToClassNameMap[display], { 'ouiSwitch--compressed': compressed, + 'ouiSwitch-isDisabled': disabled, }, className ); diff --git a/src/global_styling/variables/_form.scss b/src/global_styling/variables/_form.scss index 0c7c15b9ed..78f547b1b4 100644 --- a/src/global_styling/variables/_form.scss +++ b/src/global_styling/variables/_form.scss @@ -36,6 +36,19 @@ $ouiSwitchHeightMini: $ouiSwitchHeight * .5 !default; $ouiSwitchWidthMini: $ouiSwitchWidth * .5 !default; $ouiSwitchThumbSizeMini: $ouiSwitchHeightMini !default; +// Modifier naming and colors. +$ouiSwitchColors: ( + primary: $ouiColorPrimary, + accent: $ouiColorAccent, + secondary: $ouiColorSecondary, + success: $ouiColorSuccess, + warning: $ouiColorWarning, + danger: $ouiColorDanger, + subdued: $ouiTextSubduedColor, // Should get deprecated in favor of `text` + ghost: $ouiColorGhost, // Ghost is special, and does not care about theming. + text: $ouiColorDarkShade, // Reserved for special use cases +) !default; + // Coloring $ouiFormBackgroundColor: tintOrShade($ouiColorLightestShade, 60%, 40%) !default; $ouiFormBackgroundDisabledColor: darken($ouiColorLightestShade, 2%) !default; @@ -97,6 +110,7 @@ $euiSwitchThumbSizeCompressed: $ouiSwitchThumbSizeCompressed; $euiSwitchHeightMini: $ouiSwitchHeightMini; $euiSwitchWidthMini: $ouiSwitchWidthMini; $euiSwitchThumbSizeMini: $ouiSwitchThumbSizeMini; +$euiSwitchColors: $ouiSwitchColors; $euiFormBackgroundColor: $ouiFormBackgroundColor; $euiFormBackgroundDisabledColor: $ouiFormBackgroundDisabledColor; $euiFormBackgroundReadOnlyColor: $ouiFormBackgroundReadOnlyColor; diff --git a/src/themes/oui-next/global_styling/variables/_form.scss b/src/themes/oui-next/global_styling/variables/_form.scss index 38bb18ddb7..7b339ec23e 100644 --- a/src/themes/oui-next/global_styling/variables/_form.scss +++ b/src/themes/oui-next/global_styling/variables/_form.scss @@ -36,6 +36,19 @@ $ouiSwitchHeightMini: $ouiSwitchHeight * .5 !default; $ouiSwitchWidthMini: $ouiSwitchWidth * .5 !default; $ouiSwitchThumbSizeMini: $ouiSwitchHeightMini !default; +// Modifier naming and colors. +$ouiSwitchColors: ( + primary: $ouiColorPrimary, + accent: $ouiColorAccent, + secondary: $ouiColorSecondary, + success: $ouiColorSuccess, + warning: $ouiColorWarning, + danger: $ouiColorDanger, + subdued: $ouiTextSubduedColor, // Should get deprecated in favor of `text` + ghost: $ouiColorGhost, // Ghost is special, and does not care about theming. + text: $ouiColorDarkShade, // Reserved for special use cases +) !default; + // Coloring $ouiFormBackgroundColor: tintOrShade($ouiColorLightestShade, 60%, 40%) !default; $ouiFormBackgroundDisabledColor: darken($ouiColorLightestShade, 2%) !default; @@ -98,6 +111,7 @@ $euiSwitchThumbSizeCompressed: $ouiSwitchThumbSizeCompressed; $euiSwitchHeightMini: $ouiSwitchHeightMini; $euiSwitchWidthMini: $ouiSwitchWidthMini; $euiSwitchThumbSizeMini: $ouiSwitchThumbSizeMini; +$euiSwitchColors: $ouiSwitchColors; $euiFormBackgroundColor: $ouiFormBackgroundColor; $euiFormBackgroundDisabledColor: $ouiFormBackgroundDisabledColor; $euiFormBackgroundReadOnlyColor: $ouiFormBackgroundReadOnlyColor;