Skip to content

v0.2.17

Latest

Choose a tag to compare

@yuhuanowo yuhuanowo released this 06 Aug 09:45
· 57 commits to main since this release

Added

  • ModelSelect gains renderHeader + filterResetKeyrenderHeader renders a caller-owned
    toolbar pinned to the TOP of the open panel, always visible even when the result list is empty
    (unlike renderFooter, which hides on an empty set) — the place for a domain control that must
    stay reachable, e.g. a browse-mode switch above the picker. filterResetKey imperatively clears
    the internal search + provider/capability filters when its value changes, WITHOUT remounting, so
    the panel keeps its open state/scroll/focus and never flashes a stale-filter "no results" after the
    option set is swapped out from under the filters (again: a browse-mode switch). Both are optional
    and fully backward-compatible.

Fixed

  • MermaidDiagram restores its documented .mermaid-container DOM contract. The content
    stylesheet already scoped responsive SVG rules to that class, but the rendered diagram omitted
    it, leaving host styling and stable diagram selection disconnected from the actual output.
  • CodeBlock no longer pulls Shiki's full language catalogue into host builds. The content
    renderer now uses Shiki core with explicit lazy grammar/theme loaders and the JavaScript regex
    engine. Common application and LLM-output languages retain VS Code-grade highlighting; unknown
    fence labels fall back to escaped plaintext. This keeps MarkdownRenderer on demand in practice,
    instead of making Next/Vite discover and compile hundreds of unused language modules.
  • Overlays are no longer see-through — dropdown menus, selects, comboboxes, popovers, the
    language & theme switchers, the mobile navbar sheet and the notification panel were painted with a
    60%-opaque bg-background/60 frosted panel, so content behind them showed through and read as if
    it were still clickable. They now use bg-popover/85 (still frosted via backdrop-blur, but
    opaque enough to occlude what's underneath) and the correct --popover surface token.
  • Button labels never wrap — the .btn base now sets white-space: nowrap, so a button
    label can no longer break onto multiple lines in a narrow container. A CJK label like 使用
    in a cramped table action column used to split vertically into 使/; it now stays on one
    line (the column widens / the table scrolls instead). Matches the standard button convention.

Added

  • Sortable TableHeadTableHead gains optional, backward-compatible sort props:
    onSort makes the header a sort control (renders its content as a <button> with an
    asc/desc/unsorted chevron and sets aria-sort on the <th>), sortDirection
    ("asc" | "desc" | false) is the column's current state, and align
    ("left" | "right" | "center") aligns both the content and the control (use "right"
    for numeric columns). Omit onSort and it behaves exactly as before. Fills the
    data-table column-sorting gap without a separate component. TableHead is also now
    whitespace-nowrap so short header labels never wrap — CJK labels in particular no
    longer break mid-word (能力 → 能/力) in narrow columns / WebKit.
  • AgentTimeline (@yuhuanowo/yunui/ai) — an agent turn rendered as an
    ordered, INLINE sequence of typed blocks (reasoning / tool call+result /
    assistant text / approval), in the neutral .card language. Unlike the
    AgentSteps panel, the answer is a text block among the tool/reasoning
    blocks in conversation order (no result-on-top / steps-below split); tool
    rows expand into $-prefixed monospace output, failures use semantic
    red-500/5 tints, and an approval block renders an amber allow/deny gate.
    Prop-driven and copy-free — the consumer maps records onto AgentTimelineBlock,
    localizes every label, and supplies a markdown renderer. Verified on Chrome +
    Safari/WebKit, desktop + mobile.
  • AgentRunStatus (@yuhuanowo/yunui/ai) — a layout-stable live surface for the
    single activity an agent is doing now (a shimmering label + pulsing dot trio,
    announced via role="status"/aria-live). Complements AgentTimeline: the status
    stays put for the whole run while timeline rows become durable history. phase
    (thinking/acting/observing/reflecting/responding/waiting) is a semantic hint.
  • TextShimmer (@yuhuanowo/yunui) — a restrained animated text sweep for transient
    work states ("Thinking…"); the label is exposed to assistive tech exactly once while the
    duplicated paint layers stay aria-hidden. active pauses the sweep without a layout shift.
  • ChatAttachment (@yuhuanowo/yunui/chat) — a compact attachment surface shared by
    the composer and sent messages: name/meta, an optional preview or icon, a determinate
    upload progress bar, status (idle/loading/error) affordances and an actions slot.
  • InlineCitation (@yuhuanowo/yunui/content) — a claim-adjacent evidence marker for
    grounded AI output. A compact inline pill previews the concrete source (title, location, a
    bounded excerpt) on hover/focus and delegates opening to the host via onOpen.
  • ReadingProgress (@yuhuanowo/yunui/patterns) — reading position + back-to-top as one
    floating control: a circular ring fills with scroll progress around an up-arrow button (no
    full-width hairline). bar/backToTop toggle each half; threshold and labels.backToTop
    are configurable. One rAF-coalesced scroll listener; the ring animates via stroke-dashoffset.
  • SettingsShell (@yuhuanowo/yunui/patterns) — the canonical settings layout: grouped
    desktop sidebar navigation, a compact mobile Select, and one scroll-safe content lane; works
    in a dialog or full page. Controlled via value/onValueChange, sections from groups
    (SettingsNavGroup/SettingsNavItem). The host owns the active panel; YunUI owns navigation.
  • NavStateIndicator (@yuhuanowo/yunui/patterns) — the shared active/running marker that
    sits beside a selected item in Sidebar/SettingsShell; a presentational <span> driven by
    active/running data-states. Extracted so bespoke navigation surfaces can match the system.
  • CustomSelect server-backed search + infinite scrollonSearch (debounced by
    searchDebounceMs, default 250) drives results from a backend, paired with loading;
    onLoadMore + hasMore append pages as the list nears its end. Both optional and independent
    of the existing client-side searchable filtering.
  • Combobox gains clearable (default true) — a clear (×) action for the current value;
    set clearable={false} when the field must always hold a value.
  • useAnchoredPosition flips above the trigger when there isn't room below, and remeasures
    open panels as layout changes — hand-rolled floating panels now match the collision behavior of
    the Radix-based overlays.
  • getModelDeveloperId (@yuhuanowo/yunui/ai) — model-family icon resolution is centralized,
    so a model id resolves to its developer/family icon through one shared helper.

Fixed

  • Untrusted Mermaid/KaTeX is sanitizedMermaidDiagram renders with a strict
    securityLevel and KaTeX with trust: false, so diagram/math content coming from model
    or user input can't inject scripts or navigate via crafted labels (XSS hardening).
  • Tooltip content escapes clipping ancestors — tooltips now portal out, so they're no
    longer cut off by an overflow: hidden/clip parent.

Removed

  • AgentSteps (@yuhuanowo/yunui/ai) — the earlier Codex-style execution
    panel (result-on-top / steps-below split) is removed, superseded by
    AgentTimeline, which renders the same agent-turn data as an inline ordered
    sequence of typed blocks. No consumer shipped against AgentSteps.

Changed

  • ModelSelect selection bar inset refined to 5px (from left-1.5/6px),
    set as an inline style since Tailwind's 1.25 step isn't core and could be
    dropped by a consumer's JIT scan.
  • AgentTimeline now speaks YunUI's semantic status vocabulary — the error /
    success / warning affordances moved off raw Tailwind red-*/emerald-*/amber-*
    onto the --error / --success / --warning tokens, so they track the active
    theme (light / dark / brand) instead of drifting from the system's palette.
  • ./package.json is now an export so tooling and consumers can read the
    package version at runtime (the docs site uses it for its version badge).
  • Dependencies refreshed to latest — React 19.2.8, the Radix primitives,
    Tailwind 4.3.3, shiki 4, framer-motion 12.43, lucide-react 1.28 and more.
    No API changes; typescript intentionally held at 6.x (7.x isn't yet compatible
    with the tsup/rollup-plugin-dts build toolchain).