@edux-design/comments
v0.1.4
Published
Structured comment block for discussion threads, with avatar, metadata, actions, and nested replies.
Readme
@edux-design/comments
Structured comment block for discussion threads, with avatar, metadata, actions, and nested replies.
Install
npm i @edux-design/comments @edux-design/avatarsUsage
import { Comment } from "@edux-design/comments";
import { CommentComposer } from "@edux-design/comments";
import { CommentMention } from "@edux-design/comments";
export function Example() {
const [resolved, setResolved] = React.useState(false);
return (
<Comment
author="Alex Johnson"
timestamp="2h ago"
body="Left a few notes on the introduction. Let me know if you want me to draft the edits."
avatarProps={{ name: "Alex Johnson" }}
resolved={resolved}
onResolve={() => setResolved((prev) => !prev)}
replies={
<Comment
author="Taylor"
timestamp="1h ago"
body="Happy to take the edits."
avatarProps={{ name: "Taylor" }}
variant="resolved"
/>
}
>
<Comment.Actions>
<Comment.Reply />
<Comment.Edit />
<Comment.Resolve />
</Comment.Actions>
</Comment>
);
}export function ComposerExample() {
const [value, setValue] = React.useState("");
const [query, setQuery] = React.useState("");
return (
<CommentComposer
value={value}
onChange={(event) => setValue(event.target.value)}
onSubmit={() => setValue("")}
onCancel={() => setValue("")}
avatarProps={{ name: "Alex Johnson" }}
>
<CommentMention
peopleList={[
{ id: "alex", name: "Alex Johnson", handle: "alex" },
{ id: "priya", name: "Priya Singh", handle: "priya" },
]}
onQueryChange={setQuery}
/>
<div className="mt-8 text-xs text-fg-subtle">
Mention query: <span className="font-semibold">{query || "—"}</span>
</div>
</CommentComposer>
);
}Mentions
CommentMention handles the in-editor mention menu and emits the active query via
onQueryChange when the user types @query at the cursor. Debounce behavior is
left to the consumer.
import { CommentComposer, CommentMention } from "@edux-design/comments";
<CommentComposer value={value} onChange={(event) => setValue(event.target.value)}>
<CommentMention peopleList={people} onQueryChange={setQuery} />
</CommentComposer>;Resolve / Re-open
Comment.Resolve swaps label and styling based on the resolved state. You can
override the label if needed.
<Comment resolved={isResolved} onResolve={toggleResolved}>
<Comment.Actions>
<Comment.Resolve />
<Comment.Resolve label="Re-open thread" />
</Comment.Actions>
</Comment>