Skip to content

Commit

Permalink
feat: update divider to use custom states (#31735)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdholt authored Jun 18, 2024
1 parent 6ef8678 commit 81f2ac5
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat: update divider to use custom states",
"packageName": "@fluentui/web-components",
"email": "13071055+chrisdholt@users.noreply.github.com",
"dependentChangeType": "patch"
}
31 changes: 25 additions & 6 deletions packages/web-components/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,13 @@ export const accordionTemplate: ElementViewTemplate<Accordion>;
// @public (undocumented)
export class AnchorButton extends BaseAnchor {
appearance?: AnchorButtonAppearance | undefined;
appearanceChanged(prev: AnchorButtonAppearance | undefined, next: AnchorButtonAppearance | undefined): void;
iconOnly: boolean;
iconOnlyChanged(prev: boolean, next: boolean): void;
shape?: AnchorButtonShape | undefined;
shapeChanged(prev: AnchorButtonShape | undefined, next: AnchorButtonShape | undefined): void;
size?: AnchorButtonSize;
sizeChanged(prev: AnchorButtonSize | undefined, next: AnchorButtonSize | undefined): void;
}

// @internal
Expand All @@ -147,7 +151,6 @@ export const AnchorButtonAppearance: {
readonly primary: "primary";
readonly outline: "outline";
readonly subtle: "subtle";
readonly secondary: "secondary";
readonly transparent: "transparent";
};

Expand Down Expand Up @@ -374,9 +377,15 @@ export const AvatarTemplate: ElementViewTemplate<Avatar>;
// @public
export class Badge extends FASTElement {
appearance: BadgeAppearance;
appearanceChanged(prev: BadgeAppearance | undefined, next: BadgeAppearance | undefined): void;
color: BadgeColor;
colorChanged(prev: BadgeColor | undefined, next: BadgeColor | undefined): void;
// @internal
elementInternals: ElementInternals;
shape?: BadgeShape;
shapeChanged(prev: BadgeShape | undefined, next: BadgeShape | undefined): void;
size?: BadgeSize;
sizeChanged(prev: BadgeSize | undefined, next: BadgeSize | undefined): void;
}

