11<script setup lang="ts">
22import type { ResolvedAuthor } from ' #shared/schemas/blog'
33
4- const props = withDefaults (
5- defineProps <{
6- title: string
7- authors? : ResolvedAuthor []
8- date? : string
9- primaryColor? : string
10- }>(),
11- {
12- authors : () => [],
13- date: ' ' ,
14- primaryColor: ' #60a5fa' ,
15- },
16- )
4+ const {
5+ title,
6+ authors = [],
7+ date = ' ' ,
8+ } = defineProps <{
9+ title: string
10+ authors? : ResolvedAuthor []
11+ date? : string
12+ }>()
1713
1814const formattedDate = computed (() => {
19- if (! props . date ) return ' '
15+ if (! date ) return ' '
2016 try {
21- return new Date (props . date ).toLocaleDateString (' en-US' , {
17+ return new Date (date ).toLocaleDateString (' en-US' , {
2218 year: ' numeric' ,
2319 month: ' short' ,
2420 day: ' numeric' ,
2521 })
2622 } catch {
27- return props . date
23+ return date
2824 }
2925})
3026
@@ -39,71 +35,54 @@ const getInitials = (name: string) =>
3935 .slice (0 , 2 )
4036
4137const visibleAuthors = computed (() => {
42- if (props . authors .length <= 3 ) return props . authors
43- return props . authors .slice (0 , MAX_VISIBLE_AUTHORS )
38+ if (authors .length <= 3 ) return authors
39+ return authors .slice (0 , MAX_VISIBLE_AUTHORS )
4440})
4541
4642const extraCount = computed (() => {
47- if (props . authors .length <= 3 ) return 0
48- return props . authors .length - MAX_VISIBLE_AUTHORS
43+ if (authors .length <= 3 ) return 0
44+ return authors .length - MAX_VISIBLE_AUTHORS
4945})
5046
5147const formattedAuthorNames = computed (() => {
52- const allNames = props . authors .map (a => a .name )
48+ const allNames = authors .map (a => a .name )
5349 if (allNames .length === 0 ) return ' '
5450 if (allNames .length === 1 ) return allNames [0 ]
5551 if (allNames .length === 2 ) return ` ${allNames [0 ]} and ${allNames [1 ]} `
5652 if (allNames .length === 3 ) return ` ${allNames [0 ]}, ${allNames [1 ]}, and ${allNames [2 ]} `
57- // More than 3: show first 2 + others
5853 const shown = allNames .slice (0 , MAX_VISIBLE_AUTHORS )
5954 const remaining = allNames .length - MAX_VISIBLE_AUTHORS
6055 return ` ${shown .join (' , ' )} and ${remaining } others `
6156})
6257 </script >
6358
6459<template >
65- <div
66- class =" h-full w-full flex flex-col justify-center px-20 bg-[#050505] text-[#fafafa] relative overflow-hidden"
67- >
68- <!-- npmx logo - top right -->
69- <div
70- class =" absolute top-12 z-10 flex items-center gap-1 text-5xl font-bold tracking-tight"
71- style =" font-family : ' Geist' , sans-serif ; right : 6rem "
72- >
73- <span :style =" { color: primaryColor }" class =" opacity-80" >./</span >
74- <span class =" text-white" >npmx</span >
75- </div >
60+ <OgLayout >
61+ <div class =" px-15 py-12 flex flex-col justify-center gap-5 h-full" >
62+ <OgBrand :height =" 48" />
7663
77- <div class =" relative z-10 flex flex-col gap-2" >
78- <!-- Date -->
79- <span
80- v-if =" formattedDate"
81- class =" text-3xl text-[#a3a3a3] font-light"
82- style =" font-family : ' Geist' , sans-serif "
83- >
84- {{ formattedDate }}
85- </span >
64+ <!-- Date + Title -->
65+ <div class =" flex flex-col gap-2" >
66+ <span v-if =" formattedDate" class =" text-3xl text-fg-muted" >
67+ {{ formattedDate }}
68+ </span >
8669
87- <!-- Blog title -->
88- < h1
89- class = " text-6xl font-semibold tracking-tight leading-snug w-9/10 "
90- style = " font-family : ' Geist ' , sans-serif ; letter-spacing : -0.03 em "
91- >
92- {{ title }}
93- </h1 >
70+ < div
71+ class = " lg:text-6xl text-5xl tracking-tighter font-mono leading-tight "
72+ :style = " { lineClamp: 2, textOverflow: 'ellipsis' } "
73+ >
74+ {{ title }}
75+ </ div >
76+ </div >
9477
9578 <!-- Authors -->
96- <div
97- v-if =" authors.length"
98- class =" flex items-center gap-4 self-start justify-start flex-nowrap"
99- style =" font-family : ' Geist' , sans-serif "
100- >
79+ <div v-if =" authors.length" class =" flex items-center gap-4 flex-nowrap" >
10180 <!-- Stacked avatars -->
10281 <span >
10382 <span
10483 v-for =" (author, index) in visibleAuthors"
10584 :key =" author.name"
106- class =" flex items-center justify-center rounded-full border border-[#050505] bg-[#1a1a1a] overflow-hidden w-12 h-12"
85+ class =" flex items-center justify-center rounded-full border border-bg bg-bg-muted overflow-hidden w-12 h-12"
10786 :style =" { marginLeft: index > 0 ? '-20px' : '0' }"
10887 >
10988 <img
@@ -114,29 +93,22 @@ const formattedAuthorNames = computed(() => {
11493 height =" 48"
11594 class =" w-full h-full object-cover"
11695 />
117- <span v-else style = " font-size : 20 px ; color : #666 ; font-weight : 500 " >
96+ <span v-else class = " text-5 text-fg-muted font-medium " >
11897 {{ getInitials(author.name) }}
11998 </span >
12099 </span >
121100 <!-- +N badge -->
122101 <span
123102 v-if =" extraCount > 0"
124- class =" flex items-center justify-center text-lg font-medium text-[#a3a3a3] rounded-full border border-[#050505] bg-[#262626] overflow-hidden w-12 h-12"
103+ class =" flex items-center justify-center text-lg font-medium text-fg-muted rounded-full border border-bg bg-bg-muted overflow-hidden w-12 h-12"
125104 :style =" { marginLeft: '-20px' }"
126105 >
127106 +{{ extraCount }}
128107 </span >
129108 </span >
130109 <!-- Names -->
131- <span style =" font-size : 24px ; color : #a3a3a3 ; font-weight : 300 " >{{
132- formattedAuthorNames
133- }}</span >
110+ <span class =" text-6 text-fg-muted font-light" >{{ formattedAuthorNames }}</span >
134111 </div >
135112 </div >
136-
137- <div
138- class =" absolute -top-32 -inset-ie-32 w-[550px] h-[550px] rounded-full blur-3xl"
139- :style =" { backgroundColor: primaryColor + '10' }"
140- />
141- </div >
113+ </OgLayout >
142114</template >
0 commit comments