Skip to content

Commit

Permalink
feat: improve boilerplate, tests and storybook
Browse files Browse the repository at this point in the history
  • Loading branch information
sgomez committed Mar 17, 2024
1 parent 5d78e08 commit 5b8a14a
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 95 deletions.
Binary file modified docs/images/storybook-configured.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 63 additions & 12 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,11 @@ npm run lint -- --fix
{
"editor.codeActionsOnSave": {
"source.fixAll": "always",
"source.organizeImports": "always"
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
"editor.formatOnSave": true,
"css.lint.unknownAtRules": "ignore"
}
```

Expand All @@ -151,7 +152,9 @@ npm run lint -- --fix
"recommendations": [
"esbenp.prettier-vscode",
"vitest.explorer",
"bradlc.vscode-tailwindcss"
"bradlc.vscode-tailwindcss",
"dbaeumer.vscode-eslint",
"usernamehw.errorlens"
]
}
```
Expand Down Expand Up @@ -268,26 +271,49 @@ npm install --save-dev vitest @testing-library/react @vitejs/plugin-react jsdom

Y creamos el archivo de configuración:

```js title="vitest.config.mjs"
```ts title="vitest.config.mts"
/* eslint-disable unicorn/prefer-module */
import path from 'node:path'

import react from '@vitejs/plugin-react'
import { defineConfig } from 'vitest/config'

export default defineConfig({
// Add react plugin
plugins: [react()],

// Configure nextjs default paths
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},

// Specify the test environment
test: {
// Use jsdom environment
environment: 'jsdom',
// Setup files to be run before each test
// setupFiles: ['./vitest.setup.js'],


// Import assertion library or any global setup
globals: true,

// Add react plugin
plugins: [react()],
// Setup files to be run before each test
setupFiles: ['./vitest.setup.mts'],
},
})
```

A continuación creamos el siguiente fichero:

// Enable if you're using React 18's server components or need top-level await support
// ssr: true,
}
```ts title="vitest.setup.mts"
import * as matchers from '@testing-library/jest-dom/matchers'
import { cleanup } from '@testing-library/react'
import { afterEach, expect } from 'vitest'

expect.extend(matchers)

afterEach(() => {
cleanup()
})
```

Expand All @@ -297,6 +323,31 @@ Y con el siguiente comando podremos añadir un comando test a npm:
npm pkg set scripts.test="vitest"
```

### Crear un test de ejemplo

Para comprobar que vitest funciona correctamente vamos a crear un pequeño test. Si usas la plantilla en un futuro
este ya no te servirá, así que recuerda actualizarlo.

```ts title="src/app/page.spec.tsx"
import { render, screen } from '@testing-library/react'
import { expect, test } from 'vitest'

import Page from './page'

test('App Router: Works with Server Components', () => {
render(<Page />)
expect(screen.getByRole('main')).toBeDefined()
})
```

Y a continuación ejecutamos las pruebas para comprobar que se ejecuta sin problemas:

```bash
npm run test
```

Por defecto vitest se ejecuta en modo `watch`. Eso significa que al terminar de pasar los test no termina, sino que se queda observando si los ficheros cambian para volver a ejecutarlos. Resulta muy útil si haces TDD. Para terminar simplemente pulsa ++control+c++ en la consola.

!!! question "Ejercicio"
Se deja como ejercicio, guardar los cambios en git con la configuración de
Vitest y siguiendo conventional commits para el mensaje.
Expand Down
4 changes: 2 additions & 2 deletions docs/new-project.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
En este capítulo, aprenderemos a crear un nuevo proyecto de React utilizando Next.js y el framework de diseño NextUI. React es una biblioteca de JavaScript ampliamente utilizada para construir interfaces de usuario interactivas, mientras que Next.js es un framework de React que facilita la creación de aplicaciones web avanzadas con rutas y renderización del lado del servidor. NextUI es un marco de diseño que proporciona componentes de interfaz de usuario preestilizados y personalizables, lo que acelera el proceso de diseño y desarrollo.
En este capítulo, aprenderemos a crear un nuevo proyecto de React utilizando Next.js y el framework de diseño NextUI. React es una biblioteca de JavaScript ampliamente utilizada para construir interfaces de usuario interactivas, mientras que Next.js es un framework de React que facilita la creación de aplicaciones web avanzadas con rutas y renderización del lado del servidor. NextUI es una biblioteca de componentes que proporciona componentes de interfaz de usuario preestilizados y personalizables, lo que acelera el proceso de diseño y desarrollo.

## Instalación

Crear un boilerplate desde cero para hacer funcionar múltiples herramientas de Node.js, como React, NextUI, Vitest y Storybook, puede ser una tarea desafiante y propensa a errores, especialmente para los novatos. Los problemas de configuración, las dependencias en conflicto y las incompatibilidades pueden ser una fuente de frustración significativa. Esto puede desanimar a los principiantes y hacer que el proceso de inicio sea más largo y complicado de lo deseado, en lugar de permitirles centrarse directamente en el desarrollo de sus aplicaciones.

## Dependencias

### Frameworks: NextJS
### Frameworks: Next.js

Aunque es posible agregar React a un proyecto existente o crear una aplicación desde cero, la documentación oficial de React aconseja considerar el uso de un framework como Next.js para proyectos web más grandes. Esto se debe a que los frameworks proporcionan una estructura y herramientas adicionales que facilitan el desarrollo, el enrutamiento y la optimización del rendimiento de la aplicación.

Expand Down
90 changes: 52 additions & 38 deletions docs/nextui.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ claro.
npm install @nextui-org/react framer-motion @heroicons/react next-themes
```

Ahora necesitamos configurar el fichero de estilos de `tailwindcss` para que
soporte los componentes de NextUI.
Ahora necesitamos configurar el fichero de estilos de `tailwindcss` para que soporte los componentes de NextUI. De paso vamos a eliminar la clave theme porque es una personalización de la plantilla de Next.js que no vamos a necesitar.

```typescript title="tailwind.config.ts" hl_lines="1 9 11 12"
import { nextui } from '@nextui-org/react'
Expand All @@ -25,32 +24,33 @@ const config: Config = {
],
darkMode: 'class',
plugins: [nextui()],
theme: {
extend: {
backgroundImage: {
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
},
},
},
}
export default config
```

Y eliminamos los estilos que nos trae por defecto la plantilla de Next. Edita este archivo y deja solo
estas lineas:

```css title="src/app/globals.css"
@tailwind base;
@tailwind components;
@tailwind utilities;
```


### Dark theme

Para poder aplicar el tema oscuro o claro en nuestra aplicación, necesitamos configurar una librería llamada `next-theme`. En este caso NextUI también lo explica en la [web oficial](https://storiesv2.nextui.org/docs/customization/dark-mode).

Si hemos seguido las instrucciones correctamente, tendremos un fichero providers con el siguiente código:
Necesitamos, en cualquier caso crear un nuevo fichero con los providers de NextUI con el siguiente contenido:

```typescript title="src/app/providers.tsx"
"use client";
'use client'

import {NextUIProvider} from '@nextui-org/react'
import {ThemeProvider as NextThemesProvider} from "next-themes";
import { NextUIProvider } from '@nextui-org/react'
import { ThemeProvider as NextThemesProvider } from 'next-themes'

export function Providers({children}: { children: React.ReactNode }) {
export function Providers({ children }: { children: React.ReactNode }) {
return (
<NextUIProvider>
<NextThemesProvider attribute="class" defaultTheme="dark">
Expand All @@ -62,7 +62,7 @@ export function Providers({children}: { children: React.ReactNode }) {
```

!!! info
La notación ```"use client";``` es exclusiva de algunos frameworks con soporte de `React Server Components`. Se verá su uso durante el curso.
La notación ```'use client'``` es exclusiva de algunos frameworks con soporte de `React Server Components`. Se verá su uso durante el curso.

Y este archivo de providers se debe cargar en el layout principal:

Expand Down Expand Up @@ -103,33 +103,36 @@ Para poder ver en funcionamiento el selector de tema claro/oscuro, vamos a crear
Para eso crearemos el siguiente componente:

```typescript title="src/components/theme-switcher/theme-switcher.tsx"
"use client";
'use client'

import { MoonIcon, SunIcon } from "@heroicons/react/24/solid";
import { Switch } from "@nextui-org/react";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
import { MoonIcon, SunIcon } from '@heroicons/react/24/solid'
import { Switch } from '@nextui-org/react'
import { useTheme } from 'next-themes'
import { useEffect, useState } from 'react'

/**
* Theme dark/light switcher
*/
export function ThemeSwitcher() {
const [mounted, setMounted] = useState(false); // (1)!
const { theme, setTheme } = useTheme(); // (2)!
const [mounted, setMounted] = useState(false)
const { setTheme, theme } = useTheme()

useEffect(() => {
setMounted(true);
}, [setMounted]); // (3)!
setMounted(true)
}, [setMounted])

if (!mounted) return null;
if (!mounted) return null

return (
<Switch
defaultSelected={theme === "light"}
defaultSelected={theme === 'light'}
size="md"
color="secondary"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
startContent={<SunIcon />}
endContent={<MoonIcon />}
/>
);
)
}
```

Expand All @@ -150,8 +153,9 @@ export * from './theme-switcher'

Vamos a probar a añadir nuestro componente a la pagina principal:

```typescript title="src/app/page.tsx" hl_lines="2 13"
``` { .typescript .no-copy title="src/app/page.tsx" hl_lines="3 14" linenums="1" }
import Image from 'next/image'
import { ThemeSwitcher } from '@/components/theme-switcher'
export default function Home() {
Expand All @@ -162,7 +166,7 @@ export default function Home() {
Get started by editing&nbsp;
<code className="...">src/app/page.tsx</code>
</p>
<div className="...">
<div className="fixed bottom-0 left-0 flex h-48 ...">
<ThemeSwitcher /> // (1)!
<a className="...">
By{' '}
Expand All @@ -175,13 +179,23 @@ export default function Home() {

1. Añadimos el componente antes del logo de Vercel. El IDE importará automáticamente el componente.

Y para que funcione vamos a hacer un par de cambios. Eliminamos los estilos que nos trae por defecto la plantilla de Next:
!!! warning

En este caso no puedes copiar y pegar el código. Aprende a importar y usar
componentes.

Hay dos maneras de escribir una marca HTML. Si la marca tiene contenido:

```html
<div>Content</div>
```

Y si no lo tiene, como es el caso de nuestro componente:

```html
<ThemeSwitcher />
```

```css title="src/app/globals.css"
@tailwind base;
@tailwind components;
@tailwind utilities;
```

Ahora, ya tendremos la página principal con nuestro componente para cambiar al tema claro:

Expand Down
Loading

0 comments on commit 5b8a14a

Please sign in to comment.