diff --git a/src/assets/inclusive-range.svg b/src/assets/inclusive-range.svg
new file mode 100644
index 0000000000..88a53e93a4
--- /dev/null
+++ b/src/assets/inclusive-range.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/ruler.svg b/src/assets/ruler.svg
new file mode 100644
index 0000000000..4a7451fabc
--- /dev/null
+++ b/src/assets/ruler.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/components/sequencing/CommandPanel/CommandArg.svelte b/src/components/sequencing/CommandPanel/CommandArg.svelte
new file mode 100644
index 0000000000..1f8fa9be22
--- /dev/null
+++ b/src/components/sequencing/CommandPanel/CommandArg.svelte
@@ -0,0 +1,33 @@
+
+
+
+
+
+ {#if typeDisplay}
+
+ {/if}
+ {#if range}
+ {#if type === 'boolean'}
+
+ {range.min}|{range.max}
+
+ {:else}
+
+
+ {range.min}
-{range.max}
+
+ {/if}
+ {/if}
+ {#if isValidUnit(unit, unitShortName)}
+
+
+ {unitShortName || unit}
+
+ {/if}
+
+
+
diff --git a/src/components/sequencing/CommandPanel/CommandArgUnit.svelte.test.ts b/src/components/sequencing/CommandPanel/CommandArgUnit.svelte.test.ts
new file mode 100644
index 0000000000..5eeffe0002
--- /dev/null
+++ b/src/components/sequencing/CommandPanel/CommandArgUnit.svelte.test.ts
@@ -0,0 +1,58 @@
+import { cleanup, render } from '@testing-library/svelte';
+import { afterEach, describe, expect, it } from 'vitest';
+import CommandArgUnit from './CommandArgUnit.svelte';
+
+describe('CommandArgUnit component', () => {
+ afterEach(() => {
+ cleanup();
+ });
+
+ it('Should render units for a boolean command argument', () => {
+ const { getByText } = render(CommandArgUnit, {
+ range: { max: 'Foo true', min: 'Foo false' },
+ type: 'boolean',
+ typeDisplay: 'Foo boolean',
+ });
+ expect(getByText(/Foo false/)).toBeDefined();
+ expect(getByText(/Foo true/)).toBeDefined();
+ });
+
+ it('Should render a range for a command argument', () => {
+ const { getByText } = render(CommandArgUnit, {
+ range: { max: '24', min: '2' },
+ type: 'number',
+ typeDisplay: 'Foo number',
+ });
+ expect(getByText(/2/)).toBeDefined();
+ expect(getByText(/-/)).toBeDefined();
+ expect(getByText(/24/)).toBeDefined();
+ });
+
+ it('Should render units for a string command argument', () => {
+ const { getByText } = render(CommandArgUnit, {
+ type: 'string',
+ typeDisplay: 'Foo string',
+ });
+ expect(getByText(/Foo string/)).toBeDefined();
+ });
+
+ it('Should render short version of unit', () => {
+ const { getByText, queryByText } = render(CommandArgUnit, {
+ type: 'string',
+ typeDisplay: 'Foo string',
+ unit: 'bar baz',
+ unitShortName: 'foo',
+ });
+ expect(getByText('foo')).toBeDefined();
+ expect(queryByText('bar baz')).toBeNull();
+ });
+
+ it('Should render unit if no short version is provided', () => {
+ const { getByText } = render(CommandArgUnit, {
+ type: 'string',
+ typeDisplay: 'Foo string',
+ unit: 'bar baz',
+ });
+ expect(getByText('bar baz')).toBeDefined();
+ });
+});
diff --git a/src/components/sequencing/CommandPanel/CommandBooleanArgDef.svelte b/src/components/sequencing/CommandPanel/CommandBooleanArgDef.svelte
new file mode 100644
index 0000000000..74dd574fd2
--- /dev/null
+++ b/src/components/sequencing/CommandPanel/CommandBooleanArgDef.svelte
@@ -0,0 +1,20 @@
+
+
+
+ {#if selectedCommandDefinition !== null}
+
+
+
{selectedCommandDefinition.stem}
+ {:else}
+ {commandDictionary.id}
+ {/if}
+
+
+ {#if selectedCommandDefinition !== null}
+
+
+ {/if}
+
+
+
+
+
+
+ {#if commandResults.length > 0}
+ {#each commandResults as commandResult}
+
+
+
+ {/each}
+ {:else}
+ No {searchFieldMap[searchField]} matched your search query.
+ {/if}
+
+
+
+
+
+
diff --git a/src/components/sequencing/CommandPanel/CommandEnumArgDef.svelte b/src/components/sequencing/CommandPanel/CommandEnumArgDef.svelte
new file mode 100644
index 0000000000..1c7de2f509
--- /dev/null
+++ b/src/components/sequencing/CommandPanel/CommandEnumArgDef.svelte
@@ -0,0 +1,29 @@
+
+ {#if commandName != null}
+
+ {/if}
+ {#if commandDef != null && commandDef.description != null}
+
{commandDef.description}
+ {/if}
+ {#if !!timeTagNode}
+
+ {/if}
+ {#if !!commandNode}
+ {#if commandInfoMapper.nodeTypeHasArguments(commandNode)}
+ {#if !!commandDef}
+
+
+ {#each editorArgInfoArray as argInfo}
+
setInEditor(editorSequenceView, token, val), 250)}
+ addDefaultArgs={(commandNode, missingArgDefArray) =>
+ addDefaultArgs(commandDictionary, editorSequenceView, commandNode, missingArgDefArray, commandInfoMapper)}
+ />
+ {/each}
+
+ {#if missingArgDefArray.length}
+
+ {/if}
+ {:else}
+
+ Command type is not present in dictionary
+ {/if}
+ {:else}
+
+ {/if}
+ {:else}
+
+ Select a command or open the
+
+ .
+
+
+ {/if}
+
+
+
diff --git a/src/components/sequencing/CommandPanel/TimeTagEditor.svelte b/src/components/sequencing/CommandPanel/TimeTagEditor.svelte
new file mode 100644
index 0000000000..7f4208d081
--- /dev/null
+++ b/src/components/sequencing/CommandPanel/TimeTagEditor.svelte
@@ -0,0 +1,31 @@
+