Description list
Labels and their values, in rows or stacked in columns, for the details of an order, a customer or any record.
Install
If this is the first component in the project, set up once. This writes ermine.json and copies the theme stylesheet. The installation guide covers Vue, Nuxt and Astro.
npx ermineui initpnpm dlx ermineui inityarn dlx ermineui initbunx ermineui initThen add the component:
npx ermineui add description-listpnpm dlx ermineui add description-listyarn dlx ermineui add description-listbunx ermineui add description-listThat copies 3 files into src/components/ui/description-list/. Files you already have are kept.
Use
import { DescriptionList, DescriptionItem } from '@/components/ui/description-list'<script setup lang="ts">
import { DescriptionList } from '@/components/ui/description-list'
</script>
<template>
<DescriptionList />
</template>In Nuxt, with the auto-import setting, the tags work in templates without the import. In Astro, use it inside a Vue island. The props are documented in the source below, on each one.
What gets copied
| File | Where it goes |
|---|---|
DescriptionItem.vue | src/components/ui/description-list/DescriptionItem.vue |
DescriptionList.vue | src/components/ui/description-list/DescriptionList.vue |
index.ts | src/components/ui/description-list/index.ts |
The folders are the suggested ones. ermine.json says where yours are.
Source
This is exactly what the command copies. To install by hand, create each file below and the helpers listed above.
DescriptionItem.vue 14 lines
<script setup lang="ts">
defineProps<{
/** What the value is. */
label: string
}>()
</script>
<template>
<div class="er-description-item">
<dt>{{ label }}</dt>
<dd><slot /></dd>
</div>
</template>DescriptionList.vue 91 lines
<script setup lang="ts">
withDefaults(
defineProps<{
/** "rows" puts each label beside its value with a line between rows; "stacked" puts the label above the value. */
layout?: 'rows' | 'stacked'
/** With "stacked": how many items sit side by side when there is room. */
columns?: number
}>(),
{ layout: 'rows', columns: 1 },
)
</script>
<template>
<dl class="er-description-list" :data-layout="layout" :style="{ '--er-description-columns': columns }">
<slot />
</dl>
</template>
<style>
@layer components {
.er-description-list {
display: grid;
width: 100%;
min-width: 0;
margin: 0;
font-size: 0.875rem;
line-height: 1.25rem;
}
.er-description-item {
min-width: 0;
}
.er-description-item dt {
color: var(--er-muted-foreground);
}
.er-description-item dd {
min-width: 0;
margin: 0;
overflow-wrap: anywhere;
}
/* Rows: labels in one column, values in the next. On a narrow list each label moves above its value. */
.er-description-list[data-layout='rows'] {
container-type: inline-size;
}
.er-description-list[data-layout='rows'] .er-description-item {
display: grid;
gap: 0.125rem 1rem;
padding-block: 0.625rem;
border-bottom: 1px solid var(--er-border);
}
.er-description-list[data-layout='rows'] .er-description-item:first-child {
padding-top: 0;
}
.er-description-list[data-layout='rows'] .er-description-item:last-child {
padding-bottom: 0;
border-bottom: 0;
}
@container (min-width: 24rem) {
.er-description-list[data-layout='rows'] .er-description-item {
grid-template-columns: minmax(8rem, 1fr) 2fr;
}
}
.er-description-list[data-layout='stacked'] {
grid-template-columns: repeat(auto-fit, minmax(min(100%, max(9rem, calc((100% - (var(--er-description-columns) - 1) * 1.5rem) / var(--er-description-columns)))), 1fr));
gap: 1rem 1.5rem;
}
.er-description-list[data-layout='stacked'] .er-description-item {
display: grid;
align-content: start;
gap: 0.125rem;
}
.er-description-list[data-layout='stacked'] dt {
font-size: 0.8125rem;
}
.er-description-list[data-layout='stacked'] dd {
font-weight: var(--er-weight-medium);
}
}
</style>index.ts 4 lines
/** Description list — labels and their values, in rows or stacked in columns, for the details of an order, a customer or any record. */
export { default as DescriptionList } from './DescriptionList.vue'
export { default as DescriptionItem } from './DescriptionItem.vue'