← All proposals

Suggestion Card

A card for use inside an agent `ChatMessage`:

Net-new componentOpen in Storybook

proposals/SuggestionCard/suggestion-card.css184 lines · View on GitHub
.pds-suggestion-card {
	--suggestion-card-actions-gap: var(--pds-spacing-m);
	--suggestion-card-gap: var(--pds-spacing-s);
}

.pds-suggestion-card__body {
	display: flex;
	flex-direction: column;
	gap: var(--suggestion-card-gap);
}

/* The title and description sit closer together (xs) than the sections of the
   card (s). */
.pds-suggestion-card__heading {
	display: flex;
	flex-direction: column;
	gap: var(--pds-spacing-xs);
}

/* The type comes from the PDS `pds-heading-m` class on the element. */
.pds-suggestion-card__title {
	margin: 0;
}

.pds-suggestion-card__description {
	color: var(--pds-color-foreground-default-secondary);
	margin: 0;
}

.pds-suggestion-card__changes {
	display: flex;
	flex-direction: column;
	gap: var(--pds-spacing-m);
}

/* The space above the buttons is larger than the gap between the other
   sections: the body gap plus this margin adds up to the actions gap. */
.pds-suggestion-card__footer {
	margin-block-start: calc(
		var(--suggestion-card-actions-gap) - var(--suggestion-card-gap)
	);
}

/* The footer row: the decision buttons (or, once accepted, the result line) at
   the start and the `actionsEnd` slot at the end; it wraps on a narrow card. */
.pds-suggestion-card__footer {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: var(--pds-spacing-xs);
}

.pds-suggestion-card__actions-end {
	margin-inline-start: auto;
}

/* No slots and not accepted: nothing to show, so the footer takes no space. The
   empty status region stays in the DOM so the result is announced when it
   appears. */
.pds-suggestion-card__footer--empty {
	margin-block-start: calc(-1 * var(--suggestion-card-gap));
}

.pds-suggestion-card__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--pds-spacing-2xs);
}

/* Accepted: the actions are replaced by a result line. */
.pds-suggestion-card__result {
	align-items: center;
	color: var(--pds-color-status-success-foreground);
	display: flex;
	font-weight: var(--pds-typography-fw-medium);
	gap: var(--pds-spacing-2xs);
}

.pds-suggestion-card--dismissed .pds-suggestion-card__result {
	color: var(--pds-color-foreground-default-secondary);
}

/* Dismissed: a quiet record. The title goes secondary too. */
.pds-suggestion-card--dismissed .pds-suggestion-card__title {
	color: var(--pds-color-foreground-default-secondary);
}

.pds-suggestion-card__result-icon {
	flex-shrink: 0;
}

/* One change: the field name over a Content Diff. */
.pds-suggestion-change {
	display: flex;
	flex-direction: column;
	gap: var(--pds-spacing-2xs);
}

.pds-suggestion-change__field {
	font-size: var(--pds-typography-size-xs);
	font-weight: var(--pds-typography-fw-semibold);
	margin: 0;
}

/* Multiple choice (`type='choice'`): the card has no padding of its own. The
   header and footer are padded sections divided from the rows by lines, and the
   rows are a PDS panel list that runs edge to edge. */
.pds-suggestion-card__section {
	padding: var(--pds-spacing-m) var(--pds-spacing-l);
}

.pds-suggestion-card__section--footer {
	border-block-start: var(--pds-border-width-default) solid
		var(--pds-color-border-default);
}

.pds-suggestion-card__section--footer .pds-suggestion-card__footer {
	margin-block-start: 0;
}

.pds-suggestion-card__choices {
	border-block-start: var(--pds-border-width-default) solid
		var(--pds-color-border-default);
	border-radius: 0;
}

/* A dismissed choice card has no rows, so the header carries the only line. */
.pds-suggestion-card--choice.pds-suggestion-card--dismissed
	.pds-suggestion-card__section--footer {
	border-block-start: var(--pds-border-width-default) solid
		var(--pds-color-border-default);
}

/* One choice: a PDS radio or PDS checkbox with its text. The label fills the
   row width so the label is a large target. The radio's look comes from the
   package (`.pds-radio-group__option`); the checkbox is the PDS Checkbox. */
.pds-suggestion-choice .pds-panel-row__items {
	flex: 1 1 auto;
	width: 100%;
}

.pds-suggestion-choice__control {
	width: 100%;
}

.pds-suggestion-choice .pds-suggestion-choice__label {
	align-items: flex-start;
	column-gap: var(--pds-spacing-xs);
	width: 100%;
}

.pds-suggestion-choice__label input[type='radio'] {
	margin-block-start: var(--pds-spacing-5xs);
}

.pds-suggestion-choice .pds-checkbox__label {
	align-items: flex-start;
	width: 100%;
}

.pds-suggestion-choice__extra {
	margin-block-start: var(--pds-spacing-2xs);
	margin-inline-start: calc(var(--pds-spacing-m) + var(--pds-spacing-xs));
}

.pds-suggestion-choice__extra > * {
	max-width: none;
	width: 100%;
}

.pds-suggestion-choice__text {
	display: flex;
	flex-direction: column;
	gap: var(--pds-spacing-5xs);
}

.pds-suggestion-choice__name {
	font-weight: var(--pds-typography-fw-medium);
}

.pds-suggestion-choice__description {
	color: var(--pds-color-foreground-default-secondary);
}