defuss-shadcn / Website / Comments / comment-item
Comment ItemBLK
Displays one comment with its author, timestamp, and reply action - nested replies on a thread line, permalinks that highlight, compact and deleted states. Part of the Comments blocks.
On this page (7)
§Thread
A comment with two replies on a thread line. The timestamp is a permalink to the comment's own id; the author's reply carries a Badge.
§Highlighted
The comment a permalink opened lights up via :target - or mark it with data-highlighted (here). The flash is off under reduced motion.
§Compact and deleted
data-variant='compact' tightens a thread (small avatar, 14px); data-variant='deleted' keeps the place of a removed comment.
A pinned comment (a Badge) with reaction chips - toggle buttons with aria-pressed, click one (the page script counts) - and a ⋯ Dropdown Menu at the end of the head.
§Q&A: votes and the accepted answer
data-variant='voted' puts a score column before the avatar; data-variant='accepted' marks the answer - with a Code Mockup in the comment text.
§Collapsed replies
Replies inside a native <details class="mk-comment-item-thread"> - "Show 2 replies" opens them, no script.
§CSS view file
/* -- Comment Item (website) ----------------------------------------- One comment: avatar, author (+ a role Badge), the timestamp (a permalink to the comment's own id), the text and its actions (reply, like) - and its replies, nested on a thread line. A comment reached by its permalink (:target) or marked data-highlighted lights up. */@layer components { .mk-comment-item { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 0.75rem; padding-block: 0.875rem; scroll-margin-block-start: 5rem; & > .avatar { grid-row: span 2; } } .mk-comment-item-main { display: flex; flex-direction: column; gap: 0.375rem; min-width: 0; } .mk-comment-item-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; font-size: 0.875rem; } .mk-comment-item-author { color: var(--foreground); font-weight: 600; text-decoration: none; &:is(a):hover { text-decoration: underline; text-underline-offset: 0.2em; } &:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: var(--radius-sm); } } .mk-comment-item-time { color: var(--muted-foreground); font-size: 0.8125rem; text-decoration: none; &:hover { text-decoration: underline; text-underline-offset: 0.2em; } &:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: var(--radius-sm); } } .mk-comment-item-body { font-size: 0.9375rem; line-height: 1.6; overflow-wrap: anywhere; & > * { margin: 0; } & > * + * { margin-block-start: 0.5em; } & a { color: var(--primary); text-underline-offset: 0.2em; } & blockquote { padding-inline-start: 0.75em; border-inline-start: 2px solid var(--border); color: var(--muted-foreground); } } .mk-comment-item-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.125rem; margin-inline-start: -0.5rem; color: var(--muted-foreground); } /* replies: nested comments on a thread line */ .mk-comment-item-replies { grid-column: 2; margin: 0.25rem 0 0; padding: 0 0 0 1rem; border-inline-start: 2px solid var(--border); list-style: none; & > li > .mk-comment-item:last-child { padding-block-end: 0; } } /* reached by its permalink, or marked */ .mk-comment-item:target, .mk-comment-item[data-highlighted] { margin-inline: -0.75rem; padding-inline: 0.75rem; border-radius: var(--radius-lg); background: color-mix(in oklch, var(--primary) 8%, transparent); animation: mk-comment-item-flash 1.6s ease-out; } /* compact: a tighter thread */ .mk-comment-item[data-variant="compact"] { padding-block: 0.5rem; & .mk-comment-item-body { font-size: 0.875rem; } & .mk-comment-item-head { font-size: 0.8125rem; } } /* deleted: the text is gone, the thread stays */ .mk-comment-item[data-variant="deleted"] .mk-comment-item-body { color: var(--muted-foreground); font-style: italic; } /* the ⋯ menu (a Dropdown trigger) at the end of the head */ .mk-comment-item-menu { margin-inline-start: auto; } /* reactions: emoji chips - toggle buttons (aria-pressed), an add button */ .mk-comment-item-reactions { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-block-start: 0.125rem; & button { display: inline-flex; align-items: center; gap: 0.25rem; height: 1.625rem; padding: 0 0.5rem; border: 1px solid var(--border); border-radius: 999px; background: transparent; color: var(--muted-foreground); font: inherit; font-size: 0.75rem; font-variant-numeric: tabular-nums; cursor: pointer; transition: background-color 120ms, border-color 120ms, color 120ms; &:hover { background: var(--accent); color: var(--accent-foreground); } &[aria-pressed="true"] { border-color: color-mix(in oklch, var(--primary) 45%, transparent); background: color-mix(in oklch, var(--primary) 10%, transparent); color: var(--foreground); } &:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; } & svg { width: 0.875rem; height: 0.875rem; } } } /* voted: a score column (up / count / down) instead of the avatar column */ .mk-comment-item-votes { display: flex; flex-direction: column; align-items: center; gap: 0.125rem; grid-row: span 2; color: var(--muted-foreground); font-size: 0.8125rem; font-weight: 700; font-variant-numeric: tabular-nums; & output { color: var(--foreground); } & button[aria-pressed="true"] { color: var(--primary); } } .mk-comment-item[data-variant="voted"] { grid-template-columns: auto auto minmax(0, 1fr); & > .avatar { grid-row: auto; align-self: start; } & > .mk-comment-item-replies { grid-column: 3; } } /* accepted: the answer - a green rail and a check badge */ .mk-comment-item[data-variant="accepted"] { padding-inline: 0.875rem; margin-inline: -0.875rem; border-inline-start: 3px solid oklch(0.62 0.15 150); border-radius: var(--radius-md); background: color-mix(in oklch, oklch(0.62 0.15 150) 7%, transparent); } /* collapsible replies: a native <details> - "Show 3 replies" */ .mk-comment-item-thread { grid-column: 2; & > summary { display: inline-flex; align-items: center; gap: 0.375rem; margin-block-start: 0.375rem; padding: 0.25rem 0.5rem; margin-inline-start: -0.5rem; border-radius: var(--radius-sm); color: var(--primary); font-size: 0.8125rem; font-weight: 600; cursor: pointer; list-style: none; &::-webkit-details-marker { display: none; } &::before { content: ""; width: 0.375rem; height: 0.375rem; border-inline-end: 1.5px solid currentColor; border-block-end: 1.5px solid currentColor; rotate: -45deg; transition: rotate 150ms; } &:hover { background: var(--accent); } &:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; } } &[open] > summary::before { rotate: 45deg; } & > .mk-comment-item-replies { grid-column: auto; } } @keyframes mk-comment-item-flash { from { background: color-mix(in oklch, var(--primary) 22%, transparent); } } /* -- Accessibility ------------------------------------------- */ @media (prefers-reduced-motion: reduce) { .mk-comment-item:target, .mk-comment-item[data-highlighted] { animation: none; } .mk-comment-item-reactions button, .mk-comment-item-thread > summary::before { transition: none; } } @media (prefers-contrast: more) { .mk-comment-item-time, .mk-comment-item-actions { color: var(--foreground); } .mk-comment-item-replies { border-inline-start-color: var(--foreground); } } @media (forced-colors: active) { .mk-comment-item:target, .mk-comment-item[data-highlighted] { outline: 2px solid Highlight; } }}Comments, ideas or improvements? Edit this page's source on GitHub