Skip to content

Commit

Permalink
feat: update text to use element internals for custom states (#31770)
Browse files Browse the repository at this point in the history
Co-authored-by: Dave Rupert <[email protected]>
  • Loading branch information
chrisdholt and davatron5000 authored Jun 25, 2024
1 parent 54f5ccc commit a651436
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "updates the Text component to use Element Internals custom states for presentational attributes",
"packageName": "@fluentui/web-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
10 changes: 10 additions & 0 deletions packages/web-components/docs/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -3102,15 +3102,25 @@ export const TabTemplate: ElementViewTemplate<Tab, any>;
// @public
class Text_2 extends FASTElement {
align?: TextAlign;
alignChanged(prev: TextAlign | undefined, next: TextAlign | undefined): void;
block: boolean;
// (undocumented)
connectedCallback(): void;
// @internal
elementInternals: ElementInternals;
font?: TextFont;
fontChanged(prev: TextFont | undefined, next: TextFont | undefined): void;
// @internal
handleChange(source: any, propertyName: string): void;
italic: boolean;
nowrap: boolean;
size?: TextSize;
sizeChanged(prev: TextSize | undefined, next: TextSize | undefined): void;
strikethrough: boolean;
truncate: boolean;
underline: boolean;
weight?: TextWeight;
weightChanged(prev: TextWeight | undefined, next: TextWeight | undefined): void;
}
export { Text_2 as Text }

Expand Down
176 changes: 166 additions & 10 deletions packages/web-components/src/text/text.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test.describe('Text Component', () => {
await expect(element).toBeVisible();
});

test(`should set and reflect and update the nowrap attribute and property on the internal control`, async () => {
test(`should set and reflect and update the nowrap attribute and property when provided`, async () => {
await element.evaluate((node: Text) => {
node.nowrap = true;
});
Expand All @@ -71,7 +71,21 @@ test.describe('Text Component', () => {
await expect(element).toHaveJSProperty('nowrap', false);
});

test(`should set and reflect and update the truncate attribute and property on the internal control`, async () => {
test(`should add a custom state matching the nowrap for the font attribute when provided`, async () => {
await element.evaluate((node: Text) => {
node.nowrap = true;
});

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

await element.evaluate((node: Text) => {
node.nowrap = false;
});

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

test(`should set and reflect and update the truncate attribute and property when provided`, async () => {
await element.evaluate((node: Text) => {
node.truncate = true;
});
Expand All @@ -86,7 +100,21 @@ test.describe('Text Component', () => {
await expect(element).toHaveJSProperty('truncate', false);
});

test(`should set and reflect and update the italic attribute and property on the internal control`, async () => {
test(`should add a custom state matching the truncate for the font attribute when provided`, async () => {
await element.evaluate((node: Text) => {
node.truncate = true;
});

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

await element.evaluate((node: Text) => {
node.truncate = false;
});

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

test(`should set and reflect and update the italic attribute and property when provided`, async () => {
await element.evaluate((node: Text) => {
node.italic = true;
});
Expand All @@ -101,7 +129,21 @@ test.describe('Text Component', () => {
await expect(element).toHaveJSProperty('italic', false);
});

test(`should set and reflect and update the underline attribute and property on the internal control`, async () => {
test(`should add a custom state matching the italic for the font attribute when provided`, async () => {
await element.evaluate((node: Text) => {
node.italic = true;
});

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

await element.evaluate((node: Text) => {
node.italic = false;
});

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

test(`should set and reflect and update the underline attribute and property when provided`, async () => {
await element.evaluate((node: Text) => {
node.underline = true;
});
Expand All @@ -116,7 +158,21 @@ test.describe('Text Component', () => {
await expect(element).toHaveJSProperty('underline', false);
});

test(`should set and reflect and update the strikethrough attribute and property on the internal control`, async () => {
test(`should add a custom state matching the underline for the font attribute when provided`, async () => {
await element.evaluate((node: Text) => {
node.underline = true;
});

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

await element.evaluate((node: Text) => {
node.underline = false;
});

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

test(`should set and reflect and update the strikethrough attribute and property when provided`, async () => {
await element.evaluate((node: Text) => {
node.strikethrough = true;
});
Expand All @@ -131,7 +187,21 @@ test.describe('Text Component', () => {
await expect(element).toHaveJSProperty('strikethrough', false);
});

test(`should set and reflect and update the block attribute and property on the internal control`, async () => {
test(`should add a custom state matching the strikethrough for the font attribute when provided`, async () => {
await element.evaluate((node: Text) => {
node.strikethrough = true;
});

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

await element.evaluate((node: Text) => {
node.strikethrough = false;
});

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

test(`should set and reflect and update the block attribute and property when provided`, async () => {
await element.evaluate((node: Text) => {
node.block = true;
});
Expand All @@ -146,44 +216,130 @@ test.describe('Text Component', () => {
await expect(element).toHaveJSProperty('block', false);
});

test(`should add a custom state matching the block for the font attribute when provided`, async () => {
await element.evaluate((node: Text) => {
node.block = true;
});

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

await element.evaluate((node: Text) => {
node.block = false;
});

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

for (const [, value] of Object.entries(sizeAttributes)) {
test(`should set and reflect the size attribute to \`${value}\` on the internal control`, async () => {
test(`should set and reflect the size attribute to \`${value}\` when provided`, async () => {
await element.evaluate((node: Text, sizeValue: string) => {
node.size = sizeValue as TextSize;
}, value as string);

await expect(element).toHaveJSProperty('size', `${value}`);
await expect(element).toHaveAttribute('size', `${value}`);
});

test(`should add a custom state matching the \`${value}\` for the size attribute when provided`, async () => {
await element.evaluate((node: Text, sizeValue: string) => {
node.size = sizeValue as TextSize;
}, value as string);

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(`size-${value}`), value),
).toBe(true);

await element.evaluate((node: Text) => {
node.size = undefined;
});

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(`size-${value}`), value),
).toBe(false);
});
}
for (const [, value] of Object.entries(weightAttributes)) {
test(`should set and reflect the weight attribute to \`${value}\` on the internal control`, async () => {
test(`should set and reflect the weight attribute to \`${value}\` when provided`, async () => {
await element.evaluate((node: Text, weightValue: string) => {
node.weight = weightValue as TextWeight;
}, value as string);

await expect(element).toHaveJSProperty('weight', `${value}`);
await expect(element).toHaveAttribute('weight', `${value}`);
});

test(`should add a custom state matching the \`${value}\` for the weight attribute when provided`, async () => {
await element.evaluate((node: Text, weightValue: string) => {
node.weight = weightValue as TextWeight;
}, value as string);

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(value), value),
).toBe(true);

await element.evaluate((node: Text) => {
node.weight = undefined;
});

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(value), value),
).toBe(false);
});
}
for (const [, value] of Object.entries(alignAttributes)) {
test(`should set and reflect the align attribute to \`${value}\` on the internal control`, async () => {
test(`should set and reflect the align attribute to \`${value}\` when provided`, async () => {
await element.evaluate((node: Text, alignValue: string) => {
node.align = alignValue as TextAlign;
}, value as string);

await expect(element).toHaveJSProperty('align', `${value}`);
await expect(element).toHaveAttribute('align', `${value}`);
});

test(`should add a custom state matching the \`${value}\` for the align attribute when provided`, async () => {
await element.evaluate((node: Text, alignValue: string) => {
node.align = alignValue as TextAlign;
}, value as string);

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(value), value),
).toBe(true);

await element.evaluate((node: Text) => {
node.align = undefined;
});

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(value), value),
).toBe(false);
});
}
for (const [, value] of Object.entries(fontAttributes)) {
test(`should set and reflect the font attribute to \`${value}\` on the internal control`, async () => {
test(`should set and reflect the font attribute to \`${value}\` when provided`, async () => {
await element.evaluate((node: Text, fontValue: string) => {
node.font = fontValue as TextFont;
}, value as string);

await expect(element).toHaveJSProperty('font', `${value}`);
await expect(element).toHaveAttribute('font', `${value}`);
});

test(`should add a custom state matching the \`${value}\` for the font attribute when provided`, async () => {
await element.evaluate((node: Text, fontValue: string) => {
node.font = fontValue as TextFont;
}, value as string);

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(value), value),
).toBe(true);

await element.evaluate((node: Text) => {
node.font = undefined;
});

expect(
await element.evaluate((node: Text, value: string) => node.elementInternals.states.has(value), value),
).toBe(false);
});
}
});
Loading

0 comments on commit a651436

Please sign in to comment.