.pds-icon-button {
--icon-button-size: var(--pds-spacing-button-height-s);
--icon-button-background: var(
--pds-color-button-secondary-background-default
);
--icon-button-background-hover: var(
--pds-color-button-secondary-background-hover
);
--icon-button-border: var(--pds-color-button-secondary-border);
--icon-button-border-hover: var(--pds-color-button-secondary-border);
--icon-button-foreground: var(
--pds-color-button-secondary-foreground-default
);
align-items: center;
background-color: var(--icon-button-background);
border: var(--pds-border-width-default) solid transparent;
border-radius: var(--pds-border-radius-input);
box-sizing: border-box;
color: var(--icon-button-foreground);
cursor: pointer;
display: flex;
height: var(--icon-button-size);
justify-content: center;
position: relative;
text-decoration: none;
transition: var(--pds-animation-transition-button);
width: var(--icon-button-size);
}
.pds-icon-button__content {
align-content: stretch;
align-items: center;
display: flex;
height: 100%;
justify-content: center;
}
.pds-icon-button:disabled {
cursor: not-allowed;
opacity: 70%;
}
.pds-icon-button:disabled .pds-icon-button__content {
opacity: 30%;
}
.pds-icon-button:hover:enabled,
a.pds-icon-button:hover {
background-color: var(--icon-button-background-hover);
color: var(--icon-button-foreground);
text-decoration: none;
}
.pds-icon-button--has-border {
border-color: var(--icon-button-border);
}
.pds-icon-button--has-border:hover:enabled,
a.pds-icon-button--has-border:hover {
border-color: var(--icon-button-border-hover);
}
.pds-icon-button:focus-visible {
outline: var(--pds-border-width-outline) solid
var(--pds-color-interactive-focus);
}
/* Button Variants */
.pds-icon-button--reverse {
--icon-button-background: var(
--pds-color-button-reverse-secondary-background-default
);
--icon-button-background-hover: var(
--pds-color-button-reverse-secondary-background-hover
);
--icon-button-border: var(--pds-color-button-reverse-secondary-border);
--icon-button-border-hover: var(--pds-color-button-reverse-secondary-border);
--icon-button-foreground: var(
--pds-color-button-reverse-secondary-foreground
);
&:focus-visible {
outline-color: var(--pds-color-interactive-reverse-focus);
}
}
.pds-icon-button--critical {
--icon-button-background: var(
--pds-color-button-critical-secondary-background-default
);
--icon-button-background-hover: var(
--pds-color-button-critical-secondary-background-hover
);
--icon-button-border: var(
--pds-color-button-critical-secondary-border-default
);
--icon-button-border-hover: var(
--pds-color-button-critical-secondary-border-hover
);
--icon-button-foreground: var(
--pds-color-button-critical-secondary-foreground
);
}
/* Pressed / active toggle state — fill with border color, subtle inner ring for edge definition */
.pds-icon-button--pressed:not(.pds-icon-button--critical),
.pds-icon-button--pressed:not(.pds-icon-button--critical):hover:enabled {
background-color: var(--icon-button-border);
border-color: var(--icon-button-border);
box-shadow: var(--pds-elevation-icon-button-pressed);
}
/* Active (click) state */
.pds-icon-button:active:enabled,
a.pds-icon-button:active {
background-color: var(--pds-color-button-secondary-background-active);
box-shadow: var(--pds-elevation-button-secondary-active);
}
.pds-icon-button--critical:active:enabled,
a.pds-icon-button--critical:active {
background-color: var(
--pds-color-button-critical-secondary-background-active
);
box-shadow: var(--pds-elevation-button-critical-secondary-active);
}
.pds-icon-button--reverse:active:enabled,
a.pds-icon-button--reverse:active {
background-color: var(--pds-color-button-reverse-secondary-background-active);
box-shadow: var(--pds-elevation-button-reverse-secondary-active);
}
/* Agentic: the AI gradient as the border. --pds-gradient-ai-active is a
gradient, not a color, so it cannot go in border-color. The border is
transparent and the gradient is painted on the border-box underneath; the
fill layers sit on the padding-box above it. The secondary background
tokens are translucent, so an opaque surface layer keeps the gradient from
showing through the middle. The fill is a custom property so hover, active
and pressed can swap it. Selectors are doubled up to beat the has-border,
pressed and hover rules above. */
.pds-icon-button.pds-icon-button--agentic {
--icon-button-fill: var(--icon-button-background);
background-clip: padding-box, padding-box, border-box;
background-color: transparent;
background-image:
linear-gradient(var(--icon-button-fill), var(--icon-button-fill)),
linear-gradient(
var(--pds-color-surface-default),
var(--pds-color-surface-default)
),
var(--pds-gradient-ai-active);
background-origin: border-box;
border-color: transparent;
}
.pds-icon-button.pds-icon-button--agentic:hover:enabled {
--icon-button-fill: var(--icon-button-background-hover);
background-color: transparent;
border-color: transparent;
}
.pds-icon-button.pds-icon-button--agentic:active:enabled,
.pds-icon-button.pds-icon-button--agentic.pds-icon-button--pressed,
.pds-icon-button.pds-icon-button--agentic.pds-icon-button--pressed:hover:enabled {
--icon-button-fill: var(--pds-color-button-secondary-background-active);
background-color: transparent;
border-color: transparent;
}
/* Button Sizes */
.pds-icon-button--xs {
--icon-button-size: var(--pds-spacing-button-height-xs);
}
.pds-icon-button--m {
--icon-button-size: var(--pds-spacing-button-height-m);
}
/* Animation & Icons */
.pds-icon-button__icon-wrapper {
align-items: center;
display: flex;
inset: 0;
justify-content: center;
position: absolute;
}
.pds-icon-button--fadeOut {
-webkit-animation: scale-down-center 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94)
both;
animation: scale-down-center 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
opacity: 0;
transition: 0.2s ease-in;
}
.pds-icon-button--hide {
display: none;
}
.pds-icon-button--scaleIn {
-webkit-animation: scale-in-center 0.2s
cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
animation: scale-in-center 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
}
/** mods to specific icons **/
.pds-icon--copy.pds-icon--copy.pds-icon-button__icon {
transform: translateX(8%) translateY(-2%);
}
@keyframes scale-in-center {
0% {
opacity: 1;
-webkit-transform: scale(0);
transform: scale(0);
}
100% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1);
}
}
Icon Button
Starting point for an IconButton proposal.
Extends a PDS componentOpen in Storybook