{
  "id": "TB02",
  "title": "Actions only",
  "topic": "toolbar",
  "use": "On a detail page the toolbar carries actions only. There is no search, no filter and no view switch — there is only this one record. The bar starts at the left and stays there, without a spacer. It sticks above the form, so that “Save voucher” does not scroll away on a long form.",
  "decisions": [
    "A detail page's toolbar carries actions only: with a single record there is nothing to search, filter or switch.",
    "The bar starts at the left and stays there: with no view controls there is no second group to hold at the right edge.",
    "The voucher's name, number and state stand in the page header, not in the bar, so the bar carries actions and nothing else on every detail page.",
    "The bar sticks above the form, so Save voucher stays in reach in the fortieth field; Save therefore stands only there, not again under the form.",
    "The sticky wrapper has an opaque background, the application's surface, or the content scrolls visibly through the bar.",
    "Two states, two badges: the voucher's processing state and the unsaved change are different things, and one badge for both would swallow one of them.",
    "Save voucher is disabled while nothing has changed, and an ed-tooltip on it says why; the header shows the change as the Unsaved badge, not the reason in words. The tooltip stands outside the bar, since in the action slot it would count as an action."
  ],
  "try": [
    {
      "do": "Point at Save voucher",
      "then": "the button is disabled, and its tooltip says why — “Nothing has changed”"
    },
    {
      "do": "Change a field",
      "then": "Save voucher becomes available, and the Unsaved badge appears in the header"
    },
    {
      "do": "Type the old value back in",
      "then": "the badge goes away, and the button is disabled again"
    },
    {
      "do": "Press Review voucher",
      "then": "the state becomes Reviewed; an unsaved change stays beside it"
    },
    {
      "do": "Press Save voucher",
      "then": "the toast confirms with the voucher number, Unsaved disappears, the state stays"
    },
    {
      "do": "Make the window narrow",
      "then": "the toolbar stays at the left and does not move to the right"
    },
    {
      "do": "Scroll down",
      "then": "the toolbar stays at the top, the header scrolls away"
    }
  ],
  "revision": 2,
  "changes": [
    {
      "revision": 2,
      "change": "Why Save voucher is disabled is an ed-tooltip on the button, outside the toolbar; the header no longer says Nothing has changed, and the button has no title."
    }
  ],
  "reviewed": true,
  "source": "<style>\n  .tb02-toolbar {\n    position: sticky;\n    inset-block-start: 0;\n    z-index: 4;\n    background: var(--ed-color-surface-default);\n  }\n\n  .tb02-form {\n    max-inline-size: 56rem;\n  }\n</style>\n\n<div class=\"ed-stack ed-gap-4\">\n  <div class=\"ed-cluster ed-gap-3 ed-align-items-baseline\">\n    <span class=\"ed-caption-m ed-text-tabular\">RE-2026-04188</span>\n    <h2>Maintenance of lifting platform, hall 2</h2>\n    <div class=\"ed-cluster ed-gap-2 ed-align-items-baseline\" role=\"status\">\n      <ed-badge id=\"tb02-state\" variant=\"neutral\">Open</ed-badge>\n      <ed-badge id=\"tb02-unsaved\" variant=\"warning\" hidden>Unsaved</ed-badge>\n    </div>\n  </div>\n\n  <div class=\"tb02-toolbar ed-py-2\">\n    <ed-toolbar label=\"Voucher RE-2026-04188\">\n      <ed-button id=\"tb02-save\" disabled><ed-icon slot=\"start\" name=\"save\"></ed-icon>Save voucher</ed-button>\n      <ed-button id=\"tb02-review\" appearance=\"plain\"><ed-icon slot=\"start\" name=\"check\"></ed-icon>Review voucher</ed-button>\n      <ed-button appearance=\"plain\"><ed-icon slot=\"start\" name=\"copy\"></ed-icon>Copy voucher</ed-button>\n      <ed-divider orientation=\"vertical\"></ed-divider>\n      <ed-button appearance=\"plain\"><ed-icon slot=\"start\" name=\"delete\"></ed-icon>Delete voucher</ed-button>\n    </ed-toolbar>\n    <ed-tooltip id=\"tb02-save-reason\" for=\"tb02-save\">Nothing has changed</ed-tooltip>\n  </div>\n\n  <form id=\"tb02-form\" class=\"tb02-form ed-stack ed-gap-8\">\n    <section class=\"ed-stack ed-gap-4\">\n      <h3>Voucher</h3>\n      <p>Voucher number, currency and client are fixed with the voucher and cannot be changed when posting.</p>\n      <div class=\"ed-grid\" style=\"--ed-grid-min-column-size: 20rem\">\n        <ed-input name=\"voucher-number\" label=\"Voucher number\" value=\"RE-2026-04188\" readonly></ed-input>\n        <ed-input name=\"posting-text\" label=\"Posting text\" value=\"Maintenance of lifting platform, hall 2\" required></ed-input>\n      </div>\n      <div class=\"ed-grid-fill\" style=\"--ed-grid-min-column-size: 12rem\">\n        <ed-input name=\"voucher-date\" label=\"Voucher date\" value=\"08/04/2026\" required></ed-input>\n        <ed-select name=\"voucher-type\" label=\"Voucher type\" value=\"outgoing-invoice\">\n          <ed-option value=\"outgoing-invoice\">Outgoing invoice</ed-option>\n          <ed-option value=\"incoming-invoice\">Incoming invoice</ed-option>\n          <ed-option value=\"cash-receipt\">Cash receipt</ed-option>\n        </ed-select>\n      </div>\n    </section>\n\n    <section class=\"ed-stack ed-gap-4\">\n      <h3>Posting</h3>\n      <div class=\"ed-grid-fill\" style=\"--ed-grid-min-column-size: 12rem\">\n        <ed-input name=\"account\" label=\"Account\" value=\"8400\" required></ed-input>\n        <ed-input name=\"contra-account\" label=\"Contra account\" value=\"10000\" required></ed-input>\n        <ed-input name=\"cost-center\" label=\"Cost center\" value=\"4711\"></ed-input>\n        <ed-input name=\"amount\" label=\"Amount\" type=\"number\" inputmode=\"decimal\" without-spin-buttons step=\"0.01\" value=\"4812.50\" required></ed-input>\n        <ed-input name=\"vat\" label=\"VAT in %\" value=\"19\"></ed-input>\n        <ed-input name=\"currency\" label=\"Currency\" value=\"EUR\" readonly></ed-input>\n      </div>\n    </section>\n\n    <section class=\"ed-stack ed-gap-4\">\n      <h3>Assignment</h3>\n      <div class=\"ed-grid\" style=\"--ed-grid-min-column-size: 20rem\">\n        <ed-input name=\"client\" label=\"Client\" value=\"Steinbach-Wallner GmbH\" readonly></ed-input>\n        <ed-input name=\"clerk\" label=\"Clerk\" value=\"Sophie Brandt\"></ed-input>\n      </div>\n      <ed-textarea name=\"note\" label=\"Note\" rows=\"3\" value=\"Maintenance contract runs until December 31, 2026.\"></ed-textarea>\n    </section>\n  </form>\n</div>\n\n<ed-toast-stack id=\"tb02-toasts\"></ed-toast-stack>\n\n<script type=\"module\">\n  const form = document.getElementById('tb02-form');\n  const save = document.getElementById('tb02-save');\n  const review = document.getElementById('tb02-review');\n  const state = document.getElementById('tb02-state');\n  const unsaved = document.getElementById('tb02-unsaved');\n  const saveReason = document.getElementById('tb02-save-reason');\n  const toasts = document.getElementById('tb02-toasts');\n  const fields = [...form.querySelectorAll('[name]')];\n  const saved = new Map();\n\n  // A number field holds a number: 4812.5 typed over 4812.50 is the value it had.\n  const same = (field, before) =>\n    field.value === before || (field.type === 'number' && field.value !== '' && before !== '' && Number(field.value) === Number(before));\n\n  const update = () => {\n    const changed = fields.some(field => !same(field, saved.get(field)));\n    unsaved.hidden = !changed;\n    save.disabled = !changed;\n    saveReason.disabled = changed;\n  };\n\n  await Promise.all(['ed-input', 'ed-select', 'ed-option', 'ed-textarea'].map(tag => customElements.whenDefined(tag)));\n  await Promise.all(fields.map(field => field.updateComplete));\n  fields.forEach(field => saved.set(field, field.value));\n\n  form.addEventListener('input', update);\n  form.addEventListener('change', update);\n\n  save.addEventListener('click', () => {\n    fields.forEach(field => saved.set(field, field.value));\n    update();\n    toasts.create({ variant: 'success', title: 'Voucher RE-2026-04188 saved' });\n  });\n\n  review.addEventListener('click', () => {\n    state.textContent = 'Reviewed';\n    state.variant = 'info';\n  });\n</script>",
  "page": "https://test-apps.eurodata.de/a/eurodata-ui/docs/patterns/toolbar/tb02-actions-only/",
  "topicPage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/patterns/toolbar/"
}
