Skip to content

Commit

Permalink
feat(design-system): better integrate with DI and enforce constraints (
Browse files Browse the repository at this point in the history
…#4634)

* vNext: update components to extend FoundationElement (#4570)

* support foundation element on accordion and accordion item

* update anchor to use foundation element

* update AnchoredRegion to extend FoundationElement

* update Badge to extend FoundationElement

* update breadcrumb and breadcrumb item to extend FoundationElement

* update Button to extend FoundationElement

* update checkbox to extend from FoundationElement

* update Dialog to extend FoundationElement

* update disclosure to extend FoundationElement

* update divider to extend FoundationElement

* update Flipper to extend FoundationElement

* update horizontal scroll to extend FoundationElement

* update Listbox and ListboxOption to extend FoundationElement

* update combobox to extend FoundationElement

* update select to extend combobox and update tests

* fix listbox option styles and export

* update tests (wip)

* update Menu and MenuItem to extend FoundationElement

* update number field to extend FoundationElement

* update base name values

* fix: prevent the mixin helper from copying over constructor properties

* feat: fixture ergonomic improvements for foundation elements

* test: fix Anchor and associated unit tests based on new system

* remove incorrect tagFor usage

* update radio and radiogroup

* update skeleton

* update slider and slider label

* update switch

* update tabs et all to use FoundationElement

* update text area and text field to use foundation el

* Update tooltip to use FoundationElement

* update tests and tree item and view

* remove website from lerna packages in favor of npm registry to prevent breaking changes for the time being

* update progress and progress ring to use Foundation element

* fixing the tests

* feat: enable fixtures to handle N foundation elements and custom system

* fixing tests!

* Change files

* fix errors in fast-website

* update typings for explorer

* update naming convention to lowercase fast

* update imports for sites

* Change files

* update template names to lowercase

* update style casing and apply updates to component registries

* update tsdoc links for templates

Co-authored-by: Rob Eisenberg <[email protected]>

* (vNext) update casing for style exports (#4618)

* update casing  for style exports to illustrate they are functions

* Change files

* add api report

* feat: refactor color recipes (#4623)

* refactor color recipes away from DesignSystem data structure

* rename dir

* cleanup

* factor binary-search out to it's own file

* updating code docs

* Change files

* fixing binary-search

* Update packages/web-components/fast-components/src/color-vNext/palette.ts

Co-authored-by: Brian Heston <[email protected]>

* addressing feedback

* adding readme

* pretty pretty

closes #3833
Co-authored-by: nicholasrice <[email protected]>
Co-authored-by: Brian Heston <[email protected]>

* fix: update storybook to use custom element definitions and fix rollup (#4629)

* update storybook to use custom element defintions

* Change files

Co-authored-by: nicholasrice <[email protected]>

* feat(design-system): better integrate with DI and enforce constraints

* test(DesignSystem): add basic tests for new API behavior

* fix(fast-components): update rollup index to use the new DS API

* Change files

Co-authored-by: Chris Holt <[email protected]>
Co-authored-by: Nicholas Rice <[email protected]>
Co-authored-by: Brian Heston <[email protected]>
Co-authored-by: nicholasrice <[email protected]>
Co-authored-by: EisenbergEffect <[email protected]>
  • Loading branch information
6 people committed May 13, 2021
1 parent 58352f9 commit a0ef378
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 103 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "fix(fast-components): update rollup index to use the new DS API",
"packageName": "@microsoft/fast-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "major",
"comment": "feat(design-system): better integrate with DI and enforce constraints",
"packageName": "@microsoft/fast-foundation",
"email": "[email protected]",
"dependentChangeType": "patch"
}
10 changes: 3 additions & 7 deletions packages/web-components/fast-components/src/index-rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ export * from "./index";
/**
* TODO rename this to FASTDesignSystem when {@link @FASTDesignSystem} interface is removed.
*/
export const fastDesignSystem = new DesignSystem();

Object.values(fastComponents).forEach(definition => {
fastDesignSystem.register(definition());
});

fastDesignSystem.applyTo(document.body);
export const fastDesignSystem = DesignSystem.getOrCreate().register(
...Object.values(fastComponents).map(definition => definition())
);
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const verticalSliderStyles = css`
export const sliderLabelStyles = (context, definition) =>
css`
${display("block")} :host {
// font-family: ${bodyFont};
font-family: ${bodyFont};
color: ${neutralForegroundRestBehavior.var};
fill: currentcolor;
}
Expand Down
17 changes: 11 additions & 6 deletions packages/web-components/fast-foundation/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -759,17 +759,22 @@ export interface DelegatesARIATextbox extends ARIAGlobalStatesAndProperties {
export type DerivedDesignTokenValue<T> = T extends Function ? never : (target: HTMLElement) => T;

// @alpha (undocumented)
export class DesignSystem {
export interface DesignSystem {
// (undocumented)
applyTo(element: HTMLElement): Container;
register(...params: any[]): DesignSystem;
// (undocumented)
register(...params: any[]): this;
withElementDisambiguation(callback: ElementDisambiguationCallback): DesignSystem;
// (undocumented)
withElementDisambiguation(callback: ElementDisambiguationCallback): this;
// (undocumented)
withPrefix(prefix: string): this;
withPrefix(prefix: string): DesignSystem;
}

// @alpha (undocumented)
export const DesignSystem: Readonly<{
tagFor(type: Constructable): string;
responsibleFor(element: HTMLElement): DesignSystem;
getOrCreate(element?: HTMLElement): DesignSystem;
}>;

// @public
export interface DesignSystemConsumer {
// (undocumented)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,89 +1,118 @@
import type { Constructable } from "@microsoft/fast-element";
import { expect } from "chai";
import type { Container } from "../di";
import { Container, DI } from "../di";
import { uniqueElementName } from "../test-utilities/fixture";
import { DesignSystem, DesignSystemRegistrationContext } from "./design-system";

describe("DesignSystem", () => {
it("Should return the same instance for the same element", () => {
const host = document.createElement("div");
const ds1 = DesignSystem.getOrCreate(host);
const ds2 = DesignSystem.getOrCreate(host);

expect(ds1).to.equal(ds2);
});

it("Should find the responsible design system for an element in the hierarchy", () => {
const host = document.createElement("div");
const child = document.createElement("div");
host.appendChild(child);

const ds1 = DesignSystem.getOrCreate(host);
const ds2 = DesignSystem.responsibleFor(child);

expect(ds1).to.equal(ds2);
});

it("Should initialize with a default prefix of 'fast'", () => {
const host = document.createElement("div");
const container = new DesignSystem().applyTo(host);
let prefix = '';

expect(container.get(DesignSystemRegistrationContext).elementPrefix).to.equal(
"fast"
);
DesignSystem.getOrCreate(host)
.register({
register(container: Container) {
prefix = container.get(DesignSystemRegistrationContext).elementPrefix;
}
});

expect(prefix).to.equal("fast");
});

it("Should initialize with a provided prefix", () => {
const host = document.createElement("div");
const container = new DesignSystem().withPrefix("custom").applyTo(host);
let prefix = '';

expect(container.get(DesignSystemRegistrationContext).elementPrefix).to.equal(
"custom"
);
DesignSystem.getOrCreate(host)
.withPrefix("custom")
.register({
register(container: Container) {
prefix = container.get(DesignSystemRegistrationContext).elementPrefix;
}
});

expect(prefix).to.equal("custom");
});

it("Should apply registries to the container", () => {
it("Should apply registries to the container associated with the host", () => {
let capturedContainer: Container | null = null;
const host = document.createElement("div");
const container = new DesignSystem()

DesignSystem.getOrCreate(host)
.register({
register(container: Container) {
capturedContainer = container;
},
})
.applyTo(host);
});

expect(capturedContainer).to.equal(container);
const container = DI.getOrCreateDOMContainer(host);
expect(container).equals(capturedContainer);
});

it("Should provide a way for registries to define elements", () => {
let capturedDefine: any;
const host = document.createElement("div");
new DesignSystem()
DesignSystem.getOrCreate(host)
.register({
register(container: Container) {
capturedDefine = container.get(DesignSystemRegistrationContext)
.tryDefineElement;
},
})
.applyTo(host);
});

expect(capturedDefine).to.not.be.null;
});

it("Should provide a way for registries to get the default prefix", () => {
let capturePrefix: string | null = null;
const host = document.createElement("div");
new DesignSystem()
DesignSystem.getOrCreate(host)
.withPrefix("custom")
.register({
register(container: Container) {
capturePrefix = container.get(DesignSystemRegistrationContext)
.elementPrefix;
},
})
.applyTo(host);
});

expect(capturePrefix).to.equal("custom");
});

it("Should register elements when applied", () => {
it("Should register elements", () => {
const elementName = uniqueElementName();
const customElement = class extends HTMLElement {};
const host = document.createElement("div");
const system = new DesignSystem().register({
register(container: Container) {
const context = container.get(DesignSystemRegistrationContext);
context.tryDefineElement(elementName, customElement, x =>
x.defineElement()
);
},
});

expect(customElements.get(elementName)).to.be.undefined;

system.applyTo(host);
DesignSystem.getOrCreate(host)
.register({
register(container: Container) {
const context = container.get(DesignSystemRegistrationContext);
context.tryDefineElement(elementName, customElement, x =>
x.defineElement()
);
},
});

expect(customElements.get(elementName)).to.equal(customElement);
});
Expand All @@ -93,7 +122,7 @@ describe("DesignSystem", () => {
const elementName2 = uniqueElementName();
const host = document.createElement("div");
let capturedType: Constructable | null = null;
const system = new DesignSystem()
DesignSystem.getOrCreate(host)
.withElementDisambiguation((name, type, existingType) => {
capturedType = existingType;
return elementName2;
Expand All @@ -119,8 +148,7 @@ describe("DesignSystem", () => {
);
},
}
)
.applyTo(host);
);

expect(capturedType).to.not.be.null;
expect(customElements.get(elementName)).to.not.be.undefined;
Expand All @@ -131,28 +159,31 @@ describe("DesignSystem", () => {
const elementName = uniqueElementName();
const customElement = class extends HTMLElement {};
const host = document.createElement("div");
const system = new DesignSystem().register(
{
register(container: Container) {
const context = container.get(DesignSystemRegistrationContext);
context.tryDefineElement(elementName, customElement, x =>
x.defineElement()
);
},
},
{
register(container: Container) {
const context = container.get(DesignSystemRegistrationContext);
context.tryDefineElement(
elementName,
class extends HTMLElement {},
x => x.defineElement()
);
const system = DesignSystem.getOrCreate(host);

expect(() => {
system.register(
{
register(container: Container) {
const context = container.get(DesignSystemRegistrationContext);
context.tryDefineElement(elementName, customElement, x =>
x.defineElement()
);
},
},
}
);
{
register(container: Container) {
const context = container.get(DesignSystemRegistrationContext);
context.tryDefineElement(
elementName,
class extends HTMLElement {},
x => x.defineElement()
);
},
}
);
}).not.to.throw();

expect(() => system.applyTo(host)).not.to.throw();
expect(customElements.get(elementName)).to.equal(customElement);
});
});
Loading

0 comments on commit a0ef378

Please sign in to comment.