3.1.1 • Published 5 years ago

already-styled-components v3.1.1

Weekly downloads
4
License
MIT
Repository
github
Last release
5 years ago

Already styled-components

React UI components styled with ... styled-components. Depends on polished for color shades and on react-transition-group for Navbar transitions. Also contains some inline SVG from fontawesome.

Install

npm i already-styled-components styled-components

(assuming you already have installed react and react-dom)

Available components

Also includes some minor smooth scrolling and animation utilities.

Components

1. Grid

A grid layout implemented with flexbox. The implementation is from Philip Walton's "solved by flexbox" repo. What he describes as Grid is a Row component here and a Grid Cell is a Column. In short, Container component is not really important just a div, only Row and Column are "special". Each Column must be inside a Row. The Columns are responsive by passing props similar to Bootstrap (xs, sm, md, ...) but work the other way around. For example when you specify the extra large (xl) prop this applies to all lower breakpoints. Except of extra small (xs) where it takes the whole row by default. If you don't pass a responsive prop all Columns take the same space inside a Row. See the Column prop table for more details.

Example (holy grail layout)
// A holy grail layout.
import React from "react";
import { createGlobalStyle } from "styled-components";
import { Container, Row, Column } from "already-styled-components";

const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
  }
`;

export default () => (
  <>
    <GlobalStyle />
    <Container fluid ta="center">
      <Row bc="#eee" h="15vh">
        <Column>Header</Column>
      </Row>
      <Row h="70vh">
        <Column bc="#ddd">Left sidebar</Column>
        <Column bc="#bbb" lg="50%">
          Content
        </Column>
        <Column bc="#aaa">Right sidebar</Column>
      </Row>
      <Row bc="#999" h="15vh">
        <Column>Footer</Column>
      </Row>
    </Container>
  </>
);

i) Container props

✨ Be careful of overflows if you use the width property alongside the padding property (or border). You may want to use the border-box value for the box-sizing property to avoid surprises.

nameextra infotypedefault
fluidwidth: 80% or 100% (fluid prop wins over width prop)boolfalse
wwidthstring"80%"
hheightstringnull
mmarginstring"auto"
ppaddingstringnull
tatext-alignstringnull
ccolorstringnull
bcbackground-colorstringnull

ii) Row props

nameextra infotypedefault
guttersChanges the margin for the Row component and the padding for the immediate child Column components. It's visible if you add a div with a background color inside the Column.boolfalse
gutterSizeThe amount of margin for the Row and padding for the Column childrenstring"1em"
wwidthstringnull
hheightstringnull
mmargin. If you set gutters={true} this prop will be ignoredstring"0"
ppaddingstring"0"
ccolorstringnull
bcbackground-colorstringnull
aialign-itemsstringnull
jcjustify-contentstringnull
tatext-alignstringnull

iii) Column props

✨ The responsive props (xs, sm, md, lg, xl) when present alter the flex shorthand property of the Column. More specifically the third parameter which corresponds to the flex-basis. For example if you pass only md="33%" we have in the code:

const Column = styled.div`
  ....
  flex: ${({ xl }) => (xl ? `0 0 ${xl}` : 1)};
  @media screen and (max-width: 992px) {
    flex: ${({ md }) => md && `0 0 ${md}`};
  }
  ....
  @media screen and (max-width: 576px) {
    flex: ${({ xs }) => xs && `0 0 ${xs}`};
  }

`

and the result is (see the following table for defaults):

  const Column = styled.div`
  ....
  flex:  1;
  @media screen and (max-width: 992px) {
    flex: 0 0 33%;
  }
  ....
  @media screen and (max-width: 576px) {
    flex: 0 0 100%;
  }

`

You can pass in breakpoint props (xs, sm, ...) any value that is valid for width and height CSS properties. Meaning px, em, %...

nameextra infotypedefault
flextrue = display: flex, false = display: blockboolfalse
xsScreen width <= 576px. By default Columns take the whole Row in this breakpoint (xs="100%")string"100%"
smScreen width <= 768pxstringnull
mdScreen width <= 992pxstringnull
lgScreen width <= 1200pxstringnull
xlScreen width > 1200px. By default Columns occupy equal space inside a Row (flex-basis: 1).stringnull
hheightstringnull
mmarginstringnull
ppadding. If you use gutters on the parent Row component this property will be overriddenstringnull
alignSelfalign-self. as is reserved if you're wondering 😠stringnull
tatext-alignstringnull
ccolorstringnull
bcbackground-colorstringnull

iv) Centered

A simple utility component that uses flexbox to center vertically and horizontally the content. By default has height: 100%.

Centered props
nameextra infotypedefault
fdflex-directionstring"column"
aialign-itemsstring"center"
hheightstring"100%"
mmargin.stringnull
ppaddingstringnull
tatext-alignstringnull
ccolorstringnull
bcbackground-colorstringnull

2. Button

A slightly round button that is similar to the Bootstrap 4 button. It calculates the background-color on hover and adds an outline from the bc prop you specify. If you want to extend it with styled(Button), I suggest to use the bc prop to keep this functionality.

Example
import React from "react";
import { Button } from "already-styled-components";

export default () => (
  <div>
    <Button>Click me</Button>
    <Button transparent c="black">
      "Icon" button
    </Button>
  </div>
);
Example (extending Button)
import React from "react";
import styled from "styled-components";
import { Button } from "already-styled-components";

const Center = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
`;
const OrangeButton = styled(Button)`
  border-radius: 0px;
  background-color: orange;
  color: black;
`;
const PinkButton = styled(Button)`
  border-radius: 0px;
  font-size: 24px;
`;
export default () => (
  <Center>
    <OrangeButton>Not so good</OrangeButton>
    <PinkButton bc="pink" c="black">
      Better
    </PinkButton>
  </Center>
);
Button props
nameextra infotypedefault
transparentTransparent background-color and no transitions. You can use it as an icon buttonboolfalse
ccolorstring"#FFF"
bcbackground-colorstring"#00AFB1"
hchover colorstringnull
brborder-radiusstring"20px"
fffont-familystring"inherit"
fsfont-sizestring"20px"

3. Navbar

A render props component that renders a sticky navigation bar with a mobile full screen menu. More specifically renders by default a DesktopList and a MobileList component. You can pass the links via the children prop. If you want more control and customization you can use the DesktopListEmpty or MobileListEmpty. The last two render only a button that open and closes the mobile menu. Obviously you can provide you own implementations, but I believe the empty lists can cover a lot of scenarios.

Note: The Navbar component registers an IntersectionObserver if the fixed property is set to true. In order for it to work on Safari you need this polyfill. The easiest way is to include the following script before the browser parses your JavaScript (at the head of the document):

<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
Examples
Prop tables
Example 1 (without any customizations)
import React from "react";
import styled from "styled-components";
import { Container, Navbar } from "already-styled-components";

const Brand = styled.div`
  font-size: 36px;
  font-style: italic;
  color: white;
`;
export default () => (
  <Container h="200vh" fluid>
    <Navbar brand={<Brand>Styled Components</Brand>}>
      <a href="/">Home</a>
      <a href="/About">About</a>
      <a href="/Contact">Contact</a>
    </Navbar>
  </Container>
);
Navbar props
nameextra infotypedefault
desktopListA function that returns the desktop navbar (render prop)functionprops => <DesktopList {...props} />
mobileListA function that returns the mobile navbar (render prop)functionprops => <MobileList {...props} />
brandThe brand name or logo positioned at the left.A React elementnull
fixedThe desktop list is actually positioned sticky not fixed. When it's true it doesn't change the position property anymore but instead performs a height transition when the user scrolls down. I'll change the name in version 3 to make more sense.booltrue
childrenThe links that the desktop/mobile lists will renderA React element or morenull
ccolorstring"#FFF"
bcbackground-colorstring"#313131"
hc:hover colorstring"orangered"
Example 2 (extending the default DesktopList)

In this example we change the colors of the DesktopList when we scroll down. That is, if the Navbar is "fixed top" which is the default behavior.

import React from "react";
import styled from "styled-components";
import { Container, Navbar, DesktopList } from "already-styled-components";

const Brand = styled.div`
  font-size: 36px;
  font-style: italic;
  color: white;
`;

const WhiteWhenFixed = styled(DesktopList)`
  box-shadow: 0 0 3px 0 black;
  transition: all 0.3s ease-in-out !important;
  background-color: ${({ fixedTop }) => fixedTop && `white`};
  a,
  div {
    color: ${({ fixedTop }) => fixedTop && `black`};
  }
  path {
    fill: ${({ fixedTop }) => fixedTop && `black`};
  }
`;
export default () => (
  <Container fluid h="200vh" bc="beige">
    <Navbar
      brand={<Brand>Styled Components</Brand>}
      desktopList={props => (
        <WhiteWhenFixed {...props} suppressClassNameWarning />
      )}
    >
      <a href="/">Home</a>
      <a href="/About">About</a>
      <a href="/Contact">Contact</a>
    </Navbar>
  </Container>
);

3. i) DesktopList props

nameextra infotypedefault
showMobileA function that shows the mobile menufunctionnull
linksThe children of the Navbar if any.A React element or moreNone, it's required
brandThe brand name or logo positioned at the left of the desktop list.A React elementnull
fixedTopIs the Navbar "fixed top" now?boolfalse
fixedBreakpointA ref used by the IntersectionObserver of the NavbarnodeNone, it's required
mobileBreakpointA number that indicates the screen size in which we hide the desktop links and show the hamburger button that opens the mobile menu.number980
timeoutThe timeout prop of the CSSTransition. It specifies how long the Navbar will transition when it enters the "fixed top" state (the user scrolls down) and when leaves (the user scrolls at the top of the screen).object{ enter: 150, exit: 150 }
classNameFor extending with styled-components.stringnull
ccolorstring"#FFF"
bcbackground-colorstring"#1D1D1D"
hc:hover colorstring"orangered"

3. ii) MobileList props

nameextra infotypedefault
linksThe children of the Navbar, if anyA React element or moreNone, it's required
mobileMenuVisibleIs the mobile menu visible now?boolNone, it's required
hideMobileA function that hides the mobile menu.functionnull
timeoutThe timeout prop of the CSSTransition. It specifies how long will animate the mobile list when enters and leaves the screen.object{ enter: 300, exit: 150 }
classNameFor extending with styled-components.stringnull
ccolorstring"#FFF"
bcbackground-colorstring"#1D1D1D"
hc:hover color for the linksstring"orangered"
Example 3 (using and extending the MobileListEmpty)

In this example we put our own content in the mobile list and change the enter transition from fade-in to slide-down. Check these examples for more ideas.

import React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import {
  Container,
  Row,
  Column,
  Centered,
  Navbar,
  MobileListEmpty
} from "already-styled-components";

const MobileListContent = styled(MobileListEmpty)`
  &.mobile-list-enter {
    transform: translateY(-100vh);
  }
  &.mobile-list-enter-active {
    transform: translateY(0);
    transition: transform 0.5s ease-out;
  }
  &.mobile-list-exit {
    transform: translateY(0);
  }
  &.mobile-list-exit-active {
    transform: translateY(-100vh);
    transition: transform 0.3s ease-out;
  }
`;
const MobileLink = styled(Link)`
  font-size: 36px;
  text-decoration: none;
  color: white;
  :hover {
    color: #cca43b;
  }
`;

export default () => (
  <Container h="200vh" fluid>
    <Navbar
      c="white"
      bc="#242F40"
      hc="#CCA43B"
      mobileList={props => (
        <MobileListContent {...props} timeout={{ enter: 500, exit: 300 }}>
          <Centered h="100%">
            <h2>My mobile links!</h2>
            <MobileLink to="/">Home</MobileLink>
            <MobileLink to="/about">About</MobileLink>
            <MobileLink to="/contact">Contact</MobileLink>
          </Centered>
        </MobileListContent>
      )}
    >
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
      <Link to="/contact">Contact</Link>
    </Navbar>
    <Row>
      <Column h="100vh">
        <Centered bc="pink" c="white">
          <h1>Slide-down navbar</h1>
        </Centered>
      </Column>
    </Row>
  </Container>
);

3. iii) DesktopListEmpty props

nameextra infotypedefault
showMobileA function that shows the mobile menufunctionnull
childrenThe children of the desktop list (the links).nodenull
fixedTopIs the desktop list "fixed top" now?boolfalse
fixedBreakpointA ref used by the IntersectionObserver of the NavbarnodeNone, it's required
mobileBreakpointA number that indicates the screen size in which we hide the desktop links and show the hamburger button that opens the mobile menu.number980
timeoutThe timeout prop of the CSSTransition. It specifies how long the desktop list will transition when it enters the "fixed top" state (the user scrolls down) and when leaves (the user scrolls at the top of the screen).object{ enter: 150, exit: 150 }
classNameFor extending with styled-components.stringnull
ccolorstring"#FFF"
bcbackground-colorstring"#1D1D1D"
hchover color of the hamburger icon.string"orangered"

3. iv) MobileListEmpty props

nameextra infotypedefault
childrenThe children of the mobile list (the links)nodenull
mobileMenuVisibleIs the mobile menu visible now?boolNone, it's required
hideMobileA function that hides the mobile menu.functionnull
timeoutThe timeout prop of the CSSTransition. It specifies how long will animate the mobile list when enters and leaves the screen.object{ enter: 150, exit: 150 }
classNameFor extending with styled-components.stringnull
ccolorstring"#FFF"
bcbackground-colorstring"#1D1D1D"
hchover color for the close mobile menu icon.string"orangered"
More Examples using the DesktopListEmpty and MobileListEmpty

4. AnchorLink

A button that'll smooth scroll to the specified section on click. Similar to GitHub heading links in markdown. Under the hood, is basically a slightly different Button component with a transparent prop. You can also provide an offset prop (if you have a fixed/sticky navbar) or a callback (e.g close a modal or a menu after click).

Example
import React from "react";
import styled from "styled-components";
import { AnchorLink } from "already-styled-components";

const Navigation = styled.nav`
  height: 74px;
  background-color: #1d1d1d;
  position: sticky;
  top: 0;
`;
const FirstSection = styled.div`
  height: 50vh;
  color: white;
  background-color: #333;
`;
const SecondSection = styled.div`
  height: 150vh;
  background-color: azure;
`;
export default () => (
  <div>
    <Navigation />
    <FirstSection id="first-section">
      <AnchorLink scrollTo="first-section" c="white">
        First section
      </AnchorLink>
      <p>Close :(</p>
    </FirstSection>
    <SecondSection id="second-section">
      <AnchorLink scrollTo="second-section" offset={74}>
        Second section
      </AnchorLink>
      <p>Perfect!</p>
    </SecondSection>
  </div>
);
AnchorLink props
nameextra infotypedefault
scrollToIt's the section id without the # characterstringNone, it's required
offsetYou can use it if you have a fixed navbar for examplenumber0
callbackA function that you want to execute after the click.functionnull
childrennodenull
fsThe font size for the text and the width of the SVGstring"20px"
ccolor. It's the text colorstring"#000"
oopacitynumber1

5. Floating Action Button

A material floating action button that represents the primary action of the page. You can pass as child your own icon (it's empty by default). The default position is at the bottom right corner of the screen. It has a ripple effect on click and an optional pulse animation to draw the attention of the user.

Example with icons from fortawesome
npm i @fortawesome/react-fontawesome @fortawesome/free-regular-svg-icons @fortawesome/fontawesome-svg-core
import React from "react";
import { Fab } from "already-styled-components";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPaperPlane, faStar } from "@fortawesome/free-regular-svg-icons";

export default () => (
  <div>
    <Fab aria-label="send email" onClick={e => console.log("Email sent!")}>
      <FontAwesomeIcon icon={faPaperPlane} />
    </Fab>
    <Fab
      bc="#20c7b6"
      w="50px"
      fs="22px"
      t="20px"
      pulse
      aria-label="do more stuff"
      onClick={() => console.log("More stuff done!")}
    >
      <FontAwesomeIcon icon={faStar} />
    </Fab>
  </div>
);
Fab props
nameextra infotypedefault
rippleboolfalse
pulsebooltrue
ccolorstring"#FFF"
bcbackground-colorstring"crimson"
fsfont-sizestring"30px"
wwidthstring"80px"
ttopstringnull
rrightstring"3%"
bbottomstring"3%"
lleftstringnull
ziz-indexnumber1

6. Progress Bar

A YouTube/Stack Overflow like progress bar, positioned at the top of the screen.

Example
import React from "react";
import styled from "styled-components";
import { ProgressBar, Button } from "already-styled-components";

const Section = styled.section`
  min-height: 90vh;
  display: flex;
  align-items: center;
  justify-content: center;
`;

export default class Home extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      loading: true
    };

    this.toggleProgressBar = this.toggleProgressBar.bind(this);
  }

  toggleProgressBar() {
    this.setState({ loading: !this.state.loading });
  }

  render() {
    const { loading } = this.state;
    return (
      <div>
        <ProgressBar bc="rebeccapurple" visible={loading} />
        <Section>
          <Button bc="rebeccapurple" onClick={this.toggleProgressBar}>
            {loading ? "Stop" : "Start"} the progress bar
          </Button>
        </Section>
      </div>
    );
  }
}
ProgressBar props
nameextra infotypedefault
visiblebooltrue
bcbackground-colorstring"orange"
ziz-indexnumber1

Extending styles

Source

You may want to change something in a component that a prop doesn't cover (or just don't want to use props). For example the ProgressBar component is positioned fixed at the top of the screen. You may want to place it at the top of a section.

import React from "react";
import styled from "styled-components";
import { ProgressBar } from "already-styled-components";

const Section = styled.section`
  position: relative; /* important for the container */
  min-height: 40vh;
  background-color: ${({ bc }) => bc};
  display: flex;
  align-items: center;
  justify-content: center;
`;
const CustomProgressBar = styled(ProgressBar)`
  position: absolute;
  top: 100%;
`;
export default () => (
  <div>
    <ProgressBar />
    <Section bc="beige">
      <h2>
        The orange progress bar is at the default position (fixed top of the
        screen)
      </h2>
    </Section>
    <Section bc="azure">
      <h2>
        The black one (CustomProgressBar) is at the bottom of this section.
      </h2>
      <CustomProgressBar bc="black" />
    </Section>
  </div>
);

Note for extending components with styled(Component): If we take the ProgressBar example above, the original ProgressBar has top: 0. If you want to position it at the bottom of the section, you'll have to override the top property with top: 100% in order to work. For example, it won't work with bottom: 0.

3.1.1

5 years ago

3.1.0

5 years ago

3.0.5

5 years ago

3.0.4

5 years ago

3.0.3

5 years ago

3.0.2

5 years ago

3.0.1

5 years ago

3.0.0

5 years ago

2.4.0

5 years ago

2.3.1

5 years ago

2.3.0

5 years ago

2.2.1

5 years ago

2.2.0

5 years ago

2.1.4

5 years ago

2.1.3

5 years ago

2.1.2

5 years ago

2.1.1

5 years ago

2.1.0

5 years ago

2.0.1

5 years ago

2.0.0

5 years ago

1.3.1

6 years ago

1.2.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago

0.2.3

6 years ago

0.2.2

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago

0.0.7

6 years ago

0.0.5

6 years ago

0.0.4

6 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago

1.0.0

6 years ago