All files / src/components/common/Switch Switch_V2.tsx

63.63% Statements 7/11
28.57% Branches 2/7
60% Functions 3/5
63.63% Lines 7/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127                                      50x   25x   25x         25x         25x         3x                   25x                                                                                                                                                            
import { styled } from "@mui/material/styles";
import {
  Switch as MuiSwitch,
  SwitchProps as MuiSwitchProps,
  Stack,
  StackProps,
} from "@mui/material";
import React from "react";
import { switchTheme } from "./SwitchTheme";
import { Text } from "@common/Text";
import { ITextProps } from "@common/Text/Text";
 
export type SwitchProps = MuiSwitchProps & {
  label?: React.ReactNode;
  helperText?: string;
  containerProps?: StackProps;
  sxText?: ITextProps;
};
 
export const Switch_V2 = styled(
  ({ containerProps, sxText, ...props }: SwitchProps) => {
    const [focused, setFocused] = React.useState(false);
 
    const onFocus = (e: React.FocusEvent<HTMLButtonElement, Element>) => {
      props.onFocus && props.onFocus(e);
      setFocused(true);
    };
 
    const onBlur = (e: React.FocusEvent<HTMLButtonElement, Element>) => {
      props.onBlur && props.onBlur(e);
      setFocused(false);
    };
 
    return (
      <Stack direction="row" alignItems="center" gap={2} {...containerProps}>
        <MuiSwitch onFocus={onFocus} onBlur={onBlur} disableRipple {...props} />
        {props.label && (
          <Text
            color={({ palette }) => palette.neutral[70]}
            height="100%"
            sx={sxText}
          >
            {props.label}
          </Text>
        )}
      </Stack>
    );
  },
)(({ theme, size = "medium" }) => ({
  width: switchTheme.size[size].width,
  height: switchTheme.size[size].height,
  padding: 0,
  overflow: "visible",
  // Default Knob styles
  "& .MuiSwitch-thumb": {
    boxShadow: "0px 2px 4px rgba(16, 24, 40, 0.15)",
    boxSizing: "border-box",
    borderRadius: "15px",
    width: switchTheme.size[size].knob.width,
    height: switchTheme.size[size].knob.height,
    margin: 2,
  },
 
  // Non switched default track
  "& .MuiSwitch-track": {
    borderRadius: switchTheme.size[size].height / 2,
    backgroundColor: switchTheme.switched.off.background,
    width: switchTheme.size[size].width,
    height: switchTheme.size[size].height,
    opacity: 1,
  },
 
  "& .MuiSwitch-switchBase": {
    padding: 0,
    transitionDuration: `${switchTheme.switched.transition}ms`,
    "&.Mui-checked": {
      color: switchTheme.switched.knob.color,
      transform: `translateX(calc(${switchTheme.size[size].width}px -  ${switchTheme.size[size].knob.width}px - 4px))`, // 4px is the border that appears on hover + margin
      "& + .MuiSwitch-track": {
        backgroundColor: switchTheme.switched.on.background,
        opacity: 1,
        border: 0,
        "&::after": {
          backgroundColor: switchTheme.switched.on.background,
        },
      },
    },
 
    // Switch on hover
    "&:hover + .MuiSwitch-track::before": {
      content: '""',
      width: switchTheme.size[size].width,
      height: switchTheme.size[size].height,
      borderRadius: switchTheme.size[size].height / 2,
      backgroundColor: "transparent",
      position: "absolute",
      left: 0,
      opacity: 1,
      transition: theme.transitions.create(["boxShadow"], {
        duration: switchTheme.transition,
      }),
      boxShadow: `0px 0px 0px rgba(2, 2, 2, 0.25), 0px 0px 0px ${switchTheme.hover.borderWidth}px ${switchTheme.hover.borderColor}`,
    },
    "&.Mui-focusVisible .MuiSwitch-thumb": {
      border: `6px solid ${switchTheme.switched.knob.color}`,
    },
 
    // Disabled default knob
    "&.Mui-disabled .MuiSwitch-thumb": {
      boxShadow: "none",
      opacity: 1,
      backgroundColor: switchTheme.disabled.knob.color,
    },
 
    // Disabled main track
    "&.Mui-disabled + .MuiSwitch-track": {
      boxShadow: "none",
      backgroundColor: switchTheme.disabled.track.color,
      opacity: 1,
 
      // Disabled inner track
      "&::after": {
        backgroundColor: switchTheme.disabled.track.color,
      },
    },
  },
}));