依據這幾年的開發經驗,某些流程複雜但使用頻率不高的網頁操作流程,轉成下一步下一步的導引式操作(術語叫 Stepper)常能獲得使用者好評。

(補充:網頁介面依性質可粗分兩個方向:一種是使用人數不多但重度依賴,像是業務人員 Key 單,每天要重複輸入數百上千張,這種介面設計效率為王,常會將所有欄位集中在一個畫面並輔以大量快捷鍵,不必摸滑鼠就搞定,介面複雜難懂無所謂,專業使用者會當成學彈鋼琴苦練直到上手;另一種則是潛在使用者群體很大,但久久才用一次,甚至人永遠不會用到,因使用頻率不高效率不是重點,講求使用者不需學習也能做對,目標在降低客訴及客服支援成本。後者就很適合採取下一步的導引式操作 UI。)

這篇主要寫給自己備忘,示範怎麼用 bs-stepper 寫出下一步式輸入介面。

設計時有幾個重點:

  1. 介面最好能列出完整操作流程,讓使用者知道共有幾關,讓使用者知道現在在哪一關,還有幾關才完成,提供完整且精準的進度資訊能有效增強使用者體驗。
  2. 若操作許可,提供上一步、下一步按鈕,允許使用者回頭修改先前的輸入。
  3. 能否切換步驟可由商業邏輯決定,例如:表單送出後就不需要也不該讓使用切回輸入畫面修改填寫內容。
  4. 最好能支援瀏覽器的回上一頁、到下一頁(要借助 history.pushState() API)切換步驟。

直接看示範:線上展示

程式本身沒什麼了不起,都靠好用的 bs-stepper 程式庫,用法官方文件寫得蠻詳細,在此不多贅述,要補充的我寫在註解裡了,直接看程式碼最快:

<html>

<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.4.1/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bs-stepper@1.7.0/dist/css/bs-stepper.min.css">
</head>

<body>
  <h3 class="text-center">
    茶包弓箭組商品登錄
  </h3>
  <form class="container">
    <div class="bs-stepper">
      <div class="bs-stepper-header" role="tablist">
        <div class="step" data-target="#step1">
          <button type="button" class="step-trigger" role="tab">
            <span class="bs-stepper-circle">1</span>
            <span class="bs-stepper-label">商品資料</span>
          </button>
        </div>
        <div class="line"></div>
        <div class="step" data-target="#step2">
          <button type="button" class="step-trigger" role="tab">
            <span class="bs-stepper-circle">2</span>
            <span class="bs-stepper-label">連絡資訊</span>
          </button>
        </div>
        <div class="line"></div>
        <div class="step" data-target="#step3">
          <button type="button" class="step-trigger" role="tab">
            <span class="bs-stepper-circle">3</span>
            <span class="bs-stepper-label">送出資料</span>
          </button>
        </div>
        <div class="line"></div>
        <div class="step" data-target="#step4">
          <button type="button" class="step-trigger" role="tab">
            <span class="bs-stepper-circle">4</span>
            <span class="bs-stepper-label">完成登錄</span>
          </button>
        </div>
      </div>
      <div class="bs-stepper-content">
        <div id="step1" class="content" role="tabpanel">
          <div class="form-group">
            <label>
              商品型號
            </label>
            <select class="form-control">
              <option>百步穿揚組合包</option>
              <option>例無虛發同綁包</option>
              <option>亂槍打鳥特大包</option>
            </select>
          </div>
          <div class="form-group">
            <label>
              商品序號
            </label>
            <input class="form-control" />
          </div>
          <div>
            <button type="button" onclick="stepper.next()">下一步</button>
          </div>
        </div>
        <div id="step2" class="content" role="tabpanel">
          <div class="form-group">
            <label>姓名</label>
            <input class="form-control" />
          </div>
          <div class="form-group">
            <label>手機號碼</label>
            <input class="form-control" />
          </div>
          <div>
            <button type="button" onclick="stepper.previous()">上一步</button>
            <button type="button" onclick="stepper.next()">下一步</button>
          </div>
        </div>
        <div id="step3" class="content" role="tabpanel">
          <div class="form-group">
            <label>電子郵件</label>
            <input type="email" class="form-control" />
          </div>
          <div class="form-group">
            <label>
              <input type="checkbox">
              我願意收到優惠活動及商品資訊
            </label>
          </div>
          <div>
            <button type="button" onclick="stepper.previous()">上一步</button>
            <button type="button" onclick="simulateSubmit()">確認送出</button>
          </div>
        </div>
        <div id="step4" class="content" role="tabpanel">
          <div class="alert alert-success">
            感謝您購買本公司商品並完成線上登錄,祝茶包退散,永不來犯。
          </div>
        </div>
      </div>
    </div>
  </form>
  <script src="https://cdn.jsdelivr.net/npm/bs-stepper@1.7.0/dist/js/bs-stepper.min.js"></script>
  <script>
    var stepperElem = document.querySelector('.bs-stepper');
    var stepper = new Stepper(stepperElem);
    var done = false;
    var currStep = 1;
    history.pushState(currStep, '');
    //切換到步驟前觸發,呼叫e.preventDefault()可阻止切換
    stepperElem.addEventListener("show.bs-stepper", function (e) {
      if (done) { //若程序完成,不再切換
        e.preventDefault();
        return;
      }
    });
    //切換到步驟後觸發,e.detail.indexStep為目前步驟序號(從0開始)
    stepperElem.addEventListener("shown.bs-stepper", function (e) {
      var idx = e.detail.indexStep + 1;
      currStep = idx;
      //pushState()記下歷程以支援瀏覽器回上頁功能
      history.pushState(idx, '');
    })
    //瀏覽器上一頁下一頁觸發
    window.onpopstate = function (e) {
      if (e.state && e.state != currStep)
        stepper.to(e.state);
    };
    //模擬送出表單,註記已完成,不再允許切換步驟
    function simulateSubmit() {
      stepper.next();
      done = true;
    }
  </script>
</body>

</html>

Stepper-style UI is popular because of its friendliness, this example shows how to write a stepper web UI with bs-stepper which supporting browser back/next navigation.


Comments

Be the first to post a comment

Post a comment


77 + 15 =