Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
feat(pseudobox): created pseudobox component
Browse files Browse the repository at this point in the history
  • Loading branch information
codebender828 committed Oct 20, 2019
1 parent 8de50d4 commit 0660fbd
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 51 deletions.
49 changes: 22 additions & 27 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,39 @@
<br>
<h1>{{ state.count }}</h1>
<br>
<Box
:w="['auto', '50%']"
px="5"
py="5"
shadow="lg"
my="5"
mb="5"
rounded="sm"
background-color="blue.200"
border-left="4px"
color="blue.700"
font-family="body"
>
This is box component
</Box>
<Box bg="yellow.200" border-left="4px" font-family="body" rounded="md" shadow="md" p="3" color="yellow.800">
<Box bg="yellow.200" border-left="4px" font-family="body" rounded="md" mb="5" shadow="md" p="3" color="yellow.800">
<Box font-family="heading" font-size="3xl" mb="2">Random Title</Box>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Debitis incidunt dolor impedit facilis doloribus accusamus aspernatur autem amet voluptate aliquid asperiores, repellendus tempora reiciendis. Aliquid sunt quasi rem magnam, voluptate cumque libero necessitatibus ut minima numquam fugiat? Blanditiis unde earum sint labore quidem quod adipisci quae incidunt dolorum rerum, laboriosam ipsa consectetur, laborum dolore porro quaerat debitis iusto qui pariatur dicta! Quo ab exercitationem possimus, facere vero perferendis quam illum expedita dolores qui tenetur voluptatem sequi eos reprehenderit ut excepturi, ratione nostrum dolor officia labore quis? Dolor, beatae! Eaque autem vero libero. Veritatis placeat blanditiis error, deleniti autem ab quaerat?
</Box>

<Box bg="red.200" border-left="4px" my="5" rounded="md" shadow="md" p="3" color="red.800">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Debitis incidunt
</Box>
<Anchor bg="indigo.200" p="3" bb="4px" rounded="sm">
Basic Link
</Anchor>
<PseudoBox
bg="teal.300"
color="teal.800"
p="3"
rounded="md"
bl="4px"
font-family="body"
transition="all 0.2s ease-in-out"
:_hover="{
bg: 'red.200',
color: 'red.700'
}"
:_focus="{
bg: 'indigo.200',
color: 'indigo.700'
}"
>
Pseudobox here
</PseudoBox>
</theme-provider>
</template>

<script>
import ThemeProvider from './components/ThemeProvider'
import Button from './components/Button'
import { Box } from './lib/core/'
import { Box, PseudoBox } from './lib/core/'
import theme from './lib/theme'
import { useIncrement } from './use-increment'
const Anchor = Box.withComponent('a')
export default {
setup () {
const { state, increment } = useIncrement()
Expand All @@ -58,7 +53,7 @@ export default {
Button,
ThemeProvider,
Box,
Anchor
PseudoBox
}
}
</script>
Expand Down
20 changes: 3 additions & 17 deletions src/components/Box/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from 'vue-styled-components'
import pickBy from 'lodash-es/pickBy'
import { background, border, color, borderRadius, flexbox, grid, layout, position, shadow, space, typography, compose } from 'styled-system'
import { baseProps, propsConfig } from '../../lib/config/props'
import { cleanProps } from '../../lib/utils/'

const baseEllipsis = {
overflow: 'hidden',
Expand Down Expand Up @@ -35,7 +35,6 @@ const clamp = props => {
}
}

// Compose @style-system style functions
const system = compose(
layout,
color,
Expand All @@ -54,21 +53,8 @@ const system = compose(
)

/**
* @description Clears out all undefined props that are undefined from the props object
* @param {Object} props
* @returns {Object} Sanitized props object with defined values.
*/
function cleanProps (props) {
const pure = pickBy(props, (prop) => !!prop)
return pure
}

/**
* Note: All styled components in vue-styled-components forward all their props.
* If the prop is not registered in the component, it is then it is bound as a native
* HTML attribute
* @see https://github.com/styled-components/vue-styled-components#passed-props
* TODO: Will need to revisit this for Image component.
* The Box component is the base reusable component which is the building block for all other Kiwi UI components.
* The Box component by default renders a `<div/>` element.
*/
const Box = styled('div', {
...baseProps
Expand Down
19 changes: 19 additions & 0 deletions src/components/PseudoBox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import styled from 'vue-styled-components'
import css from '@styled-system/css'
import { Box } from '../../lib/core/'
import { pseudoProps } from '../../lib/config/props'
import { parsePseudoStyles } from './utils'

/**
* The PseudoBox component is a wrapper for the Box component that allows us to provide pseudo styles for `_focus`, `_hover`, `_active`, etc. and `aria-*` attributes
*/
const PseudoBox = styled(Box, {
...pseudoProps
})`
${(props) => {
const styles = parsePseudoStyles(props)
return css(styles)
}
}`

export default PseudoBox
Empty file removed src/components/PseudoBox/props.js
Empty file.
50 changes: 50 additions & 0 deletions src/components/PseudoBox/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import map from 'lodash-es/map'
import { cleanProps, filterPseudo, tx } from '../../lib/utils/'

/**
* PseudoBox pseudo selectors
*/
export const selectors = {
_hover: '&:hover',
_active: '&:active, &[data-active=true]',
_focus: '&:focus',
_visited: '&:visited',
_even: '&:nth-of-type(even)',
_odd: '&:nth-of-type(odd)',
_disabled: '&:disabled, &:disabled:focus, &:disabled:hover, &[aria-disabled=true], &[aria-disabled=true]:focus, &[aria-disabled=true]:hover',
_checked: '&[aria-checked=true]',
_mixed: '&[aria-checked=mixed]',
_selected: '&[aria-selected=true]',
_invalid: '&[aria-invalid=true]',
_pressed: '&[aria-pressed=true]',
_readOnly: '&[aria-readonly=true], &[readonly]',
_first: '&:first-of-type',
_last: '&:last-of-type',
_expanded: '&[aria-expanded=true]',
_grabbed: '&[aria-grabbed=true]',
_notFirst: '&:not(:first-of-type)',
_notLast: '&:not(:last-of-type)',
_groupHover: '[role=group]:hover &',
_before: '&:before',
_after: '&:after',
_focusWithin: '&:focus-within',
_placeholder: '&::placeholder'
}

/**
* Filter undefined props and parse pseudo style props to generate css styles object
* @param {Object} props - Props
* @returns {Object} Parsed pseudo styles object
*/
export function parsePseudoStyles (props) {
const styles = {}
const clean = cleanProps(props)
const pseudoProps = filterPseudo(clean)
const result = map(pseudoProps, (value, prop) => ({ prop, value }))
result.forEach((pair) => {
if (selectors[pair.prop]) {
styles[selectors[pair.prop]] = tx(pair.value)
}
})
return styles
}
1 change: 1 addition & 0 deletions src/lib/config/props/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as baseProps } from './props'
export { default as propsConfig } from './props.config'
export { default as pseudoProps } from './pseudo'
7 changes: 7 additions & 0 deletions src/lib/config/props/pseudo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const pseudoProps = {
_hover: [Object, String, Array],
_active: [Object, String, Array],
_focus: [Object, String, Array]
}

export default pseudoProps
1 change: 1 addition & 0 deletions src/lib/core/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as Box } from '../../components/Box'
export { default as PseudoBox } from '../../components/PseudoBox'
11 changes: 4 additions & 7 deletions src/lib/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import Logger from './logger'
import { provideTheme } from './provide-theme'

export {
Logger,
provideTheme
}
export { default as Logger } from './logger'
export { provideTheme } from './provide-theme'
export { transformAlias as tx } from './transform'
export { pickProperty as cleanProps, filterPseudo } from './object'
19 changes: 19 additions & 0 deletions src/lib/utils/object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import pickBy from 'lodash-es/pickBy'
import startsWith from 'lodash-es/startsWith'

/**
* @description Clears out all undefined properties from an object.
* @param {Object} props
* @returns {Object} Sanitized object with defined values.
*/
export function pickProperty (props) {
const pure = pickBy(props, (prop) => !!prop)
return pure
}

export function filterPseudo (props) {
const pseudos = pickBy(props, (_value, key) => {
return startsWith(key, '_')
})
return pseudos
}
46 changes: 46 additions & 0 deletions src/lib/utils/transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { propsConfig as config } from '../config/props'

/**
* @description Transforms the custom prop alias to a format that styled-system CSS supports
* @param {*} prop - Prop
* @param {*} propValue - Prop value
* @returns {Object} Style object with transformed alias.
* @see chakra-ui PseudoBox tx_ method.
*/
function normalizeAlias (prop, propValue) {
const configKeys = Object.keys(config)
let result = {}

if (configKeys.includes(prop)) {
const { properties, property } = config[prop]
if (properties) {
properties.forEach(_cssProp => (result[_cssProp] = propValue))
}
if (property) {
result[property] = propValue
}
if (config[prop] === true) {
result[prop] = propValue
}
} else {
result[prop] = propValue
}
return result
}

/**
* @description Transforms the alias prop object to style-system supported syntax
* @param {Object} props - Props object
* @returns {Object} Normalized Props object
*/
export const transformAlias = props => {
let result = {}
for (let prop in props) {
if (typeof props[prop] === 'object') {
result = { ...result, [prop]: transformAlias(props[prop]) }
} else {
result = { ...result, ...normalizeAlias(prop, props[prop]) }
}
}
return result
}

0 comments on commit 0660fbd

Please # to comment.