Skip to content

Commit

Permalink
feat: Table component roles and labels (#516)
Browse files Browse the repository at this point in the history
* feat: add roles for the Table component and caption prop
  • Loading branch information
Kyzyl-ool authored Aug 23, 2023
1 parent e9d6b8c commit d9faf89
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 23 deletions.
4 changes: 3 additions & 1 deletion src/components/HTML/HTML.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ export interface HTMLProps {
block?: boolean;
className?: string;
itemProp?: string;
id?: string;
}

const HTML = ({children, block = false, className, itemProp}: WithChildren<HTMLProps>) => {
const HTML = ({children, block = false, className, itemProp, id}: WithChildren<HTMLProps>) => {
if (!children) {
return null;
}
Expand All @@ -19,6 +20,7 @@ const HTML = ({children, block = false, className, itemProp}: WithChildren<HTMLP
dangerouslySetInnerHTML: {__html: children},
className,
itemProp,
id,
});
};

Expand Down
26 changes: 20 additions & 6 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,26 @@ import {block} from '../../utils';

import './Table.scss';

function getMarkerId(index: number): string | undefined {
if (isNaN(index)) {
return undefined;
}

return `marker-${index}`;
}

const b = block('table');

export default class Table extends React.Component<TableProps & ClassNameProps> {
render() {
const {content, legend, marker = 'disk', className} = this.props;
const {content, legend, marker = 'disk', className, caption} = this.props;

if (!content || !content.length || !content[0].length) {
return null;
}

return (
<div className={b(null, className)}>
<div className={b(null, className)} role={'table'} aria-label={caption}>
{this.renderTable(content, marker, legend)}
{legend && this.renderLegend(legend, marker)}
</div>
Expand All @@ -28,11 +36,11 @@ export default class Table extends React.Component<TableProps & ClassNameProps>
const justify = this.getDefaultJustify(content, this.props.justify);

return (
<div className={b('table')}>
<div className={b('table')} role={'rowgroup'}>
{content.map((row, i) => (
<div key={i} className={b('row')}>
<div key={i} className={b('row')} role={'row'}>
{row.map((cell, j) => (
<div key={j} className={b('cell', {justify: justify[j]})}>
<div key={j} className={b('cell', {justify: justify[j]})} role={'cell'}>
{legend && i && j ? (
this.renderMarker(marker, cell)
) : (
Expand All @@ -47,7 +55,12 @@ export default class Table extends React.Component<TableProps & ClassNameProps>
}

private renderMarker(type: LegendTableMarkerType, cell: string) {
return <div className={b('marker', {type, index: String(cell)})} />;
return (
<div
aria-labelledby={getMarkerId(Number(cell))}
className={b('marker', {type, index: String(cell)})}
/>
);
}

private renderLegend(legend: string[], marker: LegendTableMarkerType) {
Expand All @@ -60,6 +73,7 @@ export default class Table extends React.Component<TableProps & ClassNameProps>
className={b('legent-item-text')}
content={item}
modifiers={{constructor: true}}
id={getMarkerId(index)}
/>
</div>
))}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Table/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
["Ut enim ad minim veniam", "0", "1", "1"],
["Ut enim ad minim veniam", "1", "1", "1"]
],
"legend": ["Lorem ", "ipsum"],
"legend": ["Lorem", "ipsum"],
"justify": ["start", "center", "center", "center"]
}
}
Expand Down
17 changes: 8 additions & 9 deletions src/components/YFMWrapper/YFMWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@ import {ClassNameProps, Modifiers} from '../../models';

const yfm = block('yfm');

export interface YFMWrapperProps {
className?: string;
export interface YFMWrapperProps extends ClassNameProps {
content: string;
modifiers?: Modifiers;
itemProp?: string;
id?: string;
}

const YFMWrapper = ({
content,
modifiers,
className,
itemProp,
}: YFMWrapperProps & ClassNameProps) => (
<HTML className={yfm(modifiers ? toSnakeCase(modifiers) : {}, className)} itemProp={itemProp}>
const YFMWrapper = ({content, modifiers, className, itemProp, id}: YFMWrapperProps) => (
<HTML
className={yfm(modifiers ? toSnakeCase(modifiers) : {}, className)}
itemProp={itemProp}
id={id}
>
{content}
</HTML>
);
Expand Down
10 changes: 6 additions & 4 deletions src/grid/Col/Col.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React, {CSSProperties, forwardRef} from 'react';

import {QAProps, Refable} from '../../models/common';
import {WithChildren} from '../../models/react';
import {QAProps, Refable, Roleable, WithChildren} from '../../models';
import {GridColumnClassParams} from '../types';
import {getColClass} from '../utils';

export interface GridColumnProps extends GridColumnClassParams, Refable<HTMLDivElement>, QAProps {
export interface GridColumnProps
extends GridColumnClassParams,
Refable<HTMLDivElement>,
QAProps,
Roleable {
style?: CSSProperties;
children?: React.ReactNode;
role?: React.AriaRole;
}

export const Col = forwardRef<HTMLDivElement, WithChildren<GridColumnProps>>((props, ref) => {
Expand Down
6 changes: 5 additions & 1 deletion src/models/constructor-items/blocks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ButtonSize} from '@gravity-ui/uikit';

import {GridColumnSize, GridColumnSizesType} from '../../grid/types';
import {GridColumnSize, GridColumnSizesType} from '../../grid';
import {ThemeSupporting} from '../../utils';

import {
Expand Down Expand Up @@ -251,6 +251,10 @@ export interface TableProps {
legend?: string[];
justify?: Justify[];
marker?: LegendTableMarkerType;
/**
* Only as accessible name, not displayed explicitly
*/
caption?: string;
}

export interface TableBlockProps {
Expand Down
6 changes: 5 additions & 1 deletion src/models/constructor-items/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {CSSProperties, ReactNode} from 'react';
import React, {CSSProperties, ReactNode} from 'react';

import {ButtonView, ButtonProps as UikitButtonProps} from '@gravity-ui/uikit';

Expand Down Expand Up @@ -83,6 +83,10 @@ export interface Tabbable {
tabIndex?: number;
}

export interface Roleable {
role?: React.AriaRole;
}

//common props
export interface Background {
image?: string;
Expand Down

0 comments on commit d9faf89

Please sign in to comment.