Better :focus and :active styles for buttons and links

This commit is contained in:
Joachim Robert 2019-02-06 12:34:38 +01:00
parent 66fabbb197
commit 33cdf24e38
7 changed files with 129 additions and 52 deletions

View file

@ -58,11 +58,15 @@ const base = css`
cursor: not-allowed;
}
&:hover {
&:hover, &:active, &:focus {
transition: all 0.2s ease-in-out;
box-shadow: ${props =>
props.disabled ? 'none' : `${theme.shadows.button}`};
}
&:active, &:focus {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.5)};
}
`;
export const Button = styled.button`
@ -126,7 +130,7 @@ export const PrimaryButton = styled.button`
&:focus {
box-shadow: 0 0 0 1px ${props =>
props.theme.bg.default}, 0 0 0 3px ${props =>
hexa(props.theme.brand.alt, 0.16)};
hexa(props.theme.brand.alt, 0.5)};
}
`;
@ -137,15 +141,15 @@ export const GhostButton = styled.button`
background-color: transparent;
background-image: none;
&:hover {
background: ${props => tint(props.theme.bg.wash, -3)};
&:hover, &:active, &:focus {
background: ${props => tint(props.theme.bg.wash, -8)};
color: ${theme.text.default};
box-shadow: none;
}
&:focus {
&:active, &:focus {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.08)};
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
}
`;
@ -220,12 +224,12 @@ export const ButtonSegmentRow = styled.div`
${PrimaryButton} {
&:focus {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.brand.alt, 0.16)};
0 0 0 3px ${props => hexa(props.theme.brand.alt, 0.5)};
}
}
`;
export const FacebookButton = styled.span`
export const FacebookButton = styled.a`
${base}
border: 1px solid ${theme.social.facebook};
color: ${theme.bg.default};
@ -262,11 +266,11 @@ export const FacebookButton = styled.span`
&:focus {
box-shadow: 0 0 0 1px ${props =>
props.theme.bg.default}, 0 0 0 3px ${props =>
hexa(props.theme.social.facebook, 0.16)};
hexa(props.theme.social.facebook, 0.5)};
}
`;
export const TwitterButton = styled.span`
export const TwitterButton = styled.a`
${base}
border: 1px solid ${theme.social.twitter};
color: ${theme.bg.default};
@ -303,7 +307,7 @@ export const TwitterButton = styled.span`
&:focus {
box-shadow: 0 0 0 1px ${props =>
props.theme.bg.default}, 0 0 0 3px ${props =>
hexa(props.theme.social.twitter, 0.16)};
hexa(props.theme.social.twitter, 0.5)};
}
`;
@ -357,7 +361,7 @@ export const CopyLinkButton = styled.button`
box-shadow: 0 0 0 1px ${props =>
props.theme.bg.default}, 0 0 0 3px ${props =>
props.isClicked
? hexa(props.theme.success.default, 0.16)
? hexa(props.theme.success.default, 0.5)
: props.theme.border.default};
}
`;

View file

@ -2,7 +2,7 @@
import styled, { css } from 'styled-components';
import Markdown from 'react-markdown';
import { theme } from '../theme';
import { Shadows, tint } from '../globals';
import { Shadows, tint, hexa } from '../globals';
export const Container = styled.div`
margin-bottom: 24px;
@ -132,6 +132,16 @@ export const CheckboxContainer = styled.div`
opacity: 1;
background-color: ${theme.success.default};
}
input[type="checkbox"]:active + label, input[type="checkbox"]:focus + label {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.brand.default, 0.5)};
}
input[type="checkbox"]:active:checked + label, input[type="checkbox"]:focus:checked + label {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.spectrum.default, 0.5)};
}
`;
export const ResourceContent = styled.div`
@ -151,11 +161,6 @@ export const ResourceContent = styled.div`
export const AppsContainer = styled.div``;
export const AppMeta = styled.a`
display: flex;
align-items: center;
`;
export const AppRowContainer = styled.div`
display: flex;
justify-content: space-between;
@ -192,6 +197,19 @@ export const AppRowContainer = styled.div`
}
`;
export const AppMeta = styled.a`
display: flex;
align-items: center;
padding-right: 6px;
border-radius: 8px;
&:active, &:focus {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
background: ${theme.bg.wash};
}
`;
export const AppIcon = styled.img`
width: 40px;
height: 40px;
@ -229,8 +247,7 @@ export const AppSourcesListItem = styled.li`
align-items: center;
justify-content: center;
color: ${theme.text.tertiary};
padding: 4px 10px;
border-radius: 4px;
padding: 2px 8px;
min-width: 56px;
transition: all 0.1s ease-in-out;
@ -239,6 +256,19 @@ export const AppSourcesListItem = styled.li`
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2px;
border-radius: 8px;
&:hover {
color: ${theme.text.default};
}
&:active, &:focus {
color: ${theme.text.default};
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
background: ${theme.bg.wash};
}
}
.icon {
@ -247,9 +277,6 @@ export const AppSourcesListItem = styled.li`
left: 4px;
}
&:hover {
color: ${theme.text.default};
}
@media (max-width: 768px) {
padding: 4px;
@ -302,11 +329,16 @@ export const ResourceRowContainer = styled.a`
margin-right: 8px;
}
&:hover {
&:hover, &:active, &:focus {
background: ${theme.bg.wash};
color: ${theme.text.default};
}
&:active, &:focus {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
}
@media (max-width: 768px) {
width: calc(100% + 40px);
border-radius: 0;
@ -314,7 +346,7 @@ export const ResourceRowContainer = styled.a`
margin-left: -24px;
padding-left: 24px;
&:hover {
&:hover, &:active, &:focus {
background: ${theme.bg.default}!important;
}
@ -366,6 +398,12 @@ export const Uncollapse = styled.span`
color: ${theme.text.default};
background: ${tint(theme.bg.wash, -4)};
}
&:active, &:focus {
transition: all 0.2s ease-in-out;
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
}
`;
export const OfferContainer = styled.a`
@ -401,6 +439,12 @@ export const OfferContainer = styled.a`
&:hover {
color: ${theme.text.secondary};
}
&:active, &:focus {
box-shadow: inset 0 0 1px ${theme.border.active},
0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
background: ${theme.bg.wash};
}
`;
export const LeftBorder = styled.div`

View file

@ -1,6 +1,7 @@
// @flow
import styled from 'styled-components';
import { theme } from '../theme';
import { hexa } from '../globals';
export const Container = styled.div`
margin-top: 128px;
@ -34,10 +35,15 @@ export const Icons = styled.div`
color: ${theme.text.tertiary};
}
a:hover {
a:hover, a:active, a:focus {
color: ${theme.text.default};
}
a:active, a:focus {
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
}
.icon {
margin-left: 16px;
}

View file

@ -1,7 +1,7 @@
// @flow
import * as React from 'react';
import Link from 'next/link';
import { Container, ButtonRowContainer, Label } from './style';
import { Container, ButtonRowContainer, Label, LogoLink } from './style';
import { PrimaryButton, GhostButton } from '../Button';
import Logo from './Logo';
@ -14,27 +14,30 @@ export default function Header(props: Props) {
return (
<Container showHeaderShadow={showHeaderShadow} data-cy="header">
<Link href="/">
<a style={{ display: 'flex', alignItems: 'center' }}>
<Label>Security Checklist</Label>
<Logo />
</a>
</Link>
<div>
<Link href="/">
<LogoLink href="/">
<Label>Security Checklist</Label>
<Logo />
</LogoLink>
</Link>
</div>
<ButtonRowContainer>
<Link href="/about">
<a>
<GhostButton>About</GhostButton>
</a>
<GhostButton as="a" href="/about">
About
</GhostButton>
</Link>
<a
<PrimaryButton
href="https://github.com/brianlovin/security-checklist"
target="_blank"
rel="noopener noreferrer"
as="a"
>
<PrimaryButton>Contribute</PrimaryButton>
</a>
Contribute
</PrimaryButton>
</ButtonRowContainer>
</Container>
);

View file

@ -1,6 +1,7 @@
// @flow
import styled from 'styled-components';
import { theme } from '../theme';
import { hexa } from '../globals';
export const Container = styled.div`
display: grid;
@ -18,10 +19,6 @@ export const Container = styled.div`
props.showHeaderShadow ? '0 4px 8px rgba(0,0,0,0.04)' : 'none'};
transition: all 0.2s ease-in-out;
a {
margin-left: 8px;
}
@media (max-width: 968px) {
padding: 8px 16px;
grid-template-columns: 1fr 1fr;
@ -41,6 +38,26 @@ export const ButtonRowContainer = styled.div`
justify-content: flex-end;
grid-area: actions;
align-items: center;
a {
margin-left: 8px;
}
`;
export const LogoLink = styled.a`
transition: all ${props => props.theme.animations.default};
display: inline-flex;
align-items: center;
border-radius: 6px;
&:hover {
transform: scale(1.2);
}
&:active, &:focus {
transform: scale(1.2);
box-shadow: 0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.text.tertiary, 0.25)};
}
`;
export const Label = styled.h1`

