small a11y fixes

This commit is contained in:
Tao Bojlén 2020-06-19 11:46:43 +01:00
parent 9078c0315d
commit a8874c82ba
No known key found for this signature in database
GPG key ID: C6EC7AAB905F9E6F
12 changed files with 101 additions and 66 deletions

View file

@ -24,6 +24,8 @@ There are several environment variables you can set to configure how the crawler
- `FRONTEND_DOMAIN` (required). Used to generate login links for instance admins. - `FRONTEND_DOMAIN` (required). Used to generate login links for instance admins.
- Don't enter `https://`, this is added automatically. - Don't enter `https://`, this is added automatically.
- `SENDGRID_API_KEY`. Needed to send emails to the admin, or to instance admins who want to opt in/out. - `SENDGRID_API_KEY`. Needed to send emails to the admin, or to instance admins who want to opt in/out.
- `MASTODON_DOMAIN`. The domain (e.g. `mastodon.social`) that your bot login account is hosted on.
- `MASTODON_TOKEN`. The access token for the bot login account.
## Deployment ## Deployment

View file

@ -17,7 +17,12 @@ defmodule BackendWeb.RateLimiter do
end end
def rate_limit_authentication(conn, options \\ []) do def rate_limit_authentication(conn, options \\ []) do
%{"id" => domain} = conn.params domain =
if Map.has_key?(conn.params, "id") do
Map.get(conn.params, "id")
else
Map.get(conn.params, "domain")
end
options = Keyword.put(options, :bucket_name, "authorization: #{domain}") options = Keyword.put(options, :bucket_name, "authorization: #{domain}")
rate_limit(conn, options) rate_limit(conn, options)
end end

View file

@ -62,6 +62,7 @@
"@types/node": "^14.0.1", "@types/node": "^14.0.1",
"@types/numeral": "^0.0.28", "@types/numeral": "^0.0.28",
"@types/react": "^16.9.35", "@types/react": "^16.9.35",
"@types/react-axe": "^3.1.0",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.8", "@types/react-redux": "^7.1.8",
"@types/react-router-dom": "^5.1.5", "@types/react-router-dom": "^5.1.5",
@ -79,7 +80,7 @@
"husky": "^4.2.5", "husky": "^4.2.5",
"lint-staged": "^10.2.4", "lint-staged": "^10.2.4",
"prettier": "^2.0.5", "prettier": "^2.0.5",
"react-axe": "^3.3.0", "react-axe": "3.3.0",
"typescript": "^3.9.2" "typescript": "^3.9.2"
}, },
"browserslist": [ "browserslist": [

View file

@ -19,6 +19,7 @@ const AppRouter: React.FC = () => (
<ConnectedRouter history={history}> <ConnectedRouter history={history}>
<div className={`${Classes.DARK} App`}> <div className={`${Classes.DARK} App`}>
<Nav /> <Nav />
<main role="main">
<Route path="/instances" exact component={TableScreen} /> <Route path="/instances" exact component={TableScreen} />
<Route path="/about" exact component={AboutScreen} /> <Route path="/about" exact component={AboutScreen} />
<Route path="/admin/login" exact component={LoginScreen} /> <Route path="/admin/login" exact component={LoginScreen} />
@ -26,6 +27,7 @@ const AppRouter: React.FC = () => (
<Route path="/admin" exact component={AdminScreen} /> <Route path="/admin" exact component={AdminScreen} />
{/* We always want the GraphScreen to be rendered (since un- and re-mounting it is expensive */} {/* We always want the GraphScreen to be rendered (since un- and re-mounting it is expensive */}
<GraphScreen /> <GraphScreen />
</main>
</div> </div>
</ConnectedRouter> </ConnectedRouter>
); );

View file

@ -143,7 +143,7 @@ class InstanceTable extends React.PureComponent<InstanceTableProps> {
const isEndOfSection = nextPage !== undefined && page + 1 !== nextPage && page !== totalPages; const isEndOfSection = nextPage !== undefined && page + 1 !== nextPage && page !== totalPages;
return ( return (
<> <React.Fragment key={page}>
<Button <Button
key={page} key={page}
onClick={this.loadPageFactory(page)} onClick={this.loadPageFactory(page)}
@ -157,7 +157,7 @@ class InstanceTable extends React.PureComponent<InstanceTableProps> {
... ...
</Button> </Button>
)} )}
</> </React.Fragment>
); );
})} })}
</ButtonGroup> </ButtonGroup>

View file

@ -21,30 +21,31 @@ class Nav extends React.Component<{}, NavState> {
public render() { public render() {
return ( return (
<Navbar fixedToTop> <nav role="navigation">
<Navbar fixedToTop={true}>
<Navbar.Group align={Alignment.LEFT}> <Navbar.Group align={Alignment.LEFT}>
<Navbar.Heading>fediverse.space</Navbar.Heading> <Navbar.Heading>fediverse.space</Navbar.Heading>
<Navbar.Divider /> <Navbar.Divider />
<NavLink <NavLink
to="/" to="/"
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.GLOBE_NETWORK}`} className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.GLOBE_NETWORK}`}
activeClassName={Classes.INTENT_PRIMARY}
isActive={graphIsActive as any} isActive={graphIsActive as any}
activeClassName="current-navbar-item"
> >
Home Home
</NavLink> </NavLink>
<NavLink <NavLink
to="/instances" to="/instances"
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.TH}`} className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.TH}`}
activeClassName={Classes.INTENT_PRIMARY} activeClassName="current-navbar-item"
> >
Instances Instances
</NavLink> </NavLink>
<NavLink <NavLink
to="/about" to="/about"
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.INFO_SIGN}`} className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.INFO_SIGN}`}
activeClassName={Classes.INTENT_PRIMARY} activeClassName="current-navbar-item"
exact exact={true}
> >
About About
</NavLink> </NavLink>
@ -53,12 +54,13 @@ class Nav extends React.Component<{}, NavState> {
<NavLink <NavLink
to="/admin" to="/admin"
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.COG}`} className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.COG}`}
activeClassName={Classes.INTENT_PRIMARY} activeClassName="current-navbar-item"
> >
Administration Administration
</NavLink> </NavLink>
</Navbar.Group> </Navbar.Group>
</Navbar> </Navbar>
</nav>
); );
} }
} }

View file

