Skip to content

Conversation

@zcei
Copy link
Collaborator

@zcei zcei commented May 5, 2025

User description

This PR adds a bunch of options to be configured on a per-field basis. It does not work for all fields in a Strapi instance at once

Things still to consider/do

  • Font size is not configurable
    • whether it's shown at all
    • config could include min/max
    • also optionally allow to give a set of fixed font sizes to choose from (our editor toolbar code can do it already anyways)
  • Font family is not configurable
    • whether it's shown at all
    • config could which fonts are available
  • Enabled block nodes not configurable (paragraph, headlines, lists, ...)
  • "Convert to different block type" meta field
    • only visible when there are more than one block type available based on the config
    • force hide even if when there are multiple block types
  • Floating action/toolbar has to change based on the config
  • empty groups / dropdowns shouldn't render if none of the children are enabled
  • indent / outdent
  • sane defaults: right now no options are enabled by default, this might turn out pretty annoying
  • add a new screenshot how it looks as a configurable editor (full, empty, sub-selection)

PR Type

Enhancement


Description

  • Refactored toolbar to be fully configurable per field

    • Toolbar items now rendered dynamically based on field config
    • Node types and actions are now modular and extensible
    • Added context providers for field and toolbar dependencies
  • Added support for per-field enabled node types and actions

    • Options UI for enabling/disabling node types, actions, and developer settings
    • supportedNodeTypes registry for node type plugins and toolbar items
  • Modularized toolbar item components for maintainability

    • Each toolbar action (bold, link, image, etc.) now in its own file
    • Toolbar groups and dropdowns render only enabled items
  • Improved documentation and configuration instructions


Changes walkthrough 📝

Relevant files
Enhancement
23 files
index.ts
Add per-field configurable options for node types and actions
+112/-1 
Input.tsx
Inject field config context into editor input                       
+15/-8   
Editor.tsx
Render plugins dynamically based on enabled node types     
+13/-12 
StrapiFieldContext.tsx
Add context for per-field configuration                                   
+33/-0   
ToolbarItemRenderDependenciesContext.tsx
Add context for toolbar item render dependencies                 
+27/-0   
index.tsx
Refactor toolbar to render items/groups dynamically           
+270/-660
utils.ts
Remove clearFormatting, move to codeLessUtils                       
+2/-73   
codeLessUtils.ts
Add utility for clearing formatting and dropdown classes 
+75/-0   
richText.tsx
Add modular toolbar items for rich text actions                   
+282/-0 
code.tsx
Add modular toolbar item for code formatting                         
+35/-0   
link.tsx
Add modular toolbar item for links                                             
+44/-0   
strapiImage.tsx
Add modular toolbar item for Strapi images                             
+26/-0   
other.tsx
Add modular toolbar item for clearing formatting                 
+36/-0   
horizontalRule.tsx
Add modular toolbar item for horizontal rule                         
+43/-0   
pageBreak.tsx
Add modular toolbar item for page break                                   
+44/-0   
image.tsx
Add modular toolbar items for image and inline image         
+89/-0   
table.tsx
Add modular toolbar item for table insertion                         
+42/-0   
columns.tsx
Add modular toolbar item for columns layout                           
+41/-0   
equation.tsx
Add modular toolbar item for equation insertion                   
+41/-0   
collapsible.tsx
Add modular toolbar item for collapsible container             
+32/-0   
history.tsx
Add modular toolbar items for undo/redo history                   
+55/-0   
index.tsx
Use new clearFormatting utility from codeLessUtils             
+1/-1     
supportedNodeTypes.tsx
Add registry for supported node types and plugins               
+311/-0 
Documentation
1 files
README.md
Update documentation for new configuration and usage         
+38/-38 
Additional files
1 files
ToolbarContext.tsx +1/-1     

Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • @qodo-code-review
    Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    CSS Class Typo

    There's a typo in the CSS class name for horizontal rule icon. The class name has a space in it ("horizonta l-rule") which will cause the icon to not display correctly.

    <i className="icon horizonta l-rule" />
    <span className="text">
    
    Missing Exports

    Several node types are defined but not included in the named exports section, including equation and collapsible, which could lead to import errors elsewhere in the codebase.

    export {
      bold,
      italic,
      underline,
      inlineCode,
      emojiPicker,
      lowercase,
      uppercase,
      capitalize,
      strikethrough,
      subscript,
      superscript,
      clearFormatting,
      link,
      strapiImage,
      horizontalRule,
      pageBreak,
      image,
      inlineImage,
      table,
      columns,
    };
    
    Duplicate Toolbar Items

    There are duplicate toolbar items in the ToolbarGroup components. The "meta.blockTypes" item appears twice in consecutive ToolbarGroups which will cause duplicate UI elements.

      <ToolbarItem id="meta.blockTypes" />
    </ToolbarGroup>
    <ToolbarGroup>
      <ToolbarItem id="meta.blockTypes" />
    </ToolbarGroup>
    

    @qodo-code-review
    Copy link

    qodo-code-review bot commented May 5, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Add null check

    The function doesn't check if nodeType exists before accessing its lexicalPlugin
    property. If a nodeTypeId doesn't match any key in supportedNodeTypes, this will
    cause a runtime error. Add a null check before accessing the property.

    admin/src/supportedNodeTypes.tsx [289-304]

     function getUniquePlugins(strapiFieldConfig: StrapiFieldConfig) {
       const plugins = new Set<LexicalPlugin<RenderPluginProps>>();
     
       for (const [nodeTypeId, enabled] of Object.entries(strapiFieldConfig.enabledNodeTypes)) {
         if (!enabled) {
           continue;
         }
         const nodeType = supportedNodeTypes[nodeTypeId as keyof typeof supportedNodeTypes];
     
    -    if (nodeType.lexicalPlugin) {
    +    if (nodeType && nodeType.lexicalPlugin) {
           plugins.add(nodeType.lexicalPlugin);
         }
       }
     
       return Array.from(plugins);
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    __

    Why: The suggestion correctly identifies a potential runtime error in the new getUniquePlugins function. Accessing nodeType.lexicalPlugin without first checking if nodeType exists (i.e., if the nodeTypeId was found in supportedNodeTypes) could lead to an error. Adding the suggested null check (if (nodeType && nodeType.lexicalPlugin)) makes the code more robust.

    Medium
    Remove duplicate toolbar group

    There are two identical consecutive ToolbarGroup components with the same
    "meta.blockTypes" ID. This duplication will cause rendering issues and
    potentially unexpected behavior. Remove one of the duplicate groups.

    admin/src/lexical/plugins/ToolbarPlugin/index.tsx [949-954]

    -<ToolbarGroup>
    -  <ToolbarItem id="meta.blockTypes" />
    -</ToolbarGroup>
     <ToolbarGroup>
       <ToolbarItem id="meta.blockTypes" />
     </ToolbarGroup>
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    __

    Why: The suggestion correctly points out that two identical ToolbarGroup components with the same ToolbarItem (id="meta.blockTypes") are rendered consecutively in the new code. Removing the duplicate group simplifies the component structure and prevents potential rendering issues.

    Low
    Fix icon class name
    Suggestion Impact:The commit directly implemented the suggestion by fixing the typo in the className, changing 'horizonta l-rule' to 'horizontal-rule'

    code diff:

    -      <i className="icon horizonta l-rule" />
    +      <i className="icon horizontal-rule" />

    There's a typo in the className for the horizontal rule icon. The space between
    "horizonta" and "l-rule" will cause the icon to display incorrectly. Fix the
    class name to "horizontal-rule".

    admin/src/lexical/plugins/ToolbarPlugin/toolbarItems/horizontalRule.tsx [34]

    -<i className="icon horizonta l-rule" />
    +<i className="icon horizontal-rule" />

    [Suggestion processed]

    Suggestion importance[1-10]: 5

    __

    Why: The suggestion correctly identifies a typo (horizonta l-rule) in the CSS class name for an icon within the newly added horizontalRule.tsx file. Fixing this ensures the icon displays correctly.

    Low
    General
    Fix incorrect error message
    Suggestion Impact:The commit directly implemented the suggestion by changing the error message to correctly reference 'StrapiFieldConfigProvider' instead of 'ToolbarProvider'

    code diff:

    -    throw new Error('useStrapiFieldContext must be used within a ToolbarProvider');
    +    throw new Error('useStrapiFieldContext must be used within a StrapiFieldConfigProvider');

    The error message incorrectly states that the context must be used within a
    ToolbarProvider, but it should reference StrapiFieldConfigProvider instead. This
    could lead to confusion during debugging.

    admin/src/lexical/context/StrapiFieldContext.tsx [28-30]

     if (context === undefined) {
    -  throw new Error('useStrapiFieldContext must be used within a ToolbarProvider');
    +  throw new Error('useStrapiFieldContext must be used within a StrapiFieldConfigProvider');
     }

    [Suggestion processed]

    Suggestion importance[1-10]: 5

    __

    Why: The suggestion correctly identifies that the error message in useStrapiFieldContext refers to the wrong provider (ToolbarProvider instead of StrapiFieldConfigProvider). Fixing this improves clarity for developers using the hook.

    Low
    • Update

    @axe312ger axe312ger force-pushed the feat/configurable-editor branch from 3f750fb to 96d97dc Compare May 8, 2025 08:25
    @colonder
    Copy link

    colonder commented Sep 4, 2025

    @zcei any progress on this?

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    4 participants