Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/design-system/toggle-switch/toggle-switch.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type Props = Omit<
required?: boolean;
id?: string;
testId?: string;
checkedChildren?: ReactNode;
unCheckedChildren?: ReactNode;
};

export const ToggleSwitch = ({
Expand All @@ -30,6 +32,9 @@ export const ToggleSwitch = ({
icon,
disabled,
testId,
checkedChildren,
unCheckedChildren,
checked,
...props
}: Readonly<Props>): JSX.Element => {
return (
Expand All @@ -51,12 +56,17 @@ export const ToggleSwitch = ({
)}
<Switch.Root
{...props}
checked={checked}
disabled={disabled}
className={cx.toogleSwitch}
id={id}
data-testid={testId + 'toggle-switch'}
>
<Switch.Thumb className={cx.thumb} />
{checked && <span className={cx.checkedIcon}>{checkedChildren}</span>}
{!checked && (
<span className={cx.uncheckedIcon}>{unCheckedChildren}</span>
)}
</Switch.Root>
</Flex>
);
Expand Down
29 changes: 29 additions & 0 deletions src/design-system/toggle-switch/toggle-switch.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,32 @@ export const iconContainer = style([
overflow: 'hidden',
},
]);

const icon = style([
sx({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}),
{
position: 'absolute',
top: '50%',
transform: 'translateY(-50%)',
pointerEvents: 'none',
transition: 'opacity 0.2s',
},
]);

export const checkedIcon = style([
icon,
{
left: '4px',
},
]);

export const uncheckedIcon = style([
icon,
{
right: '2px',
},
]);
33 changes: 33 additions & 0 deletions src/design-system/toggle-switch/toggle-switch.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import InfoIcon from '@icons/InfoComponent';
import type { Meta } from '@storybook/react';

import { ThemeColorScheme, LocalThemeProvider } from '../../design-tokens';
import { Moon, Sun } from '../../icons';
import { page, Variants, Section, UIStateTable } from '../decorators';
import { Divider } from '../divider';
import { Grid, Cell } from '../grid';
Expand All @@ -12,6 +13,25 @@ import { ToggleSwitch } from './toggle-switch.component';

const subtitle = `The toggle switch represents a physical switch that allows users to turn things on or off. Use toggle switch controls to present users with two mutually exclusive options (such as on/off), where choosing an option provides immediate results.`;

const WithCheckedAndUncheckedChildren = (): JSX.Element => {
const [checked, setChecked] = React.useState(false);

return (
<Variants.Row>
<Variants.Cell>
<ToggleSwitch
label="Light / Dark mode"
id="theme-switch"
checked={checked}
onCheckedChange={setChecked}
checkedChildren={<Sun width={20} height={20} />}
unCheckedChildren={<Moon width={20} height={20} />}
/>
</Variants.Cell>
</Variants.Row>
);
};

export default {
title: 'Basic Input/Toggle switch',
component: ToggleSwitch,
Expand Down Expand Up @@ -204,6 +224,19 @@ export const Overview = (): JSX.Element => (
<SwitchPreview />
</UIStateTable>
</Section>

<Divider my="$64" />

<Section title="Toogle switch with icons">
<Variants.Table>
<WithCheckedAndUncheckedChildren />
</Variants.Table>
<LocalThemeProvider colorScheme={ThemeColorScheme.Dark}>
<Variants.Table>
<WithCheckedAndUncheckedChildren />
</Variants.Table>
</LocalThemeProvider>
</Section>
</Cell>
</Grid>
);
Expand Down
9 changes: 9 additions & 0 deletions src/icons/MoonComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { type SVGProps } from 'react';

const SvgMoonComponent = (props: SVGProps<SVGSVGElement>) => (
<svg width={24} height={24} fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<path d="M13.9999 10.3067C13.2119 10.6631 12.3371 10.8615 11.416 10.8615C7.94916 10.8615 5.13868 8.051 5.13868 4.5841C5.13868 3.66292 5.3371 2.78808 5.69354 2C3.51549 2.98496 2 5.17681 2 7.72263C2 11.1895 4.81047 14 8.27737 14C10.8231 14 13.0149 12.4846 13.9999 10.3067Z" fill="white"/>
</svg>
);

export default SvgMoonComponent;
17 changes: 17 additions & 0 deletions src/icons/SunComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { SVGProps } from 'react';

const SvgSunComponent = (props: SVGProps<SVGSVGElement>) => (
<svg width={24} height={24} fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<path d="M7.99967 1.33333C8.45991 1.33333 8.83301 1.70642 8.83301 2.16666V2.99999C8.83301 3.46023 8.45991 3.83333 7.99967 3.83333C7.53944 3.83333 7.16634 3.46023 7.16634 2.99999V2.16666C7.16634 1.70642 7.53944 1.33333 7.99967 1.33333Z" fill="white"/>
<path d="M11.333 8C11.333 9.84094 9.84062 11.3333 7.99967 11.3333C6.15873 11.3333 4.66634 9.84094 4.66634 8C4.66634 6.15905 6.15873 4.66666 7.99967 4.66666C9.84062 4.66666 11.333 6.15905 11.333 8Z" fill="white"/>
<path d="M10.946 12.1248L11.5353 12.714C11.8607 13.0394 12.3883 13.0394 12.7138 12.714C13.0392 12.3886 13.0392 11.8609 12.7138 11.5355L12.1245 10.9462C11.7991 10.6208 11.2714 10.6208 10.946 10.9462C10.6206 11.2717 10.6206 11.7993 10.946 12.1248Z" fill="white"/>
<path d="M12.7137 3.28591C13.0391 3.61134 13.0391 4.13898 12.7137 4.46442L12.1244 5.05367C11.799 5.37911 11.2714 5.37911 10.9459 5.05367C10.6205 4.72824 10.6205 4.2006 10.9459 3.87516L11.5352 3.28591C11.8606 2.96047 12.3882 2.96047 12.7137 3.28591Z" fill="white"/>
<path d="M13.833 8.83333C14.2932 8.83333 14.6663 8.46023 14.6663 8C14.6663 7.53976 14.2932 7.16666 13.833 7.16666H12.9997C12.5394 7.16666 12.1663 7.53976 12.1663 8C12.1663 8.46023 12.5394 8.83333 12.9997 8.83333H13.833Z" fill="white"/>
<path d="M7.99967 12.1667C8.45991 12.1667 8.83301 12.5398 8.83301 13V13.8333C8.83301 14.2936 8.45991 14.6667 7.99967 14.6667C7.53944 14.6667 7.16634 14.2936 7.16634 13.8333V13C7.16634 12.5398 7.53944 12.1667 7.99967 12.1667Z" fill="white"/>
<path d="M3.87493 5.05369C4.20037 5.37912 4.72801 5.37912 5.05344 5.05369C5.37888 4.72825 5.37888 4.20061 5.05344 3.87518L4.46419 3.28592C4.13875 2.96048 3.61111 2.96048 3.28568 3.28592C2.96024 3.61136 2.96024 4.139 3.28568 4.46443L3.87493 5.05369Z" fill="white"/>
<path d="M5.05337 12.1247L4.46411 12.714C4.13867 13.0394 3.61104 13.0394 3.2856 12.714C2.96016 12.3886 2.96016 11.8609 3.2856 11.5355L3.87486 10.9462C4.20029 10.6208 4.72793 10.6208 5.05337 10.9462C5.3788 11.2717 5.3788 11.7993 5.05337 12.1247Z" fill="white"/>
<path d="M2.99967 8.83333C3.45991 8.83333 3.83301 8.46023 3.83301 8C3.83301 7.53976 3.45991 7.16666 2.99967 7.16666H2.16634C1.7061 7.16666 1.33301 7.53976 1.33301 8C1.33301 8.46023 1.7061 8.83333 2.16634 8.83333H2.99967Z" fill="white"/>
</svg>
);

export default SvgSunComponent;
2 changes: 2 additions & 0 deletions src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ export { default as WalletComponent } from './WalletComponent';
export { default as WarningIconCircleComponent } from './WarningIconCircleComponent';
export { default as WarningIconTriangleSolidComponent } from './WarningIconTriangleSolidComponent';
export { default as WarningIconTriangleComponent } from './WarningIconTriangleComponent';
export { default as Sun } from './SunComponent';
export { default as Moon } from './MoonComponent';