QuoteRequestButton
Trigger, dialog and open state. Renders nothing when the buyer may not request one, and takes the whole cart because commercetools refuses one whose cart has no address.
import { QuoteRequestButton } from "@evolve-storefront/feature-quote/quote-request-button";Renders inside QuoteProvider.
Preview
Usage
// One element on the basket page: the dialog comes with it, and it renders// nothing for a buyer who may not request a quote.<QuoteRequestButton cart={cart} onRequested={(request) => router.push(quoteRequestPath(request.id.id))}/>;Props
| Prop | Type | Description |
|---|---|---|
cart | QuotableCart | The cart to quote; its lines and address become the request. |
isPending? | boolean | The action is running. The button keeps its label, so its width and
accessible name hold, shows a spinner and is |
type? | "submit" | "reset" | "button" | |
tone? | ButtonTone | |
data-component? | undefined | A button's identity is not a caller's to rename — see |
variant? | ButtonVariant | |
isIconOnly? | boolean | The button has no visible label, so it is square. Structural rather than a size: it says the button has nothing to be wide for, and says nothing about how big — the brand's control tokens still decide that. MoreNot inferred from the children. A kebab menu is as often a glyph or an SVG
as an |
asChild? | boolean | |
defaultValues? | Partial<{ purchaseOrderNumber: string; comment?: string | undefined; }> | |
onRequested? | ((quoteRequest: QuoteRequest) => void) | Runs with the created request after success (e.g. navigate to it). |
Any other props go to the root element, like on a plain HTML element.
Change the layout
Pass children to QuoteRequestButton to arrange its parts yourself. Every part is exported from @evolve-storefront/feature-quote/quote-request-button.
QuoteRequestDialogRequest a quote from a cart, as a modal.
Per evolve-dialog-form: the dialog owns its DialogFooter, cancel is a
DialogClose, and the submit part lives inside the <form>. Server errors are
cleared by onClosed — after the exit animation, so the content does not blank
while it is still fading out.
It takes the cart as an id rather than reading one: a feature never depends on another feature, so the surface that knows the active cart passes it in.
One call. The cart already carries its delivery address — set on the cart, where the buyer can see the shipping costs it produces — so this dialog only asks for the reference and the comment.
| Prop | Type | Description |
|---|---|---|
cartId | string | The cart the request is created from; its lines become the quote. |
open | boolean | |
onOpenChange | (open: boolean) => void | |
defaultValues? | Partial<{ purchaseOrderNumber: string; comment?: string | undefined; }> | |
onRequested? | ((quoteRequest: QuoteRequest) => void) | Runs with the created request after success (e.g. navigate to it). |
QuoteRequestFormRequest a quote from the current basket on the evolve-feature-form pattern (RAC + Zod).
It seeds QuoteRequestFormContext so the composed Fields/Submit pieces
read the extras without prop-drilling. onValidSubmit runs the mutation;
QuoteRequestDialog is the ready-made composition.
| Prop | Type | Description |
|---|---|---|
onValidSubmit | (values: { purchaseOrderNumber: string; comment?: string | undefined; }) => void | Runs with the validated values on a valid submit — where the mutation goes. |
children | ReactNode | The composed pieces — typically |
validationBehavior? | "aria" | "native" | Default |
defaultValues? | Partial<{ purchaseOrderNumber: string; comment?: string | undefined; }> | |
isPending? | boolean | |
error? | string | null | Form-level error (e.g. a failed mutation), shown above the actions. |
serverErrors? | Partial<Record<"purchaseOrderNumber" | "comment", string | string[]>> | Server-provided field errors, merged into the same display path. |
Any other props go to the root element, like on a plain HTML element.
QuoteRequestFormContextThe context QuoteRequestForm fills.
No props of its own.
QuoteRequestFormFieldsThe PO reference + optional comment fields, seeded from QuoteRequestForm's context.
No props of its own.
QuoteRequestFormSubmitThe form's submit button — never disabled (per the evolve-feature-form pattern: submission is gated by validity in the form's onSubmit, not by a disabled control).
| Prop | Type | Description |
|---|---|---|
pendingLabel | ReactNode | Shown while a submit is in flight. |
isPending? | boolean | The action is running. The button keeps its label, so its width and
accessible name hold, shows a spinner and is |
tone? | ButtonTone | |
data-component? | undefined | A button's identity is not a caller's to rename — see |
variant? | ButtonVariant | |
isIconOnly? | boolean | The button has no visible label, so it is square. Structural rather than a size: it says the button has nothing to be wide for, and says nothing about how big — the brand's control tokens still decide that. MoreNot inferred from the children. A kebab menu is as often a glyph or an SVG
as an |
asChild? | boolean |
Any other props go to the root element, like on a plain HTML element.

