Bem-vindo à primeira parte da minha série de quatro partes sobre como criar um componente de diálogo responsivo no React. Nesta série, explorarei diferentes abordagens para obter transições de animação suaves, mantendo as dimensões fluidas do diálogo. Nesta parte inicial, configurarei o componente básico de diálogo com funcionalidade de minimizar e expandir.
Observe que a acessibilidade e o design responsivo não estão incluídos nas considerações desta série. O foco principal é a criação de um componente de diálogo reutilizável com transições de animação suaves.
Esta série faz parte de uma prova de conceito na qual venho trabalhando, com o objetivo de discutir e refinar técnicas de animação de componentes de UI. Convido comentários e insights de colegas desenvolvedores para validar minha abordagem ou sugerir melhorias.
Vamos começar criando um componente de diálogo altamente reutilizável que suporta minimização e expansão. Usarei o padrão de composição para garantir que o diálogo possa se adaptar às mudanças de conteúdo.
Estrutura do arquivo:
src/ components/ FluidDialog/ Dialog.js DialogContext.js DialogHeader.js DialogBody.js DialogFooter.js DialogContainer.js index.js App.js index.js
Primeiro, criarei um contexto para gerenciar o estado do nosso componente de diálogo.
Pontos chave:
// 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 seguir, criarei o componente de diálogo principal que usa o contexto para lidar com expansão e minimização.
Pontos chave:
// 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}
Criarei componentes adicionais para o cabeçalho, corpo, rodapé e contêiner da caixa de diálogo para garantir modularidade e reutilização.
Pontos chave:
// 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, importarei e usarei o componente de diálogo no aplicativo principal.
Pontos chave:
// 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') );
Você pode acessar todo o código-fonte no CodeSandbox.
Você também pode ver uma prévia ao vivo da implementação:
Nesta primeira parte, configurei uma caixa de diálogo básica no React com funcionalidade de minimizar e expandir. Este componente fundamental servirá de base para melhorias adicionais nos próximos artigos. O componente de diálogo foi projetado para abranger seu conteúdo e se adaptar às mudanças, tornando-o altamente reutilizável e flexível.
Fique ligado na Parte 2, onde me aprofundarei na adição de animações às transições de diálogo, explorando diferentes opções para obter efeitos suaves.
Convido feedback e comentários de colegas desenvolvedores para ajudar a refinar e melhorar essa abordagem. Seus insights são inestimáveis para tornar esta prova de conceito mais robusta e eficaz.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3