mirror of
https://github.com/react95-io/React95.git
synced 2026-04-26 03:00:18 -04:00
added flat Select
This commit is contained in:
@@ -1,41 +1,55 @@
|
||||
import React from "react";
|
||||
import propTypes from "prop-types";
|
||||
|
||||
import styled from "styled-components";
|
||||
import styled, { css } from "styled-components";
|
||||
import {
|
||||
createBorderStyles,
|
||||
createBoxStyles,
|
||||
createFlatBoxStyles,
|
||||
createDisabledTextStyles
|
||||
} from "../common";
|
||||
import { blockSizes, fontSizes, padding } from "../common/system";
|
||||
|
||||
const StyledButton = styled.button`
|
||||
${createBoxStyles()};
|
||||
const commonButtonStyles = css`
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
${props =>
|
||||
props.flat
|
||||
? null
|
||||
: props.active
|
||||
? createBorderStyles(true)
|
||||
: createBorderStyles(false)}
|
||||
height: ${props => blockSizes[props.size]};
|
||||
width: ${props =>
|
||||
props.fullWidth ? "100%" : props.square ? blockSizes[props.size] : "auto"};
|
||||
padding: ${props => (props.square ? 0 : "0 " + padding.sm)};
|
||||
height: ${({ size }) => blockSizes[size]};
|
||||
width: ${({ fullWidth, square, size }) =>
|
||||
fullWidth ? "100%" : square ? blockSizes[size] : "auto"};
|
||||
padding: ${({ square }) => (square ? 0 : "0 " + padding.sm)};
|
||||
font-size: ${fontSizes.md};
|
||||
|
||||
${props => props.isDisabled && createDisabledTextStyles()}
|
||||
&:active {
|
||||
${props => !props.isDisabled && !props.flat && createBorderStyles(true)}
|
||||
|
||||
padding-top: ${props => !props.isDisabled && "2px"};
|
||||
|
||||
padding-top: ${({ isDisabled }) => !isDisabled && "2px"};
|
||||
}
|
||||
padding-top: ${props => props.active && !props.isDisabled && "2px"};
|
||||
${props => props.flat && "border: none;"}
|
||||
padding-top: ${({ active, isDisabled }) => active && !isDisabled && "2px"};
|
||||
`;
|
||||
|
||||
const StyledButton = styled.button`
|
||||
${commonButtonStyles}
|
||||
|
||||
${({ flat }) =>
|
||||
flat
|
||||
? css`
|
||||
${createFlatBoxStyles()} /* background: none; */
|
||||
`
|
||||
: css`
|
||||
${createBoxStyles()};
|
||||
${({ srat, active }) =>
|
||||
srat
|
||||
? null
|
||||
: active
|
||||
? createBorderStyles(true)
|
||||
: createBorderStyles(false)}
|
||||
${({ isDisabled }) =>
|
||||
isDisabled && createDisabledTextStyles()}
|
||||
&:active {
|
||||
${({ isDisabled, srat }) =>
|
||||
!isDisabled && !srat && createBorderStyles(true)}
|
||||
}
|
||||
${({ srat }) => srat && "border: none;"}
|
||||
`}
|
||||
`;
|
||||
|
||||
const Button = ({
|
||||
@@ -48,6 +62,7 @@ const Button = ({
|
||||
square,
|
||||
active,
|
||||
flat,
|
||||
srat,
|
||||
className,
|
||||
children,
|
||||
...otherProps
|
||||
@@ -63,6 +78,7 @@ const Button = ({
|
||||
square={square}
|
||||
active={active}
|
||||
flat={flat}
|
||||
srat={srat}
|
||||
className={className}
|
||||
style={style}
|
||||
// onTouchStart below to enable button :active style on iOS
|
||||
@@ -83,7 +99,8 @@ Button.defaultProps = {
|
||||
size: "md",
|
||||
square: false,
|
||||
active: false,
|
||||
flat: false
|
||||
flat: false,
|
||||
srat: false
|
||||
};
|
||||
|
||||
Button.propTypes = {
|
||||
@@ -96,6 +113,7 @@ Button.propTypes = {
|
||||
square: propTypes.bool,
|
||||
active: propTypes.bool,
|
||||
flat: propTypes.bool,
|
||||
srat: propTypes.bool,
|
||||
className: propTypes.string,
|
||||
children: propTypes.node.isRequired
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import { action } from "@storybook/addon-actions";
|
||||
|
||||
import styled from "styled-components";
|
||||
|
||||
import Button from "./Button";
|
||||
import { Button, Window, WindowContent, Cutout, Toolbar } from "../";
|
||||
export const actions = { onClick: action("onClick") };
|
||||
|
||||
storiesOf("Button", module)
|
||||
@@ -45,8 +45,36 @@ storiesOf("Button", module)
|
||||
💖
|
||||
</Button>
|
||||
))
|
||||
.add("flat", () => (
|
||||
<Button {...actions} flat size="sm" accent>
|
||||
.add("srat", () => (
|
||||
<Button {...actions} srat size="sm" accent>
|
||||
File
|
||||
</Button>
|
||||
))
|
||||
.add("flat", () => (
|
||||
<Window>
|
||||
<WindowContent>
|
||||
<Cutout
|
||||
style={{ padding: "1rem", background: "white", width: "300px" }}
|
||||
>
|
||||
<p style={{ lineHeight: 1.3 }}>
|
||||
When you want to use Buttons on a light background (like scrollable
|
||||
content), just use the flat variant:
|
||||
</p>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "1.5rem"
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<Button {...actions} flat fullWidth accent>
|
||||
OK
|
||||
</Button>
|
||||
<Button {...actions} flat disabled fullWidth accent>
|
||||
Cancel
|
||||
</Button>
|
||||
</Toolbar>
|
||||
</div>
|
||||
</Cutout>
|
||||
</WindowContent>
|
||||
</Window>
|
||||
));
|
||||
|
||||
@@ -3,12 +3,12 @@ import propTypes from "prop-types";
|
||||
|
||||
import Button from "../Button/Button";
|
||||
|
||||
import styled from "styled-components";
|
||||
import { shadow } from "../common";
|
||||
import styled, { css } from "styled-components";
|
||||
import { shadow, createFlatBoxStyles } from "../common";
|
||||
import { blockSizes, fontSizes, padding } from "../common/system";
|
||||
import Cutout from "../Cutout/Cutout";
|
||||
|
||||
const StyledSelectWrapper = styled(Cutout)`
|
||||
const sharedWrapperStyles = css`
|
||||
height: ${blockSizes.md};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -17,6 +17,13 @@ const StyledSelectWrapper = styled(Cutout)`
|
||||
color: ${({ theme }) => theme.inputText};
|
||||
font-size: ${fontSizes.md};
|
||||
`;
|
||||
const StyledSelectWrapper = styled(Cutout)`
|
||||
${sharedWrapperStyles}
|
||||
`;
|
||||
const StyledFlatSelectWrapper = styled.div`
|
||||
${createFlatBoxStyles()}
|
||||
${sharedWrapperStyles}
|
||||
`;
|
||||
const StyledSelectContent = styled.div`
|
||||
width: 100%;
|
||||
padding-left: ${padding.sm};
|
||||
@@ -24,15 +31,24 @@ const StyledSelectContent = styled.div`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
const StyledDropdownButton = styled(Button)`
|
||||
height: 100%;
|
||||
width: 30px;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
border-left-color: ${({ theme }) => theme.borderLight};
|
||||
border-top-color: ${({ theme }) => theme.borderLight};
|
||||
box-shadow: inset 1px 1px 0px 1px ${({ theme }) => theme.borderLightest},
|
||||
inset -1px -1px 0 1px ${({ theme }) => theme.borderDark};
|
||||
${({ flat }) =>
|
||||
flat
|
||||
? css`
|
||||
height: calc(100% - 4px);
|
||||
margin-right: 2px;
|
||||
`
|
||||
: css`
|
||||
height: 100%;
|
||||
border-left-color: ${({ theme }) => theme.borderLight};
|
||||
border-top-color: ${({ theme }) => theme.borderLight};
|
||||
box-shadow: inset 1px 1px 0px 1px
|
||||
${({ theme }) => theme.borderLightest},
|
||||
inset -1px -1px 0 1px ${({ theme }) => theme.borderDark};
|
||||
`}
|
||||
`;
|
||||
const StyledDropdownIcon = styled.span`
|
||||
position: absolute;
|
||||
@@ -55,16 +71,27 @@ const StyledDropdownList = styled.ul`
|
||||
|
||||
font-size: ${fontSizes.md};
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
width: calc(100% - 2px);
|
||||
transform: translateY(100%);
|
||||
left: 0px;
|
||||
background: ${({ theme }) => theme.canvas};
|
||||
border: 2px solid ${({ theme }) => theme.borderDarkest};
|
||||
padding: 2px;
|
||||
border-top: none;
|
||||
box-shadow: ${props => (props.shadow ? shadow : "none")};
|
||||
cursor: default;
|
||||
z-index: 99;
|
||||
|
||||
${({ flat }) =>
|
||||
flat
|
||||
? css`
|
||||
bottom: 2px;
|
||||
width: 100%;
|
||||
border: 2px solid ${({ theme }) => theme.flatDark};
|
||||
`
|
||||
: css`
|
||||
box-shadow: ${props => (props.shadow ? shadow : "none")};
|
||||
bottom: -2px;
|
||||
width: calc(100% - 2px);
|
||||
border: 2px solid ${({ theme }) => theme.borderDarkest};
|
||||
`}
|
||||
`;
|
||||
const StyledDropdownListItem = styled.li`
|
||||
box-sizing: border-box;
|
||||
@@ -86,6 +113,7 @@ const Select = ({
|
||||
items,
|
||||
selectedIndex,
|
||||
shadow,
|
||||
flat,
|
||||
width,
|
||||
height,
|
||||
otherProps,
|
||||
@@ -100,8 +128,10 @@ const Select = ({
|
||||
if (onChange) onChange(items[i].value);
|
||||
setIndex(i);
|
||||
};
|
||||
|
||||
const Wrapper = flat ? StyledFlatSelectWrapper : StyledSelectWrapper;
|
||||
return (
|
||||
<StyledSelectWrapper
|
||||
<Wrapper
|
||||
className={className}
|
||||
onClick={() => setOpen(!open)}
|
||||
style={{ ...style, width }}
|
||||
@@ -111,12 +141,13 @@ const Select = ({
|
||||
<StyledSelectContent>
|
||||
{items.length ? items[index].label : ""}
|
||||
</StyledSelectContent>
|
||||
<StyledDropdownButton>
|
||||
<StyledDropdownButton flat={flat}>
|
||||
<StyledDropdownIcon />
|
||||
</StyledDropdownButton>
|
||||
{open && (
|
||||
<StyledDropdownList
|
||||
shadow={shadow}
|
||||
flat={flat}
|
||||
style={height && { overflowY: "scroll", height }}
|
||||
>
|
||||
{items.map((item, i) => (
|
||||
@@ -131,7 +162,7 @@ const Select = ({
|
||||
))}
|
||||
</StyledDropdownList>
|
||||
)}
|
||||
</StyledSelectWrapper>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -142,12 +173,14 @@ Select.propTypes = {
|
||||
height: propTypes.number,
|
||||
selectedIndex: propTypes.number,
|
||||
shadow: propTypes.bool,
|
||||
flat: propTypes.bool,
|
||||
style: propTypes.object,
|
||||
onChange: propTypes.func
|
||||
};
|
||||
Select.defaultProps = {
|
||||
style: {},
|
||||
shadow: true,
|
||||
flat: false,
|
||||
selectedIndex: 0
|
||||
};
|
||||
export default Select;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
import Select from "./Select";
|
||||
import { Select, Window, WindowContent, Cutout } from "../";
|
||||
|
||||
export const actions = { onClick: action("onClick") };
|
||||
|
||||
@@ -35,4 +35,36 @@ storiesOf("Select", module)
|
||||
))
|
||||
.add("no shadow", () => (
|
||||
<Select shadow={false} items={items} onChange={onChange} />
|
||||
))
|
||||
.add("flat", () => (
|
||||
<Window>
|
||||
<WindowContent>
|
||||
<Cutout
|
||||
style={{
|
||||
padding: "1rem",
|
||||
paddingBottom: "3rem",
|
||||
background: "white",
|
||||
width: "300px"
|
||||
}}
|
||||
>
|
||||
<p style={{ lineHeight: 1.3 }}>
|
||||
When you want to use Buttons on a light background (like scrollable
|
||||
content), just use the flat variant:
|
||||
</p>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "1.5rem"
|
||||
}}
|
||||
>
|
||||
<Select
|
||||
flat
|
||||
items={items}
|
||||
onChange={onChange}
|
||||
height={100}
|
||||
width={150}
|
||||
/>
|
||||
</div>
|
||||
</Cutout>
|
||||
</WindowContent>
|
||||
</Window>
|
||||
));
|
||||
|
||||
@@ -15,8 +15,10 @@ export const createBoxStyles = () =>
|
||||
background-color: ${({ theme }) => theme.material};
|
||||
color: ${({ theme }) => theme.text};
|
||||
`;
|
||||
// TODO for flat box styles add checkered background when disabled (not solid color)
|
||||
export const createFlatBoxStyles = () =>
|
||||
css`
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
color: ${({ theme }) => theme.text};
|
||||
|
||||
Reference in New Issue
Block a user