Closed EisenbergEffect closed 5 months ago
Another nice to have would be an option for the CLI to upgrade existing projects to the newer way of doing things.
Great feedback @KingOfTac ! @janechu Can you capture the requests for the CLI? I think we have most of this on our list but just want to make sure we don't miss something.
What about a generator for a standalone component with a convention that when followed enables that community component to be pulled into the design system project from the CLI? I was thinking about #3960 and how I might distribute such a thing in this new world. Something like fast add-component https://github.com/CuddleBunny/fast-placeholder
perhaps?
For starters this could just copy the component and register it like the CLI will do with the original fast components. A pipe dream future enhancement could be missing token detection where any design tokens that the new component uses which do not match any in the current project could be raised by the CLI where the end-user is asked whether they want to add that token or substitute with an existing token.
Great feedback. We had thought about supporting multiple project templates but this is more like being able to import a component template. Cool idea. Maybe we could support something like Gist, where you whatever files are in the gist get pulled in? /cc @janechu
I'm really excited about the builder pattern for templates. We've needed to extend fast-foundation
templates by adding extra DOM elements for a few components. The only options have been sub-optimal: to do flaky string concatenation or to copy the FAST template into our design system and modify it. I think the builder pattern will make this a lot cleaner.
For extending and sharing CSS the builder pattern seems less urgently useful; this is because we've been able to leverage the existing appearanceBehavior
pattern to share CSS between components and we haven't needed to extend FAST's CSS as often as we've extended templates. But organizing CSS by purpose as you show in your example looks really tidy so I won't be surprised if we find uses for that pattern too.
Great to hear the builders will be valuable for you @jattasNI. We'll definitely have the template builder work first. I actually spent some time prototyping it today. A little more time next week and I think I will have nailed down the details enough for us to move ahead with that. On the CSS side, there's a lot more to work out, so I think that will probably be the last piece, and we'll likely need a bit more time to experiment with it and see what works.
This is a well thought out write up. It sort of reminds me of the days when frontend tooling was iterating, browserify -> grunt -> gulp -> yeoman / parceljs / create-react-app / etc. type of progression.
The FAST vision for design systems seems more comparable to the yeoman level approach for building frontend projects. These things really helped accelerate and empower (especially smaller) teams to do bigger things. It also helped the need to spawn many projects rapidly.
The trade off with all management and automation systems is control over details in trade for velocity and ease of use. I think this will apply in a similar way to mostly smaller teams who don't necessarily have the resourcing or expertise to build all the details themselves, but want or need a system to fill the resourcing and expertise gap.
Whereas, I would expect for larger teams with 1) a single project to build 2) funding to manage the details and 3) strict specifications requiring exact details, it would be more efficient to directly implement the design system. Just as in the case of yeoman, parceljs, or other build system tools, with a large enough team and specific enough requirements there is always the need to "eject" from the tool and manage the system in full detail manually.
What are your thoughts on this?
It's certainly possible to eject or not use the template DSLs at all. No one is prevented from doing that.
However, the main point is that for the standard components, the core anatomies are largely the same with only a narrow set of variations per component. There are typically core functional structures that are required, if only to ensure that the accessibility model is correct. So, why rebuild that once it's worked out? Just use the DSL to specify the variation you want and be done with it. Hybrid models are also supported. So, if it works for ten of the components but not the eleventh, you can just build custom for the eleventh. It's another tool in the toolbox for any team looking to be efficient in building out a design system.
We've had two years of feedback from partners and customers around this, and paired it with a bunch of performance testing on template variations, so I'm feeling pretty good about forming an API that can handle all the variations and perf optimization scenarios we've seen with plenty of flexibility for things we haven't seen.
Thanks for the reply. It would be interesting to investigate shared tests for conformance as well. This is one step closer to the DIY end of the spectrum but still allows adherence. I'm thinking something similar to what singel tried to do with the single element pattern.
Absolutely. So, one of the cool things is that the build
phase for each template has a validation
step. This allows the anatomy to apply arbitrary rules to ensure functional structures, accessibility, or whatever else is desired.
We tend to duplicate patterns from fast-components, like making a direction token for handling ltr-rtl, appearance behavior pattern like mentioned above, dozens of nitty gritty things like styles for button alignment, and even today I was trying to figure out if FAST has a pattern for z-order management which was closed because of the change in direction.
Some of these problems are going to need to be solved for any design system built on FAST and (at least speaking for us) we are looking to FAST to find the good patterns for localization, accessibility, and handling issues we expect are common like the z-order management.
Having the fast-components as the reference package for components that "do things pretty well" and is worth borrowing ideas from has been useful. It looks like the intention is to do away with that component library from the source tree: https://github.com/microsoft/fast/pull/5853. That also intends to remove the component explorer which is a valuable compare point when testing our fast-foundation based components against a "known good" implementation for filing issues.
Thanks for the feedback @rajsite - while #5853 does remove those packages, #5849 provides some insight into the "why" and reasoning behind that, as well as how we plan on continuing to provide some of those valuable out of the box implementations. If you haven't yet taken a look, hopefully that can provide some additional insight and background to the intent of 5853.
In terms of some of the OOTB patterns and whatnot, @bheston is working on somewhat of a "spec" to detail out plans for starting to abstract out some of the goodness that was previously delivered via fast-components for use in building design systems. While there's an open PR, we feel that a spec will help us scope and plan to scale for what's most urgent, and then what can be followed up with.
For instance, we believe that it's vital to get the adaptive color algorithms and recipes abstracted for use a la carte by folks. What is not known, is how much of an implementation should be brought in immediately and what other abstractions might be valuable. Over time, I could see including baseline resets as css partials, such as the base button styles, etc. Part of this also folds into the later stages of this proposal. Our hope with the spec is that it can help us draw clear lines for where those goodies live and what the best approach for abstraction and delivery is for each (IE, does it become a part of foundation, or does foundation take a dependency to provide that, etc...)
Wanted to get a quick response over - would love to hear more about what specifically has been valuable and how you've been leveraging so we can use that information to make sure our decisions help meet your needs long term!
if only to ensure that the accessibility model is correct
@EisenbergEffect this actually just reminded me of another question I have about these proposed changes.
One of the long terms goals for the Webview UI Toolkit is to make sure that our accessibility model is aligned with that of VS Code core UI. We haven't done much work auditing the differences between the toolkit a11y model and VS Code core a11y model so there might not actually be that big of a difference (at least that's me hoping 🤞), but if possible it would be great to hear a bit more about how much flexibility (or "variations" as you put it) you hope the template DSLs will have?
The underlying need here is that we will always have to defer/align to whatever VS Code has defined as its core a11y model, but it would still be fantastic to take advantage of (or at least partial advantage of) any template DSLs that FAST might ship that ensure good a11y models.
Also forgive any apparent lack of knowledge/correct verbiage on the wider topic of a11y models, it's something I'm still ramping up on/learning about (thus the desire to take advantage of any expertise you all collectively have on the topic).
Great question @hawkticehurst. I feel pretty confident that you'll be able to get what you want. The template DSLs will be pretty flexible, and as always, we want to work with the community to refine these over time. So, if there's something blocking in a particular component DSL design, then we're always open to find a way to fix that. I think early feedback will be key here. To that end, let me just show some real code from my first prototype.
Here's what some code to produce an AccordionItem
would look like, to setup the same default template structure that we have today:
AccordionItemAnatomy.define()
.anatomy(item =>
item
.heading(heading =>
heading
.button()
.startSlot()
.endSlot()
.icons(icons =>
icons
.expanded({ fallback: "icon..." })
.collapsed({ fallback: "icon..." })
)
)
.defaultSlot()
).build();
This creates an anatomy with a heading area that contains the expand/collapse button, with a start and end slot, as well as custom icons for both expanded and collapsed states. It also has a default slot where the item's content will be rendered. When you call build
, the API returns a strongly typed ViewTemplate
that can be used with anything that matches the interface for an AccordionItem
. Of course, by pairing that with the AccordionItem
base class and your own styles, you can very quickly build a production-ready standard AccordionItem
component.
Now, imagine you want to change the AccordionItem
anatomy a bit. Here's another code sample from my prototype that shows a different configuration:
AccordionItemAnatomy.define()
.parts({
button: "control",
region: "content",
})
.anatomy(item =>
item
.heading(
heading =>
heading
.html`first`
.button()
.startSlot({ name: "prefix" })
.html`last`
)
.defaultSlot()
).build();
This anatomy is quite a bit different. It has a heading area, but inside that there's some custom html before and after the expand/collapse button. That could be any HTML you want, including using FAST HTML Directives and bindings. Then notice that we only have a start slot and that we've renamed it to be "prefix" instead of "start". We also don't have any icons or their associated slots. Of course there's a default slot for item content as well. Besides customizing the anatomy, we've also customized the part names by renaming the "button" part to "control" and renaming the "region" part to "content".
The accessibility model is baked into the standard parts of each anatomy. But what you can see here is that you could choose not to leverage a particular part if it didn't match your model, and you could instead replace just that part with custom HTML. We hope that won't be necessary for most folks, but it's something this type of API enables, which we couldn't really do before.
If anyone is interested in how the AccordionItemAnatomy
class shown above is implemented, here's the code for that. Please bear in mind that this is early prototype code and will probably change a bit. That said, I'm pleased so far with how easy it is to build these anatomy classes based on core FAST primitives.
type AccordionItemParts =
| "region"
| "heading"
| "button"
| "heading-content"
| "start"
| "end"
| "icon"
| "expanded-icon"
| "collapsed-icon";
export class AccordionItemAnatomy extends Anatomy<AccordionItem, AccordionItemParts> {
protected begin() {
this.html`<template class="${x => (x.expanded ? "expanded" : "")}">`;
}
heading(callback: (a: AccordionItemHeadingAnatomy) => void) {
this.internals.anatomy(AccordionItemHeadingAnatomy, callback);
return this;
}
defaultSlot() {
const { part } = this.internals;
return this.html`
<div
class="region"
${part("region")}
id="${x => x.id}-panel"
role="region"
aria-labelledby="${x => x.id}"
>
<slot></slot>
</div>
`;
}
protected end(): void {
this.html`</template>`;
}
}
class AccordionItemHeadingAnatomy extends Anatomy<AccordionItem, AccordionItemParts> {
protected begin(): void {
const { part } = this.internals;
this.html`
<div class="heading"
${part("heading")}
role="heading"
aria-level="${x => x.headinglevel}"
>
`;
}
button(options?: Partial<SlotOptions>) {
const { part, slot } = this.internals;
return this.html`
<button
class="button"
${part("button")}
${ref("expandbutton")}
aria-expanded="${x => x.expanded}"
aria-controls="${x => x.id}-panel"
id="${x => x.id}"
@click="${(x, c) => x.clickHandler(c.event as MouseEvent)}"
>
<span class="heading-content" ${part("heading-content")}>
${slot(Object.assign({ name: "button", fallback: "" }, options))}
</span>
</button>
`;
}
startSlot(options?: Partial<SlotOptions>) {
const { slot } = this.internals;
return this.html`${slot(Object.assign({ name: "start" }, options), ref("start"))}`;
}
endSlot(options?: Partial<SlotOptions>) {
const { slot } = this.internals;
return this.html`${slot(Object.assign({ name: "end" }, options), ref("end"))}`;
}
icons(callback: (a: AccordionIconAnatomy) => void) {
this.internals.anatomy(AccordionIconAnatomy, callback);
return this;
}
protected end(): void {
this.html`</div>`;
}
}
class AccordionIconAnatomy extends Anatomy<AccordionItem, AccordionItemParts> {
protected begin(): void {
const { part } = this.internals;
this.html`<span class="icon" ${part("icon")} aria-hidden="true">`;
}
expanded(options?: Partial<SlotOptions>) {
const { part, slot } = this.internals;
return this.html`${slot(Object.assign({ name: "expanded-icon" }, options), part("expanded-icon"))}`;
}
collapsed(options?: Partial<SlotOptions>) {
const { part, slot } = this.internals;
return this.html`${slot(Object.assign({ name: "collapsed-icon" }, options), part("collapsed-icon"))}`;
}
protected end(): void {
this.html`</span>`;
}
}
Took a minute to digest the new syntax, but it looks great.
@EisenbergEffect thank you for the write-up/explanation, this helps a lot!
I'm excited to see how this evolves, but it all looks very promising. I especially appreciate the ability to include arbitrary HTML as a sort of backdoor for the whole process if it's needed.
Also as time/energy permits, I would love to see more examples of this API as it evolves over the coming months.
Next week I plan to start the work to move foundation to Iteration 4. That won't include the anatomies but it will get us through the breaking changes needed to enable that in the next iteration. I'm very much looking forward to that milestone. Once that's in place we can start building anatomy APIs in an incremental fashion for each component without introducing breaking changes.
In other words, I hope you'll be seeing more of this soon 😄
Update: Foundation Iteration 4 is committed to our main branch and released in beta. The CLI does not yet generate components based on this version, but that work is in progress now.
From iteration 1 the FAST Foundation is really a time saver just as it is for now and it will just improve in the future.
The ability to manipulate the anatomy of templates. This can be really useful in combination with the correct styles to create comprehensive and intuitive components.
No, I've thought that in the past of some features but they became really handy in many situations.
I don't really care about React wrappers. Everything else is already included.
I couldn't see a direct guideline on how to document the components that are created. I think the Storybook will help, but I'm more looking for things like automatic documentation generation from JSDoc annotations.
Good support and really good community interactions. But as far as I can see they are already extremely good. Thank you much for that! :)
First a small component library that will be used in some smaller projects. If the library works well in those smaller projects we want to make our web component library a standard for each new web project.
Aside from that I've just created an issue at the custom elements analyzer project concerning FAST Element compositions. I currently use the analyzer to automatically create the documentation of my project which works kind of good. If you don't already have it on your agenda it would be really nice to have this analyzer or similar tools available or at least good working as they really decrease the time that is necessary to create documentations.
Great feedback @sonntag-philipp ! On the documentation/analyzer front, we have plans around that as part of the CLI. We've recently done some work to generate custom-elements.json
files from our foundation components and then to generate markdown documentation from that. We're looking at bringing this into the CLI so that the same can be auto-generated for any design system.
Alright, I'm really glad to hear that! Are you able to share some information of the parts that will describe the custom elements? Like, if they will be statically analyzed JSDoc annotations like the ones already used by the cem analyzer? I could also think of a completely different solution that uses TypeScript decorators or something else. It's also fine if you can not say anything about that for now. I just want to be somewhat safe for the future in the ways I will create my component documentation :)
At present, the plan is to use the CEM analyzer. This is what we're using for our current foundation docs. We hope to have the CLI set this up for any design system projects as well.
Until there is an issue specifically for tracking the template builder work for iteration 5. This brings up being able to customize shadow parts for some interesting styling scenarios, and likely would fit somewhere in that work in some shape. #6523
for iteration 4, the registration APIs that enabled overrides indeed was never used as we override (copy and edit) templates directly. so iteration 5 with breaking down template portions seem very promising. love the idea.
back to iteration 4, can you please clarify the registry: customElements
?
export const designSystem = Object.freeze({
prefix: "fluent",
shadowRootMode: "open",
registry: customElements
});
In the future the browser will support Scoped Element Registries. For vNext we're working to make sure the APIs are all ready for that when it arrives. So, for this configuration object, it has a registry
option so that you can specify a custom registry for your system components. However, you can also just use the global customElements
registry, which is what the setup here shows (and the only option today).
Thanks. was surprised to see it already baked in to the API
At present, the plan is to use the CEM analyzer. This is what we're using for our current foundation docs. We hope to have the CLI set this up for any design system projects as well.
trying to wrap my head around an issue where design system provider is used by consumers to customize the prefix.
in @sonntag-philipp cem issue
the following
/**
* @tag qds-button
*/
export class Button extends FoundationButton { }
will output to JSON as
"tagName": "odui-button",
"customElement": true
but then consumers of a library prefixing their provider will no longer get intellisense over their <custom-button>
tags.
is it a highly rare use-case?
Up to this point, @microsoft/fast-foundation only provides you with pre-constructed templates for each component. That's great for most cases, but a few scenarios aren't possible. Examples include: You can't add/remove/change slots. You can't add/remove/change parts. You can't add new HTML before, after, or around the existing markup.
Spot on! 🥇
This point is something my lean and mean engineering team is facing as potential maintenance burden if we are copying and extending component templates in order to:
This is moreso commentary; I wish I had a solution to offer but I'm not smart enough to write a language yet 😅
Update: I'm currently working on tech to get us all the way to Iteration 6 and beyond. I'm taking a bit of a different approach to what is talked about here from an implementation perspective. The new approach is much more powerful and will enable many creative possibilities and collaborations. I've probably got another month or two of work to get it ready for a PR. Thank you for your patience.
@EisenbergEffect Any more updates on this new approach? This is a real cliffhanger, and I'm a little curious! 😄
@ThorFjelldalen I left Microsoft in November of last year. Since then, I haven't been able to contribute much to FAST. The work I was doing back in March was a side project and unfortunately had to be paused as it didn't align with what I needed to do for my current business.
Ah, I understand. Thanks for the quick answer!
Okay, so... if EisenbergEffect is gone, what's the status of Fast? Is there any chance of this ambitious project moving forward? Is MS still putting any resources into this project? An update would be appreciated.
Okay, so... if EisenbergEffect is gone, what's the status of Fast? Is there any chance of this ambitious project moving forward? Is MS still putting any resources into this project? An update would be appreciated.
The project is still moving forward. I won't speak fully for @EisenbergEffect, he is still a valued part of the Steering Committee, and we just met together recently (last week). It's still moving forward and different people across Microsoft make up the core maintainers, as well as a few core people outside of MS. The work that has been done on FAST has always been an OSS effort and that continues to be the case as it will into the future.
Not only does Microsoft help maintain FAST but it is also a user of FAST. To use it, we needed a version of Web Components fully aligned with Fluent 2. Over the last year or so, that is where a lot of our focus has been centered and that effort is nearing completion to the point that we have a large set of Fluent UI Web Components available to use inside Microsoft and by 3rd parties. Once teams have a chance to onboard to these components, focus and investment should shift back toward FAST as teams need features and improvements.
Alright, I'm really glad to hear that! Are you able to share some information of the parts that will describe the custom elements? Like, if they will be statically analyzed JSDoc annotations like the ones already used by the cem analyzer? I could also think of a completely different solution that uses TypeScript decorators or something else. It's also fine if you can not say anything about that for now. I just want to be somewhat safe for the future in the ways I will create my component documentation :)
Might be of interest https://github.com/genesiscommunitysuccess/custom-elements-lsp
Closing this as Foundation is being deprecated, for details please refer to #6955.
Last week @chrisdholt shared our vision for the future of FAST Components. In that post, we briefly touched on how FAST Foundation might evolve and play a more prominent role in the future, combined with the introduction of our new command-line interface (CLI). I want to take some time now to expand those ideas, paint a bit of a technical vision for the future, and show you how that might unfold over a series of iterations.
The Big Picture: Design System as Code
Wait. What? Isn't this post supposed to be about FAST Foundation and Design Systems?
Why yes, it is.
The goal for FAST Foundation and what we call "Adaptive UI" has always been to get us to what I'm going to refer to as "Design System as Code". Here's a simple definition inspired by the above.
We believe that DSaC will become a essential DesignOps and UX Engineering practice, used in conjunction with experimentation and continuous delivery.
To provide some light justification for this claim, let's look back at a trend in the broader industry over the last couple of decades. We can see a common pattern that goes something like this (using DevOps and IaC as an example again):
(I should note that step 6 often comes before 4, depending on market opportunity. Eventually, it repeats itself later after standardization occurs, where the original provider deprecates the previous version and ships a new offering or they make significant changes to the existing product to support standards. The reality of the innovation/standardization tug-of-war is always more complex, but hopefully, this still makes its point.)
Ok, before we get too far off track, let me pull this back to design systems. This post isn't intended to analyze the history of software industry trends or DevOps. It's about where we're going with FAST Foundation.
So, let's take the IaC and DevOps sequence from above and look at it in terms of design systems.
Interestingly, the design system industry was stuck in phase 3 for a very, very long time. It is only within the last two years that phases 4 and 5 have begun. This stall was mainly due to Web Components taking about 7 - 8 years of standards work to ship in every browser. That was a huge milestone that unlocked the industry and enabled us to move forward with FAST.
The Past, Present, and Future of FAST Foundation
As it exists today, FAST Foundation was a first attempt at a 2nd generation framework for design systems. We think it's pretty nifty, but we're also keenly aware of its shortcomings and limitations (thank you, the community, for all the amazing engagement and feedback over the last two years!). In the following few sections, we'll look at the previous and current states of FAST Foundation as an initial phase 5 offering, and then I'll walk you step-by-step through the changes we're considering and show you how we're going to unlock the path to phase 6.
Iteration 1 (Past)
The
@microsoft/fast-foundation
library started as a collection of component base classes and templates. We used it to build the first version of the Fluent UI Web Components. As the community came on board, we got a lot of feedback, mainly that things weren't configurable. For example, component names, prefixes, shadow DOM modes, etc. couldn't be changed. So, we built a new set of APIs that led us to...Iteration 2 (Present)
@microsoft/fast-foundation
now consists of component base classes, template factory functions, and various primitives, such as a design token object model and a design system configuration model. It's a good start at building the runtime of a DSaC system, and we used it to build v2 of the Fluent UI Web Components, which are the foundation for various experiences in Edge, Windows 11, and MSN. However, FAST Foundation still has a few problems:Most people don't experience these problems through FAST Foundation but through what we've previously called "FAST Components," which introduced another set of challenges:
Ultimately, this method just isn't working. It's not meeting the community's needs, nor is it giving us the power we need to move forward with v3 of the Fluent UI Web Components. The next set of iterations lays out how we will solve these problems.
Iteration 3 (In Progress)
The next iteration isn't so much a change in
@microsoft/fast-foundation
as it introduces the FAST CLI. The CLI is intended to address several of the biggest problems we've seen the community struggle with:The CLI will provide a command to generate a design system similar to the following.
What we previously shipped as a component library in
@microsoft/fast-components
will now be a set of templates for your design system. The goal is that within a couple of minutes, you should be able to generate a new design system and then immediately be able to run Storybook to see all your Web Components in action. You should also be able to add new Foundation components as needed with a simple command like this:Based on the feedback we've heard from the community, we think this will significantly improve your experience building design systems right out of the gate. Once you no longer fight against a preset package of components like
@microsoft/fast-components
but instead own the design system code directly, working with them becomes much more manageable. You'll be able to look at the styles for each component and see how the tokens are used. If you need to add custom styles, it's no longer a series of arcane overrides. If you need to introduce your design tokens on top of the base tokens, you just create them and use them in the styles you control, following existing patterns you can see. Many things get much easier to use and learn.Iteration 4 (Future)
While Iteration 3 puts a lot more control into your hands and gets you up and running faster, the underlying programming model is still burdened by old APIs that were designed based on needing tons of runtime configuration and overrides. Iteration 4 will remove that code, addressing the following problems:
We'd like to remove the registration APIs that enabled overrides. These are no longer needed now that you control the design system code. We can then move the Web Components back to a normal registration approach. The CLI templates will update in lockstep with this and will still support centralizing various configuration details using standard JavaScript techniques. To illustrate this, let's look at a few code samples.
First, the CLI will create a simple constant to store shared configuration details. This constant will be generated based on the answers provided to CLI prompts when you create a new project.
design-system.ts
The component code will follow standard patterns that give you full control. Let's look at how a button might be defined in your design system project. Here's what the folder layout could look like:
First, the core component class (state, behavior, etc.) doesn't change from today's implementation. The CLI generates a class for you based on the appropriate foundation component base class.
button.ts
Second, the template for your component also doesn't change (see Iteration 5 below for how we'll introduce customization in the future). The CLI generates a
.template.ts
file with a simple export of the foundation template.button.template.ts
The styles are handled in much the same way. The CLI will generate default styles for you to start.
button.styles.ts
The first new part is that we generate a
.definition.ts
file. This file contains all the metadata thatFASTElement
needs to define the component.button.definition.ts
The second new part is that we generate a
define
file that invokes FAST's define API, provided by the definition, against your default registry.define.ts
The above code, which would all be generated by the CLI, provides complete customization of the component base class and styles and centralized configuration for the design system. With this new setup, we can enable these capabilities without the runtime cost of the current FAST Foundation
provideDesignSystem().register()
APIs. You also retain complete control over when/how the platform defines the component. If you want to auto-define components, import thedefine
module wherever you use the component.The CLI can even configure
package.json
entry points for you so that you can have shorter paths.If you want to control the platform more, import the definition and call
define
yourself whenever you want. You'll even be able to leverage the upcoming W3C Scoped Element Registries feature as soon as it's available.Notice how this approach now also introduces the first governance features. By removing the runtime configuration APIs, you can now prevent consumers of your design system from overriding styles, changing tokens, or messing with your templates. You still have full control, but you can now guard against misuse.
Iteration 5 (Future)
Things are starting to come together, but we've still got problems. Iteration 5 seeks to address the following issues:
Up to this point,
@microsoft/fast-foundation
only provides you with pre-constructed templates for each component. That's great for most cases, but a few scenarios aren't possible. Examples include:To address these needs, I'm proposing that in addition to exporting pre-built templates for components, we also export "template builders," which can be used to construct OpenUI-based template variations.
Let's look at an example of using a
ButtonAnatomy
template builder to customize an Open UI-based button template.button.template.ts
These aren't the actual APIs, but hopefully, this serves as an example of what we could enable. We want to make
@microsoft/fast-foundation
into more and more of a toolkit that helps you build design systems following Open UI patterns. This is the first iteration where something that resembles DSaC starts to emerge, with a fully-typed object model for Open UI-based Web Components.Once again, you may be thinking, "Wait. What? Wasn't it a goal to have customization without runtime cost? This seems like it could impact startup time."
On that note...
Let's talk about a parallel effort already in development as part of the FASTElement 2.0 stream of work: FAST Template Pre-compilation.
So, what's the runtime cost of the template builder code and template customizations?
ZERO.
Actually, the costs are less than zero. We have tech we're working on that allows us to run the template builder code...at build time. The result is an entirely pre-compiled template, ready for immediate instantiation. The builder code, FAST's
html
template function, and the full FASTElement template compiler can all be tree shaken away. You are left with precisely what you need to render your component. Nothing more.We'll be talking about this more in the future. I want to let people know that this is being built in a general-purpose way for use with all your FAST-based Web Components and with whatever bundler you want.
Iteration 6 (Future)
There's still one little problem left to address:
Hopefully, you can start to see where we're going with this. The CLI has been generating starter CSS into projects for each component. In Iteration 6, we'll introduce a CSS API for Open UI-based Web Components, similar to the templating API. Additionally, we'll enable the CLI to generate a default CSS configuration using this API. This iteration is the most speculative part of what we're proposing, but you can imagine something like this:
button.styles.ts
Naturally, we'll use our pre-compilation technology to run this at build time so that you have optimized CSS that needs no further processing to render. This process allows us to tree shake the builder and shake out the
css
template helper, CSS directives, and associated runtime code.Beyond FAST Foundation
We have arrived at something we can call "Design System as Code," enabled by design tokens, standard component behaviors, and standard anatomy/presentation object models. However, there's much more we can unlock once we get to this point. It's just the beginning. For example, the builder code shown above has a declarative look. Could a JSON or Yaml language be mapped over the builders? Could tools be created to emit this JSON? There are lots of exciting opportunities.
Wrapping Up
We're not satisfied with the state of design system creation in the industry. We believe we've made solid strides in improving it with what we've got in FAST today. However, we're not there yet. Above I've outlined what I think are the next set of iterations in our foundation technology, which will take FAST and the industry forward. We would love to hear your thoughts.
If you're not sure how to provide feedback, here are a few things we'd love to hear from you about: