diff --git a/libs/angular-components/src/lib/components/callout/callout.ts b/libs/angular-components/src/lib/components/callout/callout.ts index d6f4e3eac..e4b5f349f 100644 --- a/libs/angular-components/src/lib/components/callout/callout.ts +++ b/libs/angular-components/src/lib/components/callout/callout.ts @@ -2,6 +2,7 @@ import { GoabCalloutAriaLive, GoabCalloutSize, GoabCalloutType, + GoabCalloutEmphasis, GoabCalloutIconTheme, } from "@abgov/ui-components-common"; import { CUSTOM_ELEMENTS_SCHEMA, Component, Input } from "@angular/core"; @@ -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" @@ -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"; diff --git a/libs/common/src/lib/common.ts b/libs/common/src/lib/common.ts index a7f46a113..b8610d408 100644 --- a/libs/common/src/lib/common.ts +++ b/libs/common/src/lib/common.ts @@ -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"; diff --git a/libs/react-components/src/lib/callout/callout.spec.tsx b/libs/react-components/src/lib/callout/callout.spec.tsx index fe83ffa22..7c324cb76 100644 --- a/libs/react-components/src/lib/callout/callout.spec.tsx +++ b/libs/react-components/src/lib/callout/callout.spec.tsx @@ -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( + + Test content + , + ); + + 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( + + Test content + , + ); + + const el = result.container.querySelector("goa-callout"); + expect(el?.getAttribute("size")).toBe("medium"); + expect(el?.getAttribute("emphasis")).toBe("high"); + }); }); diff --git a/libs/react-components/src/lib/callout/callout.tsx b/libs/react-components/src/lib/callout/callout.tsx index ef05e84d2..deb7c9a98 100644 --- a/libs/react-components/src/lib/callout/callout.tsx +++ b/libs/react-components/src/lib/callout/callout.tsx @@ -2,6 +2,7 @@ import { GoabCalloutAriaLive, GoabCalloutSize, GoabCalloutType, + GoabCalloutEmphasis, GoabCalloutIconTheme, Margins, } from "@abgov/ui-components-common"; @@ -10,6 +11,7 @@ interface WCProps extends Margins { heading?: string; type?: GoabCalloutType; size?: GoabCalloutSize; + emphasis?: GoabCalloutEmphasis; arialive?: GoabCalloutAriaLive; maxwidth?: string; icontheme?: GoabCalloutIconTheme; @@ -29,6 +31,7 @@ export interface GoabCalloutProps extends Margins { heading?: string; type?: GoabCalloutType; size?: GoabCalloutSize; + emphasis?: GoabCalloutEmphasis; iconTheme?: GoabCalloutIconTheme; maxWidth?: string; testId?: string; @@ -41,6 +44,7 @@ export const GoabCallout = ({ type = "information", iconTheme = "outline", size = "large", + emphasis = "medium", maxWidth, testId, ariaLive = "off", @@ -55,6 +59,7 @@ export const GoabCallout = ({ heading={heading} type={type} size={size} + emphasis={emphasis} maxwidth={maxWidth} arialive={ariaLive} icontheme={iconTheme} diff --git a/libs/web-components/src/assets/css/variables.css b/libs/web-components/src/assets/css/variables.css index dc58af565..fbfdc883c 100644 --- a/libs/web-components/src/assets/css/variables.css +++ b/libs/web-components/src/assets/css/variables.css @@ -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); -} \ No newline at end of file + + /* 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); +} diff --git a/libs/web-components/src/components/callout/Callout.spec.ts b/libs/web-components/src/components/callout/Callout.spec.ts index b76ff30a6..39621173f 100644 --- a/libs/web-components/src/components/callout/Callout.spec.ts +++ b/libs/web-components/src/components/callout/Callout.spec.ts @@ -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 () => { @@ -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(); + }); + }); }); diff --git a/libs/web-components/src/components/callout/Callout.svelte b/libs/web-components/src/components/callout/Callout.svelte index 8784830b7..97216e206 100644 --- a/libs/web-components/src/components/callout/Callout.svelte +++ b/libs/web-components/src/components/callout/Callout.svelte @@ -19,6 +19,11 @@ "medium", "large", ]); + const [CalloutEmphasis, validateCalloutEmphasis] = typeValidator("Callout emphasis", [ + "high", + "medium", + "low", + ]); const [AriaLive, validateAriaLive] = typeValidator("Aria live", [ "off", "assertive", @@ -28,6 +33,7 @@ // Types type CalloutType = (typeof Types)[number]; type CalloutSize = (typeof CalloutSizes)[number]; + type CalloutEmphasisType = (typeof CalloutEmphasis)[number]; type AriaLiveType = (typeof AriaLive)[number]; // margin @@ -38,6 +44,7 @@ export let size: CalloutSize = "large"; export let type: CalloutType; + export let emphasis: CalloutEmphasisType = "medium"; export let heading: string = ""; export let maxwidth: string = "none"; export let testid: string = ""; @@ -66,13 +73,20 @@ ? "calendar" : ""; + $: actualIconTheme = emphasis === "high" ? icontheme : "filled"; + + $: iconSize = isMediumCallout ? "small" : "medium"; + onMount(() => { validateCalloutSize(size); + validateCalloutEmphasis(emphasis); validateAriaLive(arialive); setTimeout(() => { validateType(type); - iconSize = isMediumCallout ? "small" : "medium"; + if (type === "event") { + console.warn("Callout type 'event' is deprecated and will be removed in a future version. Please use a different type."); + } }); }); @@ -85,24 +99,55 @@ ${calculateMargin(mt, mr, mb, ml)}; max-width: ${maxwidth}; `} - class="notification {type}" + class="notification {type} emphasis-{emphasis}" class:medium={isMediumCallout} + class:no-heading={!heading} data-testid={testid} aria-live={arialive} > - - - - - {#if heading} -

{heading}

- {/if} - -
+ {#if emphasis === "high" || emphasis === "medium"} + +
+ + {#if heading} +

{heading}

+ {/if} +
+
+ +
+ {:else if emphasis === "low" && !heading} + +
+ +
+ +
+
+ {:else} + +
+ + {#if heading} +

{heading}

+ {/if} +
+
+ +
+ {/if} @@ -111,114 +156,348 @@ box-sizing: border-box; font-family: var(--goa-font-family-sans); } + .notification { display: flex; - align-items: stretch; + flex-direction: column; overflow: hidden; - font: var(--goa-callout-l-text-size); - border: var(--goa-callout-l-border-width) solid; + border: var(--goa-border-width-s) solid; border-radius: var(--goa-callout-border-radius); } - h3 { - font: var(--goa-callout-l-heading-size); - margin-top: var(--goa-space-none); - margin-bottom: var(--goa-callout-l-content-gap); + /* High, Medium, and Low emphasis: Full-width statusbar on top */ + .notification.emphasis-high, + .notification.emphasis-medium, + .notification.emphasis-low { + display: flex; + flex-direction: column; } - .icon.information { - background-color: var(--goa-callout-info-color-bg-statusbar); + .statusbar { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: var(--goa-space-xs); + padding: var(--goa-callout-h-statusbar-padding); /* Default to high emphasis padding */ } - .icon.information > * { - fill: var(--fill-color, var(--goa-callout-info-icon-color)); - color: var(--fill-color, var(--goa-callout-info-icon-color)); + /* Adjust text alignment to match icon baseline */ + .statusbar .heading { + margin-top: -3px; } - .icon.important > * { - fill: var(--fill-color, var(--goa-callout-warning-icon-color)); - color: var(--fill-color, var(--goa-callout-warning-icon-color)); + + .heading { + font: var(--goa-callout-heading-typography); + margin: 0; } - .icon.success > * { - fill: var(--fill-color, var(--goa-callout-success-icon-color)); - color: var(--fill-color, var(--goa-callout-success-icon-color)); + + .content { + padding: var(--goa-callout-h-content-padding); /* Default to high emphasis padding */ } - .icon.emergency > * { - fill: var(--fill-color, var(--goa-callout-emergency-icon-color)); - color: var(--fill-color, var(--goa-callout-emergency-icon-color)); + + /* Low emphasis content: Reduced top padding */ + .notification.emphasis-low .content { + padding: var(--goa-callout-l-content-padding) !important; } - .icon.event > * { - fill: var(--fill-color, var(--goa-callout-event-icon-color)); - color: var(--fill-color, var(--goa-callout-event-icon-color)); + + /* Background colors for entire low emphasis callouts */ + .notification.information.emphasis-low { + background-color: var(--goa-callout-info-color-bg-content-l); } - .icon.emergency { - background-color: var(--goa-color-emergency-default); + .notification.important.emphasis-low { + background-color: var(--goa-callout-important-color-bg-content-l); } - .icon.important { - background-color: var(--goa-callout-warning-color-bg-statusbar); + + .notification.success.emphasis-low { + background-color: var(--goa-callout-success-color-bg-content-l); } - .icon.information { - background-color: var(--goa-color-info-default); + + .notification.emergency.emphasis-low { + background-color: var(--goa-callout-emergency-color-bg-content-l); } - .icon.event { - background-color: var(--goa-color-info-default); + + .notification.event.emphasis-low { + background-color: var(--goa-callout-info-color-bg-content-l); } - .icon.success { - background-color: var(--goa-callout-success-color-bg-statusbar); + + + /* Low emphasis without heading: Horizontal layout */ + .low-no-heading-container { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 8px; + padding: var(--goa-callout-l-no-heading-padding); } - .icon.emergency { - background-color: var(--goa-callout-emergency-color-bg-statusbar); + + /* Adjust content text alignment in no-heading layout */ + .low-no-heading-container .content { + margin-top: -3px; } - .icon { - text-align: center; - padding: var(--goa-callout-l-statusbar-padding); + /* Remove padding from content inside no-heading container */ + .notification.emphasis-low.no-heading .low-no-heading-container .content { + padding: 0 !important; } - .content.information { - background-color: var(--goa-callout-info-color-bg-content); + /* Background colors for low emphasis no-heading containers */ + .notification.information.emphasis-low.no-heading .low-no-heading-container { + background-color: var(--goa-callout-info-color-bg-content-l); } - .content.important { - background-color: var(--goa-callout-warning-color-bg-content); + + .notification.important.emphasis-low.no-heading .low-no-heading-container { + background-color: var(--goa-callout-important-color-bg-content-l); } - .content.success { - background-color: var(--goa-callout-success-color-bg-content); + + .notification.success.emphasis-low.no-heading .low-no-heading-container { + background-color: var(--goa-callout-success-color-bg-content-l); } - .content.emergency { - background-color: var(--goa-callout-emergency-color-bg-content); + + .notification.emergency.emphasis-low.no-heading .low-no-heading-container { + background-color: var(--goa-callout-emergency-color-bg-content-l); } - .content { - flex: 1 1 auto; - background-color: var(--goa-color-greyscale-100); - padding: var(--goa-callout-l-content-padding); + + .notification.event.emphasis-low.no-heading .low-no-heading-container { + background-color: var(--goa-callout-info-color-bg-content-l); + } + + /* Border colors by type and emphasis */ + .notification.information.emphasis-high { border-color: var(--goa-callout-info-border-color-h); } + .notification.information.emphasis-medium { border-color: var(--goa-callout-info-border-color-m); } + .notification.information.emphasis-low { border-color: var(--goa-callout-info-border-color-l); } + + .notification.important.emphasis-high { border-color: var(--goa-callout-important-border-color-h); } + .notification.important.emphasis-medium { border-color: var(--goa-callout-important-border-color-m); } + .notification.important.emphasis-low { border-color: var(--goa-callout-important-border-color-l); } + + .notification.success.emphasis-high { border-color: var(--goa-callout-success-border-color-h); } + .notification.success.emphasis-medium { border-color: var(--goa-callout-success-border-color-m); } + .notification.success.emphasis-low { border-color: var(--goa-callout-success-border-color-l); } + + .notification.emergency.emphasis-high { border-color: var(--goa-callout-emergency-border-color-h); } + .notification.emergency.emphasis-medium { border-color: var(--goa-callout-emergency-border-color-m); } + .notification.emergency.emphasis-low { border-color: var(--goa-callout-emergency-border-color-l); } + + /* Statusbar background colors */ + .statusbar.information.emphasis-high { background-color: var(--goa-callout-info-color-bg-statusbar-h); } + .statusbar.information.emphasis-medium { background-color: var(--goa-callout-info-color-bg-statusbar-m); } + .statusbar.information.emphasis-low { background-color: var(--goa-callout-info-color-bg-statusbar-l); } + + .statusbar.important.emphasis-high { background-color: var(--goa-callout-important-color-bg-statusbar-h); } + .statusbar.important.emphasis-medium { background-color: var(--goa-callout-important-color-bg-statusbar-m); } + .statusbar.important.emphasis-low { background-color: var(--goa-callout-important-color-bg-statusbar-l); } + + .statusbar.success.emphasis-high { background-color: var(--goa-callout-success-color-bg-statusbar-h); } + .statusbar.success.emphasis-medium { background-color: var(--goa-callout-success-color-bg-statusbar-m); } + .statusbar.success.emphasis-low { background-color: var(--goa-callout-success-color-bg-statusbar-l); } + + .statusbar.emergency.emphasis-high { background-color: var(--goa-callout-emergency-color-bg-statusbar-h); } + .statusbar.emergency.emphasis-medium { background-color: var(--goa-callout-emergency-color-bg-statusbar-m); } + .statusbar.emergency.emphasis-low { background-color: var(--goa-callout-emergency-color-bg-statusbar-l); } + + /* Content background colors */ + .content.information.emphasis-high { background-color: var(--goa-callout-info-color-bg-content-h); } + .content.information.emphasis-medium { background-color: var(--goa-callout-info-color-bg-content-m); } + .content.information.emphasis-low { background-color: var(--goa-callout-info-color-bg-content-l); } + + .content.important.emphasis-high { background-color: var(--goa-callout-important-color-bg-content-h); } + .content.important.emphasis-medium { background-color: var(--goa-callout-important-color-bg-content-m); } + .content.important.emphasis-low { background-color: var(--goa-callout-important-color-bg-content-l); } + + .content.success.emphasis-high { background-color: var(--goa-callout-success-color-bg-content-h); } + .content.success.emphasis-medium { background-color: var(--goa-callout-success-color-bg-content-m); } + .content.success.emphasis-low { background-color: var(--goa-callout-success-color-bg-content-l); } + + .content.emergency.emphasis-high { background-color: var(--goa-callout-emergency-color-bg-content-h); } + .content.emergency.emphasis-medium { background-color: var(--goa-callout-emergency-color-bg-content-m); } + .content.emergency.emphasis-low { background-color: var(--goa-callout-emergency-color-bg-content-l); } + + /* Icon colors using proper design tokens */ + .statusbar.information.emphasis-high > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-h); + color: var(--goa-callout-info-icon-color-h); + } + + .statusbar.success.emphasis-high > goa-icon { + --fill-color: var(--goa-callout-success-icon-color-h); + color: var(--goa-callout-success-icon-color-h); + } + + .statusbar.emergency.emphasis-high > goa-icon { + --fill-color: var(--goa-callout-emergency-icon-color-h); + color: var(--goa-callout-emergency-icon-color-h); + } + + .statusbar.important.emphasis-high > goa-icon { + --fill-color: var(--goa-callout-important-icon-color-h); + color: var(--goa-callout-important-icon-color-h); + } + + /* Heading text colors for high emphasis */ + .statusbar.information.emphasis-high .heading, + .statusbar.success.emphasis-high .heading, + .statusbar.emergency.emphasis-high .heading, + .statusbar.event.emphasis-high .heading { + color: var(--goa-color-text-light); + } + + /* Medium and low emphasis icons use proper design tokens */ + .statusbar.information.emphasis-medium > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-m); + color: var(--goa-callout-info-icon-color-m); + } + + .statusbar.information.emphasis-low > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-l); + color: var(--goa-callout-info-icon-color-l); + } + + .statusbar.important.emphasis-medium > goa-icon { + --fill-color: var(--goa-callout-important-icon-color-m); + color: var(--goa-callout-important-icon-color-m); + } + + .statusbar.important.emphasis-low > goa-icon { + --fill-color: var(--goa-callout-important-icon-color-l); + color: var(--goa-callout-important-icon-color-l); } - .notification.information { - border-color: var(--goa-callout-info-border-color); + .statusbar.success.emphasis-medium > goa-icon { + --fill-color: var(--goa-callout-success-icon-color-m); + color: var(--goa-callout-success-icon-color-m); } - .notification.important { - border-color: var(--goa-callout-warning-border-color); + + .statusbar.success.emphasis-low > goa-icon { + --fill-color: var(--goa-callout-success-icon-color-l); + color: var(--goa-callout-success-icon-color-l); } - .notification.success { - border-color: var(--goa-callout-success-border-color); + + .statusbar.emergency.emphasis-medium > goa-icon { + --fill-color: var(--goa-callout-emergency-icon-color-m); + color: var(--goa-callout-emergency-icon-color-m); } - .notification.emergency { - border-color: var(--goa-callout-emergency-border-color); + + .statusbar.emergency.emphasis-low > goa-icon { + --fill-color: var(--goa-callout-emergency-icon-color-l); + color: var(--goa-callout-emergency-icon-color-l); } - /*Medium callout style*/ + + /* Low emphasis no-heading icon styling - use proper design tokens */ + .notification.information.emphasis-low.no-heading .low-no-heading-container > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-l); + color: var(--goa-callout-info-icon-color-l); + } + + .notification.important.emphasis-low.no-heading .low-no-heading-container > goa-icon { + --fill-color: var(--goa-callout-important-icon-color-l); + color: var(--goa-callout-important-icon-color-l); + } + + .notification.success.emphasis-low.no-heading .low-no-heading-container > goa-icon { + --fill-color: var(--goa-callout-success-icon-color-l); + color: var(--goa-callout-success-icon-color-l); + } + + .notification.emergency.emphasis-low.no-heading .low-no-heading-container > goa-icon { + --fill-color: var(--goa-callout-emergency-icon-color-l); + color: var(--goa-callout-emergency-icon-color-l); + } + + /* Event type (deprecated) - use same colors as information type */ + .notification.event.emphasis-high { border-color: var(--goa-callout-info-border-color-h); } + .notification.event.emphasis-medium { border-color: var(--goa-callout-info-border-color-m); } + .notification.event.emphasis-low { border-color: var(--goa-callout-info-border-color-l); } + + .statusbar.event.emphasis-high { background-color: var(--goa-callout-info-color-bg-statusbar-h); } + .statusbar.event.emphasis-medium { background-color: var(--goa-callout-info-color-bg-statusbar-m); } + .statusbar.event.emphasis-low { background-color: var(--goa-callout-info-color-bg-statusbar-l); } + + .content.event.emphasis-high { background-color: var(--goa-callout-info-color-bg-content-h); } + .content.event.emphasis-medium { background-color: var(--goa-callout-info-color-bg-content-m); } + .content.event.emphasis-low { background-color: var(--goa-callout-info-color-bg-content-l); } + + /* Event type icon colors - same as information type */ + .statusbar.event.emphasis-high > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-h); + color: var(--goa-callout-info-icon-color-h); + } + .statusbar.event.emphasis-medium > goa-icon, + .statusbar.event.emphasis-low > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-m); + color: var(--goa-callout-info-icon-color-m); + } + + /* Event type no-heading icon styling */ + .notification.event.emphasis-low.no-heading .low-no-heading-container > goa-icon { + --fill-color: var(--goa-callout-info-icon-color-l); + color: var(--goa-callout-info-icon-color-l); + } + + /*Medium size callout compatibility (deprecated size prop)*/ .notification.medium { font: var(--goa-callout-m-text-size); border-width: var(--goa-callout-m-border-width); } - h3.medium { - font: var(--goa-callout-m-heading-size); - margin-bottom: var(--goa-callout-m-content-gap); - } .notification.medium .content { padding: var(--goa-callout-m-content-padding); - margin-top: calc(-1 * var(--goa-space-3xs)); } - .notification.medium .icon { + .notification.medium .statusbar { padding: var(--goa-callout-m-statusbar-padding); } + .notification.medium .heading { + font: var(--goa-callout-m-heading-size); + } + + /* Mobile viewport specific adjustments (max-width: 623px) */ + @media (max-width: 623px) { + /* Borders should show on mobile - same as large viewport */ + .notification { + border: var(--goa-border-width-s) solid !important; + } + + /* Border colors for mobile - use proper design tokens */ + .notification.information.emphasis-high { border-color: var(--goa-callout-info-border-color-h) !important; } + .notification.information.emphasis-medium { border-color: var(--goa-callout-info-border-color-m) !important; } + .notification.information.emphasis-low { border-color: var(--goa-callout-info-border-color-l) !important; } + + .notification.important.emphasis-high { border-color: var(--goa-callout-important-border-color-h) !important; } + .notification.important.emphasis-medium { border-color: var(--goa-callout-important-border-color-m) !important; } + .notification.important.emphasis-low { border-color: var(--goa-callout-important-border-color-l) !important; } + + .notification.success.emphasis-high { border-color: var(--goa-callout-success-border-color-h) !important; } + .notification.success.emphasis-medium { border-color: var(--goa-callout-success-border-color-m) !important; } + .notification.success.emphasis-low { border-color: var(--goa-callout-success-border-color-l) !important; } + + .notification.emergency.emphasis-high { border-color: var(--goa-callout-emergency-border-color-h) !important; } + .notification.emergency.emphasis-medium { border-color: var(--goa-callout-emergency-border-color-m) !important; } + .notification.emergency.emphasis-low { border-color: var(--goa-callout-emergency-border-color-l) !important; } + + .notification.event.emphasis-high { border-color: var(--goa-callout-info-border-color-h) !important; } + .notification.event.emphasis-medium { border-color: var(--goa-callout-info-border-color-m) !important; } + .notification.event.emphasis-low { border-color: var(--goa-callout-info-border-color-l) !important; } + + /* Use mobile-specific design tokens for padding */ + .statusbar { + padding: var(--goa-callout-h-statusbar-padding-mobile) !important; + } + + /* Content padding using mobile-specific tokens */ + .notification.emphasis-high .content { + padding: var(--goa-callout-h-content-padding-mobile) !important; + } + + .notification.emphasis-medium .content { + padding: var(--goa-callout-m-content-padding-mobile) !important; + } + + .notification.emphasis-low .content { + padding: var(--goa-callout-l-content-padding-mobile) !important; + } + + /* Mobile no-heading layout adjustments */ + .notification.emphasis-low.no-heading .low-no-heading-container { + padding: var(--goa-callout-l-no-heading-padding-mobile) !important; + } + } diff --git a/libs/web-components/src/components/callout/doc.md b/libs/web-components/src/components/callout/doc.md index 26635b5d6..7a65932fd 100644 --- a/libs/web-components/src/components/callout/doc.md +++ b/libs/web-components/src/components/callout/doc.md @@ -2,13 +2,44 @@ Callouts communicate important changes or facts within the body layout through a strong visual emphasis, so that users take notice and read the information. +## Emphasis Levels + +The `emphasis` prop controls the visual prominence and layout spacing of the callout: + +- **high**: Maximum visual prominence with larger padding and stronger styling +- **medium** (default): Balanced visual prominence suitable for most use cases +- **low**: Minimal visual emphasis with compact spacing, especially when no heading is provided + Use it like this: ```html - + + + This requires immediate attention from all users. + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + + + Your action was completed successfully. + + + + + Brief informational message with compact spacing. + +``` + +## Legacy Size Property + +The `size` property is still supported for backward compatibility but is deprecated: + +```html + Lorem ipsum dolor sit amet, consectetur adipiscing elit.