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

💬 RFC: Component Composability in Frontend Plugins #16876

Open
benjdlambert opened this issue Mar 15, 2023 · 12 comments
Open

💬 RFC: Component Composability in Frontend Plugins #16876

benjdlambert opened this issue Mar 15, 2023 · 12 comments
Labels
frontend-system rfc Request For Comment(s)

Comments

@benjdlambert
Copy link
Member

benjdlambert commented Mar 15, 2023

🔖 Need

This RFC is designed to address the topic of being able to configure / replace components deeply nested inside plugins without the additions of props to a public facing component that gets drilled all the way down to where it needs to be.

There's been a few issues and PR's that have popped up that have tried to capture this need like #11819 and #11404, and it might be that one of these ways are what we want to achieve but let's try and collect it all here to come up with a standard or a new system for doing this.

The problem

As the amount of adoption grows, so does requirements for different plugins to do different things, and this sometimes exceeds the capabilities of what the plugin does today. Let's take a few examples from the last few weeks

The list goes on, but the story is the same, contributors want to be able to replace components deeply nested in plugins that aren't accessible to them.

Our solution until this point has been to provide an API for developers to customise these components using props in React components. This then leads to pollution of the API surface for these props.

Let's take a look at the @backstage/plugin-scaffolder Router component, you have these props which all do replacing of some content or component inside the plugin:

export type RouterProps = {
  // This replaces components deep inside the plugin
  components?: {
    ReviewStepComponent?: ComponentType<ReviewStepProps>;
    TemplateCardComponent?:
      | ComponentType<{
          template: TemplateEntityV1beta3;
        }>
      | undefined;
    TaskPageComponent?: ComponentType<{}>;
  };
  groups?: Array<{
    title?: React_2.ReactNode;
    filter: (entity: Entity) => boolean;
  }>;
  // This replaces some Text Component
  defaultPreviewTemplate?: string;
  // This also replaces some Components or Text inside the headers
  headerOptions?: {
    pageTitleOverride?: string;
    title?: string;
    subtitle?: string;
  };
  contextMenu?: {
    editor?: boolean;
    actions?: boolean;
  };
};

Let's take a different plugin, let's take some of the @backstage/plugin-catalog API surface. This plugin is basically engineered for composability in the first place, so that you can provide you own EntityPage component to drive your Entity views inside Backstage. There was an entire epic around Composability specifically around the Widgets and Cards for the Catalog plugin #1536, but as the needs grow, so does the API surface.

export interface EntityLayoutProps {
  children?: React_2.ReactNode;
  // Here's a component that gets replaced
  NotFoundComponent?: React_2.ReactNode;
  // Here's something to show and hide different options
  UNSTABLE_contextMenuOptions?: EntityContextMenuOptions;
  // Here's something to provide additional items
  UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];
}

It could be argued that the UNSTABLE_* API's from the EntityLayoutProps could be solved differently by using #11404 to be able to configure new options, but I'm also highlighting the fact that we don't have a standard for what is a prop and what is not.

These additions of props to override components or text deep inside components promotes propdrilling and messy code of passing components through components and bloats the API surface, making evolvability and maintainability harder in the long run.

🎉 Proposal

I want to preface this by saying 🤷 I don't think we know what this looks like yet, and we want to explore along with the community some form of solution or standard to help us clarify the approach.

From looking through the codebase and some of the requests that we get for customisation, it's simple things like text overrides, to more complex things like replacing entire components with something more custom.

I think that the text example is quite interesting, as #4454 could be a part solution for this. i18n in general is something that would allow us to provide default strings, that you could override with your own locale which could replace the text contents of the things that you're trying to configure or override.

The Component approach is something that's a little more difficult. There's some approaches from other projects like Docusaurus using swizzling, there's also approaches like Adaptable Components #11819, or there could be something entirely new that we come up with here.

@benjdlambert benjdlambert added the rfc Request For Comment(s) label Mar 15, 2023
@padupe
Copy link
Contributor

padupe commented Mar 17, 2023

@angeliski Your initial proposal has been referenced.
How much can we, as a local community (Brazil), corroborate?

@angeliski
Copy link
Contributor

Hi, @padupe I am trying to get back in this RFC but other priorities are blocking me.

I think you can try to solve those points in this comment.

I started to experiment a little with lazy loading translations but I didn't do enough to get a good result yet.

@antoniobergas
Copy link
Contributor

Hi! Just wanted to keep an eye on this RFC, also we did some first few steps to this direction in the Playlist plugin
#16955

@github-actions
Copy link
Contributor

github-actions bot commented Jun 4, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@awanlin
Copy link
Collaborator

awanlin commented Jun 5, 2023

Wondering if there are any ideas form this that could be used here, maybe it's already been mentioned not sure: https://engineering.atspotify.com/2023/05/multiple-layers-of-abstraction-in-design-systems/

@github-actions
Copy link
Contributor

github-actions bot commented Aug 4, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale label Aug 4, 2023
@freben freben removed the stale label Aug 7, 2023
@freben
Copy link
Member

freben commented Aug 7, 2023

Linking in #18372 for context, tangentially related

@github-actions
Copy link
Contributor

github-actions bot commented Oct 6, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Copy link
Contributor

github-actions bot commented Dec 8, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@Rugvip
Copy link
Member

Rugvip commented Dec 12, 2023

There's a lot added towards this in both #19545 and #17436. Most likely the solution here will be to add extensions in the new system as needed to achieve the right level of customizability. We are also experimenting with components refs in the new system that allows for replacement of more widely used components, but it remains to be seen exactly what that will look like in the end.

Copy link
Contributor

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Copy link
Contributor

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
frontend-system rfc Request For Comment(s)
Projects
None yet
Development

No branches or pull requests

7 participants