A Garden guide for support work with real theme aliases, type and radius scales, a complete reply composer, visibility-aware local drafts and field recovery.
Zendesk Garden Design System Support Workspace Structure
Keep the customer request in view
A support composer needs enough context to avoid a polished but irrelevant reply. The specimen places the customer request above the draft, with requester, organization and topic beside it. The interface is dense enough to compare the new text with the original question without switching screens.
Separate history from the active draft
Saved local entries appear above the composer with an explicit visibility label. The active draft remains in the native Textarea. Saving adds a snapshot and clears that field, so later edits cannot silently rewrite an earlier saved note.
Zendesk Garden Design System Theme Roles and Palette
Read aliases before copying colors
Garden 9 DEFAULT_THEME maps semantic roles to hue families and numbered palette values. A role such as background.primaryEmphasis is not a literal hexadecimal value. The reference table retains those aliases so a custom theme can change the primary hue without leaving hardcoded blue fragments in native controls.
Keep authored regions compatible with the provider
ThemeProvider supplies native component styling. This specimen uses DEFAULT_THEME and a matching light custom workspace; it does not add a fake dark-mode toggle that only changes the surrounding background. If adding color-scheme support, convert the custom message and sidebar colors alongside the provider.
Zendesk Garden Design System Typography and Density
Keep 14px work text readable
The default theme exposes a 14px medium role and a 20px medium line height, with separate 12px supporting and 18px heading roles. The sample uses a 26px ticket title and smaller context metadata. The original customer message and saved notes stay in normal body text rather than compressed labels.
Let long replies wrap naturally
Saved text preserves line breaks and wraps long words. A narrow mobile screen therefore retains the full note instead of forcing a horizontal scroll. The composer grows vertically through its textarea rather than turning the whole message history into an internal scrolling box.
Zendesk Garden Design System Field and Button Composition
Keep label, hint and error connected
The native Field groups Label, Hint, Textarea and conditional Message. The validation prop changes the textarea appearance when the authored minimum-length rule fails. This follows the component composition rather than applying error color to an unrelated paragraph outside the field.
Give visibility its own control
Zendesk Garden Design System Draft State and Local History
Validate before appending a message
The application requires at least twelve trimmed characters. A failed submission leaves the draft intact, reveals a field message and focuses the textarea. Editing clears the stale error; a later submission checks the current text again. This rule is application behavior, not an undocumented Garden default.
Keep internal notes visually distinct
Internal entries have a warm authored background and a written Internal note draft label. Public entries use the normal surface. Both explicitly say not sent. The distinction demonstrates visibility context without imitating a live Zendesk conversation or implying that another person has received anything.
Zendesk Garden Design System Responsive Work Areas
Stack the context after the main task
At the application breakpoint the ticket context moves below the conversation and composer. The order of the underlying document remains the same. On a phone, the visibility control spans the available width and the action row wraps so button labels are not compressed.
Use moderate radii and thin dividers
Native controls draw from the 2px, 4px and 8px radius scale. The original message panels use a 4px corner with subtle borders. Stronger visual emphasis belongs to the active action and validation state, not to shadows around every message.
Zendesk Garden Design System Validation and Keyboard Recovery
Exercise the complete draft flow
A useful check starts with an invalid submission, then verifies that typing, changing visibility, saving and clearing all leave the interface understandable. The source uses a React ref to restore focus after an error or clear action. The result count is announced in a status region.
Submit a short draft and follow the field error.
Choose Internal note, enter a useful note and save it.
Clear a later draft and confirm that the saved local snapshot remains.
Preserve a stable reading order
The request precedes the draft, and newly saved local snapshots stay in chronological order. Native buttons expose their actions as text. No keyboard shortcut or automatic sending behavior is hidden behind the composer, and the visibility choice remains a labeled select.
Zendesk Garden Design System React Integration
Install matching package generations
The specimen pins theming, buttons and forms to 9.16.1 and uses React 18 with styled-components. Mixing older Garden package generations can create mismatched theme expectations. The full JSX entry includes the provider, field composition and local state, while the CSS file contains only authored layout.
@zendeskgarden/react-theming 9.16.1
@zendeskgarden/react-buttons 9.16.1
@zendeskgarden/react-forms 9.16.1
Extend only the missing service layer
Zendesk Garden Design System Component Examples
main.jsx — complete working specimen
Draft a reply with the customer context in view. The source below is the full React entry, including all state and validation.
jsx
import React, { useState, useRef } from "react";
import { createRoot } from "react-dom/client";
import { ThemeProvider, DEFAULT_THEME } from "@zendeskgarden/react-theming";
import { Button } from "@zendeskgarden/react-buttons";
import {
Field,
Label,
Textarea,
Hint,
Message,
Select,
} from "@zendeskgarden/react-forms";
import "./garden.css";
function App() {
const [mode, setMode] = useState("public"),
[text, setText] = useState(""),
[error, setError] = useState(false),
[items, setItems] = useState([]);
const ref = useRef();
function submit(e) {
e.preventDefault();
if (text.trim().length < 12) {
setError(true);
ref.current.focus();
return;
}
setItems([...items, { mode, text: text.trim() }]);
setText("");
setError(false);
}
return (
<ThemeProvider theme={DEFAULT_THEME}>
<main className="garden-workspace">
<header>
<span>SUPPORT WORKSPACE / FICTIONAL TICKET</span>
<h1>Help with an invoice address</h1>
<p>Ticket #1028 · Nadia Walker · Email channel</p>
</header>
<div className="garden-grid">
<section>
<div className="message customer">
<strong>Nadia Walker</strong>
<small>Customer · example message</small>
<p>
Could you update the company address on our next invoice? The
billing contact has changed.
</p>
</div>
{items.map((i, n) => (
<article className={"message " + i.mode} key={n}>
<strong>
{i.mode === "public"
? "Public reply draft"
: "Internal note draft"}
</strong>
<small>Saved locally · not sent</small>
<p>{i.text}</p>
</article>
))}
<form onSubmit={submit} noValidate>
<div className="composer-head">
<h2>Compose a draft</h2>
<Field>
<Label>Visibility</Label>
<Select
value={mode}
onChange={(e) => setMode(e.target.value)}
>
<option value="public">Public reply</option>
<option value="internal">Internal note</option>
</Select>
</Field>
</div>
<Field>
<Label>
{mode === "public" ? "Reply text" : "Internal note"}
</Label>
<Hint>
{mode === "public"
? "Prepared for the customer; this demo will not send it."
: "Internal context for the support team; saved only in this page."}
</Hint>
<Textarea
ref={ref}
value={text}
rows={5}
validation={error ? "error" : undefined}
onChange={(e) => {
setText(e.target.value);
setError(false);
}}
/>
{error && (
<Message validation="error">
Write at least 12 characters.
</Message>
)}
</Field>
<div className="composer-actions">
<span>{text.length} characters</span>
<Button
type="button"
onClick={() => {
setText("");
setError(false);
ref.current.focus();
}}
>
Clear draft
</Button>
<Button isPrimary type="submit">
Save local draft
</Button>
</div>
</form>
<p role="status">
{items.length > 0
? `${items.length} draft${items.length === 1 ? "" : "s"} saved locally. No message sent.`
: ""}
</p>
</section>
<aside>
<h2>Ticket context</h2>
<dl>
<dt>Requester</dt>
<dd>Nadia Walker</dd>
<dt>Organization</dt>
<dd>Northstar Studio</dd>
<dt>Priority</dt>
<dd>Normal</dd>
<dt>Topic</dt>
<dd>Billing details</dd>
</dl>
<div className="context-note">
<h3>Before replying</h3>
<ul>
<li>Confirm the billing contact.</li>
<li>Keep invoice identifiers out of public examples.</li>
<li>State whether the change affects future invoices.</li>
</ul>
</div>
</aside>
</div>
<footer>
Native Garden 9.16.1 React components. Original local drafting
workflow; no Zendesk connection.
</footer>
</main>
</ThemeProvider>
);
}
createRoot(document.getElementById("root")).render(<App />);
Build a Garden support composer with native Field/Label/Hint/Textarea/Message composition. Keep visibility in each saved draft snapshot, validate before appending, preserve customer context, and distinguish local saving from sending. Use the exact theme roles and complete source here.
05
Zendesk Garden Design System Sources and Scope
OpenDesign application guide. Native Garden components render the specimen; fictional ticket content and local drafts do not connect to Zendesk or send messages.