// @internal
Expand Down Expand Up @@ -468,6 +477,7 @@ export const borderRadiusXLarge = "var(--borderRadiusXLarge)";
export class Button extends FASTElement {
constructor();
appearance?: ButtonAppearance;
appearanceChanged(prev: ButtonAppearance | undefined, next: ButtonAppearance | undefined): void;
autofocus: boolean;
// @internal
clickHandler(e: Event): boolean | void;
Expand All @@ -479,7 +489,7 @@ export class Button extends FASTElement {
// @internal
disabledFocusableChanged(previous: boolean, next: boolean): void;
// @internal
protected elementInternals: ElementInternals;
elementInternals: ElementInternals;
get form(): HTMLFormElement | null;
formAction?: string;
static readonly formAssociated = true;
Expand All @@ -491,13 +501,16 @@ export class Button extends FASTElement {
formNoValidate?: boolean;
formTarget?: ButtonFormTarget;
iconOnly: boolean;
iconOnlyChanged(prev: boolean, next: boolean): void;
keypressHandler(e: KeyboardEvent): boolean | void;
get labels(): ReadonlyArray<Node>;
name?: string;
protected press(): void;
resetForm(): void;
shape?: ButtonShape;
shapeChanged(prev: ButtonShape | undefined, next: ButtonShape | undefined): void;
size?: ButtonSize;
sizeChanged(prev: ButtonSize | undefined, next: ButtonSize | undefined): void;
type: ButtonType;
// @internal
typeChanged(previous: ButtonType, next: ButtonType): void;
Expand All @@ -513,7 +526,6 @@ export const ButtonAppearance: {
readonly primary: "primary";
readonly outline: "outline";
readonly subtle: "subtle";
readonly secondary: "secondary";
readonly transparent: "transparent";
};

Expand Down Expand Up @@ -1668,7 +1680,6 @@ export const CompoundButtonAppearance: {
readonly primary: "primary";
readonly outline: "outline";
readonly subtle: "subtle";
readonly secondary: "secondary";
readonly transparent: "transparent";
};

Expand Down Expand Up @@ -1712,19 +1723,26 @@ export const CompoundButtonTemplate: ElementViewTemplate<CompoundButton>;
// @public
export class CounterBadge extends FASTElement {
appearance?: CounterBadgeAppearance;
appearanceChanged(prev: CounterBadgeAppearance | undefined, next: CounterBadgeAppearance | undefined): void;
color?: CounterBadgeColor;
colorChanged(prev: CounterBadgeColor | undefined, next: CounterBadgeColor | undefined): void;
count: number;
// (undocumented)
protected countChanged(): void;
dot: boolean;
dotChanged(prev: boolean | undefined, next: boolean | undefined): void;
// @internal
elementInternals: ElementInternals;
overflowCount: number;
// (undocumented)
protected overflowCountChanged(): void;
// @internal
setCount(): string | void;
shape?: CounterBadgeShape;
shapeChanged(prev: CounterBadgeShape | undefined, next: CounterBadgeShape | undefined): void;
showZero: boolean;
size?: CounterBadgeSize;
sizeChanged(prev: CounterBadgeSize | undefined, next: CounterBadgeSize | undefined): void;
}

// @internal
Expand Down Expand Up @@ -1875,14 +1893,17 @@ export function display(displayValue: CSSDisplayPropertyValue): string;
export class Divider extends FASTElement {
// (undocumented)
alignContent?: DividerAlignContent;
alignContentChanged(prev: DividerAlignContent | undefined, next: DividerAlignContent | undefined): void;
// (undocumented)
appearance?: DividerAppearance;
appearanceChanged(prev: DividerAppearance | undefined, next: DividerAppearance | undefined): void;
// (undocumented)
connectedCallback(): void;
// @internal
elementInternals: ElementInternals;
// (undocumented)
inset?: boolean;
insetChanged(prev: boolean, next: boolean): void;
orientation?: DividerOrientation;
// @internal
orientationChanged(previous: string | null, next: string | null): void;
Expand Down Expand Up @@ -2293,7 +2314,6 @@ export const MenuButtonAppearance: {
readonly primary: "primary";
readonly outline: "outline";
readonly subtle: "subtle";
readonly secondary: "secondary";
readonly transparent: "transparent";
};

Expand Down Expand Up @@ -3301,7 +3321,6 @@ export const ToggleButtonAppearance: {
readonly primary: "primary";
readonly outline: "outline";
readonly subtle: "subtle";
readonly secondary: "secondary";
readonly transparent: "transparent";
};

Expand Down
73 changes: 73 additions & 0 deletions packages/web-components/src/divider/divider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ test.describe('Divider', () => {
await expect(element).not.toHaveJSProperty('elementInternals.ariaOrientation', 'horizontal');
});

test('should add a custom state matching the `orientation` attribute when provided', async () => {
await element.evaluate((node: Divider) => {
node.orientation = 'vertical';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('vertical'))).toBe(true);

await element.evaluate((node: Divider) => {
node.orientation = 'horizontal';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('vertical'))).toBe(false);
expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('horizontal'))).toBe(true);
});

test('should initialize to the provided value attribute if set post-connection', async () => {
await root.evaluate(node => {
node.innerHTML = /* html */ `
Expand Down Expand Up @@ -135,4 +150,62 @@ test.describe('Divider', () => {

await expect(element).toHaveJSProperty('inset', true);
});

test('should add a custom state matching the `appearance` attribute when provided', async () => {
await element.evaluate((node: Divider) => {
node.appearance = 'strong';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('strong'))).toBe(true);

await element.evaluate((node: Divider) => {
node.appearance = 'brand';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('strong'))).toBe(false);
expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('brand'))).toBe(true);

await element.evaluate((node: Divider) => {
node.appearance = 'subtle';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('brand'))).toBe(false);
expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('subtle'))).toBe(true);
});

test('should add a custom state of `inset` when the value is true', async () => {
await element.evaluate((node: Divider) => {
node.inset = true;
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('inset'))).toBe(true);

await element.evaluate((node: Divider) => {
node.inset = false;
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('inset'))).toBe(false);
});

test('should add a custom state matching the `align-content` attribute value when provided', async () => {
await element.evaluate((node: Divider) => {
node.alignContent = 'start';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('align-start'))).toBe(true);

await element.evaluate((node: Divider) => {
node.alignContent = 'end';
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('align-start'))).toBe(false);
expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('align-end'))).toBe(true);

await element.evaluate((node: Divider) => {
node.alignContent = undefined;
});

expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('align-start'))).toBe(false);
expect(await element.evaluate((node: Divider) => node.elementInternals.states.has('align-end'))).toBe(false);
});
});
69 changes: 39 additions & 30 deletions packages/web-components/src/divider/divider.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import {
fontWeightRegular,
strokeWidthThin,
} from '../theme/design-tokens.js';
import {
alignEndState,
alignStartState,
brandState,
insetState,
strongState,
subtleState,
verticalState,
} from '../styles/states/index.js';

/** Divider styles
* @public
Expand All @@ -36,7 +45,7 @@ export const styles = css`
height: ${strokeWidthThin};
}
:host([inset]) {
:host(${insetState}) {
padding: 0 12px;
}
Expand All @@ -49,90 +58,90 @@ export const styles = css`
padding: 0 12px;
}
:host([align-content='start'])::before,
:host([align-content='end'])::after {
:host(${alignStartState})::before,
:host(${alignEndState})::after {
flex-basis: 12px;
flex-grow: 0;
flex-shrink: 0;
}
:host([orientation='vertical']) {
:host(${verticalState}) {
height: 100%;
min-height: 84px;
}
:host([orientation='vertical']):empty {
:host(${verticalState}):empty {
min-height: 20px;
}
:host([orientation='vertical']) {
:host(${verticalState}) {
flex-direction: column;
align-items: center;
}
:host([orientation='vertical'][inset])::before {
:host(${verticalState}${insetState})::before {
margin-top: 12px;
}
:host([orientation='vertical'][inset])::after {
:host(${verticalState}${insetState})::after {
margin-bottom: 12px;
}
:host([orientation='vertical']):empty::before,
:host([orientation='vertical']):empty::after {
:host(${verticalState}):empty::before,
:host(${verticalState}):empty::after {
height: 10px;
min-height: 10px;
flex-grow: 0;
}
:host([orientation='vertical'])::before,
:host([orientation='vertical'])::after {
:host(${verticalState})::before,
:host(${verticalState})::after {
width: ${strokeWidthThin};
min-height: 20px;
height: 100%;
}
:host([orientation='vertical']) ::slotted(*) {
:host(${verticalState}) ::slotted(*) {
display: flex;
flex-direction: column;
padding: 12px 0;
line-height: 20px;
}
:host([orientation='vertical'][align-content='start'])::before {
:host(${verticalState}${alignStartState})::before {
min-height: 8px;
}
:host([orientation='vertical'][align-content='end'])::after {
:host(${verticalState}${alignEndState})::after {
min-height: 8px;
}
:host([appearance='strong'])::before,
:host([appearance='strong'])::after {
:host(${strongState})::before,
:host(${strongState})::after {
background: ${colorNeutralStroke1};
}
:host([appearance='strong']) ::slotted(*) {
:host(${strongState}) ::slotted(*) {
color: ${colorNeutralForeground1};
}
:host([appearance='brand'])::before,
:host([appearance='brand'])::after {
:host(${brandState})::before,
:host(${brandState})::after {
background: ${colorBrandStroke1};
}
:host([appearance='brand']) ::slotted(*) {
:host(${brandState}) ::slotted(*) {
color: ${colorBrandForeground1};
}
:host([appearance='subtle'])::before,
:host([appearance='subtle'])::after {
:host(${subtleState})::before,
:host(${subtleState})::after {
background: ${colorNeutralStroke3};
}
:host([appearance='subtle']) ::slotted(*) {
:host(${subtleState}) ::slotted(*) {
color: ${colorNeutralForeground3};
}
`.withBehaviors(
forcedColorsStylesheetBehavior(css`
:host([appearance='strong'])::before,
:host([appearance='strong'])::after,
:host([appearance='brand'])::before,
:host([appearance='brand'])::after,
:host([appearance='subtle'])::before,
:host([appearance='subtle'])::after,
:host(${strongState})::before,
:host(${strongState})::after,
:host(${brandState})::before,
:host(${brandState})::after,
:host(${subtleState})::before,
:host(${subtleState})::after,
:host::after,
:host::before {
background: WindowText;
Expand Down
Loading

0 comments on commit 81f2ac5

Please sign in to comment.