Saltar al contenido principal

Desarrollo responsive y adaptativo.

¿Busca pautas de diseño? Consulte Diseño responsive y adaptativo.

Términos​

Los componentes de Jutro pueden ser:

  • Responsive: El componente se ajusta al tamaño de la pantalla automáticamente mediante consultas de medios.
  • Adaptativo: El componente no se ajusta al tamaño de la pantalla, y en cambio, debe configurarlo utilizando las propiedades de punto de interrupción. El componente se renderiza de forma diferente según el dispositivo.
  • Fijo: El componente no se ajusta al tamaño de la pantalla.

En Storybook, cada componente está rotulado como responsive, adaptativo o fijo en la barra superior.

Si bien la mayoría de los componentes son responsive en todo tipo de dispositivos, es posible que algunos no sean tan convenientes de usar de la misma manera en dispositivos pequeños que en dispositivos grandes. Le recomendamos configurar estos componentes utilizando propiedades de punto de interrupción.

Cómo trabajar con los diseñadores​

Los diseñadores pueden proporcionarle diseños de aplicaciones para diferentes puntos de interrupción. Pregúnteles sobre los comportamientos previstos y similares, para asegurarse de comprender cómo el usuario puede aprovechar al máximo la aplicación.

Los siguientes consejos generales sirven para trabajar con diseñadores:

  • Intente lograr diseños de la misma pantalla en diferentes pantallas.
  • Los diseñadores podrían utilizar el término "factor de forma" para referirse a un punto de interrupción específico: phone, phoneWide, tablet, o desktop. Consulte Propiedades de punto de interrupción para conocer los anchos exactos.
  • Utilice las herramientas de “inspección” de la aplicación de diseño para conocer el espaciado y los tamaños necesarios. Asegúrese de utilizar las variables de espaciado y tamaño de Jutro (consulte Tematización).
  • Muestre su aplicación a un diseñador lo más pronto posible para recibir comentarios e implementar más funciones de forma iterativa.
  • Pida explicaciones sobre los elementos que no comprenda o no esté seguro de cómo deberían funcionar.
  • Utilice las herramientas para desarrolladores en su navegador a fin de probar la composición y disposición en diferentes puntos de interrupción.
  • Si se requiere que la aplicación funcione en teléfonos, desarrolle primero para teléfonos y luego pase a tamaños más grandes.

Viabilidad​

Revise los diseños con el diseñador y trabaje en la viabilidad. Este proceso también se conoce como “QA de IU” (control de calidad de interfaz de usuario):

  • ¿Están disponibles todos los componentes? Por ejemplo, se le pide que proporcione un carrusel de imágenes, pero ese no es un componente estándar de Jutro. Eso significa que tendrá que crear uno propio.
  • ¿Todos los componentes funcionan según lo previsto? Es posible que tenga que crear una aplicación de prueba de concepto en este punto.
  • Si se producen funciones o interacciones complejas, compruebe si están permitidas en Jutro y si es rentable implementarlas. Por ejemplo, ¿es el carrusel la mejor manera de responder al caso de uso? Necesita una opción para detener el cambio de imagen para evitar el mareo por movimiento. ¿Es factible crear esta funcionalidad dentro del alcance de su proyecto?

Propiedades de punto de interrupción​

Las propiedades del punto de interrupción son:

Nombre de la propiedadAncho
phone< 580px
phoneWide (phone in horizontal mode)580px to 768px
tablet768px to 1024px
desktop> 1024px

Use these props to override the behavior of your component on different devices.

Override children​

For example, you want your action title bar to not include an action when the user is on a mobile device. In that case, you can use the phone prop to override the children of the component.

<ActionTitleBar
phone={{
children: (
<TitleElement>
{/* On a phone, render only a heading */}
<h4>Just a title</h4>
</TitleElement>
),
}}>
{/* On large screens, render an icon with a tooltip and a button */}
<TitleElement>
<h4>Title</h4>
<TooltipIcon {...tooltipIconProps} />
<Button {...buttonProps}>Edit</Button>
</TitleElement>
</ActionTitleBar>

Puede hacer que la mayoría de los componentes se representen de manera diferente en diferentes dispositivos utilizando propiedades de punto de interrupción.

Invalidación de propiedades​

Estas propiedades invalidan las propiedades de los componentes cuando se renderizan en un dispositivo en particular. Por ejemplo:

<RadioButtonField
availableValues={[
{
displayName: 'Perform payment on checkout',
},
{
displayName: 'Defer payment to a later date',
},
]}
phone={{
availableValues: [
{
displayName: 'Pay now',
},
{
displayName: 'Pay later',
},
],
}}
/>

Este es un ejemplo muy simple de cómo mostrar diferentes rótulos para casillas de verificación en pantallas pequeñas. Normalmente, usaría mensajes intl para renderizar el texto de un componente, pero este ejemplo ilustra cómo pasaría una copia de la propiedad availableValues e invalidaría los elementos que contiene.

Invalidación de estilos​

Otro ejemplo es la anulación de estilos para diferentes dispositivos:

<Card
className={styles.largeBanner}
phone={{
className: styles.smallBanner,
}}
tablet={{
className: styles.mediumBanner,
}}
/>

En este ejemplo, tenemos una tarjeta que tiene un estilo diferente según el tamaño del dispositivo.

El gancho useBreakpoint​

Note: Para los nuevos componentes introducidos en Jutro 10, así como una recomendación general para ese propósito, recomendamos utilizar el gancho useBreakpoint. Las propiedades de punto de interrupción como phone, tablet y phoneWide no están disponibles en los nuevos componentes listos para usar.

El gancho useBreakpoint se exporta desde @jutro/layout y se puede importar como import { useBreakpoint } from '@jutro/layout'. Devuelve un objeto con las siguientes propiedades:

  • breakpointProps: propiedades que pasó al componente se combinaron con los valores que invalidó en una de las siguientes propiedades:phone, phoneWide, tablet
  • applyBreakpoint: función que toma props como argumento y devuelve breakpointProps. Puede usarlo en cualquier código anidado dentro de su componente donde no se permitan ganchos.
  • breakpoint: nombre del punto de interrupción actual. Cualquiera de phone, phoneWide, tablet, o desktop.

Hay cuatro formas de usar el gancho para obtener el resultado esperado.

1. Obtener propiedades del gancho para un determinado punto de interrupción​

La primera forma de usar el gancho es pasar las propiedades y aplicar la salida al componente.

En el siguiente ejemplo, el objeto de propiedades phone se pasa a useBreakpoint. Las propiedades se devuelven como textInputPhoneProps en el punto de interrupción phone. A continuación, se asignan a TextInput y se invalidan las propiedades agregadas anteriormente. La propiedad label se invalida, luego placeholder y className se agregan cuando el gancho detecta que el punto de interrupción cambia a phone.

const { breakpointProps: textInputPhoneProps } = useBreakpoint({
phone: {
placeholder: 'Phone placeholder',
label: 'Phone label',
className: 'somePhoneClass',
},
});
return (
<TextInput
label="Text input"
{...textInputPhoneProps}
/>
);

2. Obtener solo el estado del punto de interrupción del gancho​

La segunda forma de usar el gancho es solo obtener el estado del punto de interrupción y usarlo para cambiar esa propiedad en función del punto de interrupción devuelto. En el siguiente ejemplo, breakpoint se obtiene del gancho y cambia en función de la ventana gráfica. Se puede asignar un valor diferente para la propiedad label si el punto de interrupción se establece en phone.

const { breakpoint } = useBreakpoint({});

return (
<TextInput label={breakpoint === 'phone' ? 'Phone label' : 'Text input'} />
);

3. Obtener la devolución de llamada que devuelve las propiedades de punto de interrupción​

La tercera forma de usar el gancho es usar applyBreakpoint. Es muy similar a la primera opción, pero puede ser mejor si hay diferentes componentes en la misma página que requerirían muchas instancias de useBreakPoints. En el siguiente ejemplo, la devolución de llamada que devuelve las propiedades se obtiene y luego applyBreakpoint se asigna a cada TextInput, y se pasan diferentes propiedades a cada componente.

const { applyBreakpoint } = useBreakpoint({});

return (
<React.Fragment>
<TextInput
label="Text input"
{...applyBreakpoint({
phone: {
placeholder: 'Phone placeholder',
label: 'Phone label',
className: 'somePhoneClass',
},
})}
/>
<TextInput
label="Text input instance 2"
{...applyBreakpoint({
phone: {
placeholder: 'Another Phone placeholder',
label: 'Another Phone label',
className: 'someOtherPhoneClass',
},
})}
/>
</React.Fragment>
);

4. Todo a la vez​

Es posible obtener las tres cosas que se devuelven de useBreakpoint y usarlas todas a la vez. Por ejemplo:

const {
breakpointProps: textInputPhoneProps,
breakpoint,
applyBreakpoint,
} = useBreakpoint({
phone: {
placeholder: 'Phone placeholder',
label: 'Phone label',
className: 'somePhoneClass',
},
});

return (
<React.Fragment>
<TextInput
label="Text input"
{...textInputPhoneProps}
/>
<TextInput
label={breakpoint === 'phone' ? 'Phone label 2' : 'Text input'}
/>
<TextInput
label="Text input"
{...applyBreakpoint({
phone: {
placeholder: 'Phone placeholder 3',
label: 'Phone label 3',
className: 'someOtherPhoneClass',
},
})}
/>
</React.Fragment>
);

Diferentes propiedades para un punto de interrupción​

Un caso de uso típico para el gancho es cuando desea pasar propiedades personalizadas a un componente en función del punto de interrupción. Cuando utilice el componente, haga lo siguiente:

