Vue 3를 사용하여 액세스 가능한 스위치를 구성하는 방법

25241 단어 vuewebdevjavascript
응용 프로그램에서 다양한 UI 구성 요소를 찾을 수 있습니다.가장 흔히 볼 수 있는 것은 단추, 입력, 폼, 이미지일 수도 있다.그것들은 매우 흔하다. HTML은 심지어 그것들에게 기본 요소를 제공한다!그러나 자신이 구축해야 할 알려지지 않은 구성 요소를 만나는 것은 드물지 않다.
나는 최근에 다음과 같은 스위치/전환 구성 요소를 연구했다.

처음에는 단순한 UI 구성 요소처럼 보였습니다.그러나 모든 상태, 접근 가능성, 중용성을 고려해야 할 때 구축하기가 어려울 수 있습니다.
너는 정말 운이 좋다!오늘 저는 이 점을 어떻게 하는지 여러분과 공유할 것입니다.
참고: Vue로 구축했지만 이러한 개념은 React 같은 다른 프레임워크에 쉽게 적용될 수 있습니다.그리고 저는 Vue 3를 사용하고 있지만 두려워하지 마세요.여기는 Vue 2와 많이 다르지 않아요!😉

개념이 좀 있어요.


키보드로 바로 넘어가서 인코딩을 시작하기 전에, 특히 스위치의 용도에 대해 고려해야 할 것은 매우 적다.실제로 스위치는 두 가지 방식으로 사용할 수 있다.
  • 어떤 물건을 켜거나 끄거나(예를 들어 전등 스위치 사용)
  • 두 옵션 중에서 선택 (예: 테마 전환기)
  • 중요한 것은 어떤 용례가 당신에게 적합한지 알아야 한다는 것이다. 왜냐하면 그것은 밑바닥의 실현에 영향을 줄 수 있기 때문이다.우리의 예에서, 우리는 첫 번째 용례를 사용할 것이다.
    그 밖에 사용자가 스위치를 바꾸면 무슨 일이 일어날지 알 수 있도록 스위치를 표시하고 싶습니다.
    사용자가 뉴스 원고를 받기로 선택한 실제 예시를 살펴보자.checked 아이템, label 아이템과 toggle 이벤트의 첫 번째 구현을 고려할 수 있습니다.
    <Switch
      :checked="shouldReceiveNewsletter"
      @toggle="toggle"
      label="Receive newsletter"
    />
    
    이거 좋아요.그러나 우리는 v-model 을 사용하여 다음과 같은 결과를 얻을 수 있다.
    <Switch v-model:checked="shouldReceiveNewsletter" label="Receive newsletter" />
    
    Vue에 익숙하면 위의 예에서 v-model을 사용한 것에 대해 놀라실 수 있습니다.이것은 Vue 3에서 가져온 변경 사항 중 하나입니다. 이제 템플릿에서 매개변수 이름을 직접 사용할 수 있습니다.위의 코드는 checked 속성을 <Switch>에 전달합니다. update:checked 이벤트를 보내서 이 속성을 업데이트할 수 있습니다.

    템플릿 구축


    HTML 요소를 선택해야 할 때마다 의미 있는 요소를 선택해야 합니다.우리의 예에서, 우리는 컨트롤을 구축할 때 반드시 input 을 사용해야 한다.스위치에는 다음과 같은 두 가지 예가 있습니다.
  • 켜기/끄기 설정: checkbox 필요
  • 한 옵션과 다른 옵션 사이를 전환합니다(예: 밝기/어두운 테마): radio buttons 두 개가 필요합니다.
  • 입력한 라벨이 정확한지 확인해야 합니다.한 가지 방법은 <input><label>에 포장하고 텍스트를 추가하는 것이다.
    마지막으로, 우리는 빈 <span>을 추가할 수 있으며, 이따가 스위치를 구축하기 위해 사용할 것입니다.Switch.vue 파일을 계속 만들면 다음 내용을 붙여넣을 수 있습니다.
    <template>
      <label>
        <input type="checkbox" />
        <span></span>
        <span>{{ label }}</span>
      </label>
    </template>
    

    아이템과 v형 모형


    우리는 두 개의 프로를 스위치에 전달해야 한다. label은 문자열이고 checked은 부울 값이다.기억하세요, checked 아이템은 v-model:checked에서 왔습니다:
    <template>
      <label>
        <input
          type="checkbox"
          :checked="checked"
          @change="$emit('update:checked', $event.target.checked)"
        />
        <span></span>
        <span>{{ label }}</span>
      </label>
    </template>
    
    <script>
      export default {
        name: "Switch",
        props: {
          label: {
            type: String,
            required: true,
          },
          checked: {
            type: Boolean,
            required: true,
          },
        },
      };
    </script>
    
    위의 입력에 문제가 있습니다.실제로 뿌리 원소는 밑바닥 입력과 다르다.입력한 다른 속성(예: disabled)에 전달할 추가 속성을 만들어야 합니다.
    이를 복구하려면 입력에 v-bind="$attrs" , 루트 요소에 disable attribute inheritance을 배치해야 합니다.
    <input
      v-bind="$attrs"
      type="checkbox"
      @change="$emit('update:checked', $event.target.checked)"
      :checked="checked"
    />
    
    <script>
      export default {
        name: "Switch",
        inheritAttrs: false,
        /* ... */
      };
    </script>
    

    어셈블리 스타일 설정하기


    컨테이너 및 레이블


    지금까지 스위치는 다음과 같습니다.

    우리 현실에 직면합시다. 이것은 너무 보기 흉합니다.보다 아름답게 만들기 위해 다양한 요소에 CSS 클래스를 추가합니다.
    <template>
      <label class="container">
        <input
          v-bind="$attrs"
          class="input"
          type="checkbox"
          :checked="checked"
          @change="$emit('update:checked', $event.target.checked)"
        />
        <span class="switch"></span>
        <span class="label">{{ label }}</span>
      </label>
    </template>
    
    우리는 하나하나 할 것이다.우선 .container입니다.우리는 텍스트가 스위치의 오른쪽에 있다는 것을 알고 있으며, 우리는 텍스트가 완전히 가운데에 있기를 바란다.전체 전환은 클릭할 수 있기를 원하기 때문에 포인터 커서를 추가합니다.
    <style scoped>
      .container {
        cursor: pointer;
        display: flex;
        align-items: center;
      }
    </style>
    
    레이블에 더 멋진 색상을 제공하고 확인란에 공간을 남겨야 합니다.
    .label {
      margin-left: 12px;
      color: #1a202c;
    }
    
    그리고 의미 때문에 <input>을 사용하지만 시각적으로 도움이 되지 않는다.시각적으로 숨겨야 하지만 액세스 가능성 때문에 DOM에 보관해야 합니다.
    /* Visually hide the checkbox input */
    .input {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border-width: 0;
    }
    
    주: 이러한 속성의 영감은 Tailwind CSS.sr-only류에서 나온다

    스위치


    스위치는 원형 용기 요소로 구성되어 있으며, 그 중 하나는 둥글다.이 원이 왼쪽이나 오른쪽으로 이동하는 것은 입력을 선택했는지 여부에 따라 달라집니다.
    화면 캡처를 보면 안쪽 코일의 크기가 용기 원소의 절반 정도인 것을 볼 수 있다.용기의 너비는 그 자체의 높이의 두 배이다.CSS를 사용하여 속성을 사용자 정의합니다.
    .switch {
      --switch-container-width: 50px;
      --switch-size: calc(var(--switch-container-width) / 2);
    }
    
    내부 코일을 만들기 위해 ::before 원소 기교를 사용합니다.용기 안에 있게 하기 위해서 우리는 용기에 relative의 위치를 주고 안쪽에 absolute의 위치를 주어야 한다.
    이 밖에 안쪽은 --switch-size의 크기에 가까워야 하지만 용기를 넘으면 안 된다.우리는 calc 함수를 사용하여 조정할 것이다.
    .switch {
      --switch-container-width: 50px;
      --switch-size: calc(var(--switch-container-width) / 2);
    
      /* Vertically center the inner circle */
      display: flex;
      align-items: center;
      position: relative;
      height: var(--switch-size);
      flex-basis: var(--switch-container-width);
      /* Make the container element rounded */
      border-radius: var(--switch-size);
      background-color: #e2e8f0;
    }
    
    .switch::before {
      content: "";
      position: absolute;
      /* Move a little bit the inner circle to the right */
      left: 1px;
      height: calc(var(--switch-size) - 4px);
      width: calc(var(--switch-size) - 4px);
      /* Make the inner circle fully rounded */
      border-radius: 9999px;
      background-color: white;
    }
    
    결과는 다음과 같습니다.

    이것은 매우 좋지만, 만약 네가 스위치를 클릭한다면 아무 일도 일어나지 않을 것이다.적어도 시각적으로는확실히 입력이 정확했지만 스위치가 연결되지 않았습니다!
    이러한 변화를 반영하기 위해서는 CSS adjacent sibling selector, 즉 +을 사용하여 입력 상태에 따라 스위치의 스타일을 설정해야 합니다.예를 들어, 확인란을 선택하면 :checked 위조 클래스가 추가됩니다.그러면 우리는 그것을 이용합시다.
    .input:checked + .switch {
      /* Teal background */
      background-color: #4fd1c5;
    }
    
    .input:checked + .switch::before {
      border-color: #4fd1c5;
      /* Move the inner circle to the right */
      transform: translateX(
        calc(var(--switch-container-width) - var(--switch-size))
      );
    }
    
    스위치가 한 상태에서 다른 상태로 전환하는 방식은 평온하지 않다.변형을 수정하려면 transformbackground-color에 추가해야 합니다.
    .switch {
      /* ... */
      transition: background-color 0.25s ease-in-out;
    }
    
    .switch::before {
      /* ... */
      transition: transform 0.375s ease-in-out;
    }
    

    초점 및 비활성화 상태


    지금, 너는 반드시 효과적인 스위치가 있어야 한다.그러나 이 일은 아직 완전히 완성되지 않았다.사실 우리가 이곳에서 실현하지 못한 입력은 여전히 다른 상태를 가지고 있다.예를 들어 Tab키를 누르면 초점 맞추기 스위치가 정확하다는 시각적 피드백이 없다.비활성화된 입력도 마찬가지입니다.
    첫 번째 단계로 .switch에 추가 CSS 사용자 정의 속성을 추가하고 하드 인코딩 색상을 대체합니다.
    .switch {
      /* ... */
    
      --light-gray: #e2e8f0;
      --gray: #cbd5e0;
      --dark-gray: #a0aec0;
      --teal: #4fd1c5;
      --dark-teal: #319795;
    
      /* ... */
      background-color: var(--light-gray);
    }
    
    .input:checked + .switch {
      background-color: var(--teal);
    }
    
    .input:checked + .switch::before {
      border-color: var(--teal);
      /* ... */
    }
    
    주의: 색깔은 Tailwind CSS에서 왔습니다.
    초점 상태를 해결합시다.우리는 UI에 있어서 어떤 복잡한 일도 하지 않을 것이다. 우리는 단지 내부 테두리에 테두리를 추가하기만 하면 된다.
    .switch::before {
      /* ... */
      border: 2px solid var(--light-gray);
    }
    
    여기서 우리는 교환기 용기의 배경과 같은 색을 선택했다.실제로 처음에 우리는 내부 경계 색깔과 배경 색깔이 혼동되기를 희망했다.이렇게 하면 초점 상태에 서로 다른 border-color을 추가할 때 우리는 그것을 볼 수 있다.초점을 입력할 때 어두운 border-color을 추가합니다.
    .input:focus + .switch::before {
      border-color: var(--dark-gray);
    }
    
    .input:focus:checked + .switch::before {
      border-color: var(--dark-teal);
    }
    
    다음은 모양입니다.

    사용 안 함 상태에서는 회색으로 코일을 채우고 스위치 용기를 어둡게 하여 작업을 수행할 수 없음을 나타냅니다.
    .input:disabled + .switch {
      background-color: var(--gray);
    }
    
    .input:disabled + .switch::before {
      background-color: var(--dark-gray);
      border-color: var(--dark-gray);
    }
    
    다음은 비활성화된 스위치의 모양입니다.

    스위치의 응답성


    우리는 아직 마지막으로 검사해야 할 일이 있다.다음 화면 캡처를 참조하십시오.

    긴 레이블이 있는 경우 스위치에 텍스트가 넘쳐 여러 줄이 필요할 수 있습니다.이것은 반응이 없다, 그렇지?스위치가 축소되지 않고 레이블이 한 줄을 넘지 않도록 합니다.
    .switch {
      /* ... */
      /* In case the label gets long, the toggle shouldn't shrink. */
      flex-shrink: 0;
    }
    
    .label {
      /* ... */
      /* Show an ellipsis if the text takes more than one line */
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    
    이제 스위치의 신속한 응답:

    봐라!우리는 이미 전환을 완성했다.전환은 UI의 일부이지만 구현하기가 쉽지 않습니다.다음은 이러한 구성 요소를 구축할 때의 주요 성과입니다.
  • 은 구성 요소의 API 및 용례를 미리 고려합니다.너는 네가 세우고 싶은 것에 대해 더 좋은 소망을 가지고 있을 것이다.
  • UI 구성 요소의 다양한 제약: 액세스 가능성, 다양한 상태, 응답성 등을 잊지 마십시오.
  • 단계적으로 구성 요소를 구축합니다.이러한 종류의 구성 요소를 처리할 수 있는 교체 방법이 있어야 합니다.
  • 전체 코드를 얻으려면 GitHub 요약에 넣습니다. 아래에서 찾을 수 있습니다.이게 얼마나 좋아요?😄

    좋은 웹페이지 즐겨찾기