@ -1,4 +1,4 @@
import { Classes, Code, H1, H2, H4 } from "@blueprintjs/core"; import { Classes, Code, H1, H2, H3 } from "@blueprintjs/core";
import * as React from "react"; import * as React from "react";
import styled from "styled-components"; import styled from "styled-components";
// import appsignalLogo from "../../assets/appsignal.svg"; // import appsignalLogo from "../../assets/appsignal.svg";
@ -36,16 +36,16 @@ const AboutScreen: React.FC = () => (
<br /> <br />
<H2>FAQ</H2> <H2>FAQ</H2>
<H4>Why can&apos;t I see details about my instance?</H4> <H3>Why can&apos;t I see details about my instance?</H3>
<p className={Classes.RUNNING_TEXT}> <p className={Classes.RUNNING_TEXT}>
fediverse.space only supports servers using the Mastodon API, the Misskey API, the GNU Social API, or Nodeinfo. fediverse.space only supports servers using the Mastodon API, the Misskey API, the GNU Social API, or Nodeinfo.
Instances with 10 or fewer users won&apos;t be crawled -- it&apos;s a tool for understanding communities, not Instances with 10 or fewer users won&apos;t be crawled -- it&apos;s a tool for understanding communities, not
individuals. individuals.
</p> </p>
<H4> <H3>
When is <Code>$OTHER_FEDIVERSE_SERVER</Code> going to be added? When is <Code>$OTHER_FEDIVERSE_SERVER</Code> going to be added?
</H4> </H3>
<p className={Classes.RUNNING_TEXT}> <p className={Classes.RUNNING_TEXT}>
Check out{" "} Check out{" "}
<a href="https://gitlab.com/taobojlen/fediverse.space/issues/24" target="_blank" rel="noopener noreferrer"> <a href="https://gitlab.com/taobojlen/fediverse.space/issues/24" target="_blank" rel="noopener noreferrer">
@ -54,10 +54,10 @@ const AboutScreen: React.FC = () => (
. .
</p> </p>
<H4>How do I add my personal instance?</H4> <H3>How do I add my personal instance?</H3>
<p className={Classes.RUNNING_TEXT}>Click on the Administration link in the top right to opt-in.</p> <p className={Classes.RUNNING_TEXT}>Click on the Administration link in the top right to opt-in.</p>
<H4>How do you calculate the strength of relationships between instances?</H4> <H3>How do you calculate the strength of relationships between instances?</H3>
<p className={Classes.RUNNING_TEXT}> <p className={Classes.RUNNING_TEXT}>
fediverse.space looks at public statuses from within the last month on the public timeline of each instance. It fediverse.space looks at public statuses from within the last month on the public timeline of each instance. It
calculates at the ratio of calculates at the ratio of

View file

@ -1,4 +1,4 @@
import { Button, Classes, FormGroup, H1, H4, Icon, InputGroup, Intent } from "@blueprintjs/core"; import { Button, Classes, FormGroup, H1, H2, Icon, InputGroup, Intent } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons"; import { IconNames } from "@blueprintjs/icons";
import React from "react"; import React from "react";
import { Redirect } from "react-router"; import { Redirect } from "react-router";
@ -132,7 +132,7 @@ class LoginScreen extends React.PureComponent<{}, LoginScreenState> {
const loginWithDm = () => this.login("fediverseAccount"); const loginWithDm = () => this.login("fediverseAccount");
return ( return (
<> <>
<H4>Choose an authentication method</H4> <H2>Choose an authentication method</H2>
<LoginTypeContainer> <LoginTypeContainer>
{loginTypes.email && ( {loginTypes.email && (
<LoginTypeButton large icon={IconNames.ENVELOPE} onClick={loginWithEmail} loading={!!isSendingLoginRequest}> <LoginTypeButton large icon={IconNames.ENVELOPE} onClick={loginWithEmail} loading={!!isSendingLoginRequest}>

View file

@ -1,4 +1,4 @@
import { Button, Callout, H2, InputGroup, Intent, NonIdealState, Spinner } from "@blueprintjs/core"; import { Button, Callout, H1, InputGroup, Intent, NonIdealState, Spinner } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons"; import { IconNames } from "@blueprintjs/icons";
import { push } from "connected-react-router"; import { push } from "connected-react-router";
import { get, isEqual } from "lodash"; import { get, isEqual } from "lodash";
@ -121,7 +121,7 @@ class SearchScreen extends React.PureComponent<SearchScreenProps, SearchScreenSt
<> <>
{isSmallScreen && results.length === 0 && this.renderMobileWarning()} {isSmallScreen && results.length === 0 && this.renderMobileWarning()}
<SearchBarContainer hasSearchResults={!!query && !!results} hasError={!!error}> <SearchBarContainer hasSearchResults={!!query && !!results} hasError={!!error}>
<H2>Find an instance</H2> <H1>Find an instance</H1>
<InputGroup <InputGroup
leftIcon={IconNames.SEARCH} leftIcon={IconNames.SEARCH}
rightElement={rightSearchBarElement} rightElement={rightSearchBarElement}

View file

@ -12,3 +12,7 @@ body {
.app-toaster { .app-toaster {
z-index: 1000; z-index: 1000;
} }
.current-navbar-item {
background-color: #293742 !important;
}

View file

@ -19,6 +19,11 @@ import { createBrowserHistory } from "history";
import AppRouter from "./AppRouter"; import AppRouter from "./AppRouter";
import createRootReducer from "./redux/reducers"; import createRootReducer from "./redux/reducers";
if (process.env.NODE_ENV === "development") {
const axe = require("react-axe"); // eslint-disable-line @typescript-eslint/no-var-requires
axe(React, ReactDOM, 1000);
}
// https://blueprintjs.com/docs/#core/accessibility.focus-management // https://blueprintjs.com/docs/#core/accessibility.focus-management
FocusStyleManager.onlyShowFocusOnTabs(); FocusStyleManager.onlyShowFocusOnTabs();

View file

@ -1573,7 +1573,16 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
"@types/react-dom@^16.9.8": "@types/react-axe@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/react-axe/-/react-axe-3.1.0.tgz#d8bd3f3f1077e7e2790c2a500f3ccefde8f5567b"
integrity sha512-zBQGSlWVwiMiKmDsFS5+2uO5tt1M2fdD3mTkOAA4EwV2uWrzi02d5NMhLZtxpyaCWtwz5xNLO4INotoWZUAg0A==
dependencies:
"@types/react" "*"
"@types/react-dom" "*"
axe-core "3.2.2"
"@types/react-dom@*", "@types/react-dom@^16.9.8":
version "16.9.8" version "16.9.8"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
@ -2245,7 +2254,12 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
axe-core@^3.5.0: axe-core@3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.2.2.tgz#b06d6e9ae4636d706068843272bfaeed3fe97362"
integrity sha512-gAy4kMSPpuRJV3mwictJqlg5LhE84Vw2CydKdC4tvrLhR6+G3KW51zbL/vYujcLA2jvWOq3HMHrVeNuw+mrLVA==
axe-core@^3.3.2:
version "3.5.3" version "3.5.3"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.3.tgz#5b7c0ee7c5197d546bd3a07c3ef701896f5773e9" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.3.tgz#5b7c0ee7c5197d546bd3a07c3ef701896f5773e9"
integrity sha512-HZpLE7xu05+8AbpqXITGdxp1Xwk8ysAXrg7MiKRY27py3DAyEJpoJQo1727pWF3F+O79V3r+cTWhOzfB49P89w== integrity sha512-HZpLE7xu05+8AbpqXITGdxp1Xwk8ysAXrg7MiKRY27py3DAyEJpoJQo1727pWF3F+O79V3r+cTWhOzfB49P89w==
@ -9198,12 +9212,12 @@ react-app-polyfill@^1.0.6:
regenerator-runtime "^0.13.3" regenerator-runtime "^0.13.3"
whatwg-fetch "^3.0.0" whatwg-fetch "^3.0.0"
react-axe@^3.3.0: react-axe@3.3.0:
version "3.4.1" version "3.3.0"
resolved "https://registry.yarnpkg.com/react-axe/-/react-axe-3.4.1.tgz#8874ca48b5af71452d97c2991d37cdcbba6c3a48" resolved "https://registry.yarnpkg.com/react-axe/-/react-axe-3.3.0.tgz#b87bff644ed3ed6f1ca12bcc64c00000e359c25b"
integrity sha512-1UDeqesgb5gCj2XPE5WXqKv2xcwGGeWIock3uBVtZSVGbZGVzjmgYf4eRyNJ8BNnHpPQKUs4Ro5jW2+V037deg== integrity sha512-JoxU2jcTla37U6MtqIoYnGaRQcAHkNm9JxTjx2wcEgFm8Zd2A2vo9eboxcmpLjklXDKJwJNbyDo2Jcbbme6xwA==
dependencies: dependencies:
axe-core "^3.5.0" axe-core "^3.3.2"
requestidlecallback "^0.3.0" requestidlecallback "^0.3.0"
react-dev-utils@^10.2.1: react-dev-utils@^10.2.1: