├── .gitignore ├── example └── Screenshot.png ├── src ├── index.tsx ├── utils.ts ├── box.tsx ├── types.ts ├── components.tsx ├── props.ts ├── flex.ts └── common.ts ├── .idea ├── .gitignore ├── prettier.xml ├── modules.xml └── chakra-layout-components.iml ├── .github └── workflows │ ├── size.yml │ └── main.yml ├── .all-contributorsrc ├── LICENSE ├── tsconfig.json ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | dist 6 | .idea 7 | -------------------------------------------------------------------------------- /example/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sizzyapp/chakra-layout-components/HEAD/example/Screenshot.png -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './components'; 2 | export * from './types'; 3 | export * from './flex'; 4 | export * from './box'; 5 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/prettier.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export const px = (a: string | number) => 2 | a?.toString()?.includes?.('px') ? a : `${a}px`; 3 | 4 | export const getOppositeDirection = (dir: string) => 5 | dir === 'horizontal' ? 'left' : 'top'; 6 | 7 | export const allChildrenSelector: string = '& > *'; 8 | -------------------------------------------------------------------------------- /.github/workflows/size.yml: -------------------------------------------------------------------------------- 1 | name: size 2 | on: [pull_request] 3 | jobs: 4 | size: 5 | runs-on: ubuntu-latest 6 | env: 7 | CI_JOB_NUMBER: 1 8 | steps: 9 | - uses: actions/checkout@v1 10 | - uses: andresz1/size-limit-action@v1 11 | with: 12 | github_token: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/box.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Box as OriginalBox, BoxProps } from '@chakra-ui/react'; 3 | 4 | interface IProps extends BoxProps { 5 | tr?: boolean | number; 6 | br?: number; 7 | } 8 | 9 | export const Box: React.FC = ({ children, tr, br, ...props }) => ( 10 | 17 | {children} 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /.idea/chakra-layout-components.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push] 3 | jobs: 4 | build: 5 | name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }} 6 | 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | node: ['10.x', '12.x', '14.x'] 11 | os: [ubuntu-latest, windows-latest, macOS-latest] 12 | 13 | steps: 14 | - name: Checkout repo 15 | uses: actions/checkout@v2 16 | 17 | - name: Use Node ${{ matrix.node }} 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node }} 21 | 22 | - name: Install deps and build (with cache) 23 | uses: bahmutov/npm-install@v1 24 | 25 | - name: Lint 26 | run: yarn lint 27 | 28 | 29 | - name: Build 30 | run: yarn build 31 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "praneetrohida", 10 | "name": "Praneet Rohida", 11 | "avatar_url": "https://avatars.githubusercontent.com/u/23721710?v=4", 12 | "profile": "https://praneet.dev", 13 | "contributions": [ 14 | "infra", 15 | "test", 16 | "code" 17 | ] 18 | }, 19 | { 20 | "login": "kitze", 21 | "name": "Kitze", 22 | "avatar_url": "https://avatars.githubusercontent.com/u/1160594?v=4", 23 | "profile": "http://kitze.io", 24 | "contributions": [ 25 | "infra", 26 | "test", 27 | "code" 28 | ] 29 | } 30 | ], 31 | "contributorsPerLine": 7, 32 | "projectName": "chakra-layout-components", 33 | "projectOwner": "sizzyapp", 34 | "repoType": "github", 35 | "repoHost": "https://github.com", 36 | "skipCi": true 37 | } 38 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { CSSProperties, Ref } from 'react'; 2 | import { CSSObject } from '@emotion/styled'; 3 | import { BoxProps } from '@chakra-ui/react'; 4 | 5 | export interface CommonProps extends BoxProps { 6 | wrap?: boolean; 7 | spaceBetween?: boolean; 8 | spaceAround?: boolean; 9 | justifyEnd?: boolean; 10 | justifyStart?: boolean; 11 | flex?: CSSObject['flex'] & BoxProps['flex']; 12 | spaceFirst?: number; 13 | spacing?: number | string; 14 | spaceBottom?: boolean; 15 | alignStart?: boolean; 16 | alignItemsStart?: boolean; 17 | center?: boolean; 18 | centerV?: boolean; 19 | centerH?: boolean; 20 | noShrink?: boolean; 21 | styles?: CSSProperties; 22 | invert?: boolean; 23 | reverse?: boolean; 24 | fullW?: boolean; 25 | fullH?: boolean; 26 | debug?: boolean; 27 | ref?: Ref; 28 | } 29 | 30 | export enum margin { 31 | horizontal = 'marginRight', 32 | vertical = 'marginBottom', 33 | left = 'marginLeft', 34 | top = 'marginTop', 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Praneet Rohida 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/components.tsx: -------------------------------------------------------------------------------- 1 | import { Box as OriginalBox } from '@chakra-ui/react'; 2 | import styled from '@emotion/styled'; 3 | import { fixedHeight, fixedWidth } from 'styled-mixins'; 4 | import { motion } from 'framer-motion'; 5 | import { CommonProps } from './types'; 6 | import { getHorizontalProps, getVerticalProps } from './props'; 7 | import React, { forwardRef } from 'react'; 8 | 9 | const spaceUnit = 1; 10 | 11 | export const Space = styled.div<{ size: number }>(({ size = 1 }) => ({ 12 | ...fixedHeight(spaceUnit * size), 13 | ...fixedWidth(spaceUnit * size), 14 | })); 15 | 16 | const HorizontalSC = styled(OriginalBox)(getHorizontalProps); 17 | 18 | const VerticalSC = styled(OriginalBox)(getVerticalProps); 19 | 20 | export const Horizontal: React.FC = forwardRef< 21 | HTMLDivElement, 22 | CommonProps 23 | >((props, ref) => ); 24 | 25 | export const Vertical: React.FC = forwardRef< 26 | HTMLDivElement, 27 | CommonProps 28 | >((props, ref) => ); 29 | 30 | export const MHorizontal = motion(Horizontal); 31 | 32 | export const MVertical = motion(Vertical); 33 | -------------------------------------------------------------------------------- /src/props.ts: -------------------------------------------------------------------------------- 1 | import { CommonProps } from './types'; 2 | import flex from './flex'; 3 | import { common } from './common'; 4 | import { CSSObject } from '@emotion/styled'; 5 | 6 | const horizontalProps = (props: CommonProps): CSSObject => { 7 | const { center, centerV, reverse, centerH } = props; 8 | return { 9 | ...flex.horizontal, 10 | ...(reverse && flex.horizontalReverse), 11 | ...(center && flex.centerHorizontal), 12 | ...(centerV && flex.centerHorizontalV), 13 | ...(centerH && flex.centerHorizontalH), 14 | ...common('horizontal', reverse)(props), 15 | }; 16 | }; 17 | 18 | const verticalProps = (props: CommonProps): CSSObject => { 19 | const { center, reverse, centerV, centerH } = props; 20 | return { 21 | ...flex.vertical, 22 | ...(reverse && flex.verticalReverse), 23 | ...(center && flex.centerVertical), 24 | ...(centerV && flex.centerVerticalV), 25 | ...(centerH && flex.centerVerticalH), 26 | ...common('vertical', reverse)(props), 27 | }; 28 | }; 29 | 30 | export const getHorizontalProps = ({ 31 | invert = false, 32 | ...rest 33 | }: CommonProps): CSSObject => { 34 | return invert === false ? horizontalProps(rest) : verticalProps(rest); 35 | }; 36 | 37 | export const getVerticalProps = ({ 38 | invert = false, 39 | ...rest 40 | }: CommonProps): CSSObject => { 41 | return invert === false ? verticalProps(rest) : horizontalProps(rest); 42 | }; 43 | -------------------------------------------------------------------------------- /src/flex.ts: -------------------------------------------------------------------------------- 1 | import { CSSObject } from '@emotion/styled'; 2 | export const flex: Record = { 3 | horizontal: { 4 | display: 'flex', 5 | flexDirection: 'row', 6 | }, 7 | vertical: { 8 | display: 'flex', 9 | flexDirection: 'column', 10 | }, 11 | flexWrap: { 12 | display: 'flex', 13 | flexWrap: 'wrap', 14 | }, 15 | centerHorizontal: { 16 | justifyContent: 'center', 17 | alignItems: 'center', 18 | }, 19 | wrap: { 20 | flexWrap: 'wrap', 21 | }, 22 | noWrap: { 23 | flexWrap: 'nowrap', 24 | }, 25 | centerHorizontalH: { 26 | justifyContent: 'center', 27 | }, 28 | centerHorizontalV: { 29 | alignItems: 'center', 30 | }, 31 | centerVertical: { 32 | alignItems: 'center', 33 | justifyContent: 'center', 34 | }, 35 | centerVerticalH: { 36 | alignItems: 'center', 37 | }, 38 | centerVerticalV: { 39 | justifyContent: 'center', 40 | }, 41 | spaceAround: { 42 | justifyContent: 'space-around', 43 | }, 44 | spaceBetween: { 45 | justifyContent: 'space-between', 46 | }, 47 | justifyEnd: { 48 | justifyContent: 'flex-end', 49 | }, 50 | justifyStart: { 51 | justifyContent: 'flex-start', 52 | }, 53 | alignStart: { 54 | alignContent: 'flex-start', 55 | }, 56 | stretchSelf: { 57 | alignSelf: 'stretch', 58 | }, 59 | alignItemsStart: { 60 | alignItems: 'flex-start', 61 | }, 62 | selfEnd: { 63 | alignSelf: 'flex-end', 64 | }, 65 | }; 66 | 67 | export default flex; 68 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | // output .d.ts declaration files for consumers 9 | "declaration": true, 10 | // output .js.map sourcemap files for consumers 11 | "sourceMap": true, 12 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 13 | "rootDir": "./src", 14 | // stricter type-checking for stronger correctness. Recommended by TS 15 | "strict": true, 16 | // linter checks for common issues 17 | "noImplicitReturns": true, 18 | "noFallthroughCasesInSwitch": true, 19 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | // use Node's module resolution algorithm, instead of the legacy TS one 23 | "moduleResolution": "node", 24 | // transpile JSX to React.createElement 25 | "jsx": "react", 26 | // interop between ESM and CJS modules. Recommended by TS 27 | "esModuleInterop": true, 28 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 29 | "skipLibCheck": true, 30 | // error out if import and file system have a casing mismatch. Recommended by TS 31 | "forceConsistentCasingInFileNames": true, 32 | // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc` 33 | "noEmit": true, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/common.ts: -------------------------------------------------------------------------------- 1 | import { CommonProps, margin } from './types'; 2 | import { allChildrenSelector, getOppositeDirection, px } from './utils'; 3 | import flex from './flex'; 4 | import { CSSObject } from '@emotion/styled'; 5 | 6 | export const common = ( 7 | direction: 'horizontal' | 'vertical' | 'left' | 'top', 8 | reverse?: boolean 9 | ) => (p: CommonProps): CSSObject => { 10 | direction = reverse === true ? getOppositeDirection(direction) : direction; 11 | return { 12 | ...(!!p.spaceBetween && flex.spaceBetween), 13 | ...(!!p.wrap && flex.wrap), 14 | ...(!!p.spaceAround && flex.spaceAround), 15 | ...(!!p.justifyEnd && flex.justifyEnd), 16 | ...(!!p.justifyStart && flex.justifyStart), 17 | ...(!!p.alignStart && flex.alignStart), 18 | ...(!!p.alignItemsStart && flex.alignItemsStart), 19 | ...(!!p.flex && { flex: p.flex }), 20 | ...(!!p.debug && { border: '1px solid purple' }), 21 | 22 | ...(!!p.spaceFirst && { 23 | '&:first-child': { 24 | [margin[direction]]: `${px(p.spaceFirst)} !important`, 25 | }, 26 | }), 27 | ...(!!p.spacing 28 | ? { 29 | [allChildrenSelector]: { 30 | [margin[direction]]: `${px(p.spacing)} !important`, 31 | ...(p.spaceBottom 32 | ? { 33 | marginBottom: `${px(p.spacing)} !important`, 34 | } 35 | : {}), 36 | }, 37 | '& > :last-child': { 38 | [margin[direction]]: `0 !important`, 39 | ...(p.spaceBottom ? { marginBottom: `0 !important` } : {}), 40 | }, 41 | } 42 | : {}), 43 | 44 | ...(!!p.noShrink 45 | ? { 46 | flexShrink: 0, 47 | } 48 | : {}), 49 | ...(!!p.fullW && { width: '100%' }), 50 | ...(!!p.fullH && { height: '100%' }), 51 | ...p.styles, 52 | }; 53 | }; 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.1", 3 | "license": "MIT", 4 | "main": "dist/index.js", 5 | "typings": "dist/index.d.ts", 6 | "files": [ 7 | "dist", 8 | "src" 9 | ], 10 | "repository": "https://github.com/sizzyapp/chakra-layout-components", 11 | "engines": { 12 | "node": ">=10" 13 | }, 14 | "scripts": { 15 | "start": "tsdx watch", 16 | "build": "tsdx build", 17 | "test": "tsdx test --passWithNoTests", 18 | "lint": "tsdx lint", 19 | "prepare": "tsdx build", 20 | "size": "size-limit", 21 | "analyze": "size-limit --why" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "tsdx lint" 26 | } 27 | }, 28 | "prettier": { 29 | "printWidth": 80, 30 | "semi": true, 31 | "singleQuote": true, 32 | "trailingComma": "es5" 33 | }, 34 | "name": "chakra-layout-components", 35 | "author": "Kitze", 36 | "module": "dist/chakra-layout-components.esm.js", 37 | "size-limit": [ 38 | { 39 | "path": "dist/chakra-layout-components.cjs.production.min.js", 40 | "limit": "10 KB" 41 | }, 42 | { 43 | "path": "dist/chakra-layout-components.esm.js", 44 | "limit": "10 KB" 45 | } 46 | ], 47 | "devDependencies": { 48 | "@chakra-ui/react": "^1.3.4", 49 | "@emotion/styled": "^11.1.5", 50 | "@size-limit/preset-small-lib": "^4.10.1", 51 | "@types/react": "^17.0.3", 52 | "@types/react-dom": "^17.0.2", 53 | "framer-motion": "^4.0.0", 54 | "husky": "^5.1.3", 55 | "prettier": "^2.2.1", 56 | "react": "^17.0.1", 57 | "react-dom": "^17.0.1", 58 | "size-limit": "^4.10.1", 59 | "styled-mixins": "^0.1.10", 60 | "tsdx": "^0.14.1", 61 | "tslib": "^2.1.0", 62 | "typescript": "^4.2.3" 63 | }, 64 | "peerDependencies": { 65 | "@chakra-ui/react": "^1.3.4", 66 | "@emotion/styled": "^11.1.5", 67 | "framer-motion": "^4.0.0", 68 | "react": ">=16", 69 | "styled-mixins": "^0.1.10" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Welcome to chakra-layout-components 👋

2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors-) 4 | 5 |

6 | 7 | Version 8 | 9 | 10 | Documentation 11 | 12 | 13 | Twitter: sizzyapp 14 | 15 |

16 | 17 | > chakra-ui Layout Helper Components 18 | 19 | This project simplify uses `horizontal`, `grid`,`vertical` and `space` for [`Chakra UI`](https://chakra-ui.com/). 20 | 21 | ## Props 22 | 23 | These props are applicable to both Horizontal and Vertical components. 24 | 25 | | Prop | Type | 26 | | --------------- | :-----------: | 27 | | wrap | boolean | 28 | | spaceBetween | boolean | 29 | | spaceAround | boolean | 30 | | justifyEnd | boolean | 31 | | justifyStart | boolean | 32 | | flex | number | 33 | | spaceFirst | number | 34 | | spacing | number | 35 | | spaceBottom | boolean | 36 | | alignStart | boolean | 37 | | alignItemsStart | boolean | 38 | | center | boolean | 39 | | centerV | boolean | 40 | | centerH | boolean | 41 | | noShrink | boolean | 42 | | styles | CSSProperties | 43 | | invert | boolean | 44 | | reverse | boolean | 45 | | fullW | boolean | 46 | | fullH | boolean | 47 | | debug | boolean | 48 | 49 | In addition to this, the components also support Chakra UI's [style props](https://chakra-ui.com/docs/features/style-props). 50 | 51 | ## Example 52 | 53 | 54 | 55 | [![Edit Chakra Layout Components Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/chakra-layout-components-demo-vrd18?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.js&theme=dark) 56 | 57 | ```js 58 | const App = () => { 59 | return ( 60 | 61 | 62 | We 63 | are 64 | Vertical 65 | 66 | 67 | 68 | We 69 | are 70 | Horizontal 71 | 72 | 73 | 74 | 75 | 76 | I am centered vertically 77 | 78 | 79 | 80 | I am centered Horizontally 81 | 82 | 83 | 84 | I am just centered 85 | 86 | 87 | 88 | I will take full width 89 | 90 | 91 | ); 92 | }; 93 | ``` 94 | 95 | Produces: 96 | 97 | ![ScreenShot](./example/Screenshot.png) 98 | 99 | ## Install 100 | 101 | ```sh 102 | yarn install && yarn watch 103 | ``` 104 | 105 | ## Usage 106 | 107 | ```sh 108 | cd examples && yarn start 109 | ``` 110 | 111 | See it in browser at http://localhost:1234 112 | 113 | ## Run tests 114 | 115 | ```sh 116 | yarn run test 117 | ``` 118 | 119 | ## 🤝 Contributing 120 | 121 | Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/kitze/layout-styled-components/issues). 122 | 123 | ## Show your support 124 | 125 | Give a ⭐️ if this project helped you! 126 | 127 | ## Contributors ✨ 128 | 129 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 |

Praneet Rohida

🚇 ⚠️ 💻

Kitze

🚇 ⚠️ 💻
140 | 141 | 142 | 143 | 144 | 145 | 146 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! --------------------------------------------------------------------------------