Skip to content

Commit

Permalink
Merge pull request #49 from getpingback/feat/switchButton
Browse files Browse the repository at this point in the history
Feat/switch button
  • Loading branch information
pepeladeira authored Dec 18, 2024
2 parents d96e549 + a8d4012 commit 7d2bb4b
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/components/switch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './switch';
53 changes: 53 additions & 0 deletions src/components/switch/switch.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Switch } from './switch';

const meta: Meta<typeof Switch> = {
title: 'Components/Switch',
component: Switch,
tags: ['autodocs'],
argTypes: {
checked: {
description: 'Controls the checked state of the switch',
control: 'boolean',
value: false
},
disabled: {
description: 'Determines if the switch is disabled',
control: 'boolean',
value: false
},
highlight: {
description: 'Applies a highlight style to the switch',
control: 'boolean',
value: false
},
onChange: {
description: 'Callback function triggered when the switch state changes',
control: false
}
}
};

export default meta;
type Story = StoryObj<typeof Switch>;

export const Default: Story = {
args: {}
};

export const Checked: Story = {
args: {
checked: true
}
};

export const Highlight: Story = {
args: { highlight: true, checked: true }
};

export const Disabled: Story = {
args: {
checked: false,
disabled: true
}
};
42 changes: 42 additions & 0 deletions src/components/switch/switch.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import { Switch } from './switch';

describe('Switch Component', () => {
it('should render correctly', () => {
render(<Switch />);
expect(screen.getByRole('checkbox')).toBeInTheDocument();
});

it('should call onChange when clicked', () => {
const handleChange = jest.fn();
render(<Switch onChange={handleChange} />);

fireEvent.click(screen.getByRole('checkbox'));
expect(handleChange).toHaveBeenCalledTimes(1);
});

it('should display correct checked state', () => {
render(<Switch checked />);
expect(screen.getByRole('checkbox')).toBeChecked();
});

it('should be disabled when disabled prop is true', () => {
render(<Switch disabled />);
expect(screen.getByRole('checkbox')).toBeDisabled();
});

it('should not call onChange when clicked if disabled', () => {
const handleChange = jest.fn();
render(<Switch onChange={handleChange} disabled />);

fireEvent.click(screen.getByRole('checkbox'));
expect(handleChange).not.toHaveBeenCalled();
});

it('should have purple background when highlight prop is true', () => {
render(<Switch highlight />);
const switchElement = screen.getByRole('checkbox');
expect(switchElement).toHaveStyle({ backgroundColor: 'var(--purple-500)' });
});
});
41 changes: 41 additions & 0 deletions src/components/switch/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { cn } from '@/lib/utils';

interface SwitchProps {
checked?: boolean;
disabled?: boolean;
highlight?: boolean;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

function Switch({ checked, disabled, highlight, onChange }: SwitchProps) {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!disabled && onChange) {
onChange(event);
}
};

return (
<label className="inline-flex items-center cursor-pointer">
<input type="checkbox" className="sr-only peer" checked={checked} disabled={disabled} onChange={handleChange} />
<div
className={cn(
'relative w-9 h-5 bg-switch-bg hover:bg-switch-bg-hover transition-all shadow-switch rounded-full peer',
'peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full',
"after:content-[''] after:bg-switch-thumb after:absolute after:top-[2px] after:start-[2px]",
'after:rounded-full after:h-4 after:w-4 after:transition-all',
'after:shadow-[0px_0px_4px_0px_#00000052,0px_1px_1px_0px_#00000014]',
'peer-focus:after:ring-8 peer-focus:after:ring-[#0000000A]',
highlight
? 'peer-checked:bg-switch-highlight peer-checked:hover:bg-switch-highlight-hover peer-checked:peer-focus:after:ring-switch-highlight-ring'
: 'peer-checked:bg-switch-checked peer-checked:hover:bg-switch-checked-hover peer-checked:peer-focus:after:ring-switch-checked-ring',
'peer-disabled:bg-gray-300/0 peer-disabled:cursor-not-allowed',
'peer-disabled:shadow-[inset_0_0_0_1px_rgb(228,228,231)]',
'peer-disabled:after:bg-switch-thumb-disabled peer-disabled:after:shadow-none'
)}
/>
</label>
);
}

export { Switch };
14 changes: 14 additions & 0 deletions src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
--bottom_sheet-2: 0px 0px 1px 1px rgba(0, 0, 0, 0.04), 0px 4px 16px -2px rgba(0, 0, 0, 0.08);
--modals-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.04), 0px -6px 24px -3px rgba(0, 0, 0, 0.08);
--dropdown-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.04), 0px 10px 40px -5px rgba(0, 0, 0, 0.08);
--switch-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.161) inset;

--button-solid-shadow: 0px 0px 0px 3px #9061f940;

Expand Down Expand Up @@ -70,6 +71,19 @@
--palette-gradiente-active_menu: linear-gradient(270deg, #7e3af200 0%, #7e3af20b 100%);

--icons-default: #71717a;

--switch-bg-default: #e4e4e740;
--switch-bg-hover: #e4e4e7;
--switch-thumb-bg: #fafafa;
--switch-thumb-disabled: #e5e5e5;

--switch-checked-bg: #31c48d;
--switch-checked-hover: #0e9f6e;
--switch-checked-ring: #31c48d1f;

--switch-highlight-bg: #ac94fa;
--switch-highlight-hover: #9061f9;
--switch-highlight-ring: #ac94fa1f;
}

.classic-purple-dark {
Expand Down
23 changes: 22 additions & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ const config = {
700: '#bf125d',
800: '#99154b',
900: '#751a3d'
},
switch: {
bg: {
DEFAULT: 'var(--switch-bg-default)',
hover: 'var(--switch-bg-hover)'
},
thumb: {
DEFAULT: 'var(--switch-thumb-bg)',
disabled: 'var(--switch-thumb-disabled)'
},
checked: {
DEFAULT: 'var(--switch-checked-bg)',
hover: 'var(--switch-checked-hover)',
ring: 'var(--switch-checked-ring)'
},
highlight: {
DEFAULT: 'var(--switch-highlight-bg)',
hover: 'var(--switch-highlight-hover)',
ring: 'var(--switch-highlight-ring)'
}
}
},
extend: {
Expand All @@ -140,7 +160,8 @@ const config = {
modal: 'var(--modals-shadow)',
custom: '0px 0px 0px 1px rgba(0,0,0,0.15)',
solid: 'var(--button-solid-shadow)',
dropdown: 'var(--dropdown-shadow)'
dropdown: 'var(--dropdown-shadow)',
switch: 'var(--switch-shadow)'
},
backgroundImage: {
'active-menu': 'var(--palette-gradiente-active_menu)'
Expand Down

0 comments on commit 7d2bb4b

Please sign in to comment.