Join #components for more.
Main objective
We want to simplify the front-end development workflow, and improve maintainability of core and contrib themes.
For that we will:
- Reduce the number of framework implementation details required to put templated HTML, CSS, and JS in a Drupal page.
- Define explicit component APIs, and provide a methodology to replace a component provided upstream (in a parent theme or module).
Goals
- HTML markup in core components can be changed without breaking backward compatibility (BC).
- CSS and JS for a component is scoped to the component and automatically attached to it.
- CSS and JS for a component provided by core can be changed without breaking BC.
- Components can be provided by any module and/or theme, and then overridden explicitly or using theme specificity rules.
- All the code necessary to render a component is in the component directory.
- Components declare their props explicitly. Component props are the API of the component.
- Rendering a component in Twig uses the familiar include/embed syntax, with support for Twig blocks (slots).
- Facilitate the implementation of component libraries for design systems of themes.
- Provide an optional way to document components.
Architecture
The main concept is the component directory. Everything related to the component will be stored in that directory.
A directory becomes a component directory if it meets the following criteria:
- Contains a component definition file: my-component.component.yml
- Contains, at least, a Twig file with the name of the component: my-component.twig.
- It is stored in a module or a theme directory under "/components". Components directories can reside in nested directories for organization, but never inside another component directory.
Discovery
Components are plugins. The parsed component definition file (my-component.component.yml) constitutes the plugin definition. The plugin discovery will scan all modules and themes that contain a /components directory recursively using the existing YamlDirectoryDiscovery (using a recursive filtered iterator).
Automatic libraries
Each component will declare a library automatically with the CSS and JS assets contained in the component directory. This library will be attached to the page automatically when the component is rendered. This means that front-end developers no longer need to learn about declaring libraries, and how to attach them to the page.
It will be possible to override the automatically defined libraries when more control over its definition is needed. To do so you can add the library definition inside of the component metadata.
Component negotiation
Including a component in a Twig template looks like this:
{{ include('my-theme:my-component', {
prop1: content.field_foo
}) }}
If the component is defined by a module then use 'my-module:my-component'. Components defined in modules cannot be replaced, and therefore the component will be found in the module folder.
When Drupal encounters 'my-theme:my-component' it will search for all the components with a machine name 'my-theme:my-component'. There might be more than one if a sub-theme is replacing that particular component (see Component replacement below). The negotiation will choose the component with the following priority rules.
- The component is in the active theme.
- The component is in one of the base themes of the active theme. The closer in the inheritance chain, the more priority.
This intentionally matches the priority rules used for templates sharing the same name.
Component replacement
Themes and modules can replace components provided by other themes and modules.
Themes can replace a component by using replaces: my-theme:my-component in the component metadata. Themes can replace components provided either by modules or by themes which they extend. Note that when Drupal encounters my-theme:my-component it my use a component defined in my-other-theme if it replaces the component.
Modules cannot replace components provided by themes or other modules.
In order to replace a component, the props and slots declared on the component replacement need to be compatible with the ones declared by the component being replaced. This will be enforced programmatically.
Edge cases
PHP code
Initially we will not allow components to declare PHP code to be executed in the context of a component.

Follow-up tasks
- Per #3313520-26: Single-directory components in core and #3313520-28: Single-directory components in core, create a child issue for discussing incorporation of this concept into entity bundle classes per #3313520-25: Single-directory components in core.
| Comment | File | Size | Author |
|---|

Comments
Comment #2
e0ipsoComment #3
cilefen commentedDon't we have to go to 10.1.x for features now that 9.5 and 10.0 are in beta?
Comment #4
mherchelYep! I think @e0ipso is being extra ambitious!
I'm excited about this one!!!
Comment #5
ckrinaThis can become an incredible improvement in Drupal's front-end devs live quality! Huge +1 for this game-changer proposal. Really excited too!
Comment #6
rodrigoaguileraIs there any way to express my +1 without a comment?
Anyway big yay for this :)
Shouldn't this go in the "ideas" queue?
https://www.drupal.org/project/issues/ideas
Comment #7
lauriiiThe ideas queue is maintained by product managers and is geared towards proposing core product changes. This is more of an API change than a product change so from my perspective it seems fine to keep in the core queue.
Comment #8
nod_linking to history :)
Comment #9
jonmcl commentedI think this would be an interesting addition. Have you all seen the work being done in https://www.drupal.org/project/sfc ? I think it's a different approach, but may be some lessons learned that can be shared.
Comment #10
afinnarn commentedI like the idea of further developing the idea of components, and I wonder if anything can be drawn from Symfony and https://symfony.com/doc/current/ux-twig-component/index.html
There seem to be similarities, but I am too unfamiliar with this to make any meaningful comments other than providing a cross-link. I do hope that Drupal core leverages as much of Symfony as possible vs. developing very similar but incompatible solutions since that should ease the burden on maintenance.
Comment #11
afinnarn commenteduh oh...I think I inadvertently changed the issue metadata since I was typing while it was changed...backing away from the keyboard but please re-update that to be correct.
Comment #12
mherchel😆 happens to the best of us
Comment #13
drubbWhat a great addition! Love it +1
Comment #14
mathieuspil commentedI couldn't aggree more! But hey, about 95% of this ticket is how we built Compony for D8 back in 2019 :p
Which is also compatible for D9 and later:
This video outlines the idea. Even with component-specific php files :D
The difference was: you didn't really need a yml-file defined definition of a component, as we figured that a component is defined by a theme function. And so the key was the twig-discovery. Whichever twig file that was essentially used by the theming layer, was the component that defined its own assets and was loaded by the theming layer and libraries system.
We were so fan of the idea that we figured it would take off in the space of Drupal theming, so we built a platform (compony.io) as a repository of components that were defined within their own folders. From there you could also download a custom gulp-setup that would create css and js files within the component-specific directories as needed.
We also documented how to extend your own components with component-variations etc etc on the documentation page
This feels like a clone, but 2 major Drupal versions later: +1
Comment #15
lhockley+1 from me.Would be another leap towards modernizing the framework.
Comment #16
samuel.mortensonI maintain https://www.drupal.org/project/sfc and totally support this!
My only comment on the proposal is that the .yml file should be optional - a plugin deriver (or however you implement this) can look for the .twig file instead. You can determine the plugin ID from the .twig file, then look for .css and .js files with the same filename in the same directory. I think this is better DX and probably addresses the majority of components, which have one CSS and one JS file (or less).
Less files === more good, which is SFC's unofficial slogan, probably. Good luck!
Comment #17
jeremycaldwell commented+1 from me as well. This looks like a fantastic way to do what we already try to do by creating custom block template files and using using the theme's libraries.yml file to reference the individual CSS and JS files. Rolling that functionality right into core would be fantastic and set us up for proper component libraries moving forward.
Comment #18
pcate commented+1 This would be a massive improvement how Drupal themes are built, particularly with design systems.
Comment #19
idiaz.roncero+1 to this. I've been using a similar approach by using Radix's theme (which autoloads libraries if you follow a given directory structure) and twig, and it's a bliss. Powering this with core APIs and a more declarative approach (the yml file) would be extremely powerful.
Comment #20
hot_sauce commentedBig +1 to this too!
Took me a few minutes to wrap my head around what was being proposed because of how different it would be (@mherchel wrote a good blog post about it here that really helped) but I think that this would go a long way to lowering some of the entry cost for someone coming in to Drupal front end development for the first time. A common frame of reference for people familiar with other systems will go a long way to helping bring in other developers as well.
Comment #21
alvar0hurtad0+1
I believe it's a big step forward.
Comment #22
bernardm28 commented+1 This is pretty cool. If there was a way of previewing said components that be great also.
I think Patternlab and Storybook were great because they promoted components but also had a visual component to it.
I realize a visual component is hard to maintain in core so maybe there could be a way left for the components to plugin into something else.
Comment #23
ctrladel+1 from me as well. I've been working on RJSF which allows for decoupling the bulk of a component's form/data model from Drupal but doesn't touch much on creating a self contained component.
I agree yml should be optional, frontend developers and frontend tooling are usually more json focused so would lower the barrier to entry.
A few initial thoughts
1) External components should be able to be used alongside module/theme defined components. For example sourcing from npm packages in the libraries directory. Could pull in https://drupal.org/project/gdwc components that way.
2) Components should be fully accessible from the various apis.
3) Would be useful to include at least one integration into the Drupal authoring experience initially. Perhaps with blocks and layout builder?
Comment #24
stmh commented+1 from my side! My 2 cents:
My wishes for this new system are, that Drupal provides a plugin-type and a standard deriver for the above mentioned component-structure but allow contrib to add, subclass or create new derivers for other design systems/ component-libraries, so they are easily to ingrate with drupal. For example we use https://www.miyagi.dev as our component solution in the frontend, which differs a little bit from the proposed structure of the component. In fact it's our 4th iteration we have in use, after storybook, patternlab and (back in the 7.x days) TCM
Allowing us to integrate systems like miyagi with drupal would be a big win for us.
On the other hand, there is still so much work to do: all the manual mapping of field values to component properties could be streamlined, which is currently done manually in the theming-layer via preprocess-hooks or twig. UI Patterns went into the right direction here, but not sure, what the current status is. Having a way to map fields to component properties in an semi-automated way via an UI would empower site-builders to install a component library and map them to the view modes of their own entities.
I see here a lot of potential if we have a component plugin as part of Drupals core which is tightly integrated into its other systems and is extendable via custom derivers and subclasses.
Comment #25
larowlanI think there's a place for entity bundle classes here too - eg for wiring up data to a component
Comment #26
mherchelBig +1 to that. I discussed this with @e0ipso in Slack and he suggested he could add a
useInkey within the component's YML file that could do this.@e0ipso, should we add this to the issue summary?
Comment #27
bardiuk commentedI like the idea!
Comment #28
e0ipsoIn reply to #26
I think that's on brainstorming phase at the moment. Probably worth discussing in a child issue, when we are ready to that.
Comment #29
e0ipsoI noted a few comments (like #16) mentioning making the plugin definition file optional. While I resonate completely with making things simpler, I belive that some of the info in that file is essential. The mere presence of the file is not the only purpose, but its content as well. In other words, we not only need to know where the component is but we need the metadata in that file as well.
Comment #30
larowlanCould we use front matter in the twig file like help topics do instead of yml? They're plugins too from memory
Comment #31
samuel.mortenson@e0ipso I agree that a place for extra data is needed (yml or as #30 mentions front matter), but is there anything critical in the yml that couldn't be determined from filenames? I think you could determine a plugin/component ID and generate a Drupal library without an extra file.
Comment #32
grienauer+1 !
Comment #33
parisekMy two cents, we are using something similar in our agency and for us it was better to use Twig Annotation for component description like
{#
name: "Price list"
description: "Used for Paragraph - Price list"
#}
Comment #34
g4mbiniIn reply to #24
@stmh Indeed mapping from site building (and also clean render elements) is more streamlined than mapping from preprocesses and theme functions :
UI Patterns do it this way.
And you know what !? Good news UI Patterns is now actively maintain. We actually released a new version (8.x-1.3) during our DrupalCon session where we presented the UI Suite Initiative (Low-Code Theming Experience with UI Suite).
Comment #35
pdureau commentedHello,
Thanks @e0ipso for this issue. And thanks @stmh & @G4MBINI for mentioning https://www.drupal.org/project/ui_patterns
Indeed, UI Patterns module exists since 2017, has more than 3600 sites reporting using it, and is already used in big projects.
(Disclaimer: I am one of the co-maintainers)
Many, if not all, requirements of this issue are already fulfilled by UI Patterns:
Sometimes, doing things a bit differently:
UI Patterns is more flexible and allows component definition to be stored anywhere in module/theme, and component templates to be stored anywhere in templates/, without losing features
UI Patterns expects an explicit CSS & JS attachment in the component definition, to allows: dependencies, async & defer attributes, minification management... Anyway, an automatic attachment mechanism could be added in a future release if needed.
UI patterns introduce a pattern() function which is a bit more comfortable than include() & Twig blocks because it allows the call of components and their variants instead of directly the template file.
UI Patterns use the regular preprocess function (hook_preprocess_pattern_COMPONENT_ID) . Anyway, such PHP processing is not really expected those days.
There is more :) UI Patterns goes beyond the "template to template" API, proposing a clean and powerful integration with both:
Me and the UI Suite team are happy to see this discussion about UI components having a new momentum here. 👍
Comment #36
markconroy commentedThis is getting a MASSSIVE +1 from me. Looks fantastic.
Comment #37
birk commented+1
It seems we all been using our own different variations (and implementations) of this, so I'll chip in with the solution we've been using.
Component structure
Instead of looking for a .twig or .yml, the handler assumes that directory is the component. This allows for components that just is a single .js file.
This also means none of the files is required, which is a big relief simply needing a new and basic component.
The handler then scans the _components/ directory to build a list of all the components, and their file structure.
Each component is then made into a drupal library, with all the .css and .js files.
And a theme in the theme registry, that uses the same base hook allowing attachment of libraries, and other centralized preprocessor related functionality. The theme entry also makes sureto include the component-name.theme file (if it exists).
By utilizing Drupals existing theme system, it's easy to include directly in twig (or anywhere else), because it's called with a render array:
{{ {'#theme': 'component-name', '#data': {property: 'value'} }There's some default variables for the theme entry (
datais one, which can always be used as a generic object, so most of the time no additional variable is needed).It's always possible to include a component-name.yml to extend the theme or library:
Finding components
Before the handler knows which directories to scan it invokes a
hook_component()hook, that fills the directories (an outdated approach, extension.component.yml and YamlDiscovery would've better):This tells the handler to look inside the themes/mytheme/templates/_components/ and the modules/custom/mymodule/components/ directory, it supports sub directories so each directory can group components together.
Final thoughts
We haven't had the need for variants or overrides of components yet. But since this uses existing Drupal systems maybe theme_suggestions and library overrides could be used for this.
What I like about this solution is it's realy easy to create a new component, there's no boilerplating, no definition or metadata file is required (but still supported).
Getting a standard in core would be amazing, hopefully one that cherry picks the best from all the different solutions already described in this issue.
Comment #38
vijaycs85Based on the approach proposed in #2702061: Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering) we created a theme and launched a D8 site in 2017. you can see our implementation at Druponent for reference. It is definitely outdated profile, but just to give an idea of our implemenation.
Comment #39
drubbThe Components Module should be mentioned here, too:
https://www.drupal.org/project/components
It does some basic stuff.
Comment #40
WebbehAdded follow-up issue proposed in #24-26 to issue summary.
Comment #41
tintoVery interesting idea!
But how will the equivalent of theme suggestions look? Like this:
Or will theme suggestions become obsolete altogether?
Comment #42
jonathanshawComponents are more than an organising convenience for themers. Their metadata is a crucial glue that bridges design systems. Drupal theming, and Drupal site building.
I think the key issue here is the metadata and how it is structured. If we do this right, then contrib and core can easily iterate and build on it without painful BC.
It might be worth gathering reference examples of metadata syntax from patternlab, storybook, UI patterns etc.
2 issues cross my mind:
- dummy data really helps visual style guides
- data typing helps site building UI by narrowing the kinds of data structure that can be mapped to a certain property.
Comment #43
stmh commentedMiyagi for example uses dedicated files for name, mock-data, json-schema, the template file, css and js. There is a naming convention, so its easy to find the right files.
Miyagi relies on the declared json-schema to expose the provided property names and their types. It is using the schema for e.g. validating the mock data. The beauty of json schema is that you can compose complex components by referencing other components as childs and use it for validation.
In my eyes a component consists of a namespace, a name=foldername, a json schema exposing properties and their types, a template file and other assets like js or css-files.
I think we should focus on the integration part, and keep style guides, etc out of drupals world, there are already good solutions for that problem.
Here‘s an example for a json schema of a teaser component
The prototype for the miyagi ui patterns integration uses these schemas to validate drupals data for a particular component, if requested.
Comment #44
e0ipsoI created #3314063: Define metadata for Single Directory Components for the discussion around component metadata and YML discovery.
Comment #45
e0ipsoIt seems that several of us have already been doing this in our separate silos. To me this is a big indicator that standarization will be a big win on this topic.
During research phase, prior to posting this issue, I contacted some of the maintainers to contributed projects in this space to understand the architectures being proposed. Some of the projects are almost a 1-to-1 match with the proposal here, which validates the approaches.
Most notably, UI Patterns, has a ton of extensions on top of the concept of components (check them out here). I believe that UI Patterns' ecosystem will benefit a lot from the work here, and will be critical to validate the implementation of SDC in core.
I tried to combine the findings of my research, with my own professional experience, along with substantial feedback from @lauriii, @mikeherchel, @hawkeye.twolf, @wimleers (and others), into CL Components. I am hoping to open this proof of concept to scrutiny from the community, and discuss the decision process that led us there.
I will start posting more child issues, and invite anyone willing to collaborate with ideas, code, project management, or even take over the initiative.
Comment #46
alexander tallqvist commentedBig +1! I've personally been using Compony mentioned in #14. Anything even slightly resembling their solution would be a great addition!
Comment #47
xmacinfoWill that proposal also make it easier to load images, like SVG files? For example, a module can ship with icons and loading its image files without creating a stream wrapper would be perfect.
Comment #48
luke.leberThe one consideration that I feel needs to be taken is regarding platform lock-in.
We've made the move toward using components in order to break down silos between technology. Unless there's a way to use said components on non-Drupal sites, I feel there's a lot of lost potential. It's a two-sided door: components built in Drupal should be able to be used elsewhere, and components built elsewhere should be able to plug into Drupal too. Any chance the front-end can get off the island just like the back-end did?
Comment #49
thamas+1 +1 +1 +1 🙂
Comment #50
pdureau commentedHello tinto,
About your proposal :
in my humble opinion, components must be Drupal agnostic, so not be dependant of Drupal entities or entity types like views, nodes, taxonomy terms, fields, content bundles... Components must follow an UI/UX logic, not a business and/or data storage logic. Examples: card, banner, toast, menu, breadcrumb, tabs, buttons...
So, they can be used in many different place in Drupal (a same card component can be a entity display layout, a views row...), and they can be shared between many websites.
Templates suggestions are still useful to do "presenter templates", that means templates without HTML markup, calling the expected components with a Twig function. Those presenters templates :
Comment #51
pdureau commentedHi Luke.Leber,
It sounds like a dream. I am working with corporate design systems developments for 6 years, and this was one of the main concerns for my clients and my team.
However, they are 2 issues with components sharing nowadays : the component format & the description format.
The chosen component format is locking us in a specific tech stack:
There is no common description format :
Comment #52
e0ipso@pdureau regarding #51:
It would be great to move the discussion forward in #3314063: Define metadata for Single Directory Components.
Comment #53
pcate commentedUnlike in the issue summary screenshot, I would suggestion having the
README.mdfile follow the same naming convention as the other files. e.g.my-cta.readme.md. Or, at least have it be an alternative to theREADME.mdname.I could see having a lot of files named
README.mdbeing confusing when editing multiple ones or trying to find a specific file.Comment #54
e0ipso@PCate, that makes sense. The main drawback is that we'll lose the git forge integrations on the name `README.md`. GitHub, GitLab, and others detect that file and treat it as documentation for the folder they are hosted in.
With the
README.mdproposal you can navigate to the component directory (example) and see the documentation inlined:Comment #55
ijf8090 commentedMeaning of 'BC' reference was not obvious to me, suggesting a clarification.
Comment #56
poniesBackward compatibility (BC)
Comment #57
pcate commented@e0ipso, I'm not sure how often I would be viewing the component documentation in GitHub/GitLab, etc, but I can see that being a nice fallback option.
Perhaps the best way to implement things would be a couple standard filename conventions, and then allow the filename to be fully customized in the
ymlfile with adoc: my-custom-name.mdkey/value, or something similar.For instance:
docfilename.my-component.readme.mdfileREADME.mdfile.I could see the customized option being a big plus if you want to integrate with another documentation site generator where the markdown filename is used as the site path.
Comment #58
e0ipsoComment #59
e0ipsoI added #3315021: Define component negotiation and replacement for SDC for discussions on the negotiation and replacement of components.
Comment #60
ctrladelReally enjoying seeing how everyone has been solving this problem and sharing their approaches. With such a large problem space I thought it would be helpful to take a pass at reasoning out all the moving pieces I see, what makes sense for core support, and figuring out where we'd want flexibility for contrib.
I’ve introduced the concept of a “Component API” below and in true Drupal fashion I’m not referring to a pure API but an API as a group of services and syntax we all agree to use the same way.
Define
Definition: The service/process that describes a standardized and validated metadata structure of a component that includes everything Drupal will need to author, store, and render a component.
Discovery: The service/process responsible for finding components. This should be built so that contrib can add additional discovery methods, then core can implement a YamlDirectoryDiscovery approach for modules/themes without limiting other methods.
Create
Deriver/Integration: A service/process that uses the Discovery service to consume component definitions and expose them to a specific part of Drupal.
Authoring: The service/process responsible for using a component’s definition to create an authoring form. This will likely be unique per deriver/integration, some instances will need form api, some will need field api, some may use an entirely different authoring experience.
Validation: The service/process responsible for validating submitted content against the component definition. Ideally it would be universal to the component with the deriver/integration providing data in the structure expected by the component, the data is validated against the component definition, and the deriver/integration reports back errors to an author. The argument could be made that this needs to be unique per deriver/integration since some instances will be using form api, some will need field api, some may use an entirely different approach.
Storage: The service/process responsible for storing submitted content. This will likely be unique per deriver/integration, some destinations will need store content using form api, some will need field api, some may use an entirely different storage method.
Display
Manipulation: The service/process responsible for altering saved content before it is passed to display. Ideally this is universal to the component with the deriver/integration providing content in a valid component data structure to a service that is part of Component API which then returns the processed data back to the deriver/integration.
Display: The service/process responsible for displaying or exposing a component to the frontend. This will likely be handled by the deriver/integration but they should be able to make use of a common way to render/expose the content. I.e. the proposed ‘#theme’ => ‘component-name’ render array.
Comment #61
e0ipsoThanks for this!
- We have a ticket open for the definition of components.
- The discovery is for now only based on YML by modules and themes. Adding JSON is trivial (since JSON is valid YML after all). The front matter approach will couple 1 component to 1 single twig template, which prevents having component variants in the future. Discovery has not been contested / controversial so far, so there is no ticket yet.
- In my opinion, all the "Create" section belongs to contrib for now. Otherwise this effort will never make it in core. So I would propose to postpone that.
- Manipulation is heavily tied to the definition, because it will leverage the props schema. For core, this step is simple because components are only used by developers writing code (and not editorially).
- There is a lot to talk about in "Display". This (I think) includes component negotiation and replacement, auto-injection of JS & CSS, escaping of slots, building auto-derived libraries and applying refinements, injecting component specific context into Twig, etc. This will likely be implementation details, so we'll (probably) discuss them the last.
Comment #62
dalemoore commentedDefinitely +1 and following this. I'm trying to create my first component library and there's so many ways/approaches to do it, in and out of Drupal.
Comment #63
brianperryA little late to the party here, but don't take my lateness as a lack of enthusiasm. Seeing some version of this concept represented in core has been one of my all time Drupal dreams :) Big +1 in general, and very excited to see the activity on this issue already.
Many topics have already been covered, but one thing I'm excited about is that I think the implementation as conceptualized thus far could provide a great developer experience for using web components (as in custom elements) with Drupal. A directory with a js file, yaml file, and twig template would be enough for someone to get started. They wouldn't have to do any work to ensure Drupal loads the JS file, and furthermore they don't necessarily need to compile or bundle their js. Their twig template could include
<template shadowroot="open">to use Declarative Shadow DOM (browser support appears to be on track to expand beyond Chrome based browsers by the time this would become a reality) as a low effort approach to server side render the web component.Thinking more in the contrib space - with existing solutions to automatically generate a manifest describing a custom element, creating a tool to translate this to Drupal's yml format seems possible. This could make it easier for projects like Generic Drupal Web Components or Outline to ship with Drupal-ready components if so desired. I'd be interested in trying to explore this concept as part of https://www.drupal.org/project/gdwc
Looping back to one recent comment:
> In my opinion, all the "Create" section belongs to contrib for now. Otherwise this effort will never make it in core. So I would propose to postpone that.
I completely understand the perspective of wanting to exclude this from scope. And I'd agree that a version of this without a 'create' concept that makes it into core is better than a version that never finds a way into core, or greatly increases the timeline. But I really hope that we don't lose track of this concept for core, or leave it to contrib indefinitely. Having the integration represented somehow in Drupal's UI would play to some of Drupal's unique strengths. And it is also a big part of what made UI Patterns feel like magic to me :)
For the record, https://www.drupal.org/project/component_blocks is probably my favorite specific contrib implementation of this concept, which ties together a few other projects mentioned earlier in this thread.
Comment #64
ctrladelIt makes perfect sense for core to only support YML discovery, the important part is that core's discovery implementation should allow contrib space to provide other methods of discovery and definition parsing. In my mind support for definitions in json, frontmatter, web component manifest format, etc would come from contrib space discovery services operating alongside core's yml module/theme discovery.
Agreed that the Create section vastly increases the proposed scope of work while decreasing the chance of this making it into core in any timely fashion. That being said direct integration into Drupal's authoring experience is IMO the ultimate use case for a system like this and one that should heavily inform decisions being made now around metadata, discovery, rendering, etc so that contrib or core aren't limited when we do get around to building the Create step.
This brings up an interesting point, if we skip over the "Create" step what purpose do the props serve in the initial implementation? Without a controlled authoring experience or validation the manipulation step lacks a trusted data structure to operate against. It does consolidate the number of preprocess functions which is ++ but functionally ends up in the same spot as templates and preprocess hooks are today. Today's state being a good faith effort to provide correctly structured data with the assumption that manipulation code and component templates incorporate error handling to catch the most obvious of edge cases.
As far as my diagram goes, I think I missed giving Twig and Render array a blue background in the "Integration/Deriver" box. All the details you listed are about figuring out how to tie together Drupal's various systems into a singular developer friendly experience so would fall under "integrating" the concept of a single directory component into the existing render array and twig systems. While the Twig and Render array boxes shown in the Display section are more about usage. Usage meaning as a developer once this is built I should be able to do
'#component' => 'my-component'or{{ include('my-component', {})}}and get a rendered fully functional component without worrying about how the internals of single directory components interact with Drupal. Overall I agree this part sounds like implementation details that will largely leverage already well understood and built out systems.Comment #65
heddnI'm glad component_blocks.module was mentioned in #63. It was part of the original inspiration work behind https://www.drupal.org/project/component_library. That module actually has optional integration with that module. I'd really like to plug some of the ground breaking work in that module that already does much of what we are discussing here. All within the confines of the existing theme sub-system, thanks to some very cleaver wiring up early in the theme bootstrap. There was a drupalcon europe session highlighting parts of this module given by Fabian Franz, but the sessions haven't gone live yet for me to link to it.
Comment #66
mrweiner commentedI agree with this. Taking the SFC module as an example, there should probably be some way for that approach to translate into this new paradigm. It's taking inspiration from VueJS, which uses defineProps() in the inline javascript to define the allowed props, their typing, etc. In that spirit, I think that SFC would likely prefer to be able to generate the metadata inline without the explicit requirement of having a yml file. After all, requiring a second file means that it is no longer an SFC.
Comment #67
mherchelI want to +💯 @brianperry's comment in #63
Comment #68
matthieuscarset commentedMassive +1 for Single File or Directory Components in core. Looking forward to seeing this happening soon.
Comment #69
e0ipsoThis has been quiet for a while. However, much has been going on in the mean time. Many hours of discussions, reaching out, implementing, changing, and deleting code.
Before getting in technical details here are some goals and aspirations that we have distilled for SDC.
Goal 1. SDC is just the first step
While the introduction of the concept of components is a big step forward, it is not the end goal. Adding a solution for server rendered components in Drupal core aims to:
The current scope of work only addresses the first step, Standarize component solutions, while leaving the others for the contrib space.
Projects that provide a different component solution like Compony, UI Suite, CL Components, and others, will see their different solution on this small part (the component definition) superseded by the new core standard. That is a good thing. UI Suite (for instance) can now leverage the new component solution, and not maintain its own. The project can now focus on their goal of exposing components to editors and site builders, with their low-code/no-code vision.
It is in scope of this proposal to ensure that components are extendable in a way that these preexisting projects can add their specific metadata and conventions to achieve their goals. Having multiple projects to validate this extensibility will help us develop a more solid solution.
Goal 2. A tool for front-end developers
Single Directory Components (or SDC) are designed to improve the developer experience of front-end developers. This is the most important reason to add SDC into core.
Components will lead to cleaner templates, more maintainable themes, less boilerplate, more intentional UI APIs, and promote component re-use. These are important consequences of improving the developer experience. We'll make developer error less likely by stablishing a framework that:
On top of this we'll be shipping with accessory contrib modules to make development easier. Like a component audit page with a checklist for each component, and some insight on the internals.
All the work in SDC needs to be compatible with current front-end processes and workflows, and not get in the way. These may include SCSS compilation, JS bundling and transpilation, asset optimization, hot reloads, etc. In other words, even if SDC are driven by JS and CSS, developers should be able to make them render as they are being updated even when using TypeScript and Sass (as an example).
To achieve these goals we are presenting the SDC project, which contains a PoC of the new core module. There is still lots to do, and we will be creating tickets for those in the module. It is our hope to collaborate there with project management, writing tests, reviewing the code, fixing bugs, validating the integrations, etc.
Comment #70
geek-merlinAwesome!
Let me bring up a use case that sooner or later will pop up: Markup-less components.
Say, i have 2 components that share the same JS. Rather than going back to ye olde days of explicit library definition, i try and move that JS to a sub-component (that has no markup, but implicitly defines a library, and saves me the work of explicitly defining the library) and include it in the 2 components.
Can this be a allowed?
Comment #71
e0ipso@geek-merlin I think this can be achieved, yes. It might require an empty twig file as of today, though.
Comment #72
birk commentedIf the discovery is made by directories instead of by files, any file can be optional.
This will allow for components that are only a single js, css or twig file. A component can even a single metadata file, that defines a pseudo library by setting up dependencies to other components.
We are using this solution in our implementation, and then we skip any directory (and file) starting with _ (underscore). This allows for asset directories and files that shouldn't affect the component implementation directly.
Comment #73
geek-merlin#71 and #72 sound great!
Comment #74
e0ipsoUpdated issue summary with the corrected assumptions on the PoC.
Comment #75
andypostMaybe instead of *.component.yaml we get in #3075427: Create TemplateDiscovery for plugin managers to use and start use frontMatter for discovery?
Comment #76
geek-merlin@andypost: I opened #3339203: Use FrontMatter for discovery, but see relevant points ageinst it.
Comment #77
geek-merlinComment #78
amjad1233A huge +1, maybe we can also ship some base standard components(optional) as part of distributions-and-recipes... https://www.drupal.org/about/core/strategic-initiatives-distributions-an...
Comment #79
e0ipsoThere is now an initial Merge Request to add a new experimental module into core for this endeavor #3340712: Add Single Directory Components as a new experimental module. This took quite a lot of effort, but it will hopefully be a step forward! 🎉
Comment #80
kostyashupenkoIt's all great ideas (i'm so happy to see so many initiatives regarding component's approach)
My 50 cents are:
1. You want to build UI components, right? Example: my-button. For which purposes we will be able to use it in drupal? Basically components are UI (at least they should, with no strict relation to the drupal's entities for example). That means - my-button component can be input--submit, or link, which is visually looking like a button (so i should be able to select my-button component in view display for example as a field formatter (or some similar technique). In terms of UI - both of these cases provides visual my-button component.
2. How to deal with third-party libraries? Usually on the real projects we installing them with npm (or yarn or pnpm and so on) -> it downloads library sources into node_modules, and then we call it using import statement from js or css. What i want to say - is for example if your component requires slider library. Where this library should live? Inside of component folder (which is logical thing too), or outside, somewhere in the root of theme folder for example (if it's a theme library of course).
3. How to deal with drupal libraries.
I undestand it - but if to think more wide - we will need a component generator script (normally). Similar to drupal's script we using for starterkit theme. Maybe.. it's obvious. I don't know yet. On our real projects we using some custom approach and we have component generator script. By default this script can generate twig, js, css, yaml files. That means - if we have / we will have some template to generate component, we could consider it will have js file inside (which will be empty or almost empty inside by default). And if we don't need this js in drupal - makes sense to not load it in automatical way you proposed. Probably you can say "you can delete this unused js file", but as a developer i'm not sure if my js file will be used later on the project or not. Means - probably we could keep it, but to not use it in drupal. Somehow.
Probably we could check https://www.drupal.org/project/ui_patterns approach - they have a definition of drupal's libraries in component-name.yml files, where you can call your css/js if required, also link dependencies to your component, and so on.
4. For css and js we should have similar approach we have in drupal core -> source css file is `.pcss.css`, and for js files we also have to have 2 files -> one of these is source file, and another one is compiled. I'm not sure the naming of source file `.es6.js` we have in core - is good. Because usually we don't use babel or whatever else on the real projects already several years, since all major browsers supports es6 from the box https://caniuse.com/?search=es6
So i'm thinking about maybe `component-name.behavior.js` or something.
5. Styleguide. Please, somehow. At least let's discuss a global strategy for it. Project needs in 2023 are - to have a very detailed styleguide, so any developer, or PM, or someone from customer's side can review all components existing on the web-site. On the huge projects we may have 10-20 different pages, so it's compilcated to reproduce one or another thing in drupal just to see if my component exist somewhere or not. The thing is - we need some place to review all components at once.
For us (as a Skilld company) - we introduced storybook many years ago, and we still working with it. Basically it's just a tool where you can navigate through the components and build them from atoms (let's say from inputs, buttons, texts) till the full pages, containing views, header, footer, CTs, whatever else.
Styleguide is very important
6. Try to think about non-standard components, like image, or responsive image group components. Recently in Skilld i introduced the following - we'd better to document all image styles and responsive image groups in two different places somehow. It could be some 2 yml files for example, where all styles and groups are described. In that case drupal can somehow re-use this functionality, and also in storybook we can re-use same functionality.
For now we are here - we described simple yml files, containing all image styles and responsive image groups, then we have a custom script for drupal, which can grab these yml files and generate configs for image styles and responsive image groups for drupal.
I don't know (as i said, it's my 50 cents, at least you should keep these ideas in your head, since all these things can REALLY simplify lifes of developers & save time and money)
Comment #81
kostyashupenkoBy the way - we (some people from Skilld, like me, https://www.drupal.org/u/finnsky, https://www.drupal.org/u/andypost, https://www.drupal.org/u/gaydabura) are working on the similar stuff. But it's more custom stuff, than initiative for drupal core. Don't hesitate to ping us, to discuss all these beautiful ideas)
Comment #82
e0ipsoCreated #3345922: Single Directory Components module roadmap: the path to beta and stable for a roadmap.
Comment #83
dalemoore commentedTrying to read through these issues and understanding what this is doing a little better. This is confusing:
Can modules replace components from other themes or modules, or not? The first and last sentences contradict each other. Thanks!
Comment #84
martijn de witIs it possible to change the locations of the components directory? My thought on this; it would better fit in the root of a theme or module. Because templates is "the old way" and not comprehensive for what is inside a component.
Was also thinking of src, but there is also compiled stuff in there.
Comment #85
mherchelYou are 100% correct. I had the same feedback and @e0ipso made the change, although we neglected to update the issue summary. Updating now.
Comment #86
mherchelReplying to @dalemoore comment in #83:
My understanding is that modules cannot replace components from themes. That being said, I'd like to get confirmation from @e0ipso.
Comment #87
pdureau commentedComment moved in this issue: https://www.drupal.org/project/drupal/issues/3340712#comment-14997166
Comment #89
effulgentsia commentedIs there currently any in-progress work on creating a contrib theme (or converting an existing one) to use components exclusively (as in, for all .html.twig files that aren't in the components directory to not render anything directly themselves and instead have their sole logic be to include and pass props to components)? If such work isn't already in-progress, is it part of the vision of SDC, or not really?
Comment #90
effulgentsia commentedRelated to #89, I just now opened #3378588: Convert Umami's node.html.twig to use SDC components.
Comment #91
mherchelIMHO, not everything is or should be a component. That being said, I'm working on a USWDS theme that heavily leverages SDC.
Comment #92
dieterholvoet commentedComment #93
xjmI wonder if this issue should be credited and closed now that it's a stable part of the theme system? If we have post-stable roadmap work, it would make sense to file that as a separate issue.
Comment #94
mherchelMakes sense to me. Closing and crediting, since SDC is now a part of core and stable (in 10.3). Thank you everyone!