diff --git a/package-lock.json b/package-lock.json
index 78dc92871..9438c49e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
- "version": "1.14.1-pre-1",
+ "version": "1.14.1-pre-2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@devtron-labs/devtron-fe-common-lib",
- "version": "1.14.1-pre-1",
+ "version": "1.14.1-pre-2",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
diff --git a/package.json b/package.json
index 870b5ae5f..a1816526f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@devtron-labs/devtron-fe-common-lib",
- "version": "1.14.1-pre-1",
+ "version": "1.14.1-pre-2",
"description": "Supporting common component library",
"type": "module",
"main": "dist/index.js",
diff --git a/src/Shared/Components/Switch/Switch.component.tsx b/src/Shared/Components/Switch/Switch.component.tsx
new file mode 100644
index 000000000..b006d743c
--- /dev/null
+++ b/src/Shared/Components/Switch/Switch.component.tsx
@@ -0,0 +1,151 @@
+import { AriaAttributes, useRef } from 'react'
+import { AnimatePresence, motion } from 'framer-motion'
+
+import { Tooltip } from '@Common/Tooltip'
+import { ComponentSizeType } from '@Shared/constants'
+import { getUniqueId } from '@Shared/Helpers'
+
+import { Icon } from '../Icon'
+import { INDETERMINATE_ICON_WIDTH_MAP, LOADING_COLOR_MAP } from './constants'
+import { DTSwitchProps } from './types'
+import {
+ getSwitchContainerClass,
+ getSwitchIconColor,
+ getSwitchThumbClass,
+ getSwitchTrackColor,
+ getSwitchTrackHoverColor,
+ getThumbPadding,
+ getThumbPosition,
+} from './utils'
+
+import './switch.scss'
+
+const Switch = ({
+ ariaLabel,
+ dataTestId,
+ isDisabled,
+ isLoading,
+ isChecked,
+ tooltipContent,
+ shape = 'rounded',
+ variant = 'positive',
+ iconColor,
+ iconName,
+ indeterminate = false,
+ size = ComponentSizeType.medium,
+ name,
+ onChange,
+}: DTSwitchProps) => {
+ const inputId = useRef(getUniqueId())
+
+ const getAriaCheckedValue = (): AriaAttributes['aria-checked'] => {
+ if (!isChecked) {
+ return false
+ }
+
+ return indeterminate ? 'mixed' : true
+ }
+
+ const ariaCheckedValue = getAriaCheckedValue()
+
+ const showIndeterminateIcon = ariaCheckedValue === 'mixed'
+
+ const renderContent = () => (
+
+ {isLoading ? (
+
+
+
+ ) : (
+
+
+ {showIndeterminateIcon ? (
+
+ ) : (
+ iconName && (
+
+
+
+ )
+ )}
+
+
+ )}
+
+ )
+
+ return (
+
+
+
+ )
+}
+
+export default Switch
diff --git a/src/Shared/Components/Switch/constants.ts b/src/Shared/Components/Switch/constants.ts
new file mode 100644
index 000000000..6d1c97cbc
--- /dev/null
+++ b/src/Shared/Components/Switch/constants.ts
@@ -0,0 +1,64 @@
+import { ComponentSizeType } from '@Shared/constants'
+import { IconBaseColorType } from '@Shared/types'
+
+import { DTSwitchProps } from './types'
+
+export const ROUNDED_SWITCH_SIZE_MAP: Readonly> = {
+ [ComponentSizeType.medium]: 'w-32',
+ [ComponentSizeType.small]: 'w-24',
+}
+
+export const SQUARE_SWITCH_SIZE_MAP: typeof ROUNDED_SWITCH_SIZE_MAP = {
+ [ComponentSizeType.medium]: 'w-28',
+ [ComponentSizeType.small]: 'w-24',
+}
+
+export const SWITCH_HEIGHT_MAP: Readonly> = {
+ [ComponentSizeType.medium]: 'h-24',
+ [ComponentSizeType.small]: 'h-20',
+}
+
+export const LOADING_COLOR_MAP: Record = {
+ theme: 'B500',
+ positive: 'G500',
+}
+
+export const ROUNDED_SWITCH_TRACK_COLOR_MAP: Record = {
+ theme: 'bcb-5',
+ positive: 'bcg-5',
+}
+
+export const ROUNDED_SWITCH_TRACK_HOVER_COLOR_MAP: Record = {
+ theme: 'var(--B600)',
+ positive: 'var(--G600)',
+}
+
+export const SQUARE_SWITCH_TRACK_COLOR_MAP: typeof ROUNDED_SWITCH_TRACK_COLOR_MAP = {
+ theme: 'bcb-3',
+ positive: 'bcg-3',
+}
+
+export const SQUARE_SWITCH_TRACK_HOVER_COLOR_MAP: typeof ROUNDED_SWITCH_TRACK_HOVER_COLOR_MAP = {
+ theme: 'var(--B400)',
+ positive: 'var(--G400)',
+}
+
+export const ROUNDED_SWITCH_THUMB_SIZE_MAP: Record = {
+ [ComponentSizeType.medium]: 'icon-dim-16',
+ [ComponentSizeType.small]: 'icon-dim-12',
+}
+
+export const INDETERMINATE_ICON_WIDTH_MAP: Record = {
+ [ComponentSizeType.medium]: 'w-12',
+ [ComponentSizeType.small]: 'w-10',
+}
+
+export const SWITCH_THUMB_PADDING_MAP: Record = {
+ [ComponentSizeType.medium]: 'p-3',
+ [ComponentSizeType.small]: 'p-1',
+}
+
+export const THUMB_OUTER_PADDING_MAP: Record = {
+ rounded: 'p-2',
+ square: 'p-1',
+}
diff --git a/src/Shared/Components/Switch/index.ts b/src/Shared/Components/Switch/index.ts
new file mode 100644
index 000000000..a5ff57e39
--- /dev/null
+++ b/src/Shared/Components/Switch/index.ts
@@ -0,0 +1,2 @@
+export { default as DTSwitch } from './Switch.component'
+export type { DTSwitchProps } from './types'
diff --git a/src/Shared/Components/Switch/switch.scss b/src/Shared/Components/Switch/switch.scss
new file mode 100644
index 000000000..522b011c0
--- /dev/null
+++ b/src/Shared/Components/Switch/switch.scss
@@ -0,0 +1,9 @@
+.dt-switch {
+ &__track {
+ --switch-track-hover-color: 'transparent';
+
+ &:hover {
+ background-color: var(--switch-track-hover-color);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Shared/Components/Switch/types.ts b/src/Shared/Components/Switch/types.ts
new file mode 100644
index 000000000..2af63d037
--- /dev/null
+++ b/src/Shared/Components/Switch/types.ts
@@ -0,0 +1,122 @@
+import { ComponentSizeType } from '@Shared/constants'
+import { IconBaseColorType } from '@Shared/types'
+
+import { IconName } from '../Icon'
+
+/**
+ * Represents the properties for configuring the shape and behavior of a switch component.
+ *
+ * - When `shape` is `rounded`:
+ * - The switch will have a rounded appearance.
+ * - `iconName`, `iconColor`, and `indeterminate` are not applicable.
+ *
+ * - When `shape` is `square`:
+ * - The switch will have a square appearance.
+ * - `iconName` specifies the name of the icon to display.
+ * - `iconColor` allows customization of the icon's color in the active state.
+ * - `indeterminate` indicates whether the switch is in an indeterminate state, typically used for checkboxes to represent a mixed state.
+ * If `indeterminate` is true, the switch will not be fully checked or unchecked.
+ */
+type SwitchShapeProps =
+ | {
+ /**
+ * The shape of the switch. Defaults to `rounded` if not specified.
+ */
+ shape?: 'rounded'
+
+ /**
+ * Icon name is not applicable for the `rounded` shape.
+ */
+ iconName?: never
+
+ /**
+ * Icon color is not applicable for the `rounded` shape.
+ */
+ iconColor?: never
+ /**
+ * Indicates whether the switch is in an indeterminate state.
+ * This state is typically used for checkboxes to indicate a mixed state.
+ * If true, the switch will not be fully checked or unchecked. Due this state alone we are keeping role as `checkbox` instead of `switch`.
+ * This property is not applicable for the `square` shape.
+ * @default false
+ */
+ indeterminate?: boolean
+ }
+ | {
+ /**
+ * The shape of the switch. Must be `square` to enable icon-related properties.
+ */
+ shape: 'square'
+
+ /**
+ * The name of the icon to display when the shape is `square`.
+ */
+ iconName: IconName
+
+ /**
+ * The color of the icon. If provided, this will override the default color in the active state.
+ */
+ iconColor?: IconBaseColorType
+ indeterminate?: never
+ }
+
+/**
+ * Represents the properties for the `Switch` component.
+ */
+export type DTSwitchProps = {
+ /**
+ * The ARIA label for the switch, used for accessibility purposes.
+ */
+ ariaLabel: string
+
+ /**
+ * Used in forms to identify the switch.
+ */
+ name: string
+
+ /**
+ * A unique identifier for testing purposes.
+ */
+ dataTestId: string
+
+ /**
+ * The visual variant of the switch.
+ *
+ * @default `positive`
+ */
+ variant?: 'theme' | 'positive'
+
+ /**
+ * The size of the switch.
+ * @default `ComponentSizeType.medium`
+ */
+ size?: Extract
+
+ /**
+ * Callback function that is called when the switch state changes.
+ * This function should handle the logic for toggling the switch.
+ */
+ onChange: () => void
+
+ /**
+ * Indicates whether the switch is disabled.
+ */
+ isDisabled?: boolean
+
+ /**
+ * Indicates whether the switch is in a loading state.
+ */
+ isLoading?: boolean
+
+ /**
+ * Indicates whether the switch is currently checked (on).
+ */
+ isChecked: boolean
+
+ /**
+ * Optional tooltip content to display when hovering over the switch.
+ *
+ * @default undefined
+ */
+ tooltipContent?: string
+} & SwitchShapeProps
diff --git a/src/Shared/Components/Switch/utils.ts b/src/Shared/Components/Switch/utils.ts
new file mode 100644
index 000000000..2dd6cf73a
--- /dev/null
+++ b/src/Shared/Components/Switch/utils.ts
@@ -0,0 +1,94 @@
+import { IconBaseColorType } from '@Shared/types'
+
+import {
+ ROUNDED_SWITCH_SIZE_MAP,
+ ROUNDED_SWITCH_THUMB_SIZE_MAP,
+ ROUNDED_SWITCH_TRACK_COLOR_MAP,
+ ROUNDED_SWITCH_TRACK_HOVER_COLOR_MAP,
+ SQUARE_SWITCH_SIZE_MAP,
+ SQUARE_SWITCH_TRACK_COLOR_MAP,
+ SQUARE_SWITCH_TRACK_HOVER_COLOR_MAP,
+ SWITCH_HEIGHT_MAP,
+ SWITCH_THUMB_PADDING_MAP,
+ THUMB_OUTER_PADDING_MAP,
+} from './constants'
+import { DTSwitchProps } from './types'
+
+export const getSwitchContainerClass = ({ shape, size }: Required>): string =>
+ `${SWITCH_HEIGHT_MAP[size]} ${shape === 'rounded' ? ROUNDED_SWITCH_SIZE_MAP[size] : SQUARE_SWITCH_SIZE_MAP[size]}`
+
+export const getSwitchTrackColor = ({
+ shape,
+ variant,
+ isChecked,
+ isLoading,
+}: Required>): string => {
+ if (isLoading) {
+ return 'dc__transparent--unstyled'
+ }
+
+ if (!isChecked) {
+ return 'bcn-2'
+ }
+
+ return shape === 'rounded' ? ROUNDED_SWITCH_TRACK_COLOR_MAP[variant] : SQUARE_SWITCH_TRACK_COLOR_MAP[variant]
+}
+
+export const getSwitchTrackHoverColor = ({
+ shape,
+ variant,
+ isChecked,
+}: Required<
+ Pick
+>): (typeof ROUNDED_SWITCH_TRACK_HOVER_COLOR_MAP)[DTSwitchProps['variant']] => {
+ if (!isChecked) {
+ return 'var(--N300)'
+ }
+
+ return shape === 'rounded'
+ ? ROUNDED_SWITCH_TRACK_HOVER_COLOR_MAP[variant]
+ : SQUARE_SWITCH_TRACK_HOVER_COLOR_MAP[variant]
+}
+
+export const getSwitchThumbClass = ({
+ shape,
+ size,
+ showIndeterminateIcon,
+}: Pick & { showIndeterminateIcon: boolean }) => {
+ if (showIndeterminateIcon) {
+ return 'w-100 h-100 flex'
+ }
+
+ return `flex ${SWITCH_THUMB_PADDING_MAP[size]} ${shape === 'rounded' ? `dc__border-radius-50-per ${ROUNDED_SWITCH_THUMB_SIZE_MAP[size]}` : 'br-3'} bg__white`
+}
+
+export const getSwitchIconColor = ({
+ iconColor,
+ isChecked,
+ variant,
+}: Pick): IconBaseColorType => {
+ if (!isChecked) {
+ return 'N200'
+ }
+
+ return iconColor || (variant === 'theme' ? 'B500' : 'G500')
+}
+
+export const getThumbPosition = ({
+ isLoading,
+ isChecked,
+}: Pick): 'left' | 'right' | 'center' => {
+ if (isLoading) {
+ return 'center'
+ }
+
+ return isChecked ? 'right' : 'left'
+}
+
+export const getThumbPadding = ({ shape, isLoading }: Pick): string => {
+ if (isLoading) {
+ return ''
+ }
+
+ return THUMB_OUTER_PADDING_MAP[shape]
+}
diff --git a/src/Shared/Components/index.ts b/src/Shared/Components/index.ts
index 12e39877c..c3affe06a 100644
--- a/src/Shared/Components/index.ts
+++ b/src/Shared/Components/index.ts
@@ -87,6 +87,7 @@ export * from './SelectPicker'
export * from './ShowMoreText'
export * from './SSOProviderIcon'
export * from './StatusComponent'
+export * from './Switch'
export * from './TabGroup'
export * from './Table'
export * from './TagsKeyValueTable'