Discussion
Threaded discussion / commenting component. Two-level threading (top-level posts and replies), four sort modes, cursor-based pagination, reactions, post reporting, and authentication-aware UI.
Import
import { Discussion } from "fansunited-frontend-components";
import { DiscussionProps, DiscussionSortType } from "fansunited-frontend-core";Required props
| Prop | Type | Description |
|---|---|---|
entityId | string | Unique discussion identifier (e.g. article ID, match ID). |
sdk | FansUnitedSDKModel | SDK instance. |
language | LanguageType | Display language. |
Discussiondoes not take atemplateprop — its layout is always a single threaded list that adapts to the container width.
Optional props
| Prop | Type | Default | Description |
|---|---|---|---|
themeOptions | CustomThemeOptions | — | See Theming. |
discussionLabel | string | — | Title used when the discussion is created for the first time. |
discussionUrl | string | — | URL associated with the discussion content (used in shares/back-references). |
defaultSort | DiscussionSortType | "LATEST" | Initial sort order. |
postsPerPage | number | 20 | Posts loaded per page. 0 hides the post list (including posts the user just created) and the posts count, showing only the title and the composer. |
showReactions | boolean | true | Show reaction buttons. |
showReplies | boolean | true | Enable reply functionality. |
showReportPost | boolean | true | Show the report option in the post menu. |
showModeratedPosts | boolean | false | Display moderated posts with a masked design (content replaced by the moderation reason). |
infiniteScroll | boolean | false | Load more posts on scroll instead of showing a "Load More" button. |
showBanHistory | boolean | false | When the signed-in user is banned, add a collapsible list of their previous bans to the ban notice. |
refreshInterval | number | 0 | Check for new comments every N milliseconds and add them to the list highlighted as new. 0 disables it; values below 5000 are raised to 5000. |
userIsLoggedIn | boolean | false | Whether the current user is authenticated. |
onSignInClick | () => void | — | Callback when the sign-in prompt is clicked. |
Note:
Discussionuses a simpleronSignInClickcallback, not the fullSignInCTADetailsobject.
Sort modes
type DiscussionSortType = "LATEST" | "OLDEST" | "POPULAR" | "INTERACTED";| Value | Order |
|---|---|
LATEST | Newest first (default). |
OLDEST | Oldest first. |
POPULAR | Most-reacted first. |
INTERACTED | Most-replied first. |
Authentication and sign-in
When userIsLoggedIn={false}:
- The post composer is replaced with a sign-in prompt.
- Reactions, replies, delete, and report actions are gated behind authentication.
- Passing
onSignInClickmakes the sign-in button active; omitting it shows a disabled button.
<Discussion
{...otherProps}
userIsLoggedIn={false}
onSignInClick={() => openSignInModal()}
/>Banned users
When the signed-in user is banned from discussions, the widget shows a notice above the composer with the reason, when the ban started, and when it ends (or that it is permanent). The ban is looked up with the user ID taken from the SDK's authProvider token.
While the ban is active, the user can still read the discussion, but the composer, replying, reactions, reporting and deleting their own posts are disabled. Set showBanHistory to also list the user's previous bans in the notice.
<Discussion {...otherProps} userIsLoggedIn={true} showBanHistory={true} />Live updates
By default, comments are loaded when the page opens and when the sort changes. For live blogs and match threads, set refreshInterval so comments posted by other users appear without a page reload:
<Discussion {...otherProps} refreshInterval={15000} />Every interval, the widget checks for new comments and adds them to the list highlighted with a colored side border, a tinted background and a "New" badge. The highlight fades a few seconds after the comment has been scrolled into view.
With refreshInterval on, comments get a little padding so the highlight has room; comments don't move when it appears or fades.
- With the Latest sort, new comments are added at the top. With the other sorts, they are added at the end once all comments are loaded; before that, "Load More" brings them in.
- Checks pause while the browser tab is in the background and resume immediately when it comes back.
- Only new top-level comments are added. Replies, reactions and deletions by other users appear after a reload.
- The posts count in the header goes up by the number of new comments added.
Reactions
Eight reaction types are available when showReactions={true}:
type ReactionType = "LIKE" | "DISLIKE" | "LOVE" | "LAUGH" | "CARE" | "WOW" | "SAD" | "ANGRY";- Click an emoji to toggle the reaction.
- Click the same emoji again to remove it.
- Only authenticated users can react.
Moderated posts
showModeratedPosts={true} fetches and displays moderated comments with a masked design. The original content is replaced by the moderation reason (or a localised fallback), while avatar, username, timestamp, reactions, and reply button remain visible.
Examples
Basic
<Discussion
entityId="article-123"
sdk={sdk}
language="en"
discussionLabel="Liverpool vs Man City — Match Reaction"
/>Authenticated user, full features
<Discussion
entityId="article-123"
sdk={sdk}
language="en"
discussionLabel="Liverpool vs Man City — Match Reaction"
discussionUrl="https://your-site.com/articles/liverpool-vs-man-city"
userIsLoggedIn={true}
defaultSort="POPULAR"
postsPerPage={10}
showReactions
showReplies
showReportPost
themeOptions={{ mode: "light" }}
/>Minimal read-only style
<Discussion
entityId="article-123"
sdk={sdk}
language="en"
discussionLabel="Post Comments"
userIsLoggedIn={false}
showReactions={false}
showReplies={false}
showReportPost={false}
onSignInClick={() => openSignInModal()}
/>Dark theme with sign-in integration
<Discussion
entityId="match-456"
sdk={sdk}
language="en"
discussionLabel="Match Day Chat"
userIsLoggedIn={isUserLoggedIn}
onSignInClick={() => router.push("/login")}
defaultSort="LATEST"
postsPerPage={20}
themeOptions={{
mode: "dark",
colorSchemes: {
dark: {
surface: "#212121",
textPrimary: "#FAFAFA",
palette: {
primary: {
plainColor: "#2397F3",
primaryContainer: "#1A77D2",
onPrimary: "#FFFFFF",
},
},
},
},
}}
/>Updated 16 days ago
