토스트 메시지 구성요소 빌드

액세스 가능한 적응형 토스트 구성요소를 빌드하는 방법에 관한 기본 개요입니다.

이 게시물에서는 토스트 구성요소를 빌드하는 방법에 관한 생각을 공유하고자 합니다. 이 demo

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 데모

동영상을 선호한다면 이 게시물의 YouTube 버전을 참고하세요.

개요

토스트 메시지는 사용자를 위한 비대화형, 수동, 비동기식 짧은 메시지입니다. 일반적으로 사용자에게 정보를 제공하는 인터페이스 피드백 패턴으로 사용됩니다. 정보를 볼 수 있습니다

상호작용 수

토스트 메시지는 알림과는 달리 알림프롬프트를 상호작용이 되지 않습니다. 닫히거나 지속되는 것이 아닙니다. 알림은 더 중요한 정보인 동기식 메시징을 위한 것으로 상호작용 또는 시스템 수준 메시지 (페이지 수준이 아님)가 필요한 경우 토스트 메시지는 다른 알림 전략보다 수동적입니다.

마크업

<output> 토스트 메시지는 화면에 안내하기 때문에 있습니다. 올바른 HTML은 JavaScript 및 JavaScript가 많이 사용될 것입니다.

건배

<output class="gui-toast">Item added to cart</output>

포용적 role="status" 추가 이를 통해 브라우저가 <output> 요소에 역할 설계할 수 있습니다

<output role="status" class="gui-toast">Item added to cart</output>

토스트 메시지 컨테이너

한 번에 두 개 이상의 토스트 메시지가 표시될 수 있습니다. 여러 애플리케이션을 컨테이너가 사용됩니다 또한 이 컨테이너는 화면에 토스트 메시지가 표시됩니다

<section class="gui-toast-group">
  <output role="status">Wizard Rose added to cart</output>
  <output role="status">Self Watering Pot added to cart</output>
</section>

레이아웃

토스트 메시지를 inset-block-end 토스트 메시지가 더 추가되면 해당 화면 가장자리에서 스택됩니다.

GUI 컨테이너

토스트 메시지 컨테이너는 토스트 메시지를 표시하기 위한 모든 레이아웃 작업을 실행합니다. 그것은 fixed를 표시 영역에 적용하고 논리 속성을 사용합니다. inset: 고정할 가장자리와 동일한 block-end 가장자리에서 약간의 padding를 더합니다.

.gui-toast-group {
  position: fixed;
  z-index: 1;
  inset-block-end: 0;
  inset-inline: 0;
  padding-block-end: 5vh;
}

DevTools 상자 크기와 패딩이 .gui-toast-container 요소에 오버레이된 스크린샷

토스트 메시지 컨테이너는 표시 영역 내에 위치하는 것 외에도 토스트 메시지를 정렬하고 배포할 수 있는 그리드 컨테이너입니다. 항목이 justify-items을(를) 기준으로 각각 중앙에 배치된 justify-content 그룹 토스트가 닿지 않도록 gap를 약간 던집니다.

.gui-toast-group {
  display: grid;
  justify-items: center;
  justify-content: center;
  gap: 1vh;
}

이번에는 토스트 메시지 그룹의 CSS 그리드 오버레이가 있는 스크린샷
토스트 메시지 하위 요소 사이의 공간과 간격 강조

GUI 토스트

개별 토스트에는 padding가 있고 모서리는 부드러운데 border-radius, 및 min() 함수를 사용하여 모바일 및 데스크톱 크기 조정을 지원합니다. 다음 CSS의 반응형 크기는 토스트가 표시 영역의 90% 보다 넓어지거나 25ch

.gui-toast {
  max-inline-size: min(25ch, 90vw);
  padding-block: .5ch;
  padding-inline: 1ch;
  border-radius: 3px;
  font-size: 1rem;
}

패딩과 테두리가 있는 단일 .gui-toast 요소의 스크린샷
반경이 표시되었습니다.

스타일

레이아웃과 배치가 설정된 상태에서 사용자에게 적응하는 데 도움이 되는 CSS 추가 설정 및 상호작용을 수행할 수 있습니다

토스트 메시지 컨테이너

