Card refinements
This commit is contained in:
@@ -17,14 +17,16 @@
|
||||
|
||||
<!-- exceptions / list: one line per thing, each linking to itself -->
|
||||
<ul v-else class="dc-rows">
|
||||
<li v-for="(row, index) in visibleRows(card)" :key="index" class="dc-row">
|
||||
<li v-for="(row, index) in visibleRows(card)" :key="index" class="dc-row"
|
||||
:class="{ 'dc-row-stacked': card.layout === 'stacked' }">
|
||||
<router-link v-if="row.link" :to="row.link" class="dc-row-title"
|
||||
:title="row.titletip || undefined">
|
||||
{{ row.title }}
|
||||
</router-link>
|
||||
<span v-else class="dc-row-title dc-row-nolink"
|
||||
:title="row.titletip || undefined">{{ row.title }}</span>
|
||||
<span v-if="row.detail" class="dc-row-detail">{{ row.detail }}</span>
|
||||
<span v-if="row.detail" class="dc-row-detail"
|
||||
:title="row.detailtip || undefined">{{ row.detail }}</span>
|
||||
<span v-for="(chip, c) in row.chips" :key="c" class="dc-chip"
|
||||
:class="'dc-chip-' + (chip.level || 'low')" :title="chip.title">
|
||||
{{ chip.text }}
|
||||
@@ -173,6 +175,12 @@ defineExpose({ load })
|
||||
min-width: 0;
|
||||
}
|
||||
.dc-row:last-child { border-bottom: none; }
|
||||
/* Stacked: a label on one line, prose beneath. Inline, the label is truncated
|
||||
to make room for text that is then truncated anyway, and neither reads. */
|
||||
.dc-row-stacked { flex-direction: column; align-items: stretch; gap: 0.15rem; }
|
||||
.dc-row-stacked .dc-row-title { max-width: 100%; }
|
||||
.dc-row-stacked .dc-row-detail { white-space: normal; color: var(--text-light); }
|
||||
.dc-row-stacked .dc-row-meta { margin-left: 0; padding-left: 0; }
|
||||
.dc-row-title {
|
||||
font-weight: 600;
|
||||
color: var(--link);
|
||||
|
||||
@@ -43,6 +43,14 @@ export function mapDetail(card, item) {
|
||||
return key ? item[key] : ''
|
||||
}
|
||||
|
||||
// The untruncated text behind a shortened detail. Same rule as elsewhere: the
|
||||
// tooltip explains, it never carries the only copy of something essential.
|
||||
export function mapDetailTip(card, item) {
|
||||
const key = card.map && card.map.detailtooltip
|
||||
const full = key ? (item[key] || '') : ''
|
||||
return full && full !== mapDetail(card, item) ? full : ''
|
||||
}
|
||||
|
||||
export function mapMeta(card, item) {
|
||||
const meta = (card.map && card.map.meta) || []
|
||||
return meta
|
||||
@@ -115,6 +123,7 @@ export function cardRows(card) {
|
||||
title: mapTitle(card, item),
|
||||
titletip: mapTitleTip(card, item),
|
||||
detail: mapDetail(card, item),
|
||||
detailtip: mapDetailTip(card, item),
|
||||
meta: mapMeta(card, item),
|
||||
chips: mapChips(card, item),
|
||||
link: mapLink(card, item),
|
||||
|
||||
@@ -202,3 +202,27 @@ describe('chips and tooltips', () => {
|
||||
.toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('stacked rows', () => {
|
||||
const card = {
|
||||
render: 'list',
|
||||
layout: 'stacked',
|
||||
map: { title: 'typename', detail: 'message', detailtooltip: 'fullmessage' },
|
||||
_data: [{ typename: 'Recertification', message: 'Short text', fullmessage: 'Short text' }],
|
||||
}
|
||||
|
||||
it('offers no tooltip when the detail is already whole', () => {
|
||||
// A tooltip repeating what is on screen is noise, and it makes the cursor
|
||||
// change for no reason.
|
||||
expect(cardRows(card)[0].detailtip).toBe('')
|
||||
})
|
||||
|
||||
it('offers the full text when the detail was trimmed', () => {
|
||||
const trimmed = { ...card, _data: [{
|
||||
typename: 'General', message: 'Start of a long message...',
|
||||
fullmessage: 'Start of a long message that continues well past the card',
|
||||
}] }
|
||||
expect(cardRows(trimmed)[0].detailtip)
|
||||
.toBe('Start of a long message that continues well past the card')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user