Skip to content

Soracom

Design System
Home Design System Ux Patterns Adding and deleting rows

Adding and deleting rows

Implementing adding/deleting 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
<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 --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>
XS Mobile 320px Mobile 420px Tablet 680px Desktop 960px
<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 --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
<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 --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>
XS Mobile 320px Mobile 420px Tablet 680px Desktop 960px
<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 --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
<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 --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 --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>
XS Mobile 320px Mobile 420px Tablet 680px Desktop 960px
<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 --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 --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.

<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 --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 --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>
XS Mobile 320px Mobile 420px Tablet 680px Desktop 960px
<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 --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 --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.

<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 --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 --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>
XS Mobile 320px Mobile 420px Tablet 680px Desktop 960px
<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 --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 --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>
<div class="ds-rows --gap-xsmall">
	<ul class="ds-list --plain --no-h-indent">
		<li>
			<div class="ds-input">
        <div class="ds-text --addon-light">Key</div>
				<input type="text" value="My key">
			</div>
			<div class="ds-input">
        <div class="ds-text --addon-light">Value</div>
				<input type="text" value="My value">
			</div>
			<button class="ds-button --hide-label --icon-delete --plain">
				<span>Delete row</span>
			</button>
		</li>
		<li>
			<div class="ds-input">
        <div class="ds-text --addon-light">Key</div>
				<input type="text">
			</div>
			<div class="ds-input">
        <div class="ds-text --addon-light">Value</div>
				<input type="text">
			</div>
			<button class="ds-button --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>
XS Mobile 320px Mobile 420px Tablet 680px Desktop 960px
<div class="ds-rows --gap-xsmall">
	<ul class="ds-list --plain --no-h-indent">
		<li>
			<div class="ds-input">
        <div class="ds-text --addon-light">Key</div>
				<input type="text" value="My key">
			</div>
			<div class="ds-input">
        <div class="ds-text --addon-light">Value</div>
				<input type="text" value="My value">
			</div>
			<button class="ds-button --hide-label --icon-delete --plain">
				<span>Delete row</span>
			</button>
		</li>
		<li>
			<div class="ds-input">
        <div class="ds-text --addon-light">Key</div>
				<input type="text">
			</div>
			<div class="ds-input">
        <div class="ds-text --addon-light">Value</div>
				<input type="text">
			</div>
			<button class="ds-button --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>