토스트 메시지는 대화형이 아니며 탭하거나 스와이프해도 아무 효과가 없지만 현재 포인터 이벤트를 사용합니다. 토스트 메시지를 훔치지 못하도록 방지 다음 CSS를 사용하세요.

.gui-toast-group {
  pointer-events: none;
}

GUI 토스트

맞춤 속성, HSL 및 환경설정 미디어 쿼리입니다.

.gui-toast {
  --_bg-lightness: 90%;

  color: black;
  background: hsl(0 0% var(--_bg-lightness) / 90%);
}

@media (prefers-color-scheme: dark) {
  .gui-toast {
    color: white;
    --_bg-lightness: 20%;
  }
}

애니메이션

새 토스트 메시지는 화면에 들어올 때 애니메이션과 함께 표시되어야 합니다. 감소된 움직임을 수용하려면 다음과 같이 translate 값을 0로 설정합니다. 기본값(모션 환경설정 미디어에서 모션 값을 길이로 업데이트) 쿼리 를 참조하세요 . 모두에게 애니메이션이 제공되지만 일부 사용자에게만 토스트 메시지가 표시됩니다. 이동해야 합니다.

다음은 토스트 메시지 애니메이션에 사용된 키프레임입니다. CSS에서 시작, 대기, 토스트의 종료를 모두 하나의 애니메이션으로 보여줍니다.

@keyframes fade-in {
  from { opacity: 0 }
}

@keyframes fade-out {
  to { opacity: 0 }
}

@keyframes slide-in {
  from { transform: translateY(var(--_travel-distance, 10px)) }
}

그러면 토스트 메시지 요소가 변수를 설정하고 키프레임을 조정합니다.

.gui-toast {
  --_duration: 3s;
  --_travel-distance: 0;

  will-change: transform;
  animation: 
    fade-in .3s ease,
    slide-in .3s ease,
    fade-out .3s ease var(--_duration);
}

@media (prefers-reduced-motion: no-preference) {
  .gui-toast {
    --_travel-distance: 5vh;
  }
}

자바스크립트

스타일과 스크린 리더에 액세스할 수 있는 HTML이 준비되면 JavaScript가 필요합니다. 사용자별로 토스트 메시지 생성, 추가, 폐기 조정 이벤트를 수신합니다. 토스트 메시지 구성요소의 개발자 경험은 최소화되어야 하고 다음과 같이 쉽게 시작할 수 있습니다.

import Toast from './toast.js'

Toast('My first toast')

토스트 메시지 그룹 및 토스트 메시지 만들기

JavaScript에서 토스트 메시지 모듈이 로드될 때 토스트 컨테이너를 만들어야 함 페이지에 추가합니다. body 앞에 요소를 추가하기로 했습니다. 이렇게 하면 컨테이너가 컨테이너 위에 있기 때문에 z-index 스태킹 문제가 발생할 가능성이 낮습니다. 확인할 수 있습니다.

const init = () => {
  const node = document.createElement('section')
  node.classList.add('gui-toast-group')

  document.firstElementChild.insertBefore(node, document.body)
  return node
}

head 태그와 body 태그 사이에 있는 토스트 메시지 그룹의 스크린샷

init() 함수는 모듈 내부적으로 호출되어 요소를 보관합니다. Toaster 형식:

const Toaster = init()

토스트 메시지 HTML 요소는 createToast() 함수를 사용하여 생성됩니다. 이 함수에는 토스트에 대한 텍스트가 필요하고 <output> 요소를 만들고 장식합니다. 텍스트를 설정하고 노드를 반환합니다.

const createToast = text => {
  const node = document.createElement('output')
  
  node.innerText = text
  node.classList.add('gui-toast')
  node.setAttribute('role', 'status')

  return node
}

하나 또는 여러 개의 토스트 메시지 관리

JavaScript는 이제 토스트 메시지를 포함하기 위해 문서에 컨테이너를 추가하며 생성된 토스트 메시지를 추가할 준비가 되었습니다. addToast() 함수는 다음 중 하나를 처리합니다. 또는 토스트가 많이 있습니다. 먼저 토스트 메시지 수와 모션이 정상인지 확인한 다음 이 정보를 사용하여 토스트 메시지를 추가하거나 멋진 다른 토스트 메시지가 '공간을 만드는' 것처럼 보이게 합니다. 하려고 합니다.

