React Activity Feed
Edit page
Introduction
Top Level Components
ActivityPropertiesBasic usageActivity with attached image and hashtagActivity with enriched URLActivity with custom header and content componentsFlat feedNotificationNotification dropdownNotification feedSingle postStatus update form
UI Components
Layout Components
Streami18n
Composition Components
Readme

Activity

Properties

activity
Record<string, unknown> & { attachments?: Attachments | undefined; text?: string | undefined; } & BaseActivity & Pick<Activity<Record<string, unknown>>, "time" | "foreign_id" | "id" | "analytics" | "extra_context" | "origin" | "score"> & { ...; }
required
Card
string | number | boolean | ReactElement<PropsWithElementAttributes<{ alt?: string | undefined; handleClose?: ((e: SyntheticEvent<Element, Event>) => void) | undefined; image?: string | null | undefined; nolink?: boolean | undefined; } & Pick<...>, HTMLAnchorElement>, string | ... 1 more ... | (new (props: any) => C...
({ alt, images = [], image: imageURL, handleClose, description, nolink, url, title, className, style, }: CardProps) => { const sanitizedURL = useMemo(() => sanitizeURL(url), [url]); const trimmedURL = useMemo(() => trimURL(sanitizedURL), [sanitizedURL]); const [{ image }] = !imageURL && images.length ? images : [{ image: imageURL }]; return ( <a href={nolink ? undefined : sanitizedURL} target="blank" rel="nofollow noreferrer noopener" className={className ?? `raf-card ${image !== undefined ? 'raf-card--with-image' : ''}`} style={style} > {handleClose && image ? ( <IconButton onClick={handleClose}> <CloseIcon /> </IconButton> ) : null} {image !== undefined && ( <div className="raf-card__image"> {image === null ? ( <AvatarIcon preserveAspectRatio="xMinYMin slice" /> ) : ( <img src={image} alt={alt || title || description || ''} /> )} </div> )} <div className="raf-card__content"> <div className="raf-card__content-left"> <p className="raf-card__title">{title}</p> <p className="raf-card__url">{trimmedURL}</p> <p className="raf-card__description">{description}</p> </div> {handleClose && image === undefined && ( <div className="raf-card__content-right"> <IconButton onClick={handleClose}> <CloseIcon /> </IconButton> </div> )} </div> </a> ); }
Content
string | number | boolean | ReactElement<PropsWithElementAttributes<{ activity: EnrichedActivity<UT, AT, CT, RT, CRT>; Card?: string | number | boolean | ReactElement<PropsWithElementAttributes<{ alt?: string | undefined; handleClose?: ((e: SyntheticEvent<Element, Event>) => void) | undefined; image?: string | ... 1...
< UT extends DefaultUT = DefaultUT, AT extends DefaultAT = DefaultAT, CT extends UR = UR, RT extends UR = UR, CRT extends UR = UR >({ activity, Repost, Card = DefaultCard, className, style, ...props }: ActivityContentProps<UT, AT, CT, RT, CRT>) => { const { object, text = (typeof object === 'string' ? object : '').trim(), attachments: { og, images = [], files = [] } = {}, verb, image, } = activity; return ( <div className={classNames('raf-activity__content', className)} style={style}> {text && ( <div style={{ padding: '8px 16px' }}> <p>{textRenderer(text, 'raf-activity', props.onClickMention, props.onClickHashtag)}</p> </div> )} {og && ( <div style={{ padding: '8px 16px' }}> {og.videos ? <Video og={og} /> : og.audios ? <Audio og={og} /> : smartRender(Card, og)} </div> )} {typeof image === 'string' && ( <div style={{ padding: '8px 0' }}> <Gallery images={[image]} /> </div> )} {!!images.length && ( <div style={{ padding: '8px 0' }}> <Gallery images={images} /> </div> )} {!!files.length && ( <ol className="raf-activity__attachments"> {files.map(({ name, url, mimeType }, i) => ( <a href={sanitizeURL(url)} download key={i}> <li className="raf-activity__file"> <FileIcon mimeType={mimeType} filename={name} /> {name} </li> </a> ))} </ol> )} {verb === 'repost' && typeof object === 'object' && smartRender(Repost, { ...props, activity: object as EnrichedActivity<UT, AT, CT, RT, CRT>, })} </div> ); }
feedGroup
string | undefined
Footer
string | number | boolean | ReactElement<ActivityFooterProps<UT, AT, CT, RT, CRT>, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)> | ComponentClass<...> | FunctionComponent<...> | null | undefined
Header
string | number | boolean | ReactElement<Pick<PropsWithElementAttributes<{ activity: EnrichedActivity<UT, AT, Record<string, unknown>, Record<string, unknown>, Record<string, unknown>>; Card?: string | number | boolean | ReactElement<PropsWithElementAttributes<{ ...; } & Pick<...>, HTMLAnchorElement>, string | ... 1...
<UT extends DefaultUT = DefaultUT, AT extends DefaultAT = DefaultAT>({ activity, HeaderRight, icon, onClickUser, style = { padding: '8px 16px' }, className, }: ActivityHeaderProps<UT, AT>) => { const { tDateTimeParser } = useTranslationContext(); const actor = userOrDefault<UT>(activity.actor); const handleUserClick = useOnClickUser<UT>(onClickUser); return ( <div style={style} className={className}> <UserBar username={actor.data.name} avatar={actor.data.profileImage} onClickUser={handleUserClick?.(actor)} subtitle={HeaderRight ? humanizeTimestamp(activity.time, tDateTimeParser) : undefined} timestamp={activity.time} icon={icon} Right={HeaderRight} /> </div> ); }
HeaderRight
string | number | boolean | ReactElement<Record<string, unknown>, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)> | ComponentClass<Record<...>, any> | FunctionComponent<...> | null | undefined
icon
string | undefined
onClickHashtag
WordClickHandler | undefined
onClickMention
WordClickHandler | undefined
onClickUser
((user: UserOrDefaultReturnType<UT>) => void) | undefined
Repost
string | number | boolean | ReactElement<PropsWithElementAttributes<{ activity: EnrichedActivity<UT, AT, CT, RT, CRT>; Card?: string | number | boolean | ReactElement<PropsWithElementAttributes<{ alt?: string | undefined; handleClose?: ((e: SyntheticEvent<Element, Event>) => void) | undefined; image?: string | ... 1...
< UT extends DefaultUT = DefaultUT, AT extends DefaultAT = DefaultAT, CT extends UR = UR, RT extends UR = UR, CRT extends UR = UR >({ Header = DefaultActivityHeader, HeaderRight, Content = DefaultActivityContent, activity, icon, onClickHashtag, onClickMention, onClickUser, }: ActivityProps<UT, AT, CT, RT, CRT>) => ( <div className="raf-card raf-activity raf-activity-repost"> {smartRender<ActivityHeaderProps<UT, AT>>(Header, { HeaderRight, icon, activity, onClickUser })} {smartRender<ActivityContentProps<UT, AT, CT, RT, CRT>>(Content, { onClickMention, onClickHashtag, activity })} </div> )
userId
string | undefined

Basic usage

Nora Ferguson

I just missed my train 😤

Activity with attached image and hashtag

Nora Ferguson

Just came back from this hike! #Hiking #Madeira

Activity with enriched URL

Activity with custom header and content components

Nora Ferguson
You can customize your activity however you like!