Soracom

Design System
  1. Home
  2. Design system
  3. Ux patterns
  4. Repeatable editable rows

Repeatable editable rows

Implementing adding/deleting of repeatable editable rows in a form

Overview

When implementing repeatable, editable rows the following formats should be used

Initial empty state

By default, with no saved values:

Always
  1. Show 1 row of blank fields
  2. The delete button must be disabled
  3. The Add row button must be disabled
html
Copy
<div class="ds-rows --gap-xsmall">
  <ul class="ds-list --plain --no-h-indent">
    <li>
      <div class="ds-input">
        <input type="text" placeholder="Key" />
      </div>
      <div class="ds-input">
        <input type="text" placeholder="Value" />
      </div>
      <button
        class="ds-button --left --hide-label --icon-delete --plain"
        disabled
      >
        <span>Delete row</span>
      </button>
    </li>
  </ul>
  <button class="ds-button --small --icon-plus" disabled>
    <span>Add row</span>
  </button>
</div>

Once text is entered into the first row:

Always
  1. Enable the delete button
  2. Enable the Add row button

With text entered

html
Copy
<div class="ds-rows --gap-xsmall">
  <ul class="ds-list --plain --no-h-indent">
    <li>
      <div class="ds-input">
        <input type="text" placeholder="Key" value="My key" />
      </div>
      <div class="ds-input">
        <input type="text" placeholder="Value" />
      </div>
      <button class="ds-button --left --hide-label --icon-delete --plain">
        <span>Delete row</span>
      </button>
    </li>
  </ul>
  <button class="ds-button --small --icon-plus">
    <span>Add row</span>
  </button>
</div>

Deleting a row:

Clicking the ‘Delete row’ button, should:

Always
  1. If row fields have values, show a confirmation dialog to delete the row
  2. If there is only 1 row, delete the contents of the fields
  3. If there is only 1 row, disable the Delete row button and the Add row button
  4. If there is more than one row, delete the current row

Add a row:

Clicking the ‘Add row’ button, should:

Always
  1. Add a new empty row at the bottom of the list
  2. Disable the ‘Add row’ button

With text entered

html
Copy
<div class="ds-rows --gap-xsmall">
  <ul class="ds-list --plain --no-h-indent">
    <li>
      <div class="ds-input">
        <input type="text" placeholder="Key" value="My key" />
      </div>
      <div class="ds-input">
        <input type="text" placeholder="Value" value="My value" />
      </div>
      <button class="ds-button --left --hide-label --icon-delete --plain">
        <span>Delete row</span>
      </button>
    </li>
    <li>
      <div class="ds-input">
        <input type="text" placeholder="Key" />
      </div>
      <div class="ds-input">
        <input type="text" placeholder="Value" />
      </div>
      <button class="ds-button --left --hide-label --icon-delete --plain">
        <span>Delete row</span>
      </button>
    </li>
  </ul>
  <button class="ds-button --small --icon-plus" disabled>
    <span>Add row</span>
  </button>
</div>

Examples

Using ds-table

Using ds-table is useful when implementing more than 2 fields per row, or the requirement for column labels.

html
Copy
<div class="ds-rows --gap-xsmall">
  <table class="ds-datatable --plain --no-indent --gap-xsmall">
    <thead>
      <tr>
        <th>Type</th>
        <th>Name</th>
        <th>Value</th>
        <th class="--min"></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          <div class="ds-input">
            <input type="text" value="My type" />
          </div>
        </td>
        <td>
          <div class="ds-input">
            <input type="text" value="My name" />
          </div>
        </td>
        <td>
          <div class="ds-input">
            <input type="text" value="My value" />
          </div>
        </td>
        <td>
          <button class="ds-button --left --hide-label --icon-delete --plain">
            <span>Delete row</span>
          </button>
        </td>
      </tr>
      <tr>
        <td>
          <div class="ds-input">
            <input type="text" />
          </div>
        </td>
        <td>
          <div class="ds-input">
            <input type="text" />
          </div>
        </td>
        <td>
          <div class="ds-input">
            <input type="text" />
          </div>
        </td>
        <td>
          <button class="ds-button --left --hide-label --icon-delete --plain">
            <span>Delete row</span>
          </button>
        </td>
      </tr>
    </tbody>
  </table>
  <button class="ds-button --small --icon-plus">
    <span>Add row</span>
  </button>
</div>

Using ds-list

For simple key-pairs, ds-list requires the least markup.

html
Copy
<div class="ds-rows --gap-xsmall">
  <ul class="ds-list --plain --no-h-indent">
    <li>
      <div class="ds-input">
        <input type="text" placeholder="Key" value="My key" />
      </div>
      <div class="ds-input">
        <input type="text" placeholder="Value" value="My value" />
      </div>
      <button class="ds-button --left --hide-label --icon-delete --plain">
        <span>Delete row</span>
      </button>
    </li>
    <li>
      <div class="ds-input">
        <input type="text" placeholder="Key" />
      </div>
      <div class="ds-input">
        <input type="text" placeholder="Value" />
      </div>
      <button class="ds-button --left --hide-label --icon-delete --plain">
        <span>Delete row</span>
      </button>
    </li>
  </ul>
  <button class="ds-button --small --icon-plus">
    <span>Add row</span>
  </button>
</div>