Skip to content

Conversation

@buzzwordmojo
Copy link

Summary

Allow custom Floating UI middleware configuration for FormattingToolbarController via the floatingOptions.middleware prop.

Rationale

The FormattingToolbarController currently hardcodes middleware to [offset(10), shift(), flip()], making it impossible for developers to customize toolbar positioning behavior. This limitation becomes problematic on mobile devices where:

  • The default flip() middleware can cause disorienting position changes
  • Custom centering logic is needed when the toolbar wraps to multiple rows
  • Different viewport constraints require different positioning strategies

Changes

  • Added support for custom middleware via floatingOptions.middleware prop
  • Maintained full backward compatibility - defaults to existing middleware array when not provided
  • Added TypeScript types and JSDoc documentation
  • Import Middleware type from @floating-ui/react

Modified file:

  • packages/react/src/components/FormattingToolbar/FormattingToolbarController.tsx

Line change:

// Before
middleware: [offset(10), shift(), flip()],

// After  
middleware: props.floatingOptions?.middleware || [offset(10), shift(), flip()],

Impact

  • No breaking changes - fully backward compatible
  • Existing implementations continue working without modification
  • Enables mobile-specific toolbar positioning control
  • Allows developers to implement custom positioning strategies

Testing

  • Code adheres to project standards (linting passed)
  • Existing tests remain functional (496 tests passed in core/react packages)
  • No new tests needed - this is a pass-through prop that doesn't change default behavior

Manual testing:
Tested with custom middleware for mobile toolbar centering:

<FormattingToolbarController
  floatingOptions={{
    middleware: [offset(10), shift(), mobileCenterMiddleware, flip()],
  }}
/>

Use Case Example

On mobile viewports, this change enables centered, width-constrained toolbars:

const mobileCenterMiddleware: Middleware = {
  name: "mobileCenter",
  fn: ({ x, y, elements }) => {
    if (window.innerWidth >= 768) return { x, y };
    
    const viewportWidth = window.innerWidth;
    const targetLeft = viewportWidth * 0.05; // 5% margin
    const currentLeft = elements.floating.getBoundingClientRect().left;
    
    return { x: x + (targetLeft - currentLeft), y };
  },
};

Additional Notes

This addresses mobile UX issues where toolbar flipping creates unpredictable behavior. The implementation follows Floating UI's standard patterns and maintains consistency with how other BlockNote components accept middleware customization.

…zation

This change adds an optional middleware prop to FormattingToolbarController,
allowing developers to customize the Floating UI middleware for positioning
the formatting toolbar.

Benefits:
- Enables mobile-friendly toolbar centering
- Maintains backward compatibility (defaults to existing middleware)
- Provides clear, explicit API for positioning customization
- Works alongside existing floatingOptions.middleware

Example use case: On mobile devices, the toolbar can be centered horizontally
instead of following the text selection position, improving accessibility
when the toolbar wraps to multiple rows.
@vercel
Copy link

vercel bot commented Nov 9, 2025

@rlmattax is attempting to deploy a commit to the TypeCell Team on Vercel.

A member of the Team first needs to authorize it.

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