Skip to content

Commit

Permalink
Feat toggle (#121)
Browse files Browse the repository at this point in the history
* chore: docs

* feat: toggle component

* feat: toggle component tests

* feat: toggle component docs
  • Loading branch information
YaGRRusso authored Feb 14, 2024
1 parent 2543f83 commit 8b4e5c1
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 59 deletions.
30 changes: 13 additions & 17 deletions .vscode/tsx.code-snippets
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,23 @@
"prefix": "reactcomp",
"body": [
"import { cn } from '@/src/utils/class-merge.helper'",
"import {",
" FC,",
" HTMLAttributes,",
" Ref,",
" forwardRef,",
"} from 'react'"
"",
"export interface ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}Props extends HTMLAttributes<HTMLDivElement> {}",
"import { FC, HTMLAttributes, Ref, forwardRef } from 'react'",
"",
"const ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}: FC<${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}Props> = forwardRef<HTMLDivElement, ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}Props>(",
" ({ children, className, ...rest }, ref: Ref<HTMLDivElement>) => {",
"export interface ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}Props extends HTMLAttributes<HTMLDivElement> {}",
"",
" return (",
" <div className={cn('', className)} ref={ref} {...rest}>",
" {children}",
" </div>",
" )",
" },",
")"
"const ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}: FC<${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}Props> = forwardRef<",
" HTMLDivElement,",
" ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}Props",
">(({ children, className, ...rest }, ref: Ref<HTMLDivElement>) => {",
" return (",
" <div className={cn('', className)} ref={ref} {...rest}>",
" {children}",
" </div>",
" )",
"})",
"",
"${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}.displayName = '${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}.${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}'",
"${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}.displayName = 'Toggle.Root'",
"",
"export default ${TM_DIRECTORY/(^.+\\/(.*)$)/${2:/pascalcase}/}${TM_FILENAME/(index)?[.].*/${2:/pascalcase}/}",
""
Expand Down
53 changes: 32 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,59 +10,70 @@
</a>
</p>

Uma biblioteca de componentes e design system coaktion. Com testes e documentação para todos os componentes.
Uma biblioteca de componentes e design system Droz. Com testes e documentação para todos os componentes.

## Como o projeto funciona?

O projeto é um monorepo, que foi criado utilizando o [Turborepo](https://turbo.build/repo), para saber mais acesse o [Monorepo Handbook](https://turbo.build/repo/docs/handbook). O projeto conta com dois workspaces `apps` e `packages`:
O projeto é um monorepo, que foi criado utilizando o [Turborepo](https://turbo.build/repo), para saber mais acesse o [Monorepo Handbook](https://turbo.build/repo/docs/handbook). O projeto conta com dois workspaces `docs` e `package`:

### Apps
### Docs

- `docs`: Um projeto para a documentação dos componentes criados na biblioteca Visu realizados no [Storybook](https://storybook.js.org/) que foi configurado nesse projeto.
Projeto onde são desenvolvidas as documentações dos components do Visu. Utilizando principalmente o [Storybook](https://storybook.js.org/). Os componentes documentados são baseados no último build feito na biblioteca, então é necessários que haja pelo menos um build antes de documentar os componentes.

### Packages
### Package

- `tsconfig`: `tsconfig.json` utilizado no monorepo.
Projeto onde são desenvolvidos os componentes e o design system da biblioteca Visu. O projeto utiliza principalmente [Vite](https://vitejs.dev), [React](https://react.dev/) e [Tailwindcss](https://tailwindcss.com/).
O build é realizado na pasta `src/library` para os componentes e copiando os arquivos da pasta `src/theme` para o design system que consiste em um plugin do tailwindcss.
O projeto testa os componentes utilizando [Jest](https://jestjs.io) e [React Testing Library](https://testing-library.com/docs/react-testing-library/intro).

- `visu`: Projeto onde são desenvolvidos os componentes e o design system da bilbioteca Visu. O projeto utiliza [Vite](https://vitejs.dev), [React](https://react.dev/) e [Tailwindcss](https://tailwindcss.com/). O build é realizado [Modo Lib](https://storybook.js.org) da pasta `src/library` para os componentes e copiando os arquivos da pasta `src/theme` para o design system que consiste em um plugin do tailwindcss. O projeto testa os componentes utilizando [Jest](https://jestjs.io) e [React Testing Library](https://testing-library.com/docs/react-testing-library/intro).
## Script

Abaixo a lista dos scrips principais para a utilização do projeto.

### Build

Para executar o build em todos os `apps` e `packages` utilize o comando abaixo na raiz do projeto:
Para executar o build em `docs` e `package` utilize o comando abaixo na raiz do projeto:

```
```javascript
npm run build
// npm run build:docs
// npm run build:packages
```

### Desenvolvimento

Para executar em paralelo e no modo de desenvolvimento todos os `apps` e `packages` utilize o comando abaixo na raiz do projeto:
Para executar em paralelo e no modo de desenvolvimento todos os `docs` e `package` utilize o comando abaixo na raiz do projeto:

```
```javascript
npm run dev
// npm dev build:docs
// npm dev build:packages
```

### Teste

Para executar os testes da biblioteca, acesse o diretório `package` e utilize o comando abaixo:

```
```javascript
npm run test
```

Para executar os testes em apenas um arquivo da biblioteca, acesse o diretório `package` e utilize o comando abaixo:

```
npm run test -- [pasta/arquivo]
// npm run test:watch
// npm run test:coverage
```

## Biblioteca

Na Biblioteca é publicado o conteúdo da pasta `dist` que é gerado a partir das pastas `src/library` e `src/theme`. Para realizar a publicação precisamos gerar um build da biblioteca que irá criar a pasta `dist` com essa pasta criada podemos então executar o comando `npm publish`. Já está tudo configurado no package.json para a publicação da biblioteca, caso tenha permissão para realizar a publicação. <b>Nesse primeiro momento a biblioteca está sendo publicada apenas no Github Packages.</b>
Na Biblioteca é publicado o conteúdo da pasta `dist` que é gerado a partir das pastas `src/library` e `src/theme`. Para realizar a publicação precisamos gerar um build da biblioteca que irá criar a pasta `dist` com essa pasta criada podemos então publicar o pacote.

### Publicação NPM

### Github Packages
Para realizar a publicação no Github Packages, após ter feito todas as atualizações necessárias em uma PR separada, siga os passos abaixo.

Para realizar a publicação no Github Packages, foi configurado o registry no `package.json` da bilbioteca apontando para `https://npm.pkg.github.com`. Nesse caso estamos modificando o registry padrão que tentaria publicar no NPM. É necessário estar com um token de acesso dando permissão para a publicação da bilbioteca em um arquivo `.npmrc` na raiz do usuário no Linux.
1. Abra uma nova branch chamada "release-x.x.x"
1. Na nova branch rode o script scripts/versioning [major | minor | patch]
1. Dê o nome pro commit de "release: x.x.x"
1. Faça merge dessa branch na main
1. Abra a branch main atualizada
1. Em um terminal autenticado com o NPM, execute `npm publish` dentro da pasta `packages/visu` (importante) e pronto

## Links úteis:

Expand Down
70 changes: 70 additions & 0 deletions docs/src/stories/Toggle/Item.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Toggle, ToggleItemProps } from '@droz-js/visu'
import { Meta, StoryObj } from '@storybook/react'
import { Alien } from 'phosphor-react'

const meta: Meta<ToggleItemProps> = {
title: 'Toggle/Item',
component: Toggle.Item,
argTypes: {
children: {
control: 'none',
table: {
type: {
summary: 'React.ReactNode',
},
},
type: { name: 'other', required: false, value: 'React.ReactNode' },
},
text: {
control: 'text',
description: 'Aplica o text em ToggleItem',
table: {
type: { summary: 'text' },
},
type: { name: 'string', required: false },
},
value: {
control: 'text',
description: 'Aplica o value em ToggleItem',
table: {
type: { summary: 'text' },
},
type: { name: 'string', required: true },
},
icon: {
control: 'text',
description: 'Aplica o icon em ToggleItem',
table: {
type: { summary: 'text' },
},
type: { name: 'string', required: false },
},
notification: {
control: 'boolean',
description: 'Aplica o notification em ToggleItem',
table: {
type: { summary: 'boolean' },
},
type: { name: 'boolean', required: false },
},
},
args: {
children: '',
text: 'Alien',
icon: <Alien />,
value: 'alien',
},
} as Meta<ToggleItemProps>

export default meta
type ToggleItemStory = StoryObj<ToggleItemProps>

export const Comum: ToggleItemStory = {
render: (args: ToggleItemProps) => {
return (
<Toggle.Root type="single" expanded>
<Toggle.Item {...args} />
</Toggle.Root>
)
},
}
61 changes: 61 additions & 0 deletions docs/src/stories/Toggle/Toggle.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Toggle, ToggleRootProps } from '@droz-js/visu'
import { Meta, StoryObj } from '@storybook/react'
import { Alien, FlyingSaucer, Planet } from 'phosphor-react'

const meta: Meta<ToggleRootProps> = {
title: 'Toggle/Toggle',
component: Toggle.Root,
argTypes: {
children: {
control: 'none',
table: {
type: {
summary: 'React.ReactNode',
},
},
type: { name: 'other', required: false, value: 'React.ReactNode' },
},
expanded: {
control: 'boolean',
description: 'Aplica o expanded em ToggleToggle',
table: {
type: {
summary: 'boolean',
},
},
type: { name: 'boolean', required: false },
defaultValue: true,
},
type: {
control: 'inline-radio',
description: 'Aplica o type em ToggleToggle',
options: ['multiple', 'single'] as ToggleRootProps['type'][],
table: {
type: {
summary: ['multiple', 'single'].join('|'),
},
},
type: { name: 'string', required: true },
},
},
args: {
children: '',
type: 'single',
expanded: true,
},
} as Meta<ToggleRootProps>

export default meta
type ToggleRootStory = StoryObj<ToggleRootProps>

export const Comum: ToggleRootStory = {
render: (args: ToggleRootProps) => {
return (
<Toggle.Root {...args}>
<Toggle.Item value="ufo" text="UFO" icon={<FlyingSaucer />} />
<Toggle.Item value="alien" text="Alien" icon={<Alien />} />
<Toggle.Item value="planet" text="Planet" icon={<Planet />} />
</Toggle.Root>
)
},
}
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"tailwindcss": "^3.4.1"
},
Expand Down Expand Up @@ -103,4 +104,4 @@
"access": "public",
"registry": "https://registry.npmjs.org/"
}
}
}
23 changes: 6 additions & 17 deletions package/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import LayoutDefault from './layout/Default'
import { Button } from './library'
import { Toggle } from './library'

import { zodResolver } from '@hookform/resolvers/zod'
import { Eraser, User } from 'phosphor-react'
Expand Down Expand Up @@ -36,22 +36,11 @@ function App() {
>
<form onSubmit={handleSubmit(onSubmit)}>
{/* ================================= TEST AREA ================================= */}
<Button>
<User />
User
</Button>
<Button loading>
<User />
User
</Button>
<Button ghost>
<User />
User
</Button>
<Button ghost loading>
<User />
User
</Button>
<Toggle.Root type="multiple" expanded={true}>
<Toggle.Item value="op1" text="op1" icon={<User />} />
<Toggle.Item value="op2" text="option2" icon={<User />} />
<Toggle.Item value="op3" text="op3" icon={<User />} />
</Toggle.Root>
{/* ================================= TEST AREA ================================= */}
</form>
</LayoutDefault>
Expand Down
55 changes: 55 additions & 0 deletions package/src/__tests__/Toggle/Root.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Toggle } from '@library'

import { fireEvent, render, screen } from '@testing-library/react'
import { clsx } from 'clsx'

jest.mock('clsx', () => {
return {
clsx: jest.fn().mockImplementation(() => clsx),
}
})

describe('ToggleRoot tests', () => {
it('Should render a ToggleRoot element', () => {
render(<Toggle.Root type="single" data-testid="element"></Toggle.Root>)
const element = screen.queryByTestId('element')

expect(element).toBeDefined()
})

it('Should Toggle single element', () => {
render(
<Toggle.Root type="single" data-testid="element">
<Toggle.Item value="op1">op1</Toggle.Item>
<Toggle.Item value="op2">op2</Toggle.Item>
</Toggle.Root>,
)
const element = screen.queryByTestId('element')

if (element?.children[0]) fireEvent.click(element.children[0])
expect(element?.children[0]).toHaveAttribute('data-state', 'on')
expect(element?.children[1]).toHaveAttribute('data-state', 'off')

if (element?.children[1]) fireEvent.click(element.children[1])
expect(element?.children[0]).toHaveAttribute('data-state', 'off')
expect(element?.children[1]).toHaveAttribute('data-state', 'on')
})

it('Should Toggle multiple element', () => {
render(
<Toggle.Root type="multiple" data-testid="element">
<Toggle.Item value="op1">op1</Toggle.Item>
<Toggle.Item value="op2">op2</Toggle.Item>
</Toggle.Root>,
)
const element = screen.queryByTestId('element')

if (element?.children[0]) fireEvent.click(element.children[0])
expect(element?.children[0]).toHaveAttribute('data-state', 'on')
expect(element?.children[1]).toHaveAttribute('data-state', 'off')

if (element?.children[1]) fireEvent.click(element.children[1])
expect(element?.children[0]).toHaveAttribute('data-state', 'on')
expect(element?.children[1]).toHaveAttribute('data-state', 'on')
})
})
Loading

0 comments on commit 8b4e5c1

Please sign in to comment.