웹 프론트엔드 CSS 튜토리얼 React에서 부드러운 전환 대화 상자 구성 요소 만들기(부분)

React에서 부드러운 전환 대화 상자 구성 요소 만들기(부분)

Jul 18, 2024 am 01:23 AM

Creating a Smooth Transitioning Dialog Component in React (Part )

1부: 최소화/확장 기능을 사용하여 기본 대화 상자 구성 요소 설정

React에서 반응형 대화 상자 구성 요소를 만드는 방법에 관한 4부작 시리즈 중 첫 번째 부분에 오신 것을 환영합니다. 이 시리즈에서는 대화 상자의 유동적 크기를 유지하면서 부드러운 애니메이션 전환을 달성하기 위한 다양한 접근 방식을 살펴보겠습니다. 이번 초기 부분에서는 최소화 및 확장 기능을 갖춘 기본 대화 상자 구성 요소를 설정하겠습니다.

접근성 및 반응형 디자인은 이 시리즈의 고려 사항에 포함되지 않습니다. 주요 초점은 부드러운 애니메이션 전환으로 재사용 가능한 대화 상자 구성 요소를 만드는 것입니다.

이 시리즈는 UI 구성 요소 애니메이션 기술을 논의하고 개선하는 것을 목표로 제가 작업해 온 개념 증명의 일부입니다. 내 접근 방식을 검증하거나 개선 사항을 제안하기 위해 동료 개발자의 피드백과 통찰력을 요청합니다.

기본 대화 상자 구성 요소 설정

최소화 및 확장을 지원하는 재사용 가능성이 높은 대화 상자 구성 요소를 만드는 것부터 시작해 보겠습니다. 대화가 변화하는 콘텐츠에 적응할 수 있도록 구성 패턴을 사용하겠습니다.

파일 구조:

src/
  components/
    FluidDialog/
      Dialog.js
      DialogContext.js
      DialogHeader.js
      DialogBody.js
      DialogFooter.js
      DialogContainer.js
      index.js
  App.js
  index.js
로그인 후 복사

1단계: 대화 컨텍스트

먼저 대화 상자 구성 요소의 상태를 관리하기 위한 컨텍스트를 생성하겠습니다.

핵심 사항:

  • DialogContext는 상태를 유지하고 최소화된 상태와 확장된 상태 사이에서 대화 상자를 전환하는 기능을 제공합니다.
  • DialogProvider 구성 요소는 상태를 초기화하고 이를 컨텍스트를 통해 대화 상자 구성 요소에 제공합니다.
// 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 (
    <DialogContext.Provider
      value={{ dialogId, rootRef, isExpanded, setIsExpanded, maxWidth }}
    >
      {children}
    </DialogContext.Provider>
  );
}

export function useDialog() {
  return useContext(DialogContext);
}
로그인 후 복사

2단계: 대화 상자 구성 요소

다음으로 컨텍스트를 사용하여 확장 및 최소화를 처리하는 기본 대화 상자 구성 요소를 생성하겠습니다.

핵심 사항:

  • Dialog 구성 요소는 관련 props로 컨텍스트 제공자를 초기화합니다.
  • DialogComponent 스타일 구성 요소는 대화 상자의 기본 스타일과 레이아웃을 처리합니다.
// 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 (
    <DialogProvider
      dialogId={id}
      rootRef={rootRef}
      isExpandedByDefault={isExpandedByDefault}
    >
      <DialogComponent
        role="dialog"
        aria-labelledby={`${id}_label`}
        aria-describedby={`${id}_desc`}
        ref={rootRef}
        maxWidth={maxWidth}
      >
        {children}
      </DialogComponent>
    </DialogProvider>
  );
}

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;
`;
로그인 후 복사

3단계: 추가 구성 요소

모듈화와 재사용성을 보장하기 위해 대화 상자 머리글, 본문, 바닥글, 컨테이너에 대한 추가 구성 요소를 만들겠습니다.

핵심 사항:

  • DialogHeader에는 컨텍스트를 사용하여 최소화된 상태와 확장된 상태 사이를 전환하는 버튼이 포함되어 있습니다.
  • DialogContainer는 isExpanded 값이 변경되면 본문과 바닥글 콘텐츠를 자동으로 숨기도록 래핑합니다.
  • DialogBody 및 DialogFooter 구성 요소는 대화 상자 콘텐츠에 대한 간단한 컨테이너입니다.
// 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 (
    <DialogHeaderComponent id={`${dialogId}_label`}>
      <ExpandedState isVisible={isExpanded}>
        <Title>{expandedTitle ?? children}</Title>
        <IconButtons>
          <IconButton
            icon="chevron-down"
            onClick={() => setIsExpanded(false)}
          />
        </IconButtons>
      </ExpandedState>
      <MinimizedState
        isVisible={!isExpanded}
        onClick={() => setIsExpanded(true)}
      >
        <Title>{children}</Title>
        <IconButtons>
          <IconButton icon="chevron-up" />
        </IconButtons>
      </MinimizedState>
    </DialogHeaderComponent>
  );
}

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``;
로그인 후 복사
// src/components/FluidDialog/DialogContainer.js
import { styled } from 'styled-components';
import { useDialog } from './DialogContext';

export default function DialogContainer({ children }) {
  const { isExpanded } = useDialog();

  return (
    <DialogContainerComponent isVisible={isExpanded}>
      {children}
    </DialogContainerComponent>
  );
}

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 (
    <DialogBodyComponent>
      <DialogContainer>
        <DialogBodyContent id={`${dialogId}_desc`}>
          {children}
        </DialogBodyContent>
      </DialogContainer>
    </DialogBodyComponent>
  );
}

const DialogBodyComponent = styled.div``;

const DialogBodyContent = styled.div`
  padding: 8px 16px;
