Skip to content

Conversation

@tbl0605
Copy link
Contributor

@tbl0605 tbl0605 commented Sep 12, 2025

Hello,
patch #2834 implemented keyboard navigation for BTable components, but unfortunately broke basic navigation (which previously worked).
Previously, it was possible to use the Tab key to focus elements (like buttons) in a BTable, and to use the spacebar or Enter key to activate these elements.
Now, when you use the spacebar or Enter key on these elements, either nothing happens or the TH/TR parent is incorrectly selected (when BTable has the "selectable" property).
This bug is caused by the fact that all keydown events are now handled by the BTr or BTh components and are systematically canceled, even though some keydown events should be handled by "internal" table elements.

My patch proposal is based on my own keyboard navigation implementation that I made some time ago (for my own use) and discussed here: https://stackblitz.com/edit/github-rzxbjv-nralwm3b

Maybe using document.activeElement wouldn't even be necessary, but this patch works perfectly as is in my case.

Small replication

I made 3 demos (each with the same 2 tables inside) so you can compare the results between different versions of boostrap-vue-next.

PR checklist

What kind of change does this PR introduce? (check at least one)

  • Bugfix 🐛 - fix(...)
  • Feature - feat(...)
  • ARIA accessibility - fix(...)
  • Documentation update - docs(...)
  • Other (please describe)

The PR fulfills these requirements:

  • Pull request title and all commits follow the Conventional Commits convention or has an override in this pull request body This is very important, as the CHANGELOG is generated from these messages, and determines the next version type. Pull requests that do not follow conventional commits or do not have an override will be denied

Summary by CodeRabbit

  • Bug Fixes
    • Improved keyboard navigation in tables: key actions now trigger only when focus is on header cells or rows, preventing unintended behavior when interacting with inputs or links inside the table.
    • Maintains expected Enter/Space and Arrow/Home/End behavior in the correct context, reducing accidental activations and enhancing accessibility and predictability for keyboard-only users.

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 12, 2025

Walkthrough

Adds early-return checks in BTableLite’s header and row keydown handlers to only process keys when focus is on TH or TR elements, respectively. Existing key actions (Enter/Space and navigation: ArrowUp/Down, Home, End) remain unchanged.

Changes

Cohort / File(s) Summary
Keyboard event gating in BTableLite
packages/bootstrap-vue-next/src/components/BTable/BTableLite.vue
Added pre-checks in handleHeaderKeydown and handleRowKeydown to return early when the focused event target isn’t a TH/TR. Destructured event target/code/(shiftKey). Preserved existing key handling for activation and navigation.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant DOM as DOM Element (TH/TR or other)
    participant T as BTableLite.vue
    U->>DOM: keydown
    DOM->>T: handleHeaderKeydown / handleRowKeydown(event)
    alt Target is focused and not expected tag (TH/TR)
        T-->>DOM: return (no action)
        note over T: New early-return guard
    else Target is correct (TH/TR)
        T->>T: Process key (Enter/Space, ArrowUp/Down, Home/End, Shift)
        T-->>DOM: Apply selection/focus navigation
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • VividLemon

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly identifies the bug being fixed in the BTable component: events emitted from inside TR and TH elements were suppressed (a regression introduced in v0.40.2), and it follows Conventional Commits formatting with a concise scope (fix(BTable)). It directly relates to the changes in the patch which gate keydown handling by event target and focus, so the title accurately reflects the primary intent. The wording is a bit long but specific and informative for reviewers scanning history.
Description Check ✅ Passed The PR description follows the repository template: it contains a clear problem statement and root-cause explanation, includes three reproduction links under "Small replication", and fills the PR checklist marking this as a bugfix with Conventional Commits compliance. The information provided is sufficient for reviewers to reproduce, test, and understand the intent and scope of the change. Overall the description is complete and actionable.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Poem

I tap-tap keys with cottony might,
THs and TRs now guide my flight—
If focus strays, I pause my hop,
But on the header, I won’t stop.
Arrows, Home, and End in row,
A tidy table—onward I go! 🐇⌨️

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Sep 12, 2025

bsvn-vite-ts

npm i https://pkg.pr.new/bootstrap-vue-next/bootstrap-vue-next@2841
npm i https://pkg.pr.new/bootstrap-vue-next/bootstrap-vue-next/@bootstrap-vue-next/nuxt@2841

commit: 10264e6

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/bootstrap-vue-next/src/components/BTable/BTableLite.vue (2)

473-476: Prefer currentTarget check over tagName/activeElement; also bail if default prevented

This makes the intent explicit (“only handle when the event originates on this TH”), avoids brittle tagName checks, and is friendlier to slotted content and Shadow DOM.

-  const {target, code} = event
-
-  if (target && (target as Element).tagName !== 'TH' && document.activeElement === target) return
+  const {target, currentTarget, code, defaultPrevented} = event
+  if (defaultPrevented) return
+  if (target instanceof Element && currentTarget instanceof Element && target !== currentTarget) return

484-498: Apply the same safer check for rows; keep behavior identical

Use currentTarget to ignore bubbled keydowns from descendants and early-return if already handled elsewhere.

-  const {target, code, shiftKey} = event
-
-  if (target && (target as Element).tagName !== 'TR' && document.activeElement === target) return
+  const {target, currentTarget, code, shiftKey, defaultPrevented} = event
+  if (defaultPrevented) return
+  if (target instanceof Element && currentTarget instanceof Element && target !== currentTarget) return
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9046e2 and 10264e6.

📒 Files selected for processing (1)
  • packages/bootstrap-vue-next/src/components/BTable/BTableLite.vue (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
packages/bootstrap-vue-next/src/components/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Place all new Vue components under packages/bootstrap-vue-next/src/components/

Files:

  • packages/bootstrap-vue-next/src/components/BTable/BTableLite.vue
packages/bootstrap-vue-next/src/components/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Keep component-specific styles inside the component .vue files

Files:

  • packages/bootstrap-vue-next/src/components/BTable/BTableLite.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

@VividLemon VividLemon merged commit ee8b0f7 into bootstrap-vue-next:main Sep 12, 2025
5 checks passed
@github-actions github-actions bot mentioned this pull request Sep 12, 2025
xvaara added a commit to xvaara/bootstrap-vue-next that referenced this pull request Oct 11, 2025
* upstream/main:
  chore: release main (bootstrap-vue-next#2868)
  fix(useModalOrchestrator): circular dependency (bootstrap-vue-next#2874)
  docs(BModal): Parity pass (bootstrap-vue-next#2866)
  docs: Enable directly loading examples into StackBlitz (bootstrap-vue-next#2869)
  fix(BApp): wrap our test app in BApp in main.ts to enable easy verification of useModal, etc. (bootstrap-vue-next#2865)
  export useScrollLock() (bootstrap-vue-next#2854)
  chore: release main (bootstrap-vue-next#2858)
  fix(BToggle): stop looking for missing targets after directive is unmounted (bootstrap-vue-next#2857)
  chore: release main (bootstrap-vue-next#2851)
  Fix modal transition delays by making TransitionGroup name conditional (bootstrap-vue-next#2845)
  chore: release main (bootstrap-vue-next#2842)
  fix(BTable): events being wrongly stopped when sent from elements inside TRs (bootstrap-vue-next#2841)
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