-
Notifications
You must be signed in to change notification settings - Fork 2.7k
feat(ui): fixed toolbar group customization #12108
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(ui): fixed toolbar group customization #12108
Conversation
/** | ||
* Custom configurations for toolbar groups | ||
* Key is the group key (e.g. 'format', 'indent', 'align') | ||
* Value is a partial ToolbarGroup object that will be merged with the default configuration | ||
*/ | ||
customGroups?: Record<string, Partial<ToolbarGroup>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToolbarGroup
is designed to be used on the client. To pass it as a property to FixedToolbarFeature
, we could accept only the serializable subset of properties.
This would mean excluding isEnabled
and items
from ToolbarDropdownGroup
. Theoretically, some subproperties of items
could also be retained with a bit more complexity in the types.
Your example in the PR description/video works because you only used properties from that subset of serializable properties. Also, while it's probably not a problem since they're usually static icons, I would add to the tsdoc that ChildComponent
must be a server component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for clarifying! That makes sense regarding the need for serialization.
* @note Props passed via customGroups must be serializable. Avoid using functions or dynamic components. | ||
* ChildComponent, if provided, must be a serializable server component. | ||
*/ | ||
customGroups?: Record<string, Partial<Omit<ToolbarGroup, 'isEnabled' | 'items'>>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type makes your example not work
text: {
order: 10,
ChildComponent: SwapIcon, // Object literal may only specify known properties, and 'ChildComponent' does not exist in type 'Partial<Omit<ToolbarGroup, "isEnabled" | "items">>'.
},
Additionally, if the item contains type: "button"
, it should not allow ChildComponent
or maxActiveItems
// this should give a ts error
hello: {
key: 'hello',
order: 1,
type: 'buttons',
maxActiveItems: 1,
},
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got the idea! Pushed the updated types, which pass your examples
type CustomDropdownGroup = Partial<Omit<ToolbarDropdownGroup, 'isEnabled' | 'items'>>
type CustomButtonsGroup = Partial<
Omit<ToolbarButtonsGroup, 'ChildComponent' | 'isEnabled' | 'items' | 'maxActiveItems'>
>
type CustomGroup = CustomButtonsGroup | CustomDropdownGroup
export type CustomGroups = Record<string, CustomGroup>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
### What This PR introduces a comprehensive customization system for toolbar groups in the Lexical Rich Text Editor. It allows developers to override not just the order, but virtually any aspect of toolbar components (such as format, align, indent) through the `FixedToolbarFeature` configuration. Customizable properties include order, icons, group type, and more. ### Why Previously, toolbar group configurations were hardcoded in their respective components with no way to modify them without changing the source code. This made it difficult for developers to: 1. Reorder toolbar components to match specific UX requirements 2. Replace icons with custom ones to maintain design consistency 3. Transform dropdown groups into button groups or vice versa 4. Apply other customizations needed for specific projects This enhancement provides full flexibility for tailoring the rich text editor interface while maintaining a clean and maintainable codebase. ### How The implementation consists of three key parts: 1. **Enhanced the FixedToolbarFeature API**: - Added a new `customGroups` property to `FixedToolbarFeatureProps` that accepts a record mapping group keys to partial `ToolbarGroup` objects - These partial objects can override any property of the default toolbar group configuration 2. **Leveraged existing deep merge utility**: - Used Payload's existing `deepMerge` utility to properly combine default configurations with custom overrides - This ensures that only specified properties are overridden while preserving all other default behaviors 3. **Applied customizations in the sanitization process**: - Updated the `sanitizeClientFeatures` function to identify and apply custom group configurations - Applied deep merging before the sorting process to ensure proper ordering with customized configurations - Maintained backward compatibility for users who don't need customization ### Usage Example ```typescript import { FixedToolbarFeature } from '@payloadcms/richtext-lexical' import { CustomIcon } from './icons/CustomIcon' { name: 'content', type: 'richText', admin: { features: [ // Other features... FixedToolbarFeature({ customGroups: { 'text': { order: 10, ChildComponent: CustomIcon, }, 'format': { order: 15, }, 'add': { type: 'buttons', order: 20, }, } }) ] } } ``` ### Demo https://github.com/user-attachments/assets/c3a59b60-b6c2-4721-bbc0-4954bdf52625 --------- Co-authored-by: Germán Jabloñski <[email protected]>
🚀 This is included in version v3.38.0 |
### What This PR introduces a comprehensive customization system for toolbar groups in the Lexical Rich Text Editor. It allows developers to override not just the order, but virtually any aspect of toolbar components (such as format, align, indent) through the `FixedToolbarFeature` configuration. Customizable properties include order, icons, group type, and more. ### Why Previously, toolbar group configurations were hardcoded in their respective components with no way to modify them without changing the source code. This made it difficult for developers to: 1. Reorder toolbar components to match specific UX requirements 2. Replace icons with custom ones to maintain design consistency 3. Transform dropdown groups into button groups or vice versa 4. Apply other customizations needed for specific projects This enhancement provides full flexibility for tailoring the rich text editor interface while maintaining a clean and maintainable codebase. ### How The implementation consists of three key parts: 1. **Enhanced the FixedToolbarFeature API**: - Added a new `customGroups` property to `FixedToolbarFeatureProps` that accepts a record mapping group keys to partial `ToolbarGroup` objects - These partial objects can override any property of the default toolbar group configuration 2. **Leveraged existing deep merge utility**: - Used Payload's existing `deepMerge` utility to properly combine default configurations with custom overrides - This ensures that only specified properties are overridden while preserving all other default behaviors 3. **Applied customizations in the sanitization process**: - Updated the `sanitizeClientFeatures` function to identify and apply custom group configurations - Applied deep merging before the sorting process to ensure proper ordering with customized configurations - Maintained backward compatibility for users who don't need customization ### Usage Example ```typescript import { FixedToolbarFeature } from '@payloadcms/richtext-lexical' import { CustomIcon } from './icons/CustomIcon' { name: 'content', type: 'richText', admin: { features: [ // Other features... FixedToolbarFeature({ customGroups: { 'text': { order: 10, ChildComponent: CustomIcon, }, 'format': { order: 15, }, 'add': { type: 'buttons', order: 20, }, } }) ] } } ``` ### Demo https://github.com/user-attachments/assets/c3a59b60-b6c2-4721-bbc0-4954bdf52625 --------- Co-authored-by: Germán Jabloñski <[email protected]>
What
This PR introduces a comprehensive customization system for toolbar groups in the Lexical Rich Text Editor. It allows developers to override not just the order, but virtually any aspect of toolbar components (such as format, align, indent) through the
FixedToolbarFeature
configuration. Customizable properties include order, icons, group type, and more.Why
Previously, toolbar group configurations were hardcoded in their respective components with no way to modify them without changing the source code. This made it difficult for developers to:
This enhancement provides full flexibility for tailoring the rich text editor interface while maintaining a clean and maintainable codebase.
How
The implementation consists of three key parts:
Enhanced the FixedToolbarFeature API:
customGroups
property toFixedToolbarFeatureProps
that accepts a record mapping group keys to partialToolbarGroup
objectsLeveraged existing deep merge utility:
deepMerge
utility to properly combine default configurations with custom overridesApplied customizations in the sanitization process:
sanitizeClientFeatures
function to identify and apply custom group configurationsUsage Example
Demo
fixed-toolbar-customization.mov