Files
dredgenews/resources/js/components/ArticleCard.vue
T
dredgy 439139a057
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Done
2026-07-04 23:09:00 +10:00

176 lines
3.6 KiB
Vue

<script setup lang="ts">
interface Story {
source: string;
time: string | null;
headline: string;
deck?: string | null;
image?: string | null;
link: string;
}
withDefaults(
defineProps<{
story: Story;
variant?: 'hero' | 'banner' | 'feature' | 'standard' | 'brief';
}>(),
{
variant: 'standard',
},
);
</script>
<template>
<a
:href="story.link"
target="_blank"
rel="noopener noreferrer"
class="card"
:class="[
`card--${variant}`,
{ 'card--no-image': variant !== 'brief' && !story.image },
]"
>
<div v-if="variant !== 'brief' && story.image" class="card-img">
<img :src="story.image" :alt="story.headline" loading="lazy" />
</div>
<div class="card-body">
<div class="card-source">{{ story.source }}</div>
<div class="card-headline">{{ story.headline }}</div>
<div v-if="variant === 'hero' && story.deck" class="card-deck">
{{ story.deck }}
</div>
<div v-if="story.time" class="card-time">{{ story.time }}</div>
</div>
</a>
</template>
<style scoped lang="sass">
.card
display: flex
flex-direction: column
text-decoration: none
background: #F7F7F5
&:hover
background: #fff
.card-img
width: 100%
background: #DDDDD8
overflow: hidden
flex-shrink: 0
img
width: 100%
height: 100%
object-fit: cover
display: block
.card-body
padding: 0.85rem
display: flex
flex-direction: column
gap: 5px
flex: 1
.card-source
font-size: 10px
font-weight: 600
letter-spacing: 1px
text-transform: uppercase
color: #C0392B
.card-headline
font-family: Georgia, serif
color: #111
line-height: 1.3
.card-deck
font-size: 13px
color: #555
line-height: 1.55
.card-time
font-size: 10px
color: #999
margin-top: auto
padding-top: 4px
// Hero: the big lead story
.card--hero
.card-img
height: 400px
.card-headline
font-size: 26px
font-weight: 700
// Banner: full-width lead when the section has no true hero,
// needs a taller image than feature since it's stretched much wider
.card--banner
.card-img
height: 540px
.card-headline
font-size: 20px
font-weight: 700
// Feature: supporting stories with a medium image
.card--feature
.card-img
height: 260px
.card-headline
font-size: 17px
font-weight: 700
// Standard: small image, compact headline
.card--standard
.card-img
height: 150px
.card-headline
font-size: 13px
font-weight: 700
// No image available: give the text more breathing room instead of
// leaving an empty gray box where a photo would have been
.card--no-image
.card-body
padding: 1rem 0.85rem
justify-content: center
// Brief: text only, single row, no image at all
.card--brief
flex-direction: row
align-items: baseline
justify-content: space-between
gap: 12px
background: transparent
padding: 0.55rem 0
border-bottom: 1px solid #E8E8E8
&:hover
background: transparent
.card-headline
text-decoration: underline
.card-body
padding: 0
flex-direction: row
align-items: baseline
gap: 8px
flex: 1
.card-source
display: none
.card-headline
font-size: 13px
font-weight: 400
flex: 1
.card-time
font-size: 10px
color: #999
padding-top: 0
white-space: nowrap
</style>