Skip to content

ArtifactList

<caos-artifact-list>

pick a code artifact from a long list, each row carrying its real name and what kind of thing it is

May be placed on a page inside an app.

Name Attribute Description Type Default Required
artifacts property only What is there: { name, type, storedType?, label?, dirty? }[]. storedType is shown beside the friendly type when the two differ — “Apex Class (ApexClass)” — because both names get used and making somebody transliterate is a tax paid on every line. json empty list Optional
type type, markup only Show only artifacts of this type. The filter’s CONTENTS are the types actually present — offering a type this environment has none of is offering an empty result. text — anything it does not recognise reads as every type, when the attribute is absent or empty none declared Optional
search search, markup only Narrows by name, label or type. Intersects with the type filter rather than replacing it. text none declared Optional
selected selected, markup only Which artifact is current, by name. Reflected when a row is chosen, so it can be linked to. text none declared Optional
emptyText empty-text, markup only What to say when nothing matches. text No artifacts match. Optional
Name When it fires What it carries
caos-artifact-open A row is pressed. { artifact } — the whole artifact, not just its name, so a host need not look it up again.

Not documented yet — this piece has not said.

Not documented yet — this piece has not said.

Not documented yet — this piece has not said.

Name Type What it tells you
visibleArtifacts CaosArtifact[] The artifacts surviving both filters.
dirtyArtifacts CaosArtifact[] Everything with unsaved changes, across the WHOLE set — a filter never hides this count.
Part Which piece of it When it is there
::part(list) The outer column. Always
::part(filters) The type and search row. Always
::part(type) The type dropdown. Always
::part(search) The search box. Always
::part(summary) The count line, including how many have unsaved changes. Always
::part(rows) The bordered list of rows. Always
::part(row) One artifact’s row. Always
::part(name) The first line — the real name. Always
::part(qualifier) The second line — the type and label. Always
::part(dirty) The unsaved-changes mark. The artifact has unsaved changes.

Whenever somebody chooses one thing out of many where the NAME ALONE is not enough to tell them apart — which, past a couple of dozen artifacts, is always.

  • PicklistField — the choices are short, few, and unambiguous from their labels. A dropdown option is a single string with nowhere to put a qualifier, which is the whole reason this component exists.
  • DataTable — the artifacts are being COMPARED across several columns rather than chosen between.

Each row carries ONE accessible name reading both lines and the unsaved state — “AccountTrigger — Apex Trigger (ApexTrigger) — unsaved changes” — because a screen reader announcing only the first line gets exactly the alphabetical wall this component exists to avoid. Rows are real <button> elements in a role="list", so they are reachable and pressable by keyboard in order, and the current one is marked aria-current. The summary is a role="status" live region and always states how many of the whole set survived the filters.

Three artifacts whose names differ by a suffix. The qualifier is what tells a trigger from its handler from the test that covers it, at a glance rather than by reading carefully.

{
"id": "example",
"section": "Why the second line is there",
"columns": 1,
"items": [
{
"id": "artifact_list_1",
"type": "component",
"key": "artifact_list",
"inputs": {
"selected": "AccountTrigger",
"artifacts": [
{
"name": "AccountTrigger",
"type": "Apex Trigger",
"storedType": "ApexTrigger",
"dirty": true
},
{
"name": "AccountTriggerHandler",
"type": "Apex Class",
"storedType": "ApexClass"
},
{
"name": "AccountTriggerTest",
"type": "Apex Class",
"storedType": "ApexClass",
"label": "Account trigger coverage"
},
{
"name": "InvoiceSummary",
"type": "Page",
"storedType": "ApexPage",
"label": "Invoice summary"
}
]
}
}
]
}
<caos-artifact-list id="artifactList1" selected="AccountTrigger"></caos-artifact-list>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const artifactList1 = document.getElementById('artifactList1');
artifactList1.artifacts = [
{
"name": "AccountTrigger",
"type": "Apex Trigger",
"storedType": "ApexTrigger",
"dirty": true
},
{
"name": "AccountTriggerHandler",
"type": "Apex Class",
"storedType": "ApexClass"
},
{
"name": "AccountTriggerTest",
"type": "Apex Class",
"storedType": "ApexClass",
"label": "Account trigger coverage"
},
{
"name": "InvoiceSummary",
"type": "Page",
"storedType": "ApexPage",
"label": "Invoice summary"
}
];

The summary says two of four survived, and still counts the unsaved change on the row the filter has hidden — which is exactly the one somebody is about to forget about.

{
"id": "example",
"section": "Filtered to one type",
"columns": 1,
"items": [
{
"id": "artifact_list_1",
"type": "component",
"key": "artifact_list",
"inputs": {
"type": "Apex Class",
"artifacts": [
{
"name": "AccountTrigger",
"type": "Apex Trigger",
"storedType": "ApexTrigger",
"dirty": true
},
{
"name": "AccountTriggerHandler",
"type": "Apex Class",
"storedType": "ApexClass"
},
{
"name": "AccountTriggerTest",
"type": "Apex Class",
"storedType": "ApexClass"
},
{
"name": "QuoteSummary",
"type": "Page",
"storedType": "ApexPage"
}
]
}
}
]
}
<caos-artifact-list id="artifactList1" type="Apex Class"></caos-artifact-list>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const artifactList1 = document.getElementById('artifactList1');
artifactList1.artifacts = [
{
"name": "AccountTrigger",
"type": "Apex Trigger",
"storedType": "ApexTrigger",
"dirty": true
},
{
"name": "AccountTriggerHandler",
"type": "Apex Class",
"storedType": "ApexClass"
},
{
"name": "AccountTriggerTest",
"type": "Apex Class",
"storedType": "ApexClass"
},
{
"name": "QuoteSummary",
"type": "Page",
"storedType": "ApexPage"
}
];