PXD

Todo List

Render a checklist that walks items through a workflow.

Default

Tasks1/4
  • Rewrite types.d.ts / utils.ts / index.vue
  • Delete the legacy components
  • Rewrite tests/components/todo-list.test.ts
  • Rewrite the docs page
<script setup>
import { ref } from 'vue'

const options = ref([
  { id: 'types', content: 'Rewrite types.d.ts / utils.ts / index.vue', status: 'in_progress' },
  { id: 'remove', content: 'Delete the legacy components', status: 'pending' },
  { id: 'tests', content: 'Rewrite tests/components/todo-list.test.ts', status: 'pending' },
  { id: 'docs', content: 'Rewrite the docs page', status: 'completed' },
])

function onChange({ item, status }) {
  console.log(item.content, status)
}
</script>

<template>
  <PTodoList
    v-model="options"
    title="Tasks"
    default-expanded
    @change="onChange"
  />
</template>

Readonly

readonly renders an agent’s plan without any interaction — the status buttons are disabled and rows no longer react to clicks, while the exposed methods stay inert.

Tasks2/4
  • Count TODO markers across packages
  • Read failing test and its fixture
  • Rename config key in every cordis.yml
  • Summarise the findings
<script setup>
import { ref } from 'vue'

const options = ref([
  { content: 'Count TODO markers across packages', status: 'completed' },
  { content: 'Read failing test and its fixture', status: 'completed' },
  { content: 'Rename config key in every cordis.yml', status: 'in_progress' },
  { content: 'Summarise the findings', status: 'pending' },
])
</script>

<template>
  <PTodoList
    :options="options"
    readonly
    default-expanded
  />
</template>

Uncontrolled

Without v-model the component keeps the new status internally and emits change; replacing the options array re-syncs it.

Tasks0/3
  • Review items in your cart
  • Choose a payment method
  • Order confirmed

<script setup>
import { ref } from 'vue'

const options = ref([
  { content: 'Review items in your cart', status: 'pending' },
  { content: 'Choose a payment method', status: 'pending' },
  { content: 'Order confirmed', status: 'pending' },
])

const last = ref('')
</script>

<template>
  <PTodoList
    :options="options"
    default-expanded
    @change="({ status }) => (last = `${last ? last + ' → ' : ''}${status}`)"
  >
  </PTodoList>

  <p class="mt-3 text-sm text-foreground-secondary">{{ last }}</p>
</template>

Collapsible

collapsible controls whether the header folds the list away. default-expanded decides the initial state, and toggle reports every fold.

Tasks0/3
  • Find files, not directories, whose paths match a glob pattern
  • Search file contents with a ripgrep regular expression
  • Collect every still-relevant job before the final answer

Open

<script setup>
import { ref } from 'vue'

const options = ref([
  { content: 'Find files, not directories, whose paths match a glob pattern', status: 'in_progress' },
  { content: 'Search file contents with a ripgrep regular expression', status: 'pending' },
  { content: 'Collect every still-relevant job before the final answer', status: 'pending' },
])

const expanded = ref(true)
</script>

<template>
  <PTodoList
    :options="options"
    collapsible
    default-expanded
    @toggle="expanded = $event"
  />

  <p class="mt-3 text-sm text-foreground-secondary">{{ expanded ? 'Open' : 'Folded' }}</p>
</template>

Description

Plan1/3
  • Rewrite the resizable types
    Double insert plus number[] boundary cases
  • Run type-check / tests / lint
  • Delete three obsolete tests
  • Write the pitfalls entry
<script setup>
import { ref } from 'vue'

const options = ref([
  {
    content: 'Rewrite the resizable types',
    description: 'Double insert plus number[] boundary cases',
    status: 'in_progress',
  },
  { content: 'Run type-check / tests / lint', description: '', status: 'pending' },
  { content: 'Delete three obsolete tests', status: 'completed' },
  { content: 'Write the pitfalls entry', status: 'canceled' },
])
</script>

<template>
  <PTodoList
    :options="options"
    title="Plan"
    default-expanded
  />
</template>

Empty

Tasks
  • Nothing planned yet
<template>
  <PTodoList :options="[]" empty="Nothing planned yet" default-expanded />
</template>

Props

NameTypeDefaultDescription
model-valueTodoOption[]-Bound list state; takes precedence over options.
default-valueTodoOption[]-List state used before the consumer binds v-model.
optionsTodoOption[][]Items to render while uncontrolled; each entry is { id?, content?, description?, status?, disabled? }.
readonlybooleanfalseRender as a static list: status buttons are disabled and rows ignore clicks.
collapsiblebooleantrueAllow folding the list away behind the header.
default-expandedbooleanfalseWhether the list starts open.
titleComponentLabellocale.todo.titleHeader title.
emptyComponentLabellocale.results.noDataText shown when there is no item.

Events

NameTypeDescription
change(detail: TodoChangeDetail) => voidEmitted when an item moves to another status.
update:modelValue(options: TodoOption[]) => voidEmitted together with change, carrying the next list state.
toggle(expanded: boolean, event: MouseEvent) => voidEmitted when the header folds or unfolds the list.

detail reports which item moved and what the whole list becomes:

interface TodoChangeDetail {
  item: TodoOption
  index: number
  status: TodoStatus
  prevStatus: TodoStatus
  options: TodoOption[]
}

Slots

NameDescription
headerReplaces the header content. Slot props: expanded, stats, title, summary.
itemReplaces a whole row, including its status button. Slot props: item, index, status, toggle.
item-contentReplaces the text block of a row. Slot props: item, index, status.
emptyReplaces the empty-state text.

Methods

NameTypeDescription
isExpandedbooleanWhether the list is currently open.
statsTodoStatsItem counts per status, plus total.
expand() => voidOpen the list.
collapse() => voidClose the list.
toggleExpand(next?: boolean) => voidToggle the list, or force it open or closed.
start(target: TodoItemKey) => voidMove an item to in_progress.
complete(target: TodoItemKey) => voidMove an item to completed.
cancel(target: TodoItemKey) => voidMove an item to canceled.
reset(target: TodoItemKey) => voidMove an item back to pending.

Every target is an option id, falling back to its index.

Source

Source