Skip to Content
Card SDKСправочник APIШапка карточки и диалоги

Шапка карточки и диалоги

Шапку карточки, её плитку обзора и диалоги рисует приложение, а не ваша страница, — поэтому они выглядят как родные, работают, пока карточка усыплена, и видны на телефоне. Вы задаёте их содержимое.

Вызывайте их сколько угодно часто. Приложение ограничивает частоту этих обновлений (заголовок — 30 в минуту; статус, бейдж и обзор — по 120 в минуту; внимание — раз в 10 секунд), а SDK берёт это на себя: для setTitle, setStatus, setBadge, setOverview и attention он отправляет по одному вызову каждого метода за раз, схлопывает вызовы, сделанные тем временем, в один с последним значением и повторяет последнее значение, если приложение ответило RATE_LIMITED. Из-за частоты они никогда не бросают исключений — обновлять на каждом рендере нормально. Обновление, которое ничего не меняет, ничего не стоит.

Заголовок

await card.setTitle('Checkout tests') // null clears it

Имя в шапке, в сайдбаре и в карточке «Команда». Если пользователь переименовал карточку, побеждает его имя; если нет ни того ни другого, показывается displayName из манифеста. До 120 символов; управляющие символы, символы направления текста (bidi) и невидимые символы вырезаются.

Статус

await card.setStatus('Running tests…', { busy: true }) // spinner await card.setStatus('3 failed', { tone: 'danger' }) await card.setStatus(null) // clear

Плашка в шапке, до 80 символов. Тона: default, accent, success, warning, danger.

Бейдж

await card.setBadge(3) // a count await card.setBadge('NEW', { tone: 'accent' }) // or a short text, ≤ 12 characters await card.setBadge(null) // clear

Плитка обзора

Когда пользователь отдаляет холст за порог обзора, каждая карточка вместо тела показывает плитку с главным фактом. Ваша показывает то, что вы задали здесь, — и продолжает показывать, пока карточка усыплена, и на телефоне. Приложение это запоминает.

await card.setOverview({ primary: '3 failing', // big line, ≤ 160 secondary: 'checkout, auth', // small line, ≤ 160 progress: 0.8, // 0..1, a progress bar; null hides it tone: 'danger', icon: 'bug-ant' })

Держите её актуальной: на загруженном холсте большинство видит от вашей карточки только её.

Иконки, которые умеет рисовать приложение (heroicons, контурные): academic-cap, arrow-path, beaker, bell, bolt, book-open, bug-ant, calendar, camera, chart-bar, chart-pie, chat-bubble-left-right, check-circle, clock, cloud, code-bracket, command-line, cpu-chip, cube, currency-dollar, document-text, exclamation-triangle, film, fire, flag, folder, globe-alt, heart, inbox, key, light-bulb, link, list-bullet, map, megaphone, moon, musical-note, newspaper, paper-airplane, pause, photo, play, puzzle-piece, rocket-launch, server, shield-check, signal, sparkles, star, stop, sun, table-cells, tag, trash, trophy, users, wrench-screwdriver (список — HOST_ICON_NAMES в SDK). Внутри своей страницы рисуйте любые иконки.

Внимание

await card.attention('needs-input', 'Pick a branch to deploy') await card.attention('info') // a softer pulse await card.attention('none') // clear

needs-input заставляет карточку пульсировать, как агент, который ждёт пользователя, и добавляет её во входящие (Inbox). Не чаще раза в 10 секунд. В версии 1 нет ни звука, ни уведомлений ОС.

Что показано сейчас. Приложение сохраняет заголовок, статус, бейдж, обзор и внимание карточки при перезагрузках, усыплении и обновлениях. card.context.chrome сообщает вашей странице, что там сейчас, так что карточка, поднявшая внимание до перезагрузки, может снять устаревшую пульсацию:

const attention = card.context.chrome?.attention if (attention && !stillNeedsTheUser()) await card.attention('none') declare function stillNeedsTheUser(): boolean

В старых версиях приложения chrome нет — считайте это «неизвестно».

Изменение размера

const applied = await card.requestResize({ w: 640, h: 480 }) render(applied.w, applied.h)

Ограничивается minSize/maxSize манифеста; возвращает размер, который реально применился. Шаг попадает в историю отмены холста, как изменение размера руками. Не чаще раза в 500 мс. Пользователь тоже всегда может поменять размер — слушайте card.lifecycle.onResized.

const opened = await card.openLink('https://github.com/acme/app/issues/42')

Приложение показывает полный адрес в своём диалоге на всё окно; ссылка откроется в браузере пользователя только после Open link. Только https:// и только пока карточка видна (иначе NOT_VISIBLE). Возвращает false, если пользователь отказался. Карточка не может ни перейти на другую страницу сама, ни открыть окно.

Полететь к другой карточке

await card.focusCard(cardId)

Переносит камеру к другой карточке того же воркспейса — для кнопок вида «покажи упавшего агента». Только пока ваша карточка видна, не чаще раза в 5 секунд.

Создать карточку

Нужно разрешение canvas.spawn.

// A note next to this card, connected with an arrow from this card. const noteId = await card.spawn('note', { title: 'Test report' }) await card.ports.send(noteId, 'summary', '# Report\n\nAll green.') // Another copy of this card, with data for its first start. await card.spawn('self', { init: { suite: 'e2e' }, connect: false })

Виды: self (ещё одна карточка вашего пакета, которая при первом запуске получает init как card.spawnInit), note, todo, kanban, sticky. Новая карточка встаёт рядом с вашей и соединяется стрелкой от вашей карточки, если не указать connect: false. Не больше 4 на карточку и 4 в минуту.

Сведения о карточке

const info = await card.getInfo() // CardInstanceInfo, fresh from the app render(info.instanceId, info.packageId, info.commit ?? 'dev folder', info.size)

Тосты

await card.ui.toast('Copied', { tone: 'success', durationMs: 2000 })

Небольшое уведомление внутри коробки карточки, до 280 символов, на 1–15 секунд, не чаще раза в 2 секунды.

Диалог подтверждения

alert, confirm и prompt в песочнице карточки ничего не делают. Попросите приложение:

const ok = await card.ui.confirm({ title: 'Delete all saved runs?', message: 'This removes 42 runs from this card. It cannot be undone.', confirmLabel: 'Delete', cancelLabel: 'Keep', tone: 'danger' }) if (ok) await card.storage.clear()

Приложение показывает это своим диалогом поверх всего окна, а не внутри карточки: неизменный заголовок о том, что ваша карточка просит подтверждения, ваши title и message как цитата, ваша confirmLabel (её заменяет «Confirm» приложения, если она похожа на отмену, отказ или «нет», называет NeuroSquad или содержит управляющие символы) и собственная кнопка Cancel приложения. Только пока карточка видна, не больше 10 в минуту. Диалоги от нескольких карточек выстраиваются в очередь.

Добавьте до 12 пунктов в меню ⋯ карточки, после собственных пунктов приложения (Settings…, Reload, About…).

await card.ui.setMenu([ { id: 'rerun', label: 'Run again', icon: 'arrow-path', onSelect: () => void rerun() }, { id: 'export', label: 'Copy report', icon: 'document-text', onSelect: () => void copyReport() }, { id: 'reset', label: 'Reset', tone: 'danger', disabled: true } ]) // Or handle every choice in one place: card.ui.onMenu((id) => card.log.info('menu', id)) declare function rerun(): Promise<void> declare function copyReport(): Promise<void>

Каждый вызов заменяет прежние пункты (не больше 30 вызовов в минуту). onSelect остаётся в вашей карточке — в приложение он не отправляется. Подписи до 60 символов; icon — одна из иконок приложения.

Всё на этой странице, кроме диалогов и ссылок, работает, даже когда карточки нет на экране. Диалогам, ссылкам, полёту камеры и запросам разрешений нужно, чтобы пользователь смотрел: иначе они падают с NOT_VISIBLE.