Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libs/angular-components/src/lib/components/callout/callout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
GoabCalloutAriaLive,
GoabCalloutSize,
GoabCalloutType,
GoabCalloutEmphasis,
GoabCalloutIconTheme,
} from "@abgov/ui-components-common";
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input } from "@angular/core";
Expand All @@ -15,6 +16,7 @@ import { GoabBaseComponent } from "../base.component";
[attr.type]="type"
[attr.heading]="heading"
[attr.size]="size"
[attr.emphasis]="emphasis"
[attr.maxwidth]="maxWidth"
[attr.arialive]="ariaLive"
[attr.icontheme]="iconTheme"
Expand All @@ -33,6 +35,7 @@ export class GoabCallout extends GoabBaseComponent {
@Input() type?: GoabCalloutType = "information";
@Input() heading?: string = "";
@Input() size?: GoabCalloutSize = "large";
@Input() emphasis?: GoabCalloutEmphasis = "medium";
@Input() maxWidth?: string;
@Input() ariaLive?: GoabCalloutAriaLive = "off";
@Input() iconTheme?: GoabCalloutIconTheme = "outline";
Expand Down
1 change: 1 addition & 0 deletions libs/common/src/lib/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export type GoabCalloutType =
| "emergency"
| "event";
export type GoabCalloutSize = "medium" | "large";
export type GoabCalloutEmphasis = "high" | "medium" | "low";
export type GoabCalloutAriaLive = "off" | "polite" | "assertive";
export type GoabCalloutIconTheme = "outline" | "filled";

Expand Down
39 changes: 39 additions & 0 deletions libs/react-components/src/lib/callout/callout.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,43 @@ describe("Callout", () => {
expect(el?.getAttribute("arialive")).toBe(expected);
});
});

test("Callout shall render with different emphasis levels", async () => {
const testCases = [
{ emphasis: "high", expected: "high" },
{ emphasis: "medium", expected: "medium" },
{ emphasis: "low", expected: "low" },
{ emphasis: undefined, expected: "medium" }, // default
];

testCases.forEach(({ emphasis, expected }) => {
const result = render(
<GoabCallout
type="information"
emphasis={emphasis as "high" | "medium" | "low" | undefined}
>
Test content
</GoabCallout>,
);

const el = result.container.querySelector("goa-callout");
expect(el?.getAttribute("emphasis")).toBe(expected);
});
});

test("Callout shall maintain backward compatibility with size prop", async () => {
const result = render(
<GoabCallout
type="information"
size="medium"
emphasis="high"
>
Test content
</GoabCallout>,
);

const el = result.container.querySelector("goa-callout");
expect(el?.getAttribute("size")).toBe("medium");
expect(el?.getAttribute("emphasis")).toBe("high");
});
});
5 changes: 5 additions & 0 deletions libs/react-components/src/lib/callout/callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
GoabCalloutAriaLive,
GoabCalloutSize,
GoabCalloutType,
GoabCalloutEmphasis,
GoabCalloutIconTheme,
Margins,
} from "@abgov/ui-components-common";
Expand All @@ -10,6 +11,7 @@ interface WCProps extends Margins {
heading?: string;
type?: GoabCalloutType;
size?: GoabCalloutSize;
emphasis?: GoabCalloutEmphasis;
arialive?: GoabCalloutAriaLive;
maxwidth?: string;
icontheme?: GoabCalloutIconTheme;
Expand All @@ -29,6 +31,7 @@ export interface GoabCalloutProps extends Margins {
heading?: string;
type?: GoabCalloutType;
size?: GoabCalloutSize;
emphasis?: GoabCalloutEmphasis;
iconTheme?: GoabCalloutIconTheme;
maxWidth?: string;
testId?: string;
Expand All @@ -41,6 +44,7 @@ export const GoabCallout = ({
type = "information",
iconTheme = "outline",
size = "large",
emphasis = "medium",
maxWidth,
testId,
ariaLive = "off",
Expand All @@ -55,6 +59,7 @@ export const GoabCallout = ({
heading={heading}
type={type}
size={size}
emphasis={emphasis}
maxwidth={maxWidth}
arialive={ariaLive}
icontheme={iconTheme}
Expand Down
106 changes: 105 additions & 1 deletion libs/web-components/src/assets/css/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,108 @@
--shadow-3: 0 10px 20px rgba(0, 0, 0, 0.15), 0 3px 6px rgba(0, 0, 0, 0.1);
--shadow-4: 0 15px 25px rgba(0, 0, 0, 0.15), 0 5px 10px rgba(0, 0, 0, 0.05);
--shadow-5: 0 20px 40px rgba(0, 0, 0, 0.2);
}

/* TEMPORARY: New callout design tokens for testing - these will come from @abgov/design-tokens after release */

/* Emphasis level padding tokens */
--goa-callout-h-content-padding: 16px 20px 20px 20px;
--goa-callout-h-content-padding-mobile: 12px 16px 16px 16px;
--goa-callout-h-statusbar-padding: 12px 12px 12px 18px;
--goa-callout-h-statusbar-padding-mobile: 12px 16px;

--goa-callout-m-content-padding: 16px 20px 20px 20px;
--goa-callout-m-content-padding-mobile: 12px 16px 16px 16px;
--goa-callout-m-statusbar-padding: 12px 12px 12px 18px;
--goa-callout-m-statusbar-padding-mobile: 12px 16px;

--goa-callout-l-content-padding: 4px 20px 20px 20px !important;
--goa-callout-l-content-padding-mobile: 0px 16px 16px 16px;
--goa-callout-l-statusbar-padding: 12px 12px 12px 18px;
--goa-callout-l-statusbar-padding-mobile: 12px 16px;

--goa-callout-l-no-heading-padding: 16px 20px 16px 20px;
--goa-callout-l-no-heading-padding-mobile: 16px;

/* Border colors by type and emphasis */
--goa-callout-info-border-color-h: #98D4EE;
--goa-callout-info-border-color-m: #E1DEDD;
--goa-callout-info-border-color-l: #98D4EE;

--goa-callout-important-border-color-h: #FDE3A1;
--goa-callout-important-border-color-m: #E1DEDD;
--goa-callout-important-border-color-l: #FDE3A1;

--goa-callout-success-border-color-h: #CCEAE1;
--goa-callout-success-border-color-m: #E1DEDD;
--goa-callout-success-border-color-l: #CCEAE1;

--goa-callout-emergency-border-color-h: #F4C8C5;
--goa-callout-emergency-border-color-m: #E1DEDD;
--goa-callout-emergency-border-color-l: #F4C8C5;

/* Statusbar background colors */
--goa-callout-info-color-bg-statusbar-h: #0077AD;
--goa-callout-info-color-bg-statusbar-m: #CBEAF7;
--goa-callout-info-color-bg-statusbar-l: #EBF8FF;

--goa-callout-important-color-bg-statusbar-h: #FFB800;
--goa-callout-important-color-bg-statusbar-m: #FFF1CC;
--goa-callout-important-color-bg-statusbar-l: #FFF6E5;

--goa-callout-success-color-bg-statusbar-h: #006F4C;
--goa-callout-success-color-bg-statusbar-m: #D8F7E6;
--goa-callout-success-color-bg-statusbar-l: #EDFCF0;

--goa-callout-emergency-color-bg-statusbar-h: #DA291C;
--goa-callout-emergency-color-bg-statusbar-m: #FDDED9;
--goa-callout-emergency-color-bg-statusbar-l: #FFF6F6;

/* Content background colors */
--goa-callout-info-color-bg-content-h: #EBF8FF;
--goa-callout-info-color-bg-content-m: #ffffff;
--goa-callout-info-color-bg-content-l: #EBF8FF;

--goa-callout-important-color-bg-content-h: #FFF6E5;
--goa-callout-important-color-bg-content-m: #ffffff;
--goa-callout-important-color-bg-content-l: #FFF6E5;

--goa-callout-success-color-bg-content-h: #EDFCF0;
--goa-callout-success-color-bg-content-m: #ffffff;
--goa-callout-success-color-bg-content-l: #EDFCF0;

--goa-callout-emergency-color-bg-content-h: #FFF6F6;
--goa-callout-emergency-color-bg-content-m: #ffffff;
--goa-callout-emergency-color-bg-content-l: #FFF6F6;

/* Icon colors by type and emphasis */
--goa-callout-info-icon-color-h: #ffffff;
--goa-callout-info-icon-color-m: #0077AD;
--goa-callout-info-icon-color-l: #0077AD;

--goa-callout-important-icon-color-h: #333333;
--goa-callout-important-icon-color-m: #CC9300;
--goa-callout-important-icon-color-l: #CC9300;

--goa-callout-success-icon-color-h: #ffffff;
--goa-callout-success-icon-color-m: #006F4C;
--goa-callout-success-icon-color-l: #006F4C;

--goa-callout-emergency-icon-color-h: #ffffff;
--goa-callout-emergency-icon-color-m: #DA291C;
--goa-callout-emergency-icon-color-l: #DA291C;

/* Typography tokens - with stronger overrides */
--goa-callout-heading-typography: var(--goa-typography-heading-s) !important;
--goa-callout-content-typography: var(--goa-typography-body-m) !important;

/* Text colors for headings - high emphasis uses light text on dark backgrounds */
--goa-color-text-light: #ffffff;

/* Border radius - override the existing none value */
--goa-callout-border-radius: 12px !important;

/* Medium size compatibility tokens (deprecated size prop) */
--goa-callout-m-text-size: var(--goa-typography-body-s);
--goa-callout-m-border-width: var(--goa-border-width-s);
--goa-callout-m-heading-size: var(--goa-typography-heading-xs);
}
109 changes: 108 additions & 1 deletion libs/web-components/src/components/callout/Callout.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { render, waitFor } from "@testing-library/svelte";
import GoACallout from "./Callout.svelte";
import GoACalloutWrapper from "./CalloutWrapper.test.svelte";
import { it, describe } from "vitest";
import { it, describe, vi } from "vitest";

describe("GoACalloutComponent", () => {
it("should render - emergency", async () => {
Expand Down Expand Up @@ -213,4 +213,111 @@ describe("GoACalloutComponent", () => {
expect(callout).toHaveAttribute("aria-live", "");
});
});

describe("emphasis levels", () => {
it("should have default emphasis of medium", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "information",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveClass("emphasis-medium");
});

it("should render with high emphasis", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "emergency",
emphasis: "high",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveClass("emphasis-high");
expect(callout).toHaveClass("emergency");
});

it("should render with medium emphasis", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "important",
emphasis: "medium",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveClass("emphasis-medium");
expect(callout).toHaveClass("important");
});

it("should render with low emphasis", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "success",
emphasis: "low",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveClass("emphasis-low");
expect(callout).toHaveClass("success");
});

it("should add no-heading class when heading is not provided", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "information",
emphasis: "low",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).toHaveClass("no-heading");
});

it("should not add no-heading class when heading is provided", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "information",
emphasis: "low",
heading: "Test Heading",
});
const callout = await baseElement.findByTestId("callout-test");

expect(callout).not.toHaveClass("no-heading");
});

it("should apply emphasis classes to icon and content", async () => {
const baseElement = render(GoACallout, {
testid: "callout-test",
type: "important",
emphasis: "high",
heading: "Test",
});
const callout = await baseElement.findByTestId("callout-test");
const icon = callout.querySelector(".icon");
const content = callout.querySelector(".content");
const heading = content.querySelector("h3");

expect(icon).toHaveClass("emphasis-high");
expect(content).toHaveClass("emphasis-high");
expect(heading).toHaveClass("emphasis-high");
});
});

describe("deprecation warnings", () => {
it("should warn when event type is used", async () => {
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});

render(GoACallout, {
testid: "callout-test",
type: "event",
});

await waitFor(() => {
expect(consoleSpy).toHaveBeenCalledWith(
"Callout type 'event' is deprecated and will be removed in a future version. Please use a different type."
);
});

consoleSpy.mockRestore();
});
});
});
Loading
Loading