<BigBanner
phone={{
message: 'Call us!',
}}
message="Get in touch"
/>

Eso significa que desea que sus usuarios vean el mensaje “Ponerse en contacto” en la mayoría de los casos. Pero, cuando están desde el teléfono, quiere que vean un mensaje que diga “¡Llámenos!”.

Dentro del componente funcional, se utiliza el gancho useBreakpoint y se pasan las propiedades como único argumento. Luego, se extrae el valor de la propiedad message.

En el escritorio, devuelve "Ponerse en contacto", y en el teléfono, devuelve "¡Llámenos!"

import { useBreakpoint } from '@jutro/layout';

function BigBanner(props) {
const { breakpointProps } = useBreakpoint(props);

return <div>{breakpointProps.message}</div>;
}

Diferentes estilos para un punto de interrupción​

Otro caso de uso para el gancho es aplicar un estilo diferente a un componente en función del punto de interrupción actual.

Creas dos clases en el módulo de estilos:

BigBanner.module.scss
.defaultColor {
color: magenta;
}

.phoneColor {
color: blue;
}

Para usar los estilos, debe obtener el punto de interrupción actual usando el gancho. Luego, selecciona una clase según el valor del gancho.

BigBanner.js
import React from 'react';
import { useBreakpoint } from '@jutro/layout';
import styles from './BigBanner.module.scss';

function BigBanner(props) {
const { breakpoint } = useBreakpoint(props);

const myClass =
breakpoint === 'phone' ? styles.phoneColor : styles.defaultColor;

return <div className={myClass}>Welcome to my banner!</div>;
}

O:

BigBanner.js
import React from 'react';
import cx from 'classnames';
import styles from './BigBanner.module.scss';
import { useBreakpoint } from '@jutro/layout';

function BigBanner(props) {
const { breakpointProps } = useBreakpoint({
...props,
className: cx(props.className, styles.defaultColor),
phone: {
className: cx(props.className, styles.phoneColor),
},
});
const { className } = breakpointProps;

return <div className={className}>{breakpointProps.message}</div>;
}

El contexto de BreakpointTracker​

También puede utilizar BreakpointTrackerContext y BreakpointTracker directamente. Puede usarlos dentro de los componentes de clase o en otros lugares donde es imposible usar ganchos.

Toda la aplicación está encapsulada en este proveedor de contexto, por eso, puede usarla dentro de un componente de clase, por ejemplo, dentro del bloque render. También puede usarla dentro de las funciones que no están anidadas dentro de los componentes funcionales.

BreakpointTracker.applyBreakpointOverrides devuelve sólo un objeto breakpointProps.

Se necesitan dos argumentos: props y un breakpoint.

Contexto de punto de interrupción en un componente funcional​

import React, { useContext } from 'react';
import { BreakpointTracker, BreakpointTrackerContext } from '@jutro/layout';

function BigBanner(props) {
const breakpoint = useContext(BreakpointTrackerContext);
const someRenderFunction = () => {
const breakpointProps = BreakpointTracker.applyBreakpointOverrides(
props,
breakpoint
);
return (
<pre>
<code>{JSON.stringify(breakpointProps, null, 2)}</code>
</pre>
);
};
return <div>{someRenderFunction()}</div>;
}

Contexto de punto de interrupción en un componente de clase​

import React from 'react';
import { BreakpointTracker, BreakpointTrackerContext } from '@jutro/layout';

class ClassBanner extends React.Component {
static contextType = BreakpointTrackerContext;
render() {
const breakpointProps = BreakpointTracker.applyBreakpointOverrides(
this.props,
this.context
);
return (
<pre>
<code>{JSON.stringify(breakpointProps, null, 2)}</code>
</pre>
);
}
}

export default ClassBanner;

Puntos de interrupción en pruebas unitarias​

Para probar los puntos de interrupción, puede usar el siguiente ejemplo como guía. Prueba el componente BigBanner que creamos en otras secciones de esta página.

import React from 'react';
import { render } from '@testing-library/react';
import { BreakpointTrackerContext } from '@jutro/layout';

import { BigBanner } from '../BigBanner';

import styles from '../BigBanner.module.scss';

function renderBigBannerWithBreakpoints(props = {}, breakpoint = 'desktop') {
return render(
<BreakpointTrackerContext.Provider value={breakpoint}>
<BigBanner {...props} />
</BreakpointTrackerContext.Provider>
);
}

describe('BigBanner', () => {
it('renders with default class on desktop', () => {
const { container } = renderBigBannerWithBreakpoints();

expect(container.firstChild).toHaveClass(styles.defaultColor);
});

it('renders with mobile class on phone', () => {
const { container } = renderBigBannerWithBreakpoints({}, 'phone');

expect(container.firstChild).toHaveClass(styles.phoneColor);
});
});