Plan how to evolve code component overrides

Created on 17 April 2025, 3 months ago

Experience Builder is designed to facilitate comprehensive theming across an entire site. We previously introduced an experimental concept and solution to override the output of a small set of blocks using JavaScript components: site branding, breadcrumbs, and menu blocks. The implementation was meant to be experimental.

Create an ADR that outlines alternatives and documents our decision on how we plan to evolve this implementation.

๐ŸŒฑ Plan
Status

Active

Version

0.0

Component

Theme builder

Created by

๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @balintbrews
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom AaronMcHale Edinburgh, Scotland
  • ๐Ÿ‡ซ๐Ÿ‡ฎFinland lauriii Finland
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom longwave UK
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL

    Crediting people who were part of the discussion that led to the ADR at Drupal Dev Days in Leuven.

  • Pipeline finished with Canceled
    3 months ago
    Total: 118s
    #476044
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL
  • Pipeline finished with Success
    3 months ago
    Total: 952s
    #476045
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States effulgentsia

    I really like the option 2 proposal that's in the ADR. My one nit though is I don't think we should do it as a custom hook, but instead as a plain async function that's passed to React 19's use() API. In other words, instead of:

    import { useMenuData } from '@/lib/menu';
    
    const NavigationMenu = ({ menuId, level }) => {
      const menuData = useMenuData(menuId, { level });
      // ...
    }
    

    to do:

    import { use } from 'react';
    import { fetchMenuData } from '@/lib/menu';
    
    const NavigationMenu = ({ menuId, level }) => {
      const menuData = use(fetchMenuData(menuId, { level }));
      // ...
    }
    

    This would then also work for other UI frameworks when we add support for them in the future, which we might do soon as part of the CLI work. For example, in Svelte:

    {#await fetchMenuData(menuId, { level }) then menuData}
    ...
    {/await}
    

    One hiccup with this approach though is that preact/compat doesn't implement the use() function. I opened https://github.com/preactjs/preact/issues/4756, but we can't count on that getting done in time. However, I think we can work around that by implementing our own use() function until such time as Preact implements the proper one, and ours can sidestep the need to work with Suspense, because we can rely on either server-side prefetching or async Astro island hydration to make sure we don't hydrate the component until we've already fetched the data and can return it synchronously by the time use() is called.

  • Pipeline finished with Success
    2 months ago
    #491012
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Reviewing at last ๐Ÿ˜ฌ

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Sorry for the long wait. Based on DDD discussions, I expected this to be much bigger than it turns out to be, I should've reviewed this sooner ๐Ÿ™ˆ

    @effulgentsia's remarks in #10 are squarely on the front-end implementation side of this new component source plugin, which I have no strong opinions about.

    I reviewed this from a XB data model + component source architecture + reliability + ecosystem reach POV.

    The ADR simultaneously does not go into detail about the challenges of the most common use case (menu blocks) and also doesn't really explain how we'd make other use cases (think: arbitrary other block plugins such as the branding block). We discussed much of this at length in person at DDD Leuven.

    I think this ADR is a great start, but I think there's a few crucial things that are too open-ended for this ADR to be mergeable. I'm happy to be overruled if all @balintbrews, @longwave, @effulgentsia and @lauriii all think this is sufficiently precise. But I would like to see more detail, because at least to me it's not clear how this proposes to implement "block overrides" for e.g. the breadcrumbs or site branding blocks. ๐Ÿ˜‡๐Ÿ™

    • โœ… Always passing the entire menu tree to the component is not good enough: different menus want to show different slices or subtrees of a menu โ€” for example only the top level, only the first 2 levels, starting at the 3rd level etc.

      The obvious solution to support parametrization: a HTTP API to fetch menu links, for which Drupal core has the โ†’ endpoint.

      ๐Ÿ‘‰ The ADR covers this: +

    • โŒ The ADR does not explain the code component developer/author DX for knowing the shape of the data they would receive.
    • โŒ The ADR does not explain how the breadcrumbs block would work in option 2. Drupal has no HTTP API to fetch the results of a service (the breadcrumb service in the server-side container). Is building such a HTTP API part of the envisioned scope?
    • โŒ The ADR does not explain how the site branding block would work in option 2. There's no HTTP API to fetch (simple) config (the site name + slogan). Core's JSON:API and REST modules both do not support that. Is building such a HTTP API part of the envisioned scope?
    • ๐Ÿค” The ADR does not state whether this would be a new component source plugin, or whether it's just the existing "code component" source but with additional APIs (for data fetching) available. If it's the same component source plugin, how will we ensure that the data-fetching code components end up in the UI library? (See \Drupal\experience_builder\Entity\Component::computeUiLibrary().)

      Can you confirm that the intent in all 3 options is to implement a new "block override" ComponentSource plugin, which just happens to share a lot of infrastructure with the existing "code component" ComponentSource plugin, but is about data fetching (and hence ) instead of providing props/slots?

  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL

    Wim and I will meet tomorrow to talk things through, then I will make the necessary adjustments.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Productive meeting with @balintbrews just now ๐Ÿ˜„ He'll add great clarifications on the ADR ๐Ÿ˜Š๐Ÿ‘

  • Status changed to Needs work 11 days ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States effulgentsia

    Merging the ADR is a good first step. But also, we should remove all traces of code component overrides now that we have a better solution. And best to do that before beta to not have to deal with an upgrade path for it.

  • Merge request !1210Resolve #3519737 "Remove block overrides" โ†’ (Merged) created by wim leers
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    #15: totally! Happy to do that as a secondary MR on this issue. So just did that ๐Ÿ‘

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Yay! Looks like all PHPUnit tests are passing, except for the one I know needs updating (it's become kinda tightly coupled to a particular block_override code component โ€” I need to untangle that later).

    For some reason, Cypress unit & e2e tests are refusing to run though? ๐Ÿ˜… That seems to be an npm infra problem though, because installing Cypress still isn't done after >10 minutes ๐Ÿคช

  • Pipeline finished with Failed
    10 days ago
    Total: 715s
    #537972
  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia larowlan ๐Ÿ‡ฆ๐Ÿ‡บ๐Ÿ.au GMT+10

    Working on the test

  • ๐Ÿ‡ฆ๐Ÿ‡บAustralia larowlan ๐Ÿ‡ฆ๐Ÿ‡บ๐Ÿ.au GMT+10

    Pushed a version that works, we will replace it with a real component that uses drupalSettings in the future, its not relevant for this test.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Thanks, very kind โ€” this wasn't urgent, but it's nice to see this 99% green now ๐Ÿฅณ๐Ÿ™ (Only Playwright expectations still need updating.)

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States effulgentsia

    FYI: I opened ๐Ÿ“Œ Build Breadcrumb and SiteBranding code components Needs work as a child issue of this one, and re-parented ๐Ÿ“Œ Build a navigation code component Active to be a child issue of this one as well.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Thanks! Still missing an issue for a "page title" code component, but @balintbrews thinks that should be done all in one go, so in ๐Ÿ“Œ Build Breadcrumb and SiteBranding code components Needs work .

  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL

    #23: Good catch! I adjusted ๐Ÿ“Œ Build Breadcrumb and SiteBranding code components Needs work to cover that.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    ๐Ÿ“Œ Build a navigation code component Active landed, so now we're down to just ๐Ÿ“Œ Build Breadcrumb and SiteBranding code components Needs work !

  • Pipeline finished with Success
    4 days ago
    Total: 867s
    #543014
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    ๐Ÿ“Œ Build Breadcrumb and SiteBranding code components Needs work is in, rebasingโ€ฆ

  • Pipeline finished with Skipped
    3 days ago
    #544355
  • Pipeline finished with Success
    3 days ago
    Total: 658s
    #544342
  • ๐Ÿ‡ณ๐Ÿ‡ฑNetherlands balintbrews Amsterdam, NL

    Tested the removal on the UI and in the CLI. Everything works as expected. Leaving the issue as NW to finish up the ADR, unless you prefer otherwise, Wim.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States effulgentsia

    The ADR isn't beta blocking, so untagging.

  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Leaving the issue as NW to finish up the ADR, unless you prefer otherwise, Wim.

    ๐Ÿ‘

Production build 0.71.5 2024