Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: activity actions decorator #5419

Closed
wants to merge 9 commits into from
Closed

Conversation

OEvgeny
Copy link
Collaborator

@OEvgeny OEvgeny commented Feb 5, 2025

Activity Actions Decorator

Changelog Entry

Added

  • Added ActivityActionsDecorator for customizing activity actions layout, in PR #5419, by @OEvgeny
    • Exposed ActivityButton component to be used in activity actions toolbar, in PR #5419, by @OEvgeny
    • Exposed useShowModal hook for displaying custom modal dialogs, in PR #5419, by @OEvgeny

Description

This PR introduces a new decorator API that allows customizing the layout and behavior of activity actions (buttons like copy, view code, feedback etc.). The decorator provides a flexible way to modify how these actions are presented and interact with each other.

Key additions:

  • New ActivityActionsDecorator component for wrapping activity actions
  • Exposed ActivityButton component for consistent action button styling
  • Example implementations demonstrating custom action layouts and modal interactions

Design

  1. For now activity actions decoration is handled separately from the activity decoration, but it is expected to change.

  2. Activity is passed as a prop rather than part of the middleware request because:

    • Actions often need direct access to activity data for rendering decisions when activity is already finalized
    • The request object focused on generic decoration concerns (livestreaming state, sender type)
    • Allow more flexible action handling without polluting the request object

Specific Changes

  • Added new public exports:

    export { ActivityActionsDecorator } from 'botframework-webchat-api/decorator';
    export { ActivityButton } from 'botframework-webchat-component';
    export { hooks } from 'botframework-webchat-component';
    const { useShowModal } = hooks;
  • Created supporting middleware infrastructure:

    • ActivityActionsDecoratorMiddleware.ts
    • useActivityDecoratorRequest hook
    • Integrated with createDecoratorComposer
  • Moved ActivityButton to public API for reuse

  • Added test covering:

    • Custom action layouts
    • Modal interactions
    • Integration with existing activity decorators

Example Usage

// Custom layout with modal integration
function Actions({ activity, children }) {
  const showModal = useShowModal();
  // It is advised to use a schema.org compatible parsing solution
  if (activity.entities?.[0].isBasedOn?.['@type'] === 'ImageObject') {
    return (
      <div className="custom-actions-layout">
        <ActivityButton
          onClick={() => showModal(() => <ImagePreview />, { className: 'image-modal' })}
          text="View Image"
        />
        {children}
      </div>
    );
  }
  return <>{children}</>;
}

// Middleware setup
const decoratorMiddleware = [
  init =>
    init === 'activity actions' &&
    (next => request => (!request.livestreamingState ? Actions : next(request)))
];

// Usage in app
<DecoratorComposer middleware={decoratorMiddleware}>
  <WebChat />
</DecoratorComposer>
  • I have added tests and executed them locally
  • I have updated CHANGELOG.md
  • I have updated documentation

Review Checklist

This section is for contributors to review your work.

  • Accessibility reviewed (tab order, content readability, alt text, color contrast)
  • Browser and platform compatibilities reviewed
  • CSS styles reviewed (minimal rules, no z-index)
  • Documents reviewed (docs, samples, live demo)
  • Internationalization reviewed (strings, unit formatting)
  • package.json and package-lock.json reviewed
  • Security reviewed (no data URIs, check for nonce leak)
  • Tests reviewed (coverage, legitimacy)

@OEvgeny OEvgeny force-pushed the feat/acitvity-actions-decorator branch from 3a2a57a to a705142 Compare February 5, 2025 22:51
@OEvgeny OEvgeny marked this pull request as ready for review February 5, 2025 23:37
__tests__/html2/fluentTheme/decorator.modal.html Outdated Show resolved Hide resolved
__tests__/html2/fluentTheme/decorator.modal.html Outdated Show resolved Hide resolved
__tests__/html2/fluentTheme/decorator.modal.html Outdated Show resolved Hide resolved
docs/HOOKS.md Outdated Show resolved Hide resolved
docs/HOOKS.md Outdated Show resolved Hide resolved
docs/HOOKS.md Outdated Show resolved Hide resolved
docs/HOOKS.md Outdated Show resolved Hide resolved
__tests__/html2/fluentTheme/decorator.modal.html Outdated Show resolved Hide resolved
@OEvgeny OEvgeny requested a review from compulim February 6, 2025 01:26
docs/HOOKS.md Show resolved Hide resolved
)}
{/* TODO: [P2] Fold the ActivityActionsDecorator into the ActivityDecorator to unlock more flexibility */}
<ActivityActionsDecorator activity={activity}>
{activity.type === 'message' && isBasedOnSoftwareSourceCode(messageThing) && messageThing.isBasedOn.text ? (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like each of button in this 3 button set should be their own middleware.

Say...

() => next => request => {
  if (activity.type === 'message' && isBasedOnSoftwareSourceCode(messageThing) && messageThing.isBasedOn.text) {
    return <><ActivityViewCodeButton ... />{next(request)}</>;
  }

  return next(request);
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except this is v2-style middleware, so it should return a component. We also don't want to expose activity on the request level, do we? Or, are you speaking about a dedicated middleware stack for activity actions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dedicated middleware stack for activity actions.

@OEvgeny
Copy link
Collaborator Author

OEvgeny commented Feb 6, 2025

I'll let future us decide which would be better. Apparently Web Chat doesn't need such functionality right now, so we'll revisit it when we have a use-case for such "decoration" mechanism.

@OEvgeny OEvgeny closed this Feb 6, 2025

return {
activity,
livestreamingState:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should let web devs to compute this value from activity themselves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants