Skip to content

fix(DashboardNavbar): render title only when defined (nuxt/ui@7c4c6e3) - #599

Merged
IgorShevchik merged 1 commit into
mainfrom
sync/nuxt-7c4c6e35
Sep 17, 2026
Merged

IgorShevchik merged 1 commit into
mainfrom
sync/nuxt-7c4c6e35

Conversation

@IgorShevchik

Copy link
Copy Markdown
Collaborator

Ports nuxt/ui@7c4c6e35 — fix(DashboardNavbar): render title only when defined (#6958).

Journal: .sync/log/7c4c6e3568f074cfee7a603e034895892a8ab252.md

The defect

DashboardNavbar rendered its <h1 data-slot="title"> unconditionally. With no
title prop and no title slot, the markup still carried an empty heading:

<h1 data-slot="title" class="… font-medium … truncate"></h1>

Not only dead markup — a heading with no accessible name in the document outline.

The fix

src/runtime/components/DashboardNavbar.vue:109 was line-for-line upstream's
pre-image modulo the ui → b24ui rename, so the hunk applies directly:

-<h1 data-slot="title" :class="b24ui.title({ class: props.b24ui?.title })">
+<h1 v-if="props.title || !!slots.title" data-slot="title" :class="b24ui.title({ class: props.b24ui?.title })">

Three things checked rather than assumed:

  • slots is in scope — defineSlots<DashboardNavbarSlots>() at line 69, and
    the same !!slots.X idiom already appears ten lines below at
    v-if="!!slots.default". Nothing new is introduced.
  • title has no default — withDefaults sets only toggle and toggleSide,
    so props.title is undefined when unset and the guard behaves as upstream's.
  • props, not _props — this fork wraps props in
    useComponentProps('dashboardNavbar', _props), so a title supplied through
    <B24Theme :props> or app.config lands on props and not on the raw
    defineProps result. Reading props.title is both correct and what
    bitrix24-ui/no-bare-prop-refs requires.

Snapshots

24 updated, 12 in each snapshot file. Every changed line was classified before
accepting them
, because test:update rewrites the whole suite and could quietly
absorb unrelated drift:

count change
20 <h1 data-slot="title" …></h1> → <!--v-if-->
2 …</h1>Trailing slot → <!--v-if-->Trailing slot
2 </button>Leading slot<h1 …></h1> → </button>Leading slot + <!--v-if-->

Nothing else changed, and only the four intended files are touched.

Of the 15 snapshot cases, exactly two still render the heading — with title
and with title slot. 12 of the other 13 moved; with left slot already had no
heading, since that slot replaces the default content the <h1> lives in.

Mutations

Each half of props.title || !!slots.title is independently covered:

mutation result
v-if="!!slots.title" — prop half dropped renders with title correctly fails, both environments
v-if="props.title" — slot half dropped renders with title slot correctly fails, both environments
guard removed entirely does not render the title without title fails, plus 24 snapshots

Worth recording how this nearly went wrong. The first mutation run used sed
with | as both the delimiter and part of the pattern (||). All three
substitutions failed with unknown option to 's', the file was never modified,
and all three runs reported 34 passed — which reads exactly like "the mutations
were caught by nothing"
. Re-run through Python, the real results are the table
above. A mutation that reports green because it never applied is the worst
outcome available, since it looks like evidence.

Gate

dev:prepare · lint · typecheck · build · test:coverage (353 files, 8069
passed — two more than before, the new test in both environments) · test:module
— green.

Cursor advances b2cb53f8 → 7c4c6e35, which is upstream v4's current HEAD, and
the 68cc4eb4/b2cb53f8 entries are reconciled with #598 / 66a94cb6.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JS8ypVfQSFzYVZzkTHhURb


Generated by Claude Code

`DashboardNavbar` rendered its `<h1 data-slot="title">` unconditionally, so with
no `title` prop and no `title` slot the markup still carried an empty heading —
dead markup, and a heading with no accessible name in the document outline.

Ours at `DashboardNavbar.vue:109` was line-for-line upstream's pre-image modulo
the `ui` → `b24ui` rename, so the guard transfers directly. Three things were
checked rather than assumed: `slots` is already in scope (`defineSlots` at line
69, and `!!slots.default` is used ten lines below, so the idiom is not new);
`title` has no default, since `withDefaults` sets only `toggle` and `toggleSide`;
and the guard reads `props.title` rather than the raw `defineProps` result,
because `useComponentProps` is what resolves a `title` supplied through
`<B24Theme :props>` or `app.config` — which is also what
`bitrix24-ui/no-bare-prop-refs` requires.

24 snapshots updated. Every changed line was classified before accepting them,
because `test:update` rewrites the whole suite and could absorb unrelated drift:
20 are an empty `<h1>` becoming `<!--v-if-->`, 2 the same next to a trailing
slot, 2 the same next to a leading slot. Nothing else moved. Of the 15 cases,
exactly two still render the heading — `with title` and `with title slot`.

Both halves of `props.title || !!slots.title` are independently covered:
replacing it with `!!slots.title` fails `renders with title`, replacing it with
`props.title` fails `renders with title slot`, and removing it fails the new test
plus 24 snapshots.

Also reconciles the `68cc4eb4` and `b2cb53f8` entries with #598 / 66a94cb.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JS8ypVfQSFzYVZzkTHhURb
@IgorShevchik
IgorShevchik merged commit e936c56 into main Sep 17, 2026
2 checks passed
@IgorShevchik
IgorShevchik deleted the sync/nuxt-7c4c6e35 branch September 17, 2026 13:21
IgorShevchik added a commit that referenced this pull request Sep 17, 2026
)

The scaffolder stops being a published binary: `bin` and `"cli"` in `files` are
dropped, a `"cli": "node ./cli/index.mjs"` script takes their place, and the
contributor docs move from `bitrix24-ui make …` — which needed a one-time
`npm link` — to `pnpm cli make …`.

Dropping a `bin` deserves the question of whether it breaks a consumer. It does
not: the CLI writes to `src/runtime/components/`, `src/theme/` and
`docs/content/docs/2.components/` (cli/templates.mjs:47, :158, :218), which are
repository-relative paths that mean nothing inside somebody else's
`node_modules`. It is referenced only from `AGENTS.md` and
`.github/contributing/`, and the published docs never mention it — this fork has
no CLI section in `4.contribution.md` at all, so two of upstream's five files
have no counterpart here (the other is `SupportedLanguages.vue`, which does not
exist).

Verified against the packed tarball rather than the manifest: `npm pack --dry-run
--json` reports 802 files with zero under `cli/`, `bin: null`, and top-level
entries of exactly `.nuxt`, `LICENSE`, `README.md`, `dist`, `package.json`,
`vue-plugin.d.ts`. Seven files and 14 087 bytes stop shipping. `pnpm cli --help`
still prints the command tree, so the scaffolder itself is untouched.

The new prose is pinned: `documented-scripts.spec.ts` asserts every `pnpm
<script>` quoted in the contributor docs resolves to a defined script, and
renaming the script to `cli-x` turns both edited files red. Without that the
rename could have left the docs quoting a command that does not run, which is
what that spec was written for.

Also reconciles the `7c4c6e35` entry with #599 / e936c56.


Claude-Session: https://claude.ai/code/session_01JS8ypVfQSFzYVZzkTHhURb

Co-authored-by: Shevchik Igor <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants