← All proposals

Thinking State

A small inline status: the agent icon (Zappy by default), a label ("Thinking..."), and the elapsed time in the code font ("17.1s").

Net-new componentOpen in Storybook

proposals/ThinkingState/thinking-state.css87 lines · View on GitHub
.pds-thinking-state {
	--thinking-state-gap: var(--pds-spacing-2xs);
	--thinking-state-time-size: var(--pds-typography-size-xs);

	align-items: center;
	color: var(--pds-color-foreground-default);
	display: inline-flex;
	gap: var(--thinking-state-gap);
}

/* Sizes are named after the type tokens: the text takes the matching size, the
   icon is the same height as the text, and the time is one step smaller (it
   stays at xs for the smallest size, since 10px is too small to read). The gap
   grows a step per size. */
.pds-thinking-state--xs {
	--thinking-state-gap: var(--pds-spacing-3xs);
	--thinking-state-time-size: var(--pds-typography-size-xs);
}

.pds-thinking-state--m {
	--thinking-state-gap: var(--pds-spacing-xs);
	--thinking-state-time-size: var(--pds-typography-size-s);
}

.pds-thinking-state__icon {
	flex-shrink: 0;
}

.pds-thinking-state__time {
	color: var(--pds-color-foreground-default-secondary);
	font-family: var(--pds-typography-ff-code);
	font-size: var(--thinking-state-time-size);
	font-variant-numeric: tabular-nums;
}

/* Stopped: the run was cut off, so the icon and label are muted. The time keeps
   its own secondary color. */
.pds-thinking-state--stopped .pds-thinking-state__icon,
.pds-thinking-state--stopped .pds-thinking-state__label {
	color: var(--pds-color-foreground-default-secondary);
}

/* While the agent is working the icon shrinks and returns to full size, in step
   with the label's shimmer. The shimmer is a highlight sweeping through the
   text: a gradient from the secondary to the default foreground, clipped to
   the glyphs, so there is no box to show in dark mode (the PDS shimmer overlay
   is a white band over the element's box). Off for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
	.pds-thinking-state--active .pds-thinking-state__icon {
		animation: thinking-state-pulse var(--pds-animation-duration-ai-shimmer)
			ease-in-out infinite;
	}

	.pds-thinking-state--active .pds-thinking-state__label {
		animation: thinking-state-shimmer var(--pds-animation-duration-ai-shimmer)
			linear infinite;
		background-clip: text;
		background-image: linear-gradient(
			120deg,
			var(--pds-color-foreground-default-secondary) 35%,
			var(--pds-color-foreground-default) 50%,
			var(--pds-color-foreground-default-secondary) 65%
		);
		background-size: 250% 100%;
		color: transparent;
	}
}

@keyframes thinking-state-shimmer {
	0% {
		background-position: 150% 0;
	}
	100% {
		background-position: -150% 0;
	}
}

@keyframes thinking-state-pulse {
	0%,
	100% {
		transform: scale(1);
	}
	50% {
		transform: scale(0.75);
	}
}