Skip to content

dbeaver/pro#7251 feat: add skip navigation feature for improved acces…#4245

Open
SychevAndrey wants to merge 6 commits intodevelfrom
7251-cb-add-skip-to-content-panel-for-keyboard-navigaton
Open

dbeaver/pro#7251 feat: add skip navigation feature for improved acces…#4245
SychevAndrey wants to merge 6 commits intodevelfrom
7251-cb-add-skip-to-content-panel-for-keyboard-navigaton

Conversation

@SychevAndrey
Copy link
Copy Markdown
Contributor

…sibility

Screen.Recording.2026-03-27.at.17.58.23.mov

@SychevAndrey
Copy link
Copy Markdown
Contributor Author

image


import { PANEL_ID_LEFT_SIDEBAR, PANEL_ID_MAIN_CONTENT } from './AppScreenService.js';
import { SkipNavService } from './SkipNavService.js';
import './SkipNavLinks.css';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please use css modules, dont import css like that

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

skip-nav styles are inherently global: SkipNavShortcutsLink in plugin-help needs the same styles as the main container. With CSS modules this will leed to duplicating the same styles in two .module.css files (in plugin-focus-skip and plugin-help), whereas a single plain CSS file with a BEM class covered both components with zero duplication.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We are not going to use styles like this. We want to stick with css modules. Please be consistent with a codebase patterns, if you want to reuse the same styles, you can useexport { default as CellStyles } from './Cell.module.css'; Or you can use tailwind

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i agree, that in this case it's better to use tailwind css or css-modules, because this components does not differ much from our regular components in the app


return (
<nav aria-label={translate('app_skip_nav_label')} className="dbv-kit-skip-nav">
<button type="button" className="dbv-kit-skip-nav__link" onClick={() => focusPanel(PANEL_ID_LEFT_SIDEBAR)}>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please use UnstyledButton instead so it will have extended accesibility features

Copy link
Copy Markdown
Contributor Author

@SychevAndrey SychevAndrey Apr 2, 2026

Choose a reason for hiding this comment

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

What accessibility features UnstyledButton adds on top of what a native button already provides?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can keep native button but if we will have the desire to change something about all unstyled buttons in the app, we will not be able to

}

return (
<button type="button" className="dbv-kit-skip-nav__link" onClick={handleClick}>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

UnstyledButton

Copy link
Copy Markdown
Contributor Author

@SychevAndrey SychevAndrey Apr 2, 2026

Choose a reason for hiding this comment

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

even ariakit docs suggest using native button instead their component

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think they are talking about render prop, you can render button as different html element, they suggest to keep it native. Ariakit uses native button underneath, so they are equal in terms of browser support

const SkipNavLinks = importLazyComponent(() => import('./SkipNavLinks.js').then(m => m.SkipNavLinks));

@injectable(() => [AppScreenService])
export class SkipNavBootstrap extends Bootstrap {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Move it to a separate plugin, plugin-focus-skip, mention "focus" also in the file names

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

skip-nav is essentially part of the app shell layout (just like TopNavBar, which also lives in appScreenService.placeholder). It's 3 files of actual code. Extracting it into a standalone package results in ~10 boilerplate files for 3 files of logic, plus a new dependency from plugin-help to plugin-focus-skip.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As a general tip, if you are creating a bootstrap class, it is a good indication that the logic you are implementing should be in a separate plugin. The number of lines does not matter, we have plugins with even fewer lines. Our goal is to keep the app modular, so you should be able to remove a plugin from the declaration file and have the feature removed along with it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think it's better to keep it here for now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

so TopNavBar should be a separate plugin as well?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can create a method inside NavService, something like registerLinks and call it from AppScreenBootstrap register method so we only have one bootstrap per package

@codacy-production
Copy link
Copy Markdown

codacy-production bot commented Apr 2, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 14 complexity

Metric Results
Complexity 14

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

@SychevAndrey SychevAndrey requested a review from devnaumov April 2, 2026 08:20
display: flex;
}

.dbv-kit-skip-nav__link {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why we use dbv kit prefixes here?

Comment on lines +14 to +16
export function SkipNavShortcutsLink(): React.ReactElement {
const translate = useTranslate();
const commonDialogService = useService(CommonDialogService);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

same here


export function SkipNavLinks(): React.ReactElement {
const translate = useTranslate();
const skipNavService = useService(SkipNavService);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

you should use observable with useTranslate

const SkipNavLinks = importLazyComponent(() => import('./SkipNavLinks.js').then(m => m.SkipNavLinks));

@injectable(() => [AppScreenService])
export class SkipNavBootstrap extends Bootstrap {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think it's better to keep it here for now


import { PANEL_ID_LEFT_SIDEBAR, PANEL_ID_MAIN_CONTENT } from './AppScreenService.js';
import { SkipNavService } from './SkipNavService.js';
import './SkipNavLinks.css';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i agree, that in this case it's better to use tailwind css or css-modules, because this components does not differ much from our regular components in the app

@SychevAndrey SychevAndrey requested review from Wroud and devnaumov April 3, 2026 09:31
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.

4 participants