const addToast = toast => {
  const { matches:motionOK } = window.matchMedia(
    '(prefers-reduced-motion: no-preference)'
  )

  Toaster.children.length && motionOK
    ? flipToast(toast)
    : Toaster.appendChild(toast)
}

첫 번째 토스트 메시지를 추가하면 Toaster.appendChild(toast)는 CSS 애니메이션을 실행하는 페이지: 애니메이션 시작, 3s 대기, 애니메이션 처리 기존 토스트 메시지가 있을 때 기법을 사용하여 flipToast()가 호출됩니다. 폴의 플립 루이스입니다. 이 개념은 두 값의 차이를 컨테이너 위치에 새 토스트 메시지가 추가되기 전후로 표시됩니다. 토스터의 현재 위치, 향후 위치를 표시한 다음 움직일 수 있습니다.

const flipToast = toast => {
  // FIRST
  const first = Toaster.offsetHeight

  // add new child to change container size
  Toaster.appendChild(toast)

  // LAST
  const last = Toaster.offsetHeight

  // INVERT
  const invert = last - first

  // PLAY
  const animation = Toaster.animate([
    { transform: `translateY(${invert}px)` },
    { transform: 'translateY(0)' }
  ], {
    duration: 150,
    easing: 'ease-out',
  })
}

CSS 그리드는 레이아웃을 들어 올립니다. 새 토스트 메시지가 추가되면 그리드에서 시작해서 다른 사람들과의 간격을 결정합니다. 한편 웹은 애니메이션은 애니메이션을 적용하는 데 사용됩니다.

모든 JavaScript를 하나로 묶기

Toast('my first toast')가 호출되면 토스트 메시지가 생성되어 페이지에 추가됩니다. (컨테이너도 새 토스트 메시지를 수용하도록 애니메이션 처리됨) 프라미스 반환되고 생성된 토스트 메시지는 시청함 프라미스 해결을 위한 CSS 애니메이션 완료 (키프레임 애니메이션 3개)

const Toast = text => {
  let toast = createToast(text)
  addToast(toast)

  return new Promise(async (resolve, reject) => {
    await Promise.allSettled(
      toast.getAnimations().map(animation => 
        animation.finished
      )
    )
    Toaster.removeChild(toast)
    resolve() 
  })
}

이 코드에서 혼동되는 부분이 Promise.allSettled() 함수에 있다고 느껴짐 및 toast.getAnimations() 매핑이 있습니다. 여러 키프레임 애니메이션을 사용했기 때문에 토스트를 하려면 모든 것이 완료되었다는 것을 확실히 알 수 있도록 자바스크립트에서 요청하고 finished 프라미스를 반환합니다 allSettled 우리를 위해 작동합니까, 모든 약속이 완료되면 자체적으로 해결됩니다. 처리되었는지 확인합니다. await Promise.allSettled()를 사용하면 코드는 확실히 요소를 삭제하고 토스트 메시지가 완료되었다고 가정할 수 있습니다. 수명 주기 동안 사용됩니다 마지막으로 resolve()를 호출하면 상위 수준의 토스트 메시지 약속이 처리되므로 토스트 메시지가 표시되면 개발자가 정리하거나 다른 작업을 수행할 수 있습니다.

export default Toast

마지막으로 Toast 함수를 모듈에서 내보내어 다른 스크립트가 살펴보겠습니다

토스트 메시지 구성요소 사용

토스트 또는 토스트의 개발자 환경을 사용하려면 Toast 함수를 사용하여 메시지 문자열로 이를 호출하는 방법을 보여줍니다.

import Toast from './toast.js'

Toast('Wizard Rose added to cart')

토스트 메시지가 표시된 후 개발자가 정리 작업을 하려는 경우 async와 await를 사용하면 됩니다.

import Toast from './toast.js'

async function example() {
  await Toast('Wizard Rose added to cart')
  console.log('toast finished')
}

결론

이제 제가 어떻게 했는지 알게 되셨으니 어떻게 하면 좋을까요?‽ 보상

접근방식을 다각화하고 웹에서 빌드하는 방법을 모두 알아보겠습니다. 데모를 만들고 링크를 트윗하여 추가하면 됩니다. 아래 커뮤니티 리믹스 섹션을 공유해 주세요

커뮤니티 리믹스