`;
로그인 후 복사
// src/components/FluidDialog/DialogFooter.js
import { styled } from 'styled-components';
import DialogContainer from './DialogContainer';

export default function DialogFooter({ children }) {
  return (
    <DialogFooterComponent>
      <DialogContainer>
        <DialogFooterContent>{children}</DialogFooterContent>
      </DialogContainer>
    </DialogFooterComponent>
  );
}

const DialogFooterComponent = styled.div`
  background: #f3f3f3;
`;

const DialogFooterContent = styled.div`
  padding: 8px 16px;
`;
로그인 후 복사

4단계: 모든 것을 하나로 합치기

마지막으로 메인 앱에서 대화상자 구성요소를 가져와서 사용하겠습니다.

핵심 사항:

  • 앱 구성 요소에는 머리글, 본문, 바닥글 구성 요소가 있는 대화 상자가 포함되어 있습니다.
  • 이 설정을 통해 대화는 향후 부분의 추가 개선 및 애니메이션에 대비할 수 있습니다.
// 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 (
    <div className="App">
      <Dialog>
        <DialogHeader>My dialog/DialogHeader>
        <DialogBody>This is the content of the dialog.</DialogBody>
        <DialogFooter>This is the footer of the dialog.</DialogFooter>
      </Dialog>
    </div>
  );
}

export default App;
로그인 후 복사
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
로그인 후 복사

CodeSandbox에서 전체 소스코드에 접근하실 수 있습니다.

또한 구현의 실시간 미리보기를 볼 수도 있습니다.

결론

첫 번째 부분에서는 최소화 및 확장 기능을 갖춘 React의 기본 대화 상자를 설정했습니다. 이 기본 구성 요소는 앞으로 나올 기사에서 추가 개선을 위한 기반이 될 것입니다. 대화 상자 구성 요소는 콘텐츠를 수용하고 변경 사항에 적응하도록 설계되어 재사용성과 유연성이 뛰어납니다.

2부에서는 대화 전환에 애니메이션을 추가하는 방법을 알아보고 부드러운 효과를 얻을 수 있는 다양한 옵션을 살펴보겠습니다.

이 접근 방식을 개선하고 개선하는 데 도움이 되도록 동료 개발자의 피드백과 의견을 요청합니다. 이러한 개념 증명을 더욱 강력하고 효과적으로 만드는 데 귀하의 통찰력은 매우 중요합니다.

위 내용은 React에서 부드러운 전환 대화 상자 구성 요소 만들기(부분)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

뜨거운 기사 태그

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

WordPress 블록 및 요소에 상자 그림자를 추가합니다 WordPress 블록 및 요소에 상자 그림자를 추가합니다 Mar 09, 2025 pm 12:53 PM

WordPress 블록 및 요소에 상자 그림자를 추가합니다

Smart Forms 프레임 워크로 JavaScript 연락처 양식 작성 Smart Forms 프레임 워크로 JavaScript 연락처 양식 작성 Mar 07, 2025 am 11:33 AM

Smart Forms 프레임 워크로 JavaScript 연락처 양식 작성

내용 부호 ​​속성으로 인라인 텍스트 편집기를 만듭니다 내용 부호 ​​속성으로 인라인 텍스트 편집기를 만듭니다 Mar 02, 2025 am 09:03 AM

내용 부호 ​​속성으로 인라인 텍스트 편집기를 만듭니다

GraphQL 캐싱 작업 GraphQL 캐싱 작업 Mar 19, 2025 am 09:36 AM

GraphQL 캐싱 작업

스크린 독자를 탈취시킵니다. 액세스 가능한 양식 및 모범 사례 스크린 독자를 탈취시킵니다. 액세스 가능한 양식 및 모범 사례 Mar 08, 2025 am 09:45 AM

스크린 독자를 탈취시킵니다. 액세스 가능한 양식 및 모범 사례

첫 번째 맞춤형 전환을 만듭니다 첫 번째 맞춤형 전환을 만듭니다 Mar 15, 2025 am 11:08 AM

첫 번째 맞춤형 전환을 만듭니다

5 개의 최고의 PHP 양식 빌더 (및 3 개의 무료 스크립트) 비교 5 개의 최고의 PHP 양식 빌더 (및 3 개의 무료 스크립트) 비교 Mar 04, 2025 am 10:22 AM

5 개의 최고의 PHP 양식 빌더 (및 3 개의 무료 스크립트) 비교

node.js 및 Express의 Multer와 함께 파일 업로드 node.js 및 Express의 Multer와 함께 파일 업로드 Mar 02, 2025 am 09:15 AM

node.js 및 Express의 Multer와 함께 파일 업로드

See all articles