Bienvenido a la primera parte de mi serie de cuatro partes sobre la creación de un componente de diálogo responsivo en React. En esta serie, exploraré diferentes enfoques para lograr transiciones de animación fluidas manteniendo las dimensiones fluidas del diálogo. En esta parte inicial, configuraré el componente de diálogo básico con funcionalidad de minimizar y expandir.
Tenga en cuenta que la accesibilidad y el diseño responsivo no se incluyen como parte de las consideraciones de esta serie. El objetivo principal es crear un componente de diálogo reutilizable con transiciones de animación fluidas.
Esta serie es parte de una prueba de concepto en la que he estado trabajando, cuyo objetivo es discutir y perfeccionar técnicas para animar componentes de la interfaz de usuario. Invito a otros desarrolladores a recibir comentarios y opiniones para validar mi enfoque o sugerir mejoras.
Comencemos creando un componente de diálogo altamente reutilizable que admita la minimización y la expansión. Usaré el patrón de composición para garantizar que el diálogo pueda adaptarse al contenido cambiante.
Estructura del archivo:
src/ components/ FluidDialog/ Dialog.js DialogContext.js DialogHeader.js DialogBody.js DialogFooter.js DialogContainer.js index.js App.js index.js
Primero, crearé un contexto para administrar el estado de nuestro componente de diálogo.
Puntos clave:
// src/components/FluidDialog/DialogContext.js import { createContext, useContext, useId, useState } from 'react'; const DialogContext = createContext(); export function DialogProvider({ rootRef, isExpandedByDefault, children, maxWidth, }) { const dialogId = useId(); const [isExpanded, setIsExpanded] = useState(isExpandedByDefault); return ({children} ); } export function useDialog() { return useContext(DialogContext); }
A continuación, crearé el componente de diálogo principal que utiliza el contexto para manejar la expansión y minimización.
Puntos clave:
// src/components/FluidDialog/Dialog.js import { useRef } from 'react'; import { styled } from 'styled-components'; import { DialogProvider } from './DialogContext'; export default function Dialog({ id, isExpandedByDefault = true, maxWidth = 400, children, }) { const rootRef = useRef(null); return (); } const DialogComponent = styled.section` max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : undefined)}; position: absolute; right: 16px; bottom: 16px; border: 1px solid #ccc; border-radius: 6px; box-shadow: 0 0 8px rgba(0, 0, 0, 0.35); overflow: hidden; `; {children}
Crearé componentes adicionales para el encabezado, el cuerpo, el pie de página y el contenedor del diálogo para garantizar la modularidad y la reutilización.
Puntos clave:
// src/components/FluidDialog/DialogHeader.js import { styled } from 'styled-components'; import { IconButton } from '../IconButton'; import { useDialog } from './DialogContext'; export default function DialogHeader({ children, expandedTitle }) { const { dialogId, isExpanded, setIsExpanded } = useDialog(); return (); } const DialogHeaderComponent = styled.div``; const ExpandedState = styled.header` transition: opacity 0.3s; opacity: ${({ isVisible }) => (isVisible ? 1 : 0)}; pointer-events: ${({ isVisible }) => (isVisible ? 'all' : 'none')}; position: absolute; top: 0; left: 0; width: 100%; background: #f3f3f3; display: flex; flex-direction: row; `; const MinimizedState = styled.header` transition: opacity 0.3s; opacity: ${({ isVisible }) => (isVisible ? 1 : 0)}; pointer-events: ${({ isVisible }) => (isVisible ? 'all' : 'none')}; background: #f3f3f3; display: flex; flex-direction: row; cursor: pointer; `; const Title = styled.span` flex-grow: 1; text-align: left; display: flex; align-items: center; padding: 0 16px; `; const IconButtons = styled.div``; {expandedTitle ?? children} setIsExpanded(false)} /> setIsExpanded(true)} > {children}
// src/components/FluidDialog/DialogContainer.js import { styled } from 'styled-components'; import { useDialog } from './DialogContext'; export default function DialogContainer({ children }) { const { isExpanded } = useDialog(); return ({children} ); } const DialogContainerComponent = styled.div` display: ${({ isVisible }) => (isVisible ? undefined : 'none')}; `;
// src/components/FluidDialog/DialogBody.js import { styled } from 'styled-components'; import DialogContainer from './DialogContainer'; import { useDialog } from './DialogContext'; export default function DialogBody({ children }) { const { dialogId } = useDialog(); return (); } const DialogBodyComponent = styled.div``; const DialogBodyContent = styled.div` padding: 8px 16px; `; {children}
// src/components/FluidDialog/DialogFooter.js import { styled } from 'styled-components'; import DialogContainer from './DialogContainer'; export default function DialogFooter({ children }) { return (); } const DialogFooterComponent = styled.div` background: #f3f3f3; `; const DialogFooterContent = styled.div` padding: 8px 16px; `; {children}
Finalmente, importaré y usaré el componente de diálogo en la aplicación principal.
Puntos clave:
// src/App.js import React from 'react'; import Dialog from './components/FluidDialog/Dialog'; import DialogHeader from './components/FluidDialog/DialogHeader'; import DialogBody from './components/FluidDialog/DialogBody'; import DialogFooter from './components/FluidDialog/DialogFooter'; function App() { return (); } export default App;
// src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; ReactDOM.render(, document.getElementById('root') );
Puedes acceder al código fuente completo en CodeSandbox.
También puedes ver una vista previa en vivo de la implementación:
En esta primera parte, configuré un cuadro de diálogo básico en React con funcionalidad de minimizar y expandir. Este componente fundamental servirá como base para futuras mejoras en los próximos artículos. El componente de diálogo está diseñado para abrazar su contenido y adaptarse a los cambios, lo que lo hace altamente reutilizable y flexible.
Estén atentos a la Parte 2, donde profundizaré en cómo agregar animaciones a las transiciones de diálogo y exploraré diferentes opciones para lograr efectos suaves.
Invito a otros desarrolladores a recibir comentarios y opiniones para ayudar a refinar y mejorar este enfoque. Sus conocimientos son invaluables para hacer que esta prueba de concepto sea más sólida y efectiva.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3