Improved button handling and styling

This commit is contained in:
2019-09-02 20:01:00 +02:00
parent a7f4059311
commit 1af2ceb862
8 changed files with 65 additions and 54 deletions

View File

@@ -1,4 +1,4 @@
import styled, { keyframes } from "styled-components";
import styled, { keyframes, css } from "styled-components";
const fade = keyframes`
from { transform: scale(.7) }
@@ -20,7 +20,12 @@ const Apple = styled.div.attrs(({ theme, zoom }) => ({
&:after {
content: "${props => (!props.died ? "🍎" : "🐛")}";
display: inline-block;
animation: ${fade} 1s ease-out alternate infinite;
animation: ${props =>
props.died
? "none"
: css`
${fade} 1s ease-out alternate infinite
`};
}
`;

View File

@@ -31,9 +31,14 @@ const SharedStyle = () => `
}
`;
const ButtonWrapper = styled.div`
const ButtonWrapper = styled.div.attrs(({ disabled }) => ({ tabIndex: disabled ? null : 0 }))`
position: relative;
display: inline-block;
&:focus,
&:hover {
outline: ${({ disabled }) => (!disabled ? "1px solid silver" : "none")};
}
`;
const StyledButton = styled.button`
@@ -49,13 +54,16 @@ const StyledNavLink = styled(NavLink)`
${SharedStyle}
`;
export const Button = (props, refs) => {
export const Button = props => {
const [hover, setHover] = React.useState(false);
const updatedProps = { ...props };
const disabled = props.disabled || props.toggle;
let tooltip = null;
if (props.onClick) {
updatedProps.onClick = e => e.preventDefault() || props.onClick();
updatedProps.onKeyUp = e =>
!disabled && (e.which === 13 || e.which === 32) && (e.preventDefault() || props.onClick());
updatedProps.onClick = e => (!disabled && e.preventDefault()) || props.onClick();
}
if (props.href) {
@@ -72,13 +80,19 @@ export const Button = (props, refs) => {
if (props.icon) {
return (
<ButtonWrapper onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}>
<ButtonWrapper
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
onKeyUp={updatedProps.onKeyUp}
onClick={updatedProps.onClick}
disabled={disabled}>
<i
disabled={disabled}
onClick={updatedProps.onClick}
className={`fas fa-${props.icon} ${props.className}`}
style={{ display: "inline-block", fontSize: `${props.size || 1}rem` }}
/>
{tooltip}
{!disabled && tooltip}
</ButtonWrapper>
);
}
@@ -98,6 +112,7 @@ export const IconButton = styled(Button)`
&:before {
text-shadow: 0 0 1px black, 1px 1px 3px #d0bfa3;
text-shadow: 0 0 1px gray, 0 0 1px #d0bfa3;
}
`;

View File

@@ -41,9 +41,12 @@ const ThemeSelector = styled.select`
<polygon points="0,3 16,3 8,13" fill="${({ theme }) => theme.select.color.replace("#", "%23")}" />
</svg>');
background-repeat: no-repeat;
background-position: right 0.625rem center;
background-position: right 0 center;
background-size: 1rem 1rem;
outline-offset: 3px;
&:active,
&:focus,
&:hover {
outline: 1px solid silver;
}

View File

@@ -25,15 +25,20 @@ const MenuButton = styled(NavLink)`
background: ${props => props.theme.header.menuButton.active.background};
color: ${props => props.theme.header.menuButton.active.color};
}
&:active,
&:focus,
&:hover {
outline: 1px solid silver;
}
`;
const HeaderMenu = () => (
<MenuPanel>
<MenuItem>
<MenuButton to="/snake">Snake</MenuButton>
<MenuButton to="/">Snake</MenuButton>
</MenuItem>
<MenuItem>
<MenuButton to="/" exact>
<MenuButton to="/about" exact>
About
</MenuButton>
</MenuItem>

View File

@@ -1,8 +1,14 @@
import React from "react";
import { Route, Switch } from "react-router"; // react-router v4/v5
import { Route, Switch } from "react-router";
import { connect } from "react-redux";
import { hot } from "react-hot-loader/root";
import { MODULE_NAME as UI_MODULE_NAME } from "../redux/ui.js";
import { ThemeProvider } from "styled-components";
import { themes } from "../theming/theme.js";
import GlobalStyle from "../theming/GlobalStyle.js";
/* Containers */
import Header from "./Header";
import Footer from "./Footer";
@@ -10,20 +16,26 @@ import Page from "../components/Page";
import Home from "./Home";
import Snake from "./Snake";
const App = ({ title, onNewTitle, getKeyboards, keyboards }) => (
<React.Fragment>
<Header />
<Page>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/snake" exact component={Snake} />
</Switch>
</Page>
<Footer />
</React.Fragment>
const App = ({ theme }) => (
<ThemeProvider theme={themes[theme]}>
<React.Fragment>
<GlobalStyle />
<Header />
<Page>
<Switch>
<Route exact path="/" component={Snake} />
<Route path="/snake" exact component={Snake} />
<Route path="/about" exact component={Home} />
</Switch>
</Page>
<Footer />
</React.Fragment>
</ThemeProvider>
);
const mapState = () => ({});
const mapState = state => ({
theme: state[UI_MODULE_NAME].theme || "light"
});
const mapActions = {};

View File

@@ -1,27 +0,0 @@
import React from "react";
import { connect } from "react-redux";
import { hot } from "react-hot-loader/root";
import { MODULE_NAME as UI_MODULE_NAME } from "../redux/ui.js";
import { ThemeProvider } from "styled-components";
import { themes } from "../theming/theme.js";
import GlobalStyle from "../theming/GlobalStyle.js";
const Document = ({ theme, children }) => (
<ThemeProvider theme={themes[theme]}>
<React.Fragment>
<GlobalStyle />
{children}
</React.Fragment>
</ThemeProvider>
);
const ConnectedDocument = connect(
state => ({
theme: state[UI_MODULE_NAME].theme || "light"
}),
{}
)(Document);
export default (process.env.NODE_ENV === "development" ? hot(ConnectedDocument) : ConnectedDocument);
// export default (process.env.NODE_ENV === "development" ? hot(Document) : Document);

View File

@@ -7,7 +7,6 @@ import { createStore } from "./redux/store";
import { initSnake } from "./redux/snake";
import { keyPress } from "./redux/game";
import Document from "./containers/Document.js";
import App from "./containers/App.js";
const store = createStore();
@@ -16,9 +15,7 @@ window.store = store;
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={store.history}>
<Document>
<App />
</Document>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById("root")

View File

@@ -101,6 +101,7 @@ module.middleware(INIT, (dispatch, { loopId }) => {
module.middleware(
KEY_PRESS,
(dispatch, { keyPressSubscribers = [], fps }, { key, altKey, ctrlKey, metaKey, shiftKey }) => {
console.log("key", key);
keyPressSubscribers.forEach(subscriber => dispatch({ type: subscriber, key, altKey, ctrlKey, metaKey, shiftKey }));
if (key === keys.PLUS || key === keys.EQUAL) {