Skip to content

Commit

Permalink
Merge pull request #7 from internxt/feat/switch-and-radio-button-comp…
Browse files Browse the repository at this point in the history
…onents

[_]: feat/switch and radio button components
  • Loading branch information
xabg2 authored Sep 26, 2024
2 parents cbba2c4 + 8a67d3d commit 30beeca
Show file tree
Hide file tree
Showing 18 changed files with 796 additions and 83 deletions.
13 changes: 13 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,18 @@
"extends": ["@internxt/eslint-config-internxt", "plugin:storybook/recommended"],
"rules": {
"react/react-in-jsx-scope": "off",
"max-len": [
"error",
{
"code": 120,
"tabWidth": 2,
"comments": 120,
"ignorePattern": "^import\\s.+\\sfrom\\s.+;$",
"ignoreUrls": true,
"ignoreStrings": true,
"ignoreTemplateLiterals": true,
"ignoreRegExpLiterals": true,
},
],
},
}
37 changes: 37 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Components Testing

on:
pull_request:
types:
- opened
- synchronize

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- run: echo "registry=https://registry.yarnpkg.com/" > .npmrc
- run: echo "@internxt:registry=https://npm.pkg.github.com" >> .npmrc
# You cannot read packages from other private repos with GITHUB_TOKEN
# You have to use a PAT instead https://github.com/actions/setup-node/issues/49
- run: echo //npm.pkg.github.com/:_authToken=${{ secrets.PERSONAL_ACCESS_TOKEN }} >> .npmrc
- run: echo "always-auth=true" >> .npmrc

- name: Install dependencies
run: yarn

- name: Build the project
run: yarn build

- name: Run Tests
run: yarn test
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@internxt/internxtui",
"version": "0.0.1",
"version": "0.0.2",
"description": "Library of Internxt components",
"repository": {
"type": "git",
Expand Down Expand Up @@ -69,10 +69,11 @@
"test-watch": "vitest",
"test:ui": "vitest --ui",
"coverage": "vitest run --coverage",
"sb": "storybook dev -p 6006",
"build-storybook": "storybook build"
"storybook:dev": "storybook dev -p 6006",
"storybook:build": "storybook build"
},
"dependencies": {
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/themes": "^3.0.0"
},
"lint-staged": {
Expand Down
38 changes: 22 additions & 16 deletions src/components/button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
import { ReactNode } from 'react';
import Spinner from '../spinner/Spinner';

export default function Button({
variant = 'primary',
type = 'button',
children,
className = '',
disabled = false,
onClick = () => undefined,
size = 'default',
loading,
dataTest,
autofocus,
buttonDataCy,
buttonChildrenDataCy,
}: Readonly<{
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'ghost' | 'destructive';
type?: 'button' | 'submit';
children?: ReactNode;
className?: string;
disabled?: boolean;
onClick?: () => void;
onKeyDown?: () => void;
size?: 'medium' | 'default';
loading?: boolean;
dataTest?: string;
autofocus?: boolean;
buttonDataCy?: string;
buttonChildrenDataCy?: string;
}>): JSX.Element {
}

export const Button = ({
variant = 'primary',
type = 'button',
children,
className = '',
disabled = false,
onClick = () => undefined,
onKeyDown = () => undefined,
size = 'default',
loading,
dataTest,
autofocus,
buttonDataCy,
buttonChildrenDataCy,
}: Readonly<ButtonProps>): JSX.Element => {
let styles = '';

if (variant === 'primary' && !disabled) {
Expand All @@ -49,10 +53,12 @@ export default function Button({
} else if (variant === 'ghost' && disabled) {
styles = 'text-gray-30';
}

return (
<button
data-cy={buttonDataCy}
onClick={onClick}
onKeyDown={onKeyDown}
disabled={disabled || loading}
type={type}
data-test={dataTest}
Expand All @@ -70,4 +76,4 @@ export default function Button({
</div>
</button>
);
}
};
2 changes: 1 addition & 1 deletion src/components/button/__test__/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { describe, expect, it, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import Button from '../Button';
import { Button } from '../Button';
import renderer from 'react-test-renderer';

describe('Button component', () => {
Expand Down
77 changes: 44 additions & 33 deletions src/components/button/__test__/__snapshots__/Button.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`Button component > Destructive button should render correctly 1`] = `
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 bg-red active:bg-red-dark text-white shadow-sm "
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand All @@ -25,6 +26,42 @@ exports[`Button component > Destructive disabled button should render correctly
focus-visible:ring-primary/50 bg-gray-30 text-white shadow-sm "
disabled={true}
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
className="flex items-center justify-center space-x-2"
/>
</button>
`;

exports[`Button component > Ghost button should render correctly 1`] = `
<button
className="h-10 px-5 relative flex shrink-0 select-none flex-row items-center justify-center space-x-2
whitespace-nowrap rounded-lg text-base font-medium outline-none ring-2 ring-primary/0
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 hover:bg-gray-5 active:bg-gray-10 focus-visible:bg-gray-10 "
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
className="flex items-center justify-center space-x-2"
>
Ghost
</div>
</button>
`;

exports[`Button component > Ghost disabled button should render correctly 1`] = `
<button
className="h-10 px-5 relative flex shrink-0 select-none flex-row items-center justify-center space-x-2
whitespace-nowrap rounded-lg text-base font-medium outline-none ring-2 ring-primary/0
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 text-gray-30 "
disabled={true}
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand All @@ -40,6 +77,7 @@ exports[`Button component > Primary button should render correctly 1`] = `
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 bg-primary active:bg-primary-dark text-white shadow-sm "
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand All @@ -58,6 +96,7 @@ exports[`Button component > Primary disabled button should render correctly 1`]
focus-visible:ring-primary/50 bg-gray-30 text-white shadow-sm "
disabled={true}
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand All @@ -74,6 +113,7 @@ exports[`Button component > Primary loading button should render correctly 1`] =
focus-visible:ring-primary/50 bg-primary-dark active:bg-primary-dark text-white shadow-sm "
disabled={true}
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<svg
Expand Down Expand Up @@ -112,6 +152,7 @@ exports[`Button component > Primary medium button should render correctly 1`] =
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 bg-primary active:bg-primary-dark text-white shadow-sm "
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand All @@ -127,6 +168,7 @@ exports[`Button component > Primary submit button should render correctly 1`] =
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 bg-primary active:bg-primary-dark text-white shadow-sm "
onClick={[Function]}
onKeyDown={[Function]}
type="submit"
>
<div
Expand All @@ -142,6 +184,7 @@ exports[`Button component > Secondary button should render correctly 1`] = `
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 bg-surface dark:bg-gray-5 border border-gray-10 hover:border-gray-20 active:bg-gray-1 dark:active:bg-gray-10 text-gray-80 shadow-sm "
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand All @@ -160,39 +203,7 @@ exports[`Button component > Secondary disabled button should render correctly 1`
focus-visible:ring-primary/50 bg-surface dark:bg-gray-5 text-gray-30 border border-gray-5 shadow-sm "
disabled={true}
onClick={[Function]}
type="button"
>
<div
className="flex items-center justify-center space-x-2"
/>
</button>
`;

exports[`Button component > Ghost button should render correctly 1`] = `
<button
className="h-10 px-5 relative flex shrink-0 select-none flex-row items-center justify-center space-x-2
whitespace-nowrap rounded-lg text-base font-medium outline-none ring-2 ring-primary/0
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 hover:bg-gray-5 active:bg-gray-10 focus-visible:bg-gray-10 "
onClick={[Function]}
type="button"
>
<div
className="flex items-center justify-center space-x-2"
>
Ghost
</div>
</button>
`;

exports[`Button component > Ghost disabled button should render correctly 1`] = `
<button
className="h-10 px-5 relative flex shrink-0 select-none flex-row items-center justify-center space-x-2
whitespace-nowrap rounded-lg text-base font-medium outline-none ring-2 ring-primary/0
ring-offset-2 ring-offset-transparent transition-all duration-100 ease-in-out
focus-visible:ring-primary/50 text-gray-30 "
disabled={true}
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
<div
Expand Down
1 change: 0 additions & 1 deletion src/components/button/index.ts

This file was deleted.

4 changes: 3 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './button';
export * from './button/Button';
export * from './switch/Switch';
export * from './radio-button/RadioButton';
24 changes: 24 additions & 0 deletions src/components/radio-button/RadioButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
interface RadioButtonProps {
checked: boolean;
disabled?: boolean;
onClick: () => void;
}

export const RadioButton = ({ checked, disabled = false, onClick }: RadioButtonProps) => {
const borderStyle = disabled ? 'border-gray-10' : 'border-gray-40';
const checkedStyle =
disabled && checked ? 'border-0 bg-gray-20' : checked && 'border-0 bg-primary active:bg-primary-dark';

return (
<div className="flex cursor-pointer">
<button
disabled={disabled}
onClick={onClick}
className={`flex h-5 w-5 items-center justify-center rounded-full border ${checkedStyle} ${borderStyle}`}
>
{<div className={`h-2.5 w-2.5 rounded-full ${checked || disabled ? 'bg-white' : 'hover:bg-gray-10'}`}></div>}
</button>
<input type="radio" className="h-0 w-0 appearance-none opacity-0" checked />
</div>
);
};
36 changes: 36 additions & 0 deletions src/components/radio-button/__test__/RadioButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { describe, expect, it, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import { RadioButton } from '../RadioButton';
import renderer from 'react-test-renderer';

describe('Radio Button component', () => {
it('Radio button onClick should work correctly', () => {
let checked = false;
const buttonClick = vi.fn(() => (checked = true));
render(<RadioButton checked={checked} onClick={buttonClick} />);
const radioButton = screen.getByRole('button');
radioButton.click();
expect(buttonClick).toHaveBeenCalledOnce();
});

it('Radio Button component should render correctly', () => {
const radioButton = renderer.create(<RadioButton checked={false} onClick={() => undefined} />).toJSON();
expect(radioButton).toMatchSnapshot();
});

it('Checked Radio Button component should render correctly', () => {
const radioButton = renderer.create(<RadioButton checked onClick={() => undefined} />).toJSON();
expect(radioButton).toMatchSnapshot();
});

it('Disabled Radio Button component should render correctly', () => {
const radioButton = renderer.create(<RadioButton disabled checked={false} onClick={() => undefined} />).toJSON();
expect(radioButton).toMatchSnapshot();
});

it('Disabled and Checked Radio Button component should render correctly', () => {
const radioButton = renderer.create(<RadioButton disabled checked={false} onClick={() => undefined} />).toJSON();
expect(radioButton).toMatchSnapshot();
});
});
Loading

0 comments on commit 30beeca

Please sign in to comment.