Docyrus

LogActivityForm

Presentational multi-surface activity composer with Comment, Email, Call, Meeting, Task and Status tabs, each reporting its own typed submit callback.

iOSAndroid
Preview LogActivityForm on your device

Scan with Expo Go

Download Expo Go, then scan the QR code to preview native components.

Installation

pnpm dlx @docyrus/cli add @docyrus/rn-log-activity-form
Required Packages(2 packages)
pnpm add react-native-reanimated @shopify/flash-list

A scrollable tab bar switches between six surfaces rendered inline:

TabSurfaceCallback
CommentCommentsPanel (mentions, replies, delete)onCreateComment, onDeleteComment
EmailNative EmailComposer, or the renderEmailComposer slotonSendEmail
Call / MeetingSubject, type, start, end, owner, descriptiononSubmitEvent(input, 'call' | 'meeting')
TaskSubject (required), status, priority, assignee, due date, descriptiononSubmitTask
StatusInline DocyFieldStatus with sub-status, notes and follow-up dateonSubmitStatus

The form owns no network I/O. Spread useDocyrusLogActivity(...).logActivityProps to connect it to Docyrus, or pass your own data and callbacks. Every submit shows a success or error toast through the native toast (mount a <Toaster />). A rejected callback keeps the draft so the user can retry.

Usage

import { LogActivityForm } from '@/components/docyrus-native/log-activity-form';
import { useDocyrusLogActivity } from '@/hooks/docyrus-native/use-docyrus-log-activity';

function LogActivity({ client, recordId }) {
  const { logActivityProps } = useDocyrusLogActivity({
    client,
    appSlug: 'base',
    dataSourceSlug: 'contact',
    recordId,
    relationSlug: 'contact',
    callEventTypeName: 'Call',
    meetingEventTypeName: 'Meeting'
  });

  return <LogActivityForm {...logActivityProps} defaultActivityType="call" />;
}

Without the hook

<LogActivityForm
  activityTypes={['task', 'call', 'comment']}
  taskStatusOptions={[{ id: 'open', name: 'Open' }, { id: 'done', name: 'Done' }]}
  taskUsers={[{ id: 'u1', name: 'Alice Johnson', icon: 'https://…/alice.png' }]}
  onSubmitTask={input => api.createTask(input)}
  onSubmitEvent={(input, kind) => api.createEvent({ ...input, kind })}
  comments={comments}
  users={users}
  currentUser={me}
  onCreateComment={({ content, parent_id, mentions }) => api.comment(content, parent_id, mentions)} />

Email tab

The tab renders the native EmailComposer with emailComposerProps spread onto it (from/accounts, cc/bcc, @ mentions and / slash commands when they are present). useDocyrusLogActivity fills these props from its embedded useDocyrusEmailComposer. to, subject and body are controlled by emailComposerProps when their setters are passed, and keep local state otherwise. The body is email-safe HTML. Send needs a recipient, a subject and onSendEmail, and shows the success / error toast.

Pass renderEmailComposer to render your own surface instead. It receives the same emailComposerProps and the wrapped onSendEmail.

<LogActivityForm
  {...logActivityProps}
  renderEmailComposer={({ emailComposerProps, onSendEmail, isSendingEmail, disabled }) => (
    <MyEmailComposer {...emailComposerProps} sending={isSendingEmail} disabled={disabled} onSend={onSendEmail} />
  )} />

API Reference

LogActivityFormProps

PropTypeDefaultDescription
activityTypesLoggableActivityType[]all sixTabs to show, in this order
activeTypeLoggableActivityType-Controlled active tab
defaultActivityTypeLoggableActivityTypefirst tabUncontrolled initial tab
onTypeChange(type: LoggableActivityType) => void-Tab change callback
classNamestring-Container classes
disabledbooleanfalseDisable tabs and every surface
commentsDocyrusComment[][]Comment tab list
usersCommentUser[]-Users for comment authors and mentions
currentUserCommentUser-Signed-in user (own comments)
onCreateComment(payload: LogActivityCommentPayload) => void | Promise<void>-Post a comment or reply
onDeleteComment(commentId: string) => void | Promise<void>-Delete a comment
isCommentsLoadingboolean-Comment list skeleton
isCreatingCommentboolean-Pending comment state
emailComposerPropsPartial<LogActivityEmailComposerProps>-Props spread onto the Email tab EmailComposer
onSendEmail() => void | Promise<void>-Send handler for the Email tab
isSendingEmailboolean-Pending send state
renderEmailComposer(context: LogActivityEmailComposerContext) => ReactNode-Native-only: render your own Email tab surface
statusFieldIField | null-The record's field-status / field-select field
statusEnumOptionsEnumOption[]statusField.enumsStatus options
statusInitialValuesRecord<string, unknown>{}Current status and companions, keyed by <slug> and __<slug>_secondary / _description / _followup_date
onSubmitStatus(input: LogStatusInput) => void | Promise<void>-Log a status change
isSubmittingStatusboolean-Pending status submit
isStatusLoadingboolean-Status tab loading state
taskStatusOptionsEnumOption[][]Task status options (hidden when empty)
taskPriorityOptionsEnumOption[][]Task priority options (hidden when empty)
taskUsersEnumOption[][]Assignee options (icon = avatar URL, hidden when empty)
onSubmitTask(input: LogTaskInput) => void | Promise<void>-Create a task
isSubmittingTaskboolean-Pending task submit
eventTypesEnumOption[][]Event type options (hidden when empty)
eventUsersEnumOption[][]Owner options (hidden when empty)
callEventTypeIdstring-Preset event type for the Call tab
meetingEventTypeIdstring-Preset event type for the Meeting tab
onSubmitEvent(input: LogEventInput, kind: 'call' | 'meeting') => void | Promise<void>-Log a call or meeting
isSubmittingEventboolean-Pending event submit

LogActivityCommentPayload

FieldTypeDescription
contentstringMarkdown body ([@Name](mention://id) mention tokens)
parent_idstringParent comment for replies
mentionsstring[]Mentioned user ids

LogTaskInput

FieldTypeDescription
subjectstringRequired
statusIdstring | nullTask status option id
priorityIdstring | nullTask priority option id
ownerIdstring | nullAssignee user id
dueDatestring | nullDate-only YYYY-MM-DD
descriptionstring | nullDescription

LogEventInput

FieldTypeDescription
subjectstringRequired
eventTypeIdstring | nullEvent type (calendar) id
ownerIdstring | nullOwner user id
startDatestring | nullISO datetime
endDatestring | nullISO datetime (must not be before the start)
descriptionstring | nullDescription

LogStatusInput

FieldTypeDescription
valuestringStatus option id (required)
secondaryValuestring | nullSub-status option id
descriptionstring | nullNotes
followupDatestring | nullDate-only YYYY-MM-DD

LogActivityEmailComposerContext

FieldTypeDescription
emailComposerPropsPartial<LogActivityEmailComposerProps>The props passed to the form
onSendEmail() => Promise<void>Send wrapped with the success / error toast
isSendingEmailbooleanPending send state
disabledbooleanThe form's disabled

LogActivityEmailComposerProps types to, cc, bcc (string[]), subject, body (HTML) and their on…Change setters, and lets every other EmailComposerProps key pass through to the tab's EmailComposer.

Components

ComponentDescription
LogActivityFormTab bar plus the six activity surfaces

Type Exports

TypeDescription
LogActivityFormPropsProps for LogActivityForm
LoggableActivityType'comment' | 'email' | 'call' | 'meeting' | 'task' | 'status_update'
LogActivityCommentPayloadComment tab payload
LogTaskInputTask tab payload
LogEventInputCall / Meeting tab payload
LogStatusInputStatus tab payload
LogActivityEmailComposerPropsEmail tab composer props
LogActivityEmailComposerContextArgument of renderEmailComposer
LOGGABLE_ACTIVITY_TYPESConstant: all six types in default order

Breaking changes

The form was rewritten to match the web per-tab API.

  • The single onSubmit(payload: LogActivityPayload) was replaced by per-tab callbacks: onCreateComment, onDeleteComment, onSendEmail, onSubmitStatus, onSubmitTask and onSubmitEvent. LogActivityPayload is no longer exported.
  • activityType was renamed to activeType. activityTypes now selects and orders the tabs.
  • statusOptions: StatusOption[] was replaced by statusField + statusEnumOptions + statusInitialValues. StatusOption is no longer exported.
  • isSubmitting, placeholder and submitLabel were removed. Each tab has its own pending prop (isCreatingComment, isSendingEmail, isSubmittingStatus, isSubmittingTask, isSubmittingEvent) and translated button labels (ui.logActivity.*).
  • The Comment tab is a full CommentsPanel instead of a text box, and the tab icons are DocyrusIcons instead of emoji.

On this page