Đến nội dung chính

Mục cài đặt

Một chủ đề cài đặt trên một thẻ, tách các công tắc ra khỏi những việc không thể hoàn lại.

Mẫu biểu mẫu

Xem trước trực tiếp

Nguồn

<section class="dc-set" aria-labelledby="dc-set-title">
  <div class="dc-set__head">
    <h2 class="dc-set__title" id="dc-set-title">알림</h2>
    <p class="dc-set__desc">새 소식을 어디로 받을지 정합니다. 고르면 바로 저장됩니다.</p>
  </div>

  <div class="dc-set__card">
    <div class="dc-set__row">
      <div class="dc-set__main">
        <span class="dc-set__label" id="dc-set-r1">새 공고 알림</span>
        <span class="dc-set__help">저장한 조건에 맞는 공고가 올라오면 알려 줍니다.</span>
      </div>
      <div class="dc-set__control">
        <label class="dc-set__switch">
          <input class="dc-set__switch-input" type="checkbox" role="switch" checked aria-labelledby="dc-set-r1">
          <span class="dc-set__switch-track"><span class="dc-set__switch-knob"></span></span>
        </label>
      </div>
    </div>

    <div class="dc-set__row">
      <div class="dc-set__main">
        <label class="dc-set__label" for="dc-set-hour">알림 받는 시간</label>
        <span class="dc-set__help">이 시간대에만 소리가 납니다. 밖에서는 조용히 쌓입니다.</span>
      </div>
      <div class="dc-set__control">
        <select class="dc-set__select" id="dc-set-hour">
          <option>아무 때나</option>
          <option selected>09:00 ~ 21:00</option>
          <option>18:00 ~ 22:00</option>
        </select>
      </div>
    </div>

    <div class="dc-set__row">
      <div class="dc-set__main">
        <span class="dc-set__label">알림 소리</span>
        <span class="dc-set__help">지금 쓰는 기기에서 소리를 들어 봅니다.</span>
      </div>
      <div class="dc-set__control">
        <button class="dc-set__btn" type="button">소리 듣기</button>
      </div>
    </div>
  </div>
</section>
.dc-set { display:flex; flex-direction:column; gap:var(--dc-3); width:100%; max-width:640px; font-family:var(--dc-font); }
.dc-set__head { display:flex; flex-direction:column; gap:var(--dc-1); }
.dc-set__title { font-size:17px; font-weight:700; color:var(--dc-text); }
.dc-set__desc { font-size:13px; color:var(--dc-text-sub); }
.dc-set__card { display:flex; flex-direction:column; margin:0; padding:0; border:1px solid var(--dc-line); border-radius:var(--dc-r-md); background:var(--dc-surface); }
.dc-set__card--danger { border-color:var(--dc-danger); background:var(--dc-danger-soft); }
.dc-set__legend { margin-left:var(--dc-3); padding:0 var(--dc-1); font-size:14px; font-weight:700; color:var(--dc-text); }
.dc-set__row { display:flex; align-items:center; justify-content:space-between; gap:var(--dc-4); padding:var(--dc-3) var(--dc-4); border-top:1px solid var(--dc-line); }
.dc-set__row:first-of-type { border-top:0; }
.dc-set__main { display:flex; flex-direction:column; gap:2px; min-width:0; }
.dc-set__label { font-size:14px; font-weight:600; color:var(--dc-text); }
.dc-set__help { font-size:12px; line-height:1.5; color:var(--dc-text-sub); }
.dc-set__control { flex:0 0 auto; display:flex; align-items:center; }
.dc-set__switch { position:relative; display:inline-flex; align-items:center; justify-content:flex-end; min-width:48px; min-height:44px; cursor:pointer; }
.dc-set__switch-input { position:absolute; width:1px; height:1px; opacity:0; }
.dc-set__switch-track { display:flex; align-items:center; width:48px; height:28px; padding:3px; border:1px solid var(--dc-line-field); border-radius:var(--dc-r-full); background:var(--dc-sunken); transition:background var(--dc-fast), border-color var(--dc-fast); }
.dc-set__switch-knob { display:block; width:22px; height:22px; border-radius:var(--dc-r-full); background:var(--dc-surface); box-shadow:var(--dc-sh-1); transition:transform var(--dc-fast); }
.dc-set__switch-input:checked + .dc-set__switch-track { background:var(--dc-brand); border-color:var(--dc-brand); }
.dc-set__switch-input:checked + .dc-set__switch-track .dc-set__switch-knob { transform:translateX(18px); }
.dc-set__switch-input:focus-visible + .dc-set__switch-track { outline:2px solid var(--dc-brand); outline-offset:2px; }
.dc-set__select { min-height:44px; padding:0 var(--dc-3); border:1px solid var(--dc-line-field); border-radius:var(--dc-r-sm); background:var(--dc-surface); color:var(--dc-text); font-size:14px; }
.dc-set__radio { width:22px; height:22px; margin:var(--dc-2); accent-color:var(--dc-brand); }
.dc-set__btn { min-height:44px; padding:0 var(--dc-4); border:1px solid var(--dc-line-field); border-radius:var(--dc-r-sm); background:var(--dc-surface); color:var(--dc-text); font-size:13px; font-weight:600; cursor:pointer; }
.dc-set__btn:hover { background:var(--dc-sunken); }
.dc-set__btn--danger { border-color:var(--dc-danger); background:var(--dc-surface); color:var(--dc-danger); }
.dc-set__btn--danger:hover { background:var(--dc-danger); color:var(--dc-text-on); }
@media (max-width:520px) {
  .dc-set__row { flex-direction:column; align-items:stretch; gap:var(--dc-2); }
  .dc-set__control { justify-content:flex-start; }
  .dc-set__select { width:100%; }
}

Cách dùng

  • Mỗi dòng một cài đặt: bên trái là tên và một dòng giải thích, bên phải chỉ một điều khiển
  • Nếu thay đổi được lưu ngay, bỏ nút lưu và thay bằng thông báo đã lưu
  • Đưa các hành động không thể hoàn lại ra khỏi thẻ, xuống khối riêng bên dưới

Điểm cần lưu ý

  • Công tắc cần có tên — nối với tiêu đề dòng bằng aria-labelledby hoặc thêm tên bằng dc-sr
  • Trên màn hình hẹp, để điều khiển xuống dòng dưới thay vì ép sát lề phải

Tiếp theo