Skip to main content

Dialogs

Dialogs allow you to customize modals and warnings in the configurator. There are two main areas: the order dialog and inline warnings.

Basic structure​

Dialog extensions are registered in the ui.dialogs object:

// In Plugin.tsx
export default {
// ...
ui: {
dialogs: {
order: {
root: { hoc: ..., description: "..." },
contactFields: { hoc: ..., description: "..." },
// weitere Order-Dialog Slots
},
warnings: {
invalidSelection: { hoc: ..., description: "..." },
// weitere Warning Slots
}
}
}
}

Order dialog (Order Dialog)​

The order dialog is displayed when a customer completes a configuration (order, shopping cart, PDF download, etc.).

root​

Overwrites the entire order dialog modal.

root: {
hoc: (Original) => (props) => (
<div className="custom-order-wrapper">
<Original {...props} />
</div>
),
description: "Wrapper um den gesamten Bestelldialog"
}

headline​

Overwrites the headline of the order dialog.

headline: {
hoc: (Original) => (props) => (
<div className="custom-headline">
<span className="icon">🛒</span>
<Original {...props} />
</div>
),
description: "Fügt Icon zur Überschrift hinzu"
}

contactFields​

Overwrites the contact form (name, e-mail, telephone etc.).

Application examples:

  • Add additional fields (company, department)
  • Customize field validation
  • Change layout
contactFields: {
hoc: (Original) => (props) => (
<div>
<Original {...props} />

{/* Zusätzliche Felder */}
<div className="additional-fields">
<label>
Firma:
<input type="text" name="company" />
</label>
<label>
Abteilung:
<input type="text" name="department" />
</label>
</div>
</div>
),
description: "Fügt zusätzliche Kontaktfelder hinzu"
}

priceTable​

Overwrites the entire price table in the order dialog.

priceTable: {
hoc: (Original) => (props) => (
<div className="enhanced-price-table">
<div className="table-header">Ihre Auswahl:</div>
<Original {...props} />
<div className="table-footer">
* Alle Preise verstehen sich zzgl. Versandkosten
</div>
</div>
),
description: "Erweitert Preistabelle mit Header/Footer"
}

priceTableSelectionList​

Overwrites the list of selected features/values in the price table.

priceTableSelectionList: {
hoc: (Original) => (props) => (
<div className="custom-selection-list">
<h4>Ihre Konfiguration:</h4>
<Original {...props} />
</div>
),
description: "Fügt Überschrift über Auswahliste hinzu"
}

priceTableArticleList​

Overwrites the article list (bill of materials) in the price table.

priceTableArticleList: {
hoc: (Original) => (props) => (
<div className="custom-article-list">
<h4>Benötigte Artikel:</h4>
<Original {...props} />
</div>
),
description: "Fügt Überschrift über Artikelliste hinzu"
}

priceTableTotal​

Overwrites the total line at the end of the price table.

priceTableTotal: {
hoc: (Original) => (props) => (
<div className="enhanced-total">
<Original {...props} />
<div className="savings-info">
Sie sparen 15% gegenüber Einzelkauf!
</div>
</div>
),
description: "Zeigt Ersparnis-Info unter Gesamtpreis"
}

confirmationSuccess​

Overwrites the confirmation of success after a successful order.

Application examples:

  • Custom Thank-You Message
  • Include tracking codes
  • Show additional information
confirmationSuccess: {
hoc: (Original) => (props) => (
<div className="custom-success">
<div className="success-animation">✓</div>
<Original {...props} />
<div className="next-steps">
<h4>Nächste Schritte:</h4>
<ol>
<li>Sie erhalten eine Bestätigungs-E-Mail</li>
<li>Wir prüfen Ihre Konfiguration</li>
<li>Sie erhalten ein detailliertes Angebot</li>
</ol>
</div>
</div>
),
description: "Erweiterte Erfolgsbestätigung mit Next-Steps"
}

confirmationError​

Overwrites the error display after a failed order.

confirmationError: {
hoc: (Original) => (props) => (
<div className="custom-error">
<Original {...props} />
<div className="support-info">
<p>Probleme? Kontaktieren Sie uns:</p>
<a href="tel:+4912345678">+49 123 456 78</a>
</div>
</div>
),
description: "Fügt Support-Kontakt bei Fehler hinzu"
}

Warnings (Warnings)​

Warnings are displayed inline in the sidebar if selections are invalid.

invalidSelection​

Overwrites the entire invalid selection warning (badge next to characteristic values).

invalidSelection: {
hoc: (Original) => (props) => (
<div className="custom-invalid-badge">
<Original {...props} />
</div>
),
description: "Custom Styling für ungültige Auswahl"
}

invalidSelectionIcon​

Overwrites only the icon within the warning.

invalidSelectionIcon: {
hoc: (Original) => (props) => (
<span className="custom-warning-icon">⚠️</span>
),
description: "Verwendet Custom Warning Icon"
}

invalidSelectionTooltip​

Overwrites the tooltip content that appears when hovering over the warning.

invalidSelectionTooltip: {
hoc: (Original) => (props) => (
<div className="custom-tooltip">
<strong>Ungültige Auswahl</strong>
<Original {...props} />
<div className="tooltip-help">
Klicken Sie hier für Hilfe →
</div>
</div>
),
description: "Erweiterter Tooltip mit Hilfe-Link"
}

numberWarningTooltip​

Overwrites the tooltip for warnings for numerical values outside the valid range.

numberWarningTooltip: {
hoc: (Original) => (props) => (
<div className="number-warning-tooltip">
<Original {...props} />
<div className="allowed-range">
Erlaubter Bereich: {props.min} - {props.max}
</div>
</div>
),
description: "Zeigt erlaubten Zahlenbereich im Tooltip"
}

Complete example: Enhanced Order Dialog​

__PROTECTED_0__
__PROTECTED_1__

// Root mit Badge
const orderRootHOC: HOC = (Original) => (props) => (
<div className="enhanced-order-dialog">
<div className="order-badge">Schnellbestellung</div>
<Original {...props} />
</div>
);

// Erweiterte Kontaktfelder
const contactFieldsHOC: HOC = (Original) => (props) => {
const [company, setCompany] = useState("");

return (
<div className="extended-contact-form">
<Original {...props} />

<div className="company-field">
<label>
Firma (optional):
<input
type="text"
value={company}
onChange={(e) => setCompany(e.target.value)}
placeholder="Ihre Firma"
/>
</label>
</div>

<div className="privacy-notice">
<input type="checkbox" id="privacy" required />
<label htmlFor="privacy">
Ich akzeptiere die{" "}
<a href="/datenschutz" target="_blank">
Datenschutzerklärung
</a>
</label>
</div>
</div>
);
};

// Preistabelle mit Versandinfo
const priceTotalHOC: HOC = (Original) => (props) => (
<div className="enhanced-total">
<Original {...props} />

<div className="shipping-info">
<small>zzgl. Versandkosten (werden im Checkout berechnet)</small>
</div>

<div className="payment-methods">
<span>Wir akzeptieren:</span>
<div className="payment-icons">
<img src="/icons/visa.svg" alt="Visa" />
<img src="/icons/mastercard.svg" alt="Mastercard" />
<img src="/icons/paypal.svg" alt="PayPal" />
</div>
</div>
</div>
);

// Erfolgsbestätigung mit Animation
const confirmationSuccessHOC: HOC = (Original) => (props) => {
useEffect(() => {
if (typeof window !== "undefined" && window.gtag) {
window.gtag("event", "purchase_success", {
order_id: props.orderId
});
}
}, [props.orderId]);

return (
<div className="success-wrapper">
<div className="success-icon-animation">
<svg className="checkmark" viewBox="0 0 52 52">
<circle className="checkmark-circle" />
<path className="checkmark-check" />
</svg>
</div>

<Original {...props} />

<div className="social-share">
<p>Teilen Sie Ihre Konfiguration:</p>
<button className="share-btn facebook">Facebook</button>
<button className="share-btn twitter">Twitter</button>
</div>
</div>
);
};

// Im Plugin registrieren:
export default {
// ...
ui: {
dialogs: {
order: {
root: {
hoc: orderRootHOC,
description: "Fügt Badge zum Bestelldialog hinzu"
},
contactFields: {
hoc: contactFieldsHOC,
description: "Erweitert Kontaktformular um Firma und Datenschutz"
},
priceTableTotal: {
hoc: priceTotalHOC,
description: "Zeigt Versandinfo und Zahlungsmethoden"
},
confirmationSuccess: {
hoc: confirmationSuccessHOC,
description: "Erweiterte Erfolgsseite mit Animation und Social Share"
}
},
warnings: {
invalidSelection: {
hoc: (Original) => (props) => (
<div className="custom-warning-badge">
<Original {...props} />
</div>
),
description: "Custom Styling für Warnungen"
}
}
}
}
};

Best Practices​

1. render original component​

If you do not want to replace everything, render the original component:

hoc: (Original) => (props) => (
<>
<Original {...props} />
{/* Ihr zusätzlicher Content */}
</>
)

2. form validation​

If you add additional form fields, implement validation:

const [email, setEmail] = useState("");
const [error, setError] = useState("");

const validateEmail = (value: string) => {
if (!value.includes("@")) {
setError("Bitte gültige E-Mail eingeben");
return false;
}
return true;
};

3. analytics events​

Use confirmation HOCs for tracking:

confirmationSuccess: {
hoc: (Original) => (props) => {
useEffect(() => {
// Google Analytics
if (window.gtag) {
window.gtag("event", "order_complete");
}

// Facebook Pixel
if (window.fbq) {
window.fbq("track", "Purchase");
}
}, []);

return <Original {...props} />;
}
}

4. responsive design​

Design responsive custom content:

<div className="custom-fields">
<style jsx>{`
.custom-fields {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}
`}</style>
{/* Felder */}
</div>

5. accessibility​

Use semantic HTML and ARIA attributes:

<div role="alert" aria-live="polite" className="success-message">
Bestellung erfolgreich!
</div>

TypeScript types​

Use the provided types:

__PROTECTED_2__
K3DialogExtensions,
K3OrderDialogExtensions,
K3WarningExtensions,
HOCWithDescription
} from "k3-plugin-api";

const orderExtensions: K3OrderDialogExtensions = {
headline: {
hoc: myHOC,
description: "Custom headline"
}
};

Localization​

Descriptions can be multilingual:

confirmationSuccess: {
hoc: myHOC,
description: {
de: "Erweiterte Erfolgsbestätigung",
en: "Enhanced success confirmation",
fr: "Confirmation de succès améliorée",
nl: "Uitgebreide succesbevestiging"
}
}