mirror of
https://github.com/hoornet/vega.git
synced 2026-06-14 08:43:34 -07:00
Polish pass 2 — avatar hover, reply buttons, ellipses, a11y
- Unify NoteCard avatar hover between image and fallback variants - Add aria-labels to compose toolbar buttons (emoji, attach, poll) - Fix ThreadView inline reply button sizing to match compose post button - Replace remaining '...' with unicode ellipsis across podcasts, v4v, thread, and ancestor chain components
This commit is contained in:
@@ -306,6 +306,7 @@ export function ComposeBox({ onPublished, onNoteInjected }: { onPublished?: () =
|
||||
<button
|
||||
onClick={() => setShowEmoji((v) => !v)}
|
||||
title="Insert emoji"
|
||||
aria-label="Insert emoji"
|
||||
className="text-text-dim hover:text-text text-[16px] transition-colors"
|
||||
>
|
||||
☺
|
||||
@@ -321,6 +322,7 @@ export function ComposeBox({ onPublished, onNoteInjected }: { onPublished?: () =
|
||||
onClick={handleFilePicker}
|
||||
disabled={uploading || isPoll}
|
||||
title="Attach image or video"
|
||||
aria-label="Attach image or video"
|
||||
className="text-text-dim hover:text-text text-[16px] transition-colors disabled:opacity-30"
|
||||
>
|
||||
+
|
||||
@@ -328,6 +330,7 @@ export function ComposeBox({ onPublished, onNoteInjected }: { onPublished?: () =
|
||||
<button
|
||||
onClick={() => setIsPoll((v) => !v)}
|
||||
title={isPoll ? "Cancel poll" : "Create poll"}
|
||||
aria-label={isPoll ? "Cancel poll" : "Create poll"}
|
||||
className={`text-[16px] transition-colors ${isPoll ? "text-accent" : "text-text-dim hover:text-text"}`}
|
||||
>
|
||||
▢▢
|
||||
|
||||
@@ -81,7 +81,7 @@ export const NoteCard = memo(function NoteCard({ event, focused, onReplyInThread
|
||||
<img
|
||||
src={avatar}
|
||||
alt={`${name}'s avatar`}
|
||||
className="w-9 h-9 rounded-sm object-cover bg-bg-raised hover:opacity-80 transition-opacity"
|
||||
className="w-9 h-9 rounded-sm object-cover bg-bg-raised ring-1 ring-transparent hover:ring-accent/40 transition-all"
|
||||
loading="lazy"
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).style.display = "none";
|
||||
|
||||
@@ -66,7 +66,7 @@ export function PodcastsView() {
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
onKeyDown={(e) => e.key === "Enter" && handleSearch()}
|
||||
placeholder="Search podcasts..."
|
||||
placeholder="Search podcasts…"
|
||||
className="flex-1 bg-bg-raised border border-border rounded-sm px-3 py-1.5 text-[12px] text-text placeholder:text-text-dim focus:outline-none focus:border-accent"
|
||||
/>
|
||||
<button
|
||||
|
||||
@@ -219,7 +219,7 @@ export function V4VIndicator() {
|
||||
disabled={boosting}
|
||||
className="text-[10px] text-accent hover:text-accent-hover px-2 py-0.5 bg-accent/10 rounded-sm disabled:opacity-40"
|
||||
>
|
||||
{boosting ? "..." : "boost"}
|
||||
{boosting ? "…" : "boost"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ export const PollWidget = memo(function PollWidget({ event }: { event: NDKEvent
|
||||
{pollData ? (
|
||||
<span>{total} {total === 1 ? "vote" : "votes"}</span>
|
||||
) : (
|
||||
<span className="animate-pulse">loading votes...</span>
|
||||
<span className="animate-pulse">loading votes…</span>
|
||||
)}
|
||||
{isExpired && <span>· Poll ended</span>}
|
||||
{closedAt && !isExpired && (
|
||||
|
||||
@@ -11,7 +11,7 @@ function AncestorCard({ event }: { event: NDKEvent }) {
|
||||
const { openThread } = useUIStore();
|
||||
|
||||
const truncated = event.content.length > 120
|
||||
? event.content.slice(0, 120) + "..."
|
||||
? event.content.slice(0, 120) + "…"
|
||||
: event.content;
|
||||
|
||||
return (
|
||||
|
||||
@@ -64,7 +64,7 @@ function InlineThreadReply({ replyTo, rootEvent, onPublished }: {
|
||||
value={text}
|
||||
onChange={(e) => { setText(e.target.value); autoResize(e); }}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Write a reply..."
|
||||
placeholder="Write a reply…"
|
||||
rows={2}
|
||||
className="w-full bg-transparent text-text text-[12px] placeholder:text-text-dim resize-none focus:outline-none"
|
||||
autoFocus
|
||||
|
||||
@@ -213,7 +213,7 @@ export function ThreadView() {
|
||||
value={replyText}
|
||||
onChange={(e) => { setReplyText(e.target.value); autoResize(e); }}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Write a reply..."
|
||||
placeholder="Write a reply…"
|
||||
rows={2}
|
||||
className="w-full bg-transparent text-text text-[12px] placeholder:text-text-dim resize-none focus:outline-none leading-relaxed"
|
||||
autoFocus
|
||||
@@ -248,9 +248,9 @@ export function ThreadView() {
|
||||
<button
|
||||
onClick={handleRootReply}
|
||||
disabled={!replyText.trim() || replying}
|
||||
className="px-2 py-0.5 text-[10px] bg-accent hover:bg-accent-hover text-accent-text transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
className="px-3 py-1 text-[11px] bg-accent hover:bg-accent-hover text-accent-text rounded-sm transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
|
||||
>
|
||||
{replySent ? "replied ✓" : replying ? "posting..." : "reply"}
|
||||
{replySent ? "replied ✓" : replying ? "posting…" : "reply"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ function HistoryRow({ entry }: { entry: V4VHistoryEntry }) {
|
||||
<div className="text-[9px] text-text-dim mb-1">Recipients:</div>
|
||||
{entry.recipients.map((r, i) => (
|
||||
<div key={i} className="flex items-center justify-between text-[10px]">
|
||||
<span className="text-text-muted truncate">{r.name || r.address.slice(0, 16) + "..."}</span>
|
||||
<span className="text-text-muted truncate">{r.name || r.address.slice(0, 16) + "…"}</span>
|
||||
<span className="text-text-dim shrink-0 ml-2">{r.sats} sats</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user