Comment

Comments display authored messages in threaded contexts such as support tickets, discussions, and activity feeds. The component is composable with Header and Body subcomponents, integrating the Avatar component for author display.


Installation

npm install @libretexts/davis-react

Basic Usage

import { Comment } from '@libretexts/davis-react';

export default function Example() {
  return (
    <Comment>
      <Comment.Header
        avatar={{ name: 'Jane Doe' }}
        name="Jane Doe"
      >
        <time>2 hours ago</time>
      </Comment.Header>
      <Comment.Body>
        <p>Thanks for reaching out! I've looked into this and it appears to be
        related to your account settings.</p>
      </Comment.Body>
    </Comment>
  );
}

Variants

The Comment component supports two visual variants.

{/* Default — neutral styling for standard messages */}
<Comment variant="default">
  <Comment.Header avatar={{ name: 'User' }} name="User">
    <time>Just now</time>
  </Comment.Header>
  <Comment.Body>
    <p>A standard comment.</p>
  </Comment.Body>
</Comment>

{/* Highlighted — accented left border for pinned or important messages */}
<Comment variant="highlighted">
  <Comment.Header avatar={{ name: 'Admin' }} name="Admin">
    <time>1 hour ago</time>
  </Comment.Header>
  <Comment.Body>
    <p>This message has been pinned by a moderator.</p>
  </Comment.Body>
</Comment>

Padding

Control the internal padding of the comment.

<Comment padding="none">
  <Comment.Header avatar={{ name: 'User' }} name="User" />
  <Comment.Body><p>No padding</p></Comment.Body>
</Comment>

<Comment padding="sm">
  <Comment.Header avatar={{ name: 'User' }} name="User" />
  <Comment.Body><p>Small padding</p></Comment.Body>
</Comment>

<Comment padding="md">
  <Comment.Header avatar={{ name: 'User' }} name="User" />
  <Comment.Body><p>Medium padding (default)</p></Comment.Body>
</Comment>

<Comment padding="lg">
  <Comment.Header avatar={{ name: 'User' }} name="User" />
  <Comment.Body><p>Large padding</p></Comment.Body>
</Comment>

With Rich Metadata

The Comment.Header children slot accepts any content for metadata — timestamps, badges, status indicators, and more.

import { Comment, Badge } from '@libretexts/davis-react';

export default function Example() {
  return (
    <Comment>
      <Comment.Header
        avatar={{ name: 'Sarah Chen', src: '/avatars/sarah.jpg' }}
        name="Sarah Chen"
      >
        <Badge variant="success" label="Resolved" size="sm" />
        <span>&middot;</span>
        <time>May 10, 2026</time>
        <span>&middot;</span>
        <span>Edited</span>
      </Comment.Header>
      <Comment.Body>
        <p>The configuration has been updated and the issue should be
        resolved now.</p>
      </Comment.Body>
    </Comment>
  );
}

With Rich Content

The Comment.Body accepts any children, allowing formatted text, code blocks, images, and other components.

<Comment>
  <Comment.Header avatar={{ name: 'Dev Support' }} name="Dev Support">
    <time>3 hours ago</time>
  </Comment.Header>
  <Comment.Body>
    <p className="mb-2">I found the issue. Update your configuration:</p>
    <pre className="bg-gray-100 rounded-md p-3 text-xs mb-2">
      <code>{`{ "apiVersion": "v2", "timeout": 30000 }`}</code>
    </pre>
    <p>Restart the service after making this change.</p>
  </Comment.Body>
</Comment>

Thread

Stack multiple comments to create a conversation thread. Use a divider between comments for visual separation.

import { Comment, Badge } from '@libretexts/davis-react';

export default function TicketThread() {
  return (
    <div className="flex flex-col divide-y divide-gray-200">
      <Comment>
        <Comment.Header
          avatar={{ name: 'Alex Johnson', src: '/avatars/alex.jpg' }}
          name="Alex Johnson"
        >
          <time>Yesterday at 2:30 PM</time>
        </Comment.Header>
        <Comment.Body>
          <p>I'm having trouble logging in. I keep getting a "session expired"
          error even after resetting my password.</p>
        </Comment.Body>
      </Comment>

      <Comment>
        <Comment.Header avatar={{ name: 'Support Team' }} name="Support Team">
          <Badge variant="primary" label="Staff" size="sm" />
          <time>Yesterday at 3:15 PM</time>
        </Comment.Header>
        <Comment.Body>
          <p>Hi Alex, could you try clearing your browser cache and cookies,
          then attempt to log in again?</p>
        </Comment.Body>
      </Comment>

      <Comment>
        <Comment.Header
          avatar={{ name: 'Alex Johnson', src: '/avatars/alex.jpg' }}
          name="Alex Johnson"
        >
          <time>Today at 9:00 AM</time>
        </Comment.Header>
        <Comment.Body>
          <p>That worked! Thank you for the quick help!</p>
        </Comment.Body>
      </Comment>
    </div>
  );
}

Props

Comment

PropTypeDefaultDescription
variant'default' | 'highlighted''default'Visual style variant
padding'none' | 'sm' | 'md' | 'lg''md'Internal padding
classNamestring-Additional CSS classes
childrenReactNode-Comment subcomponents

Comment.Header / CommentHeader

PropTypeDefaultDescription
avatarAvatarProps-Props forwarded to the Avatar component (name, src, initials, etc.)
namestring-Author display name
classNamestring-Additional CSS classes
childrenReactNode-Metadata content (timestamps, badges, etc.)

Comment.Body / CommentBody

PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReactNode-Comment content

Accessibility

The Comment component is built with accessibility in mind:

  • Uses <article> as the root element for proper semantic structure
  • Author names are rendered as visible text, readable by screen readers
  • The Avatar component provides accessible initials or alt text for images
  • Content and metadata areas accept arbitrary children, allowing semantic HTML (e.g., <time> elements)

Best practices:

  • Use <time> elements with datetime attributes for timestamps
  • Ensure adequate color contrast when adding custom metadata content
  • When building a thread, use a container with an appropriate ARIA role or landmark