View file

@ -1,6 +1,6 @@
// @flow
import styled from 'styled-components';
import { tint } from '../globals';
import { hexa, tint } from '../globals';
import { theme } from '../theme';
export const Container = styled.div`
@ -113,8 +113,11 @@ export const ScrollToTop = styled.button`
transition: all 0.2s ease-in-out;
}
&:active {
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.09);
&:active, &:focus {
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.09),
0 0 0 1px ${theme.bg.default},
0 0 0 3px ${props => hexa(props.theme.brand.default, 0.5)};
outline: none;
transform: translateY(-2px);
transition: all 0.2s ease-in-out;
}

View file

@ -6,21 +6,21 @@ import { Container } from './style';
export default function ShareButtons() {
return (
<Container>
<a
<FacebookButton
href="https://www.facebook.com/sharer/sharer.php?u=https://securitycheckli.st"
target="_blank"
rel="noopener noreferrer"
>
<FacebookButton>Share</FacebookButton>
</a>
Share
</FacebookButton>
<a
<TwitterButton
href="http://twitter.com/share?text=Check out Security Checklist, a checklist to help people stay safe online&url=https://securitycheckli.st"
target="_blank"
rel="noopener noreferrer"
>
<TwitterButton>Tweet</TwitterButton>
</a>
Tweet
</TwitterButton>
<CopyLinkButton text="https://securitycheckli.st">
Share Link