@bridgeline-digital/hawk-app-ui

中文文档
0.1.7发布于 2026/11/09UNLICENSEDTypeScriptES Module近 30 天下载 4542

For Bridgeline developers: the Spark look for Hawk Apps: for React + MUI, the theme (following the host's colors and mode), the app provider and shared components; for any app (vanilla, Preact, React, Next), a stylesheet and custom elements.

原始使用文档
文档目录5 节
  1. Use it
  2. Components
  3. The theme
  4. Without React and MUI
  5. Versions

@bridgeline-digital/hawk-app-ui

The Spark look for Hawk Apps, in the host's colors and mode. For Bridgeline developers. See every part live, in light and dark: the UI kit gallery (on the developer site).

  • React + MUI apps (the next-mui template): Spark's MUI theme, the provider that connects the app to its host, and the components apps keep needing: sections, KPI tiles, tables, small charts, a confirm dialog, a side drawer, toasts and formatting. Requires the Hawk Apps bridge.
  • Any other app (the react, preact, next and vanilla templates): a stylesheet and a few custom elements, no React or MUI needed. See Without React and MUI.
npm install @bridgeline-digital/hawk-app-ui @mui/material@^9 @emotion/react @emotion/styled   # React + MUI
npm install @bridgeline-digital/hawk-app-ui                                                    # any other app

Use it

// app/layout.tsx (once): Montserrat, Spark's font, bundled with the app
import '@bridgeline-digital/hawk-app-ui/fonts';

// app/providers.tsx
'use client';
import { HawkAppProvider } from '@bridgeline-digital/hawk-app-ui';

export default function Providers({ children }: { children: React.ReactNode }) {
    return <HawkAppProvider>{children}</HawkAppProvider>;
}

// any page or component inside it
import { useHawk } from '@bridgeline-digital/hawk-app-ui';

export function Page() {
    const { app, context } = useHawk(); // the connected app and its context (client, engine, dates, theme)
    // …app.data.query(...), app.analytics.report(...)
}
  • HawkAppProvider connects to the host (createApp({ autoResize: true }), change it with options), shows a spinner meanwhile and an explanation when the app is opened outside a host (connecting and error replace them), then renders its children in the theme. It follows the host when its theme changes. The spinner and the explanation are a <main> landmark, as the app's page should be, so the accessibility check finds one in every state.
  • useHawk() returns { app, context }, always connected (the provider renders children only then). useHawkAppState() is the hook underneath, for an app that wants to render the states itself.
  • <HawkComments target label?> (the comments scope) is a comment icon with a "!" when there are comments (the count in its tooltip); a click opens the thread in a drawer, where everyone at the client reads and adds comments (authors edit and delete their own). The page's badges share one count request. See the bridge guide's "Comments".
  • usePdfExport(options | false) lets the user export the page as a PDF while it's mounted: the host shows a PDF icon, and a click downloads the whole page. usePdfExport({ fileName: 'Zero results' }), or false while loading. Leave out buttons and filters with data-hawk-pdf-ignore. See the bridge guide's "Export a page as a PDF".
  • useSavedState(initial) is useState for what makes a saved view (filters, range, tab, sort): the value is the page's state for the host's Views menu, and opening a saved view or its link sets it back. const [filters, setFilters] = useSavedState({ range: 'l13', target: null }). One small JSON object, once per page. See the bridge guide's "Saved views".
  • useRoute() is the app's route for deep links and Back: const [route, setRoute] = useRoute(), show the page the route names, and setRoute('/widgets/12') when the user opens one ({ replace: true } for no Back step). The host keeps it in its URL, so a reload or a link opens the same page. In a preview (no host), routes work within the page. See the bridge guide's "Deep links and Back".
  • useScreen(name | null) counts a screen the routes don't show, such as a tab, each time it's shown: useScreen('Logs') in the tab's component. Routes and views are counted by the bridge, and so are clicks on data-hawk-usage="Export CSV" elements. See hawk-app usage --screens and the bridge guide's "Errors and usage".
  • usePageContext(object | null) says what the page shows, for the host's Explain this page button (and its assistant): usePageContext(rows ? { page: 'Zero-result searches', dateRange, top10 } : null). Plain names and numbers, at most 50 KB; sent shortly after it changes, cleared when the component unmounts. See the bridge guide's "Say what the page shows".
  • useTour() is for a "Take the tour" button: { available, active, start }. The bridge shows the tour (tour in hawk-app.json, cards by data-hawk-tour elements) on its own on first open; start() shows every step again, available is true once the version has steps, active while it shows. Nothing in a preview. See the bridge guide's "Tour".
  • Your own theme additions: <HawkAppProvider theme={{ components: { … } }}>, merged last.

Components

import { ConfirmDialog, DataTable, EmptyState, KpiRow, KpiTile, LoadingSection, Notice, Section, SideDrawer, useFormat, useToast } from '@bridgeline-digital/hawk-app-ui';
import { BarList, ColumnChart, Sparkline, StackedColumnChart } from '@bridgeline-digital/hawk-app-ui/charts';
import { DataGrid } from '@bridgeline-digital/hawk-app-ui/data-grid'; // needs @mui/x-data-grid@^9

const f = useFormat(); // in the host's locale
<KpiRow>
    <KpiTile highlight label="Revenue" value={f.money(rev)} change={rev / prevRev - 1} trend={weekly} />
    <KpiTile label="No-result searches" value={f.integer(zero)} change={zero / prevZero - 1} goodWhen="down" />
</KpiRow>
<Section title="Searches per day" subtitle="UTC days" action={<Button>Refresh</Button>}>
    <ColumnChart label="Searches per day" columns={days.map((d) => ({ label: f.date(d.date, { year: false }), value: d.searches }))} />
</Section>
<DataTable rows={terms} columns={[{ key: 'term', label: 'Term' }, { key: 'searches', label: 'Searches', align: 'right' }]}
    defaultSort={{ key: 'searches', direction: 'desc' }} totals={{ term: 'Total', searches: f.integer(total) }} download="terms.csv" />
ComponentFor
SectionA titled card (Spark's card header and padding), with an optional subtitle and action
KpiTile, KpiRowA number with its change vs. the previous period (green when good: goodWhen), an optional trend; tiles side by side
DataTableUp to a few hundred rows: sortable columns, totals row, sticky header (maxHeight), CSV download of what it shows (text that a spreadsheet would run as a formula, such as a search term starting with =, opens as text)
DataGrid (/data-grid)Thousands of rows, paging and filtering: MUI X's community grid with Spark's defaults
BarList, ColumnChart, StackedColumnChart, Sparkline (/charts)Small charts in the theme's colors, without a chart library; each has a label for screen readers and tooltips with the values
EmptyState, LoadingSection, NoticeNothing to show; a section still loading; a message (onRetry adds Try again)
ConfirmDialogAsks before an action; destructive makes it red; a promise from onConfirm keeps it open with a spinner
SideDrawerDetails of one item, from the right, with a title, close button and actions
useToast()toast(message, severity): the host's toast in the full app, a snackbar in a view
useFormat() / createFormat(locale)integer, number, compact, percent, change (+12.3%), money, date (a "2026-10-03" date stays that day), dateTime: dates from a Date or an ISO / Athena string; anything else shows "–"

The host shows the frame over the whole page while a dialog or drawer is open, so they're always fully visible.

Every component, in light and dark, is in the UI kit gallery on the developer site (the repository's gallery app, examples/ui-kit, rendered as a preview). <HawkAppProvider preview={{ mode: 'dark' }}> renders without a host, with sample context (previewContext()), for galleries, docs and screenshots. New apps get the kit from the CLI's next-mui template (hawk-app create my-app --template next-mui); an existing next-mui app gets it with hawk-app upgrade.

The theme

createHawkTheme(context.theme, ...overrides) (also at @bridgeline-digital/hawk-app-ui/theme):

PartFrom
Typography (Montserrat, 14 px base, h1–h3, featuredValue), breakpoints (sm 640 … 2xl 1536), spacing, card and list overridesSpark's theme (sparkThemeOptions)
Primary color and its text, backgrounds, text colors, dividers, border radius, light or darkThe host's theme tokens (color-button-accent-background, color-background, color-background-container, color-text-default, color-text-secondary, color-border-default, border-radius, mode), else Spark's. A color-border-default too faint to see on the host's surface (contrast under 1.2, such as HawkSearch's #f5f7fa on white) is left out, so dividers, table rows and outlined cards keep MUI's divider
Dialogs and snackbars in the part of the frame the user can seeThe kit (frameThemeOptions, from the bridge's --hawk-visible-* variables)
Menus and selects that don't lock the frame's scrolling (a lock resizes the frame and the page flickers)The kit (frameThemeOptions)
Table rows and header (borders in the divider color, a header row on the page background, rows 10px above and below, every other body row tinted; the stylesheet's .hawk-table alike)The kit (tableThemeOptions)

The font is always Spark's, whatever the host uses, so apps look the same in HawkSearch and Spark.

Without React and MUI

For vanilla, Preact, React or Next apps without MUI: the same look as a stylesheet, and a few custom elements for what CSS alone can't do. No dependencies: no React, no MUI, no bridge.

// With a bundler (Vite, Next): once, where the app starts (Next: the css in app/layout.tsx).
import '@bridgeline-digital/hawk-app-ui/css';
import '@bridgeline-digital/hawk-app-ui/elements';
<!-- Without a build step: from the CDN, at the bridge's version (the vanilla template does this). -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@bridgeline-digital/[email protected]/dist/css/hawk.css" />
<script type="module" src="https://cdn.jsdelivr.net/npm/@bridgeline-digital/[email protected]/dist/elements/index.js"></script>

The stylesheet (/css, dist/css/hawk.css) carries Montserrat (no request to Google Fonts) and maps the host's theme tokens, which the bridge sets as --hawk-* variables and <html data-hawk-theme>, as createHawkTheme does: the accent, backgrounds, text, borders, radius and dark mode, else Spark's. Use its --hawk-ui-* variables (--hawk-ui-accent, --hawk-ui-surface, --hawk-ui-text, --hawk-ui-text-secondary, --hawk-ui-border, --hawk-ui-radius, …) for your own styles. A view's page (<html data-hawk-view>) stays transparent.

ClassFor
hawk-section (hawk-section-header, -title, -subtitle)A titled card, Spark's
hawk-kpi-row, hawk-stack, hawk-row, hawk-spacerTiles side by side; a column or row of blocks
hawk-button (is-outlined, is-text, is-small)Buttons in the host's accent
hawk-field, hawk-input, hawk-selectForm fields
hawk-notice (is-error, is-warning, is-success)A message
hawk-chip (is-accent), hawk-empty, hawk-spinner, hawk-skeletonLabels, nothing to show, loading
hawk-table (in hawk-table-wrap)A plain table (or use <hawk-data-table>)
hawk-h1… hawk-h3, hawk-value, hawk-muted, hawk-caption, hawk-numType: headings, a headline number, secondary text

The elements (/elements) render that markup. Data goes in as properties (el.rows = [...]), settings as attributes. Importing defines them (in a browser; it's safe to import on a server, e.g. in Next).

ElementUse
<hawk-kpi label value hint change good-when highlight loading>A number with its change vs. the previous period (change as a fraction, none for "No previous data"; green when good)
<hawk-data-table>columns ({ key, label, align?, format?, value?, sortable?, csvLabel? }; format: integer, number, compact, percent, money, date, dateTime or a function), rows, totals, sort; attributes download="file.csv", max-height, clickable (hawk-row-click events), empty. Sortable headers, CSV download of the rows as sorted (formulas made text)
<hawk-bar-list>items ({ label, value }); selectable (hawk-select events), value-format, color, label
<hawk-column-chart>columns ({ label, value, tooltip? }); height, value-format, color, label
const table = document.querySelector('hawk-data-table');
table.columns = [{ key: 'keyword', label: 'Keyword' }, { key: 'search_count', label: 'Searches', format: 'integer' }];
table.rows = report.data;
table.setAttribute('download', 'searches.csv');

createFormat(locale) (from /elements too) formats numbers, money and dates like useFormat(). In React or Preact with TypeScript, type the elements in JSX with HawkElementTags (the templates have src/hawk-elements.d.ts):

import type { HawkElementTags } from '@bridgeline-digital/hawk-app-ui/elements';
declare module 'react' { namespace JSX { interface IntrinsicElements extends HawkElementTags {} } } // Preact: 'preact'

Toasts: app.toast(message, severity) from the bridge shows the host's own.

Versions

Released with the bridge and the CLI (one version for all three). Peer dependencies of the React + MUI part: React 19, MUI 9, Emotion 11 (optional for the stylesheet and the elements), and the bridge.

版本与发布记录

@bridgeline-digital/hawk-app-ui 共发布 36 个版本,首次发布于 2026/10/21;过去 12 个月发布了 36 个版本。

版本发布日期距今
0.1.7latest2026/11/09今天
0.2.0-dev.20261107235157dev2026/11/081 天前
0.2.0-dev.202611071348152026/11/081 天前
0.2.0-dev.202611062251282026/11/072 天前
0.2.0-dev.202611061535502026/11/062 天前
0.2.0-dev.202611061406042026/11/062 天前

关于 @bridgeline-digital/hawk-app-ui 的常见问题

@bridgeline-digital/hawk-app-ui 是什么?

For Bridgeline developers: the Spark look for Hawk Apps: for React + MUI, the theme (following the host's colors and mode), the app provider and shared components; for any app (vanilla, Preact, React, Next), a stylesheet and custom elements.

如何安装 @bridgeline-digital/hawk-app-ui?

在项目目录运行 npm install @bridgeline-digital/hawk-app-ui,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@bridgeline-digital/hawk-app-bridge(>=0.1.0 <1.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@bridgeline-digital/hawk-app-ui 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bridgeline-digital/hawk-app-ui 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@bridgeline-digital/hawk-app-ui 可以商用吗?

@bridgeline-digital/hawk-app-ui 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@bridgeline-digital/hawk-app-ui 的下载量有多少?

根据 npm 官方下载统计,@bridgeline-digital/hawk-app-ui 在 2026/10/09 – 2026/11/07 这 30 天内被下载 4,542 次,日均约 151 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bridgeline-digital/hawk-app-ui 还在维护吗?

最新版本 0.1.7 发布于 2026/11/09(今天);至今共发布 36 个版本,其中过去 12 个月发布了 36 个;首次发布于 2026/10/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。