chore: standardize api

This commit is contained in:
mathuo 2025-06-03 21:39:38 +01:00
parent 9c04db8093
commit 182a2ae664
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
9 changed files with 46 additions and 45 deletions

View File

@ -51,6 +51,7 @@ export class ContentContainer
super();
this._element = document.createElement('div');
this._element.className = 'dv-content-container';
this.element.role = 'tabpanel';
this._element.tabIndex = -1;
this.addDisposables(this._onDidFocus, this._onDidBlur);

View File

@ -24,6 +24,7 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
this.action = document.createElement('button');
this.action.type = 'button';
this.action.className = 'dv-default-tab-action';
// originally hide this, so only when it is focused is it read out.
// so the SR when focused on the tab, doesn't read "<Tab Content> Close Button"
@ -49,7 +50,7 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
init(params: GroupPanelPartInitParameters): void {
this._title = params.title;
this.action.ariaLabel = `Close "${this._title}" tab`;
this.addDisposables(
params.api.onDidTitleChange((event) => {
this._title = event.title;

View File

@ -52,7 +52,7 @@ export class Tab extends CompositeDisposable {
private readonly _onPointDown = new Emitter<MouseEvent>();
readonly onPointerDown: Event<MouseEvent> = this._onPointDown.event;
private readonly _onKeyDown = new Emitter<KeyboardEvent>();
readonly onKeyDown: Event<KeyboardEvent> = this._onKeyDown.event;
@ -76,13 +76,17 @@ export class Tab extends CompositeDisposable {
super();
this._element = document.createElement('div');
this._element.id = this.panel.tabComponentElId;
this._element.className = 'dv-tab';
this._element.role = 'tab';
this._element.tabIndex = -1;
this._element.draggable = true;
this._element.ariaSelected = 'false';
this._element.setAttribute('aria-controls', this.panel.componentElId);
Object.entries(this.panel.tabComponentAttributes).forEach(
([key, value]) => {
this._element.setAttribute(key, value);
}
);
toggleClass(this.element, 'dv-inactive-tab', true);

View File

@ -99,6 +99,9 @@ export class Tabs extends CompositeDisposable {
this._tabsList = document.createElement('div');
this._tabsList.className = 'dv-tabs-container dv-horizontal';
this._tabsList.ariaOrientation = 'horizontal';
this.element.role = 'tablist';
this.element.ariaLabel =
'Use the Left Arrow to select the previous tab, Right Arrow for the next tab, Home for the first tab, and End for the last tab. Press Enter to select the focused tab.';
this.showTabsOverflowControl = options.showTabsOverflowControl;
@ -110,10 +113,6 @@ export class Tabs extends CompositeDisposable {
this.addDisposables(scrollbar);
}
this.element.role = 'tablist';
this.element.ariaLabel =
'Use the Left Arrow to select the previous tab, Right Arrow for the next tab, Home for the first tab, and End for the last tab. Press Enter to select the focused tab.';
this.addDisposables(
this._onOverflowTabsChange,
this._observerDisposable,

View File

@ -2524,6 +2524,12 @@ export class DockviewComponent
tabComponent
);
Object.entries(options.componentAttributes ?? {}).forEach(
([key, value]) => {
view.content.element.setAttribute(key, value);
}
);
const panel = new DockviewPanel(
options.id,
contentComponent,
@ -2538,6 +2544,8 @@ export class DockviewComponent
minimumHeight: options.minimumHeight,
maximumWidth: options.maximumWidth,
maximumHeight: options.maximumHeight,
componentAttributes: options.componentAttributes,
tabComponentAttributes: options.tabComponentAttributes,
}
);

View File

@ -19,8 +19,8 @@ export interface IDockviewPanel extends IDisposable, IPanel {
readonly api: DockviewPanelApi;
readonly title: string | undefined;
readonly params: Parameters | undefined;
readonly componentElId: string;
readonly tabComponentElId: string;
readonly componentAttributes: Record<string, string>;
readonly tabComponentAttributes: Record<string, string>;
readonly minimumWidth?: number;
readonly minimumHeight?: number;
readonly maximumWidth?: number;
@ -41,18 +41,9 @@ export class DockviewPanel
implements IDockviewPanel
{
readonly api: DockviewPanelApiImpl;
/**
* The unique DOM id for the rendered panel element
*
* Used for accessibility attributes
*/
readonly componentElId: string;
/**
* The unique DOM id for the rendered tab element
*
* Used for accessibility attributes
*/
readonly tabComponentElId: string;
readonly componentAttributes: Record<string, string>;
readonly tabComponentAttributes: Record<string, string>;
private _group: DockviewGroupPanel;
private _params?: Parameters;
@ -104,7 +95,10 @@ export class DockviewPanel
private readonly containerApi: DockviewApi,
group: DockviewGroupPanel,
readonly view: IDockviewPanelModel,
options: { renderer?: DockviewPanelRenderer } & Partial<Contraints>
options: { renderer?: DockviewPanelRenderer } & Partial<Contraints> & {
componentAttributes?: Record<string, string>;
tabComponentAttributes?: Record<string, string>;
}
) {
super();
this._renderer = options.renderer;
@ -114,10 +108,8 @@ export class DockviewPanel
this._maximumWidth = options.maximumWidth;
this._maximumHeight = options.maximumHeight;
const randomId = Math.random().toString(36).slice(2);
this.tabComponentElId = `tab-${id}-${randomId}`;
this.componentElId = `tab-panel-${id}-${randomId}`;
this.componentAttributes = options.componentAttributes ?? {};
this.tabComponentAttributes = options.tabComponentAttributes ?? {};
this.api = new DockviewPanelApiImpl(
this,

View File

@ -260,6 +260,8 @@ export type AddPanelOptions<P extends object = Parameters> = {
inactive?: boolean;
initialWidth?: number;
initialHeight?: number;
componentAttributes?: Record<string, string>;
tabComponentAttributes?: Record<string, string>;
} & Partial<AddPanelOptionsUnion> &
Partial<Contraints>;

View File

@ -73,9 +73,7 @@ export class OverlayRenderContainer extends CompositeDisposable {
if (!this.map[panel.api.id]) {
const element = createFocusableElement();
element.className = 'dv-render-overlay';
element.role = 'tabpanel';
element.tabIndex = 0;
element.setAttribute('aria-labelledby', panel.tabComponentElId);
this.map[panel.api.id] = {
panel,

View File

@ -102,7 +102,7 @@ export class Splitview {
private readonly sashContainer: HTMLElement;
private readonly viewItems: ViewItem[] = [];
private readonly sashes: ISashItem[] = [];
private _orientation: Orientation;
private _orientation = Orientation.VERTICAL;
private _size = 0;
private _orthogonalSize = 0;
private _contentSize = 0;
@ -159,11 +159,15 @@ export class Splitview {
this.size = this.orthogonalSize;
this.orthogonalSize = tmp;
removeClasses(this.element, 'dv-horizontal', 'dv-vertical');
this.element.classList.add(
this.orientation == Orientation.HORIZONTAL
? 'dv-horizontal'
: 'dv-vertical'
toggleClass(
this.element,
'dv-horizontal',
this._orientation == Orientation.HORIZONTAL
);
toggleClass(
this.element,
'dv-vertical',
this._orientation == Orientation.VERTICAL
);
this.element.ariaOrientation =
this.orientation == Orientation.HORIZONTAL
@ -231,8 +235,8 @@ export class Splitview {
private readonly container: HTMLElement,
options: SplitViewOptions
) {
this._orientation = options.orientation ?? Orientation.VERTICAL;
this.element = this.createContainer();
this.orientation = options.orientation ?? Orientation.VERTICAL;
this.margin = options.margin ?? 0;
@ -1147,15 +1151,7 @@ export class Splitview {
private createContainer(): HTMLElement {
const element = document.createElement('div');
const orientationClassname =
this._orientation === Orientation.HORIZONTAL
? 'dv-horizontal'
: 'dv-vertical';
element.className = `dv-split-view-container ${orientationClassname}`;
element.ariaOrientation =
this._orientation == Orientation.HORIZONTAL
? 'horizontal'
: 'vertical';
element.className = `dv-split-view-container`;
return element;
}