diff --git a/.changeset/clever-rockets-speak.md b/.changeset/clever-rockets-speak.md new file mode 100644 index 00000000..10798ef7 --- /dev/null +++ b/.changeset/clever-rockets-speak.md @@ -0,0 +1,5 @@ +--- +"@igloo-ui/alert": minor +--- + +Added the option to have an action link instead of a button in an Alert. Allowed the horizontal appearance to have a dismiss button. It is hidden by default for backwards compatibility. diff --git a/packages/Alert/src/Alert.stories.tsx b/packages/Alert/src/Alert.stories.tsx index 0f933cc3..b514d5cb 100644 --- a/packages/Alert/src/Alert.stories.tsx +++ b/packages/Alert/src/Alert.stories.tsx @@ -111,6 +111,38 @@ export const WithButton = () => ( ); +export const WithLink = () => ( +
+ Tell me more + }} + type="info" + appearance="card" + title={mockContent.title} + message={mockContent.message} + /> + Tell me more + }} + type="info" + appearance="inline" + title={mockContent.title} + message={mockContent.message} + /> + Tell me more + }} + type="info" + appearance="horizontal" + title={mockContent.title} + closable + /> +
+); + export const Closable = () => (
, "title"> { button?: AlertButton; /** Add a data-test tag for automated tests */ dataTest?: string; + /** Alert Link. Used in place of the button */ + link?: HyperlinkProps; } const getBrand = (): string => { @@ -89,6 +93,7 @@ const renderIcon = ( const renderDismissButton = ( setShow: (show: boolean) => void, + size: IconButtonSize = "xsmall", onDismissClick?: () => void, ariaLabel?: string ): JSX.Element => { @@ -105,7 +110,7 @@ const renderDismissButton = ( appearance={{ type: "ghost", variant: "secondary" }} className="ids-alert__dismiss-btn" type="button" - size="xsmall" + size={size} icon={} onClick={action} aria-label={ariaLabel} @@ -138,6 +143,24 @@ const renderAlertActionButton = ( ); }; +const renderAlertActionLink = ( + link?: HyperlinkProps +): JSX.Element => { + if (link == null || link.children == null) { + return <>; + } + + return ( + + {link.children} + + ); +}; + const Alert: React.FunctionComponent = ({ title, message, @@ -145,11 +168,12 @@ const Alert: React.FunctionComponent = ({ type, appearance = "card", className, - closable = true, + closable = appearance !== "horizontal", icon, onClose, button, dataTest, + link, ...rest }: AlertProps) => { const stringFormatter = useLocalizedStringFormatter(intlMessages); @@ -163,8 +187,9 @@ const Alert: React.FunctionComponent = ({ const parentElement = React.useRef(null); const [show, setShow] = React.useState(true); const hasButton = button !== undefined; + const hasLink = link !== undefined; const isHorizontal = appearance === "horizontal"; - const canBeClosed = closable && !isHorizontal; + const canBeClosed = closable; const isWorkleap = getBrand() === "workleap"; if (show) { @@ -177,7 +202,7 @@ const Alert: React.FunctionComponent = ({ > {icon !== null && !isHorizontal && - renderIcon(appearance, hasButton, type, icon, isWorkleap)} + renderIcon(appearance, hasButton || hasLink, type, icon, isWorkleap)}
@@ -185,10 +210,14 @@ const Alert: React.FunctionComponent = ({

{metadata}

{!isHorizontal &&
{message}
} + {hasLink && renderAlertActionLink(link)} {hasButton && renderAlertActionButton(appearance, button, isWorkleap)}
- {canBeClosed && renderDismissButton(setShow, onClose, stringFormatter.format("close"))} + {canBeClosed && renderDismissButton(setShow, + isHorizontal ? "medium" : "xsmall", + onClose, + stringFormatter.format("close"))} ); } diff --git a/packages/Alert/src/alert.scss b/packages/Alert/src/alert.scss index bfbda01e..d4af5918 100644 --- a/packages/Alert/src/alert.scss +++ b/packages/Alert/src/alert.scss @@ -15,7 +15,7 @@ --ids-alert-title-font-weight: #{tokens.$font-weight-semi-bold}; --ids-alert-padding: #{tokens.$space-3}; --ids-alert-padding-compact: #{tokens.$space-3}; - --ids-alert-flex-gap-component: #{tokens.$space-3}; + --ids-alert-gap: #{tokens.$space-3}; --ids-alert-border-radius: #{tokens.$border-radius-sm}; --ids-alert-box-shadow: #{tokens.$shadow-6}; --ids-alert-background-color-light: #{tokens.$samoyed}; @@ -29,6 +29,7 @@ --ids-alert-icon-size-medium: 4rem; --ids-alert-btn-margin-top: #{tokens.$space-3}; --ids-alert-metadata-color: #{tokens.$grey-600}; + --ids-alert-body-gap-horizontal: #{tokens.$space-3}; /* Announcement */ --ids-alert-border-color-announcement: #{tokens.$seaweed-500}; @@ -55,7 +56,7 @@ --ids-alert-horizontal-title-font-weight: var(--hop-body-sm-font-weight); --ids-alert-padding: var(--hop-space-inset-md); --ids-alert-padding-compact: var(--hop-space-inset-sm) var(--hop-space-inset-md); - --ids-alert-flex-gap-component: var(--hop-space-inline-md); + --ids-alert-gap: var(--hop-space-inline-md); --ids-alert-border-radius: var(--hop-shape-rounded-md); --ids-alert-box-shadow: none; --ids-alert-border-default-width: 0.1rem; @@ -65,6 +66,7 @@ --ids-alert-icon-size-medium: 2.5rem; --ids-alert-btn-margin-top: var(--hop-space-stack-md); --ids-alert-metadata-color: var(--hop-neutral-text-weak); + --ids-alert-body-gap-horizontal: var(--hop-shape-rounded-md); /* Announcement */ --ids-alert-color-announcement: var(--hop-information-text); @@ -105,14 +107,10 @@ border-width: var(--ids-alert-border-default-width); font-size: var(--ids-alert-font-size); font-family: var(--ids-alert-font-family); + gap: var(--ids-alert-gap); line-height: var(--ids-alert-line-height); padding: var(--ids-alert-padding); - /* External component override */ - .ids-btn { - width: auto; - } - /* Styles */ &--card { background-color: var(--ids-alert-background-color-light); @@ -131,6 +129,10 @@ .ids-alert__title { font-weight: var(--ids-alert-horizontal-title-font-weight, var(--ids-alert-title-font-weight)) } + + & .ids-alert__dismiss-btn { + align-self: center; + } } /* Types */ @@ -228,10 +230,13 @@ align-self: center; flex-direction: column; align-items: flex-start; + } - .ids-btn { - margin-top: var(--ids-alert-btn-margin-top); - } + &__action-btn { + flex: 0 0 auto; + margin-top: var(--ids-alert-btn-margin-top); + max-width: 100%; + width: auto; } &__content { @@ -298,20 +303,17 @@ /* stylelint-disable-next-line media-query-no-invalid */ @media (width >= #{tokens.$breakpoints-sm}) { - &__icon + .ids-alert__body { - margin-left: var(--ids-alert-flex-gap-component); - } - &--horizontal &__body { flex-direction: row; align-items: center; + gap: var(--ids-alert-body-gap-horizontal); } &--horizontal &__body > .ids-alert__header { flex: 1 1 auto; } - &--horizontal &__body > .ids-btn { + &--horizontal &__body > &__action-btn { margin: 0; } } diff --git a/packages/Avatar/src/__snapshots__/Avatar.test.tsx.snap b/packages/Avatar/src/__snapshots__/Avatar.test.tsx.snap index 570b07ba..b86799cd 100644 --- a/packages/Avatar/src/__snapshots__/Avatar.test.tsx.snap +++ b/packages/Avatar/src/__snapshots__/Avatar.test.tsx.snap @@ -4,6 +4,7 @@ exports[`Avatar It should render a snapshot 1`] = `