Merge pull request #2719 from github/koesie10/fix-button-accessibility
Fix button accessibility
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
|
||||
import CompareTableComponent from "../../view/compare/CompareTable";
|
||||
|
||||
import "../../view/results/resultsView.css";
|
||||
|
||||
export default {
|
||||
title: "Compare/Compare Table",
|
||||
component: CompareTableComponent,
|
||||
} as Meta<typeof CompareTableComponent>;
|
||||
|
||||
const Template: StoryFn<typeof CompareTableComponent> = (args) => (
|
||||
<CompareTableComponent {...args} />
|
||||
);
|
||||
|
||||
export const CompareTable = Template.bind({});
|
||||
CompareTable.args = {
|
||||
comparison: {
|
||||
t: "setComparisons",
|
||||
stats: {
|
||||
fromQuery: {
|
||||
name: "Query built from user-controlled sources",
|
||||
status: "finished in 0 seconds",
|
||||
time: "8/16/2023, 3:08:37 PM",
|
||||
},
|
||||
toQuery: {
|
||||
name: "Query built from user-controlled sources",
|
||||
status: "finished in 2 seconds",
|
||||
time: "8/16/2023, 3:07:21 PM",
|
||||
},
|
||||
},
|
||||
columns: [
|
||||
{ name: "a", kind: "e" },
|
||||
{ name: "b", kind: "e" },
|
||||
],
|
||||
commonResultSetNames: ["edges", "nodes", "subpaths", "#select"],
|
||||
currentResultSetName: "edges",
|
||||
rows: {
|
||||
from: [],
|
||||
to: [
|
||||
[
|
||||
{
|
||||
label: "url : String",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 22,
|
||||
startColumn: 27,
|
||||
endLine: 22,
|
||||
endColumn: 57,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "url",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 23,
|
||||
startColumn: 33,
|
||||
endLine: 23,
|
||||
endColumn: 35,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
message: undefined,
|
||||
databaseUri: "file:///java",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
|
||||
import { ResultTablesHeader as ResultTablesHeaderComponent } from "../../view/results/ResultTablesHeader";
|
||||
|
||||
import "../../view/results/resultsView.css";
|
||||
|
||||
export default {
|
||||
title: "Results/Result Tables Header",
|
||||
component: ResultTablesHeaderComponent,
|
||||
} as Meta<typeof ResultTablesHeaderComponent>;
|
||||
|
||||
const Template: StoryFn<typeof ResultTablesHeaderComponent> = (args) => (
|
||||
<ResultTablesHeaderComponent {...args} />
|
||||
);
|
||||
|
||||
export const ResultTablesHeader = Template.bind({});
|
||||
ResultTablesHeader.args = {
|
||||
queryName: "test query",
|
||||
queryPath: "/a/b/c/query.ql",
|
||||
selectedTable: "#select",
|
||||
parsedResultSets: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
numPages: 2,
|
||||
numInterpretedPages: 2,
|
||||
resultSetNames: ["#select", "alerts"],
|
||||
resultSet: {
|
||||
t: "InterpretedResultSet",
|
||||
schema: {
|
||||
name: "#select",
|
||||
rows: 15,
|
||||
columns: [
|
||||
{
|
||||
name: "x",
|
||||
kind: "s",
|
||||
},
|
||||
],
|
||||
},
|
||||
name: "#select",
|
||||
interpretation: {
|
||||
sourceLocationPrefix: "/home/bulk-builder/bulk-builder",
|
||||
numTruncatedResults: 0,
|
||||
numTotalResults: 15,
|
||||
data: {
|
||||
t: "SarifInterpretationData",
|
||||
version: "2.1.0",
|
||||
runs: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
|
||||
import { ClickableLocation as ClickableLocationComponent } from "../../../view/results/locations/ClickableLocation";
|
||||
|
||||
import "../../../view/results/resultsView.css";
|
||||
|
||||
export default {
|
||||
title: "Results/Clickable Location",
|
||||
component: ClickableLocationComponent,
|
||||
} as Meta<typeof ClickableLocationComponent>;
|
||||
|
||||
const Template: StoryFn<typeof ClickableLocationComponent> = (args) => (
|
||||
<ClickableLocationComponent {...args} />
|
||||
);
|
||||
|
||||
export const ClickableLocation = Template.bind({});
|
||||
ClickableLocation.args = {
|
||||
loc: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 22,
|
||||
startColumn: 27,
|
||||
endLine: 22,
|
||||
endColumn: 57,
|
||||
},
|
||||
label: "url : String",
|
||||
};
|
||||
@@ -15,13 +15,22 @@ const StyledButton = styled.button<{ size: Size }>`
|
||||
const TextButton = ({
|
||||
size,
|
||||
onClick,
|
||||
className,
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
size?: Size;
|
||||
onClick: (e: React.MouseEvent) => void;
|
||||
className?: string;
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<StyledButton size={size} onClick={onClick}>
|
||||
<StyledButton
|
||||
size={size}
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
title={title}
|
||||
>
|
||||
{children}
|
||||
</StyledButton>
|
||||
);
|
||||
|
||||
@@ -7,11 +7,19 @@ import { ResultRow } from "../../common/bqrs-cli-types";
|
||||
import RawTableRow from "../results/RawTableRow";
|
||||
import { vscode } from "../vscode-api";
|
||||
import { sendTelemetry } from "../common/telemetry";
|
||||
import TextButton from "../common/TextButton";
|
||||
import { styled } from "styled-components";
|
||||
|
||||
interface Props {
|
||||
comparison: SetComparisonsMessage;
|
||||
}
|
||||
|
||||
const OpenButton = styled(TextButton)`
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
padding: 0;
|
||||
`;
|
||||
|
||||
export default function CompareTable(props: Props) {
|
||||
const comparison = props.comparison;
|
||||
const rows = props.comparison.rows!;
|
||||
@@ -46,32 +54,14 @@ export default function CompareTable(props: Props) {
|
||||
<thead>
|
||||
<tr>
|
||||
<td>
|
||||
{/*
|
||||
eslint-disable-next-line
|
||||
jsx-a11y/anchor-is-valid,
|
||||
jsx-a11y/click-events-have-key-events,
|
||||
jsx-a11y/no-static-element-interactions
|
||||
*/}
|
||||
<a
|
||||
onClick={() => openQuery("from")}
|
||||
className="vscode-codeql__compare-open"
|
||||
>
|
||||
<OpenButton onClick={() => openQuery("from")}>
|
||||
{comparison.stats.fromQuery?.name}
|
||||
</a>
|
||||
</OpenButton>
|
||||
</td>
|
||||
<td>
|
||||
{/*
|
||||
eslint-disable-next-line
|
||||
jsx-a11y/anchor-is-valid,
|
||||
jsx-a11y/click-events-have-key-events,
|
||||
jsx-a11y/no-static-element-interactions
|
||||
*/}
|
||||
<a
|
||||
onClick={() => openQuery("to")}
|
||||
className="vscode-codeql__compare-open"
|
||||
>
|
||||
<OpenButton onClick={() => openQuery("to")}>
|
||||
{comparison.stats.toQuery?.name}
|
||||
</a>
|
||||
</OpenButton>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -22,6 +22,7 @@ import { AlertTableHeader } from "./AlertTableHeader";
|
||||
import { SarifMessageWithLocations } from "./locations/SarifMessageWithLocations";
|
||||
import { SarifLocation } from "./locations/SarifLocation";
|
||||
import { EmptyQueryResultsMessage } from "./EmptyQueryResultsMessage";
|
||||
import TextButton from "../common/TextButton";
|
||||
import { AlertTableDropdownIndicatorCell } from "./AlertTableDropdownIndicatorCell";
|
||||
|
||||
type AlertTableProps = ResultTableProps & {
|
||||
@@ -74,13 +75,9 @@ export class AlertTable extends React.Component<
|
||||
return (
|
||||
<span>
|
||||
No Alerts. See{" "}
|
||||
{/*
|
||||
eslint-disable-next-line
|
||||
jsx-a11y/anchor-is-valid,
|
||||
*/}
|
||||
<a href="#" onClick={this.props.showRawResults}>
|
||||
<TextButton onClick={this.props.showRawResults}>
|
||||
raw results
|
||||
</a>
|
||||
</TextButton>
|
||||
.
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
ParsedResultSets,
|
||||
} from "../../common/interface-types";
|
||||
import { basename } from "../../common/path";
|
||||
import { styled } from "styled-components";
|
||||
import TextButton from "../common/TextButton";
|
||||
|
||||
interface Props {
|
||||
queryName: string;
|
||||
@@ -16,6 +18,47 @@ interface Props {
|
||||
selectedTable: string;
|
||||
}
|
||||
|
||||
const Container = styled.span`
|
||||
display: flex;
|
||||
padding: 0.5em 0;
|
||||
align-items: center;
|
||||
top: 0;
|
||||
background-color: var(--vscode-editorGutter-background);
|
||||
position: sticky;
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
const PaginationButton = styled.button`
|
||||
padding: 0.3rem;
|
||||
margin: 0.2rem;
|
||||
border: 0;
|
||||
font-size: large;
|
||||
color: var(--vscode-editor-foreground);
|
||||
background-color: var(--vscode-editorGutter-background);
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
|
||||
const PageNumberInput = styled.input`
|
||||
border-radius: 0;
|
||||
padding: 0.3rem;
|
||||
margin: 0.2rem;
|
||||
width: 2rem;
|
||||
color: var(--vscode-editor-foreground);
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--vscode-editor-foreground);
|
||||
background-color: var(--vscode-editorGutter-background);
|
||||
outline: none;
|
||||
`;
|
||||
|
||||
const OpenQueryLink = styled(TextButton)`
|
||||
text-decoration: none;
|
||||
`;
|
||||
|
||||
export function ResultTablesHeader(props: Props) {
|
||||
const { queryPath, queryName, parsedResultSets, selectedTable } = props;
|
||||
|
||||
@@ -104,9 +147,9 @@ export function ResultTablesHeader(props: Props) {
|
||||
}, [queryPath]);
|
||||
|
||||
return (
|
||||
<span className="vscode-codeql__table-selection-pagination">
|
||||
<button onClick={prevPageHandler}>«</button>
|
||||
<input
|
||||
<Container>
|
||||
<PaginationButton onClick={prevPageHandler}>«</PaginationButton>
|
||||
<PageNumberInput
|
||||
type="number"
|
||||
size={3}
|
||||
value={selectedPage}
|
||||
@@ -117,24 +160,16 @@ export function ResultTablesHeader(props: Props) {
|
||||
onKeyDown={onKeyDownHandler}
|
||||
/>
|
||||
<span>/ {numPages}</span>
|
||||
<button value=">" onClick={nextPageHandler}>
|
||||
<PaginationButton value=">" onClick={nextPageHandler}>
|
||||
»
|
||||
</button>
|
||||
</PaginationButton>
|
||||
<div className={tableHeaderItemClassName}>{queryName}</div>
|
||||
<div className={tableHeaderItemClassName}>
|
||||
{/*
|
||||
eslint-disable-next-line
|
||||
jsx-a11y/anchor-is-valid
|
||||
*/}
|
||||
<a
|
||||
href="#"
|
||||
onClick={openQueryHandler}
|
||||
className="vscode-codeql__result-table-location-link"
|
||||
>
|
||||
<OpenQueryLink onClick={openQueryHandler}>
|
||||
Open {basename(queryPath)}
|
||||
</a>
|
||||
</OpenQueryLink>
|
||||
</div>
|
||||
</span>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import * as React from "react";
|
||||
import { useCallback } from "react";
|
||||
import { ResolvableLocationValue } from "../../../common/bqrs-cli-types";
|
||||
import { jumpToLocation } from "../result-table-utils";
|
||||
import TextButton from "../../common/TextButton";
|
||||
import { styled } from "styled-components";
|
||||
|
||||
interface Props {
|
||||
loc: ResolvableLocationValue;
|
||||
@@ -11,6 +13,10 @@ interface Props {
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const Link = styled(TextButton)`
|
||||
text-decoration: none;
|
||||
`;
|
||||
|
||||
/**
|
||||
* A clickable location link.
|
||||
*/
|
||||
@@ -31,20 +37,5 @@ export function ClickableLocation({
|
||||
[loc, databaseUri, onClick],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/*
|
||||
eslint-disable-next-line
|
||||
jsx-a11y/anchor-is-valid,
|
||||
*/}
|
||||
<a
|
||||
href="#"
|
||||
className="vscode-codeql__result-table-location-link"
|
||||
title={title}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
return <Link onClick={handleClick}>{label}</Link>;
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.vscode-codeql__table-selection-pagination {
|
||||
display: flex;
|
||||
padding: 0.5em 0;
|
||||
align-items: center;
|
||||
top: 0;
|
||||
background-color: var(--vscode-editorGutter-background);
|
||||
position: sticky;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.vscode-codeql__table-selection-header-item {
|
||||
padding-left: 2em;
|
||||
}
|
||||
@@ -29,35 +19,6 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.vscode-codeql__table-selection-pagination button {
|
||||
padding: 0.3rem;
|
||||
margin: 0.2rem;
|
||||
border: 0;
|
||||
font-size: large;
|
||||
color: var(--vscode-editor-foreground);
|
||||
background-color: var(--vscode-editorGutter-background);
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.vscode-codeql__table-selection-pagination button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vscode-codeql__table-selection-pagination input[type="number"] {
|
||||
border-radius: 0;
|
||||
padding: 0.3rem;
|
||||
margin: 0.2rem;
|
||||
width: 2rem;
|
||||
border-radius: 0;
|
||||
color: var(--vscode-editor-foreground);
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--vscode-editor-foreground);
|
||||
background-color: var(--vscode-editorGutter-background);
|
||||
border-radius: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.vscode-codeql__result-table-alert-extras {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
@@ -129,10 +90,6 @@
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.vscode-codeql__result-table-location-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
select {
|
||||
background-color: var(--vscode-dropdown-background);
|
||||
color: var(--vscode-dropdown-foreground);
|
||||
@@ -228,11 +185,6 @@ td.vscode-codeql__path-index-cell {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.vscode-codeql__compare-open {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.vscode-codeql__compare-body > tbody {
|
||||
vertical-align: top;
|
||||
}
|
||||
@@ -249,3 +201,7 @@ td.vscode-codeql__path-index-cell {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vscode-codeql__result-table-location-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user