this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 111 lines 3.3 kB view raw
1import type { ProfileUpdateRow } from "../../lib/profile-updates.ts"; 2import ProfileVersionHistoryModal from "../../islands/ProfileVersionHistoryModal.tsx"; 3import TangledIcon from "../icons/TangledIcon.tsx"; 4 5interface Props { 6 updates: ProfileUpdateRow[]; 7 copy: { 8 heading: string; 9 empty: string; 10 versionHistory: string; 11 viewCommit: string; 12 readFullUpdate: string; 13 }; 14} 15 16const BODY_PREVIEW_LENGTH = 240; 17 18function dateLabel(ms: number): string { 19 return new Intl.DateTimeFormat("en", { 20 month: "short", 21 day: "numeric", 22 year: "numeric", 23 }).format(new Date(ms)); 24} 25 26function UpdateMeta({ update }: { update: ProfileUpdateRow }) { 27 return ( 28 <div class="profile-whats-new-meta"> 29 {update.version && <span>{update.version}</span>} 30 <time dateTime={new Date(update.createdAt).toISOString()}> 31 {dateLabel(update.createdAt)} 32 </time> 33 </div> 34 ); 35} 36 37function isLongBody(body: string): boolean { 38 return body.length > BODY_PREVIEW_LENGTH || body.split("\n").length > 3; 39} 40 41function previewBody(body: string): string { 42 if (!isLongBody(body)) return body; 43 return `${body.slice(0, BODY_PREVIEW_LENGTH).trimEnd()}...`; 44} 45 46function CommitLink( 47 { href, label }: { href: string; label: string }, 48) { 49 return ( 50 <a 51 href={href} 52 target="_blank" 53 rel="noopener noreferrer" 54 class="profile-whats-new-icon-button" 55 aria-label={label} 56 title={label} 57 > 58 <TangledIcon class="profile-whats-new-icon" /> 59 <span class="profile-whats-new-icon-arrow" aria-hidden="true"></span> 60 </a> 61 ); 62} 63 64export default function ProfileWhatsNew({ updates, copy }: Props) { 65 const [latest, ...history] = updates; 66 if (!latest) { 67 return ( 68 <section class="profile-whats-new glass"> 69 <h2 class="profile-card-section-title">{copy.heading}</h2> 70 <p class="profile-whats-new-empty">{copy.empty}</p> 71 </section> 72 ); 73 } 74 75 return ( 76 <section class="profile-whats-new glass"> 77 <div class="profile-whats-new-main"> 78 <div class="profile-whats-new-copy"> 79 <div class="profile-whats-new-heading-row"> 80 <h2 class="profile-card-section-title">{copy.heading}</h2> 81 <ProfileVersionHistoryModal 82 updates={history} 83 copy={{ 84 versionHistory: copy.versionHistory, 85 viewCommit: copy.viewCommit, 86 }} 87 /> 88 </div> 89 <UpdateMeta update={latest} /> 90 <h3 class="profile-whats-new-title">{latest.title}</h3> 91 {isLongBody(latest.body) 92 ? ( 93 <div class="profile-whats-new-expand"> 94 <p class="profile-whats-new-preview"> 95 {previewBody(latest.body)} 96 </p> 97 <details class="profile-whats-new-details"> 98 <summary>{copy.readFullUpdate}</summary> 99 <p class="profile-whats-new-full">{latest.body}</p> 100 </details> 101 </div> 102 ) 103 : <p class="profile-whats-new-body">{latest.body}</p>} 104 </div> 105 {latest.tangledCommitUrl && ( 106 <CommitLink href={latest.tangledCommitUrl} label={copy.viewCommit} /> 107 )} 108 </div> 109 </section> 110 ); 111}