Skip to content

Commit

Permalink
🪟 🎨 Aligns Switch design according to the latest Figma updates (#20629)
Browse files Browse the repository at this point in the history
* Aligns Switch design according to the latest Figma updates

* Updates snapshots tests, after adding aria-checked property for switch input; Adds mixed UI state for Switch component
  • Loading branch information
YatsukBogdan1 authored Jan 4, 2023
1 parent 3631418 commit f10c765
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ exports[`CreateConnectionForm should render 1`] = `
class="<removed-for-snapshot-test>"
>
<input
aria-checked="true"
checked=""
class="<removed-for-snapshot-test>"
data-testid="pokemon-stream-sync-switch"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Switch } from "components/ui/Switch";

import styles from "./LabeledSwitch.module.scss";

interface LabeledSwitchProps extends React.InputHTMLAttributes<HTMLInputElement> {
interface LabeledSwitchProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> {
message?: React.ReactNode;
label?: React.ReactNode;
checkbox?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const BulkHeader: React.FC = () => {
<CheckboxCell />
<ArrowCell />
<HeaderCell flex={0.4}>
<Switch small checked={options.selected} onChange={() => onChangeOption({ selected: !options.selected })} />
<Switch size="sm" checked={options.selected} onChange={() => onChangeOption({ selected: !options.selected })} />
</HeaderCell>
<HeaderCell />
<HeaderCell />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ const FieldRowInner: React.FC<FieldRowProps> = ({
<Cell flex={0}>
<SyncCheckboxContainer>
{!isNestedField && (
<Switch small checked={isSelected} onChange={() => onToggleFieldSelected(field.path, !isSelected)} />
<Switch size="sm" checked={isSelected} onChange={() => onToggleFieldSelected(field.path, !isSelected)} />
)}
{isNestedField && (
<Tooltip control={<Switch small disabled checked={isSelected} />}>
<Tooltip control={<Switch size="sm" disabled checked={isSelected} />}>
<FormattedMessage id="form.field.sync.nestedFieldTooltip" values={{ fieldName: field.path[0] }} />
</Tooltip>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const StreamHeader: React.FC<StreamHeaderProps> = ({
<div className={streamHeaderContentStyle}>
<HeaderCell flex={0.4}>
<Switch
small
size="sm"
checked={stream.config?.selected}
onChange={onSelectStream}
disabled={disabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,12 @@ export const BulkEditPanel: React.FC = () => {
<FormattedMessage id="sources.sync" />
</p>
<div className={styles.syncCellContent}>
<Switch small checked={options.selected} onChange={() => onChangeOption({ selected: !options.selected })} />
<Switch
variant="strong-blue"
size="sm"
checked={options.selected}
onChange={() => onChangeOption({ selected: !options.selected })}
/>
</div>
</HeaderCell>
<HeaderCell flex={1} className={styles.headerCell}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const CatalogTreeTableRow: React.FC<StreamHeaderProps> = ({
</div>
)}
<Cell flex={0.5} flush>
<Switch small checked={stream.config?.selected} onChange={onSelectStream} disabled={disabled} />
<Switch size="sm" checked={stream.config?.selected} onChange={onSelectStream} disabled={disabled} />
</Cell>
{/* <Cell>{fieldCount}</Cell> */}
<Cell flex={1} title={stream.stream?.namespace || ""}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const StreamPanelHeader: React.FC<StreamPanelHeaderProps> = ({
return (
<div className={styles.container}>
<div>
<Switch small checked={config?.selected} onChange={onSelectedChange} disabled={disabled} />
<Switch size="sm" checked={config?.selected} onChange={onSelectedChange} disabled={disabled} />
</div>
<div className={styles.properties}>
<StreamProperty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ exports[`<BulkEditPanel /> should render 1`] = `
class="<removed-for-snapshot-test>"
>
<input
aria-checked="false"
class="<removed-for-snapshot-test>"
type="checkbox"
value=""
Expand Down
143 changes: 96 additions & 47 deletions airbyte-webapp/src/components/ui/Switch/Switch.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,63 @@
@use "scss/variables";
@use "scss/z-indices";

@mixin knob-transform($position, $small: false) {
@mixin knob-transform($position, $size) {
@if $position == left {
transform: translateX(0);
} @else if $small {
transform: translateX(10px);
} @else if $position == middle {
@if $size == lg {
transform: translateX(8px);
}
@if $size == sm {
transform: translateX(4.5px);
}
@if $size == xs {
transform: translateX(3.5px);
}
} @else {
transform: translateX(18px);
@if $size == lg {
transform: translateX(16px);
}
@if $size == sm {
transform: translateX(9px);
}
@if $size == xs {
transform: translateX(7px);
}
}
}

@mixin all-sizes-knob-transform($position) {
&.sizeLg::before {
@include knob-transform($position, lg);
}

&.sizeSm::before {
@include knob-transform($position, sm);
}

&.sizeXs::before {
@include knob-transform($position, xs);
}
}

.switch {
position: relative;
display: inline-block;
width: 42px;
height: 26px;

&.small {
width: 28px;
height: 18px;
&.sizeLg {
width: 42px;
height: 26px;
}

&.sizeSm {
width: 25px;
height: 16px;
}

&.sizeXs {
width: 17px;
height: 10px;
}

.slider {
Expand All @@ -33,25 +71,39 @@
background: colors.$grey-100;
transition: variables.$transition;
border-radius: variables.$border-radius-pill;
border: 1px solid colors.$grey-200;

&.small::before {
height: 16px;
width: 16px;
&.sizeLg {
border: 1px solid colors.$grey-200;
}

&.sizeLg::before {
width: 24px;
height: 24px;
left: 0;
top: 0;
}

&.sizeSm::before {
height: 14px;
width: 14px;
top: 1px;
left: 1px;
}

&.sizeXs::before {
width: 8px;
height: 8px;
top: 1px;
left: 1px;
}

&::before {
position: absolute;
z-index: z-indices.$switchSliderBefore;
content: "";
height: 24px;
width: 24px;
left: -1px;
top: -1px;
background: colors.$white;
transition: variables.$transition;
border-radius: 50%;
border: 1px solid colors.$grey-200;
}
}

Expand All @@ -60,55 +112,52 @@
width: 0;
height: 0;

&:checked + .slider {
background-color: colors.$blue;

&::before {
@include knob-transform(right, false);
&[aria-checked="true"] + .slider {
&.variantDefault {
background-color: colors.$blue;
}

&.small::before {
@include knob-transform(right, true);
&.variantStrongBlue {
background-color: colors.$blue-700;
}

@include all-sizes-knob-transform(right);

&.loading {
background-image: url("./ProgressReverse.svg");

&::before {
@include knob-transform(left, false);
}

&.small::before {
@include knob-transform(left, true);
}
@include all-sizes-knob-transform(left);
}
}

&:not(:checked) + .slider {
&::before {
@include knob-transform(left, false);
}

&.small::before {
@include knob-transform(left, true);
}
&[aria-checked="false"] + .slider {
@include all-sizes-knob-transform(left);

&.loading {
background-image: url("./Progress.svg");
@include all-sizes-knob-transform(right);
}
}

&::before {
@include knob-transform(right, false);
}
&[aria-checked="mixed"] + .slider {
&.variantDefault {
background-color: colors.$blue-200;
}

&.small::before {
@include knob-transform(right, true);
}
&.loading {
background-color: colors.$blue-100;
background-image: url("./ProgressReverse.svg");
}

@include all-sizes-knob-transform(middle);
}

&:disabled + .slider {
opacity: 0.5;
cursor: auto;

&.loading {
opacity: 1;
}
}
}
}
2 changes: 1 addition & 1 deletion airbyte-webapp/src/components/ui/Switch/Switch.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ const Template: ComponentStory<typeof Switch> = (args) => <Switch {...args} />;
export const SwitchControl = Template.bind({});
SwitchControl.args = {
checked: false,
small: false,
size: "sm",
loading: false,
};
35 changes: 29 additions & 6 deletions airbyte-webapp/src/components/ui/Switch/Switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,52 @@ import React from "react";

import styles from "./Switch.module.scss";

interface SwitchProps extends React.InputHTMLAttributes<HTMLInputElement> {
small?: boolean;
type SwitchSize = "lg" | "sm" | "xs";

type SwitchVariant = "default" | "strong-blue";

interface SwitchProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> {
indeterminate?: boolean;
loading?: boolean;
size?: SwitchSize;
variant?: SwitchVariant;
}

export const Switch: React.FC<SwitchProps> = ({ loading, small, checked, value, ...props }) => {
export const Switch: React.FC<SwitchProps> = ({
checked,
disabled,
indeterminate,
loading,
size = "lg",
value,
variant = "default",
...props
}) => {
const labelStyle = classnames(styles.switch, {
[styles.small]: small,
[styles.sizeLg]: size === "lg",
[styles.sizeSm]: size === "sm",
[styles.sizeXs]: size === "xs",
[styles.loading]: loading,
});
const spanStyle = classnames(styles.slider, {
[styles.small]: small,
[styles.sizeLg]: size === "lg",
[styles.sizeSm]: size === "sm",
[styles.sizeXs]: size === "xs",
[styles.variantDefault]: variant === "default",
[styles.variantStrongBlue]: variant === "strong-blue",
[styles.indeterminate]: indeterminate,
[styles.loading]: loading,
});

return (
<label className={labelStyle}>
<input
{...props}
aria-checked={indeterminate ? "mixed" : checked}
className={styles.switchInput}
type="checkbox"
value={value}
disabled={loading || props.disabled}
disabled={loading || disabled}
checked={checked || !!value}
/>
<span className={spanStyle} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ exports[`ConnectionReplicationTab should render 1`] = `
class="<removed-for-snapshot-test>"
>
<input
aria-checked="true"
checked=""
class="<removed-for-snapshot-test>"
data-testid="pokemon-stream-sync-switch"
Expand Down

0 comments on commit f10c765

Please sign in to comment.