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

Commit 0660fbd

Browse files
committed
feat(pseudobox): created pseudobox component
1 parent 8de50d4 commit 0660fbd

File tree

11 files changed

+172
-51
lines changed

11 files changed

+172
-51
lines changed

Diff for: src/App.vue

+22-27
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,39 @@
55
<br>
66
<h1>{{ state.count }}</h1>
77
<br>
8-
<Box
9-
:w="['auto', '50%']"
10-
px="5"
11-
py="5"
12-
shadow="lg"
13-
my="5"
14-
mb="5"
15-
rounded="sm"
16-
background-color="blue.200"
17-
border-left="4px"
18-
color="blue.700"
19-
font-family="body"
20-
>
21-
This is box component
22-
</Box>
23-
<Box bg="yellow.200" border-left="4px" font-family="body" rounded="md" shadow="md" p="3" color="yellow.800">
8+
<Box bg="yellow.200" border-left="4px" font-family="body" rounded="md" mb="5" shadow="md" p="3" color="yellow.800">
249
<Box font-family="heading" font-size="3xl" mb="2">Random Title</Box>
2510
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?
2611
</Box>
27-
28-
<Box bg="red.200" border-left="4px" my="5" rounded="md" shadow="md" p="3" color="red.800">
29-
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Debitis incidunt
30-
</Box>
31-
<Anchor bg="indigo.200" p="3" bb="4px" rounded="sm">
32-
Basic Link
33-
</Anchor>
12+
<PseudoBox
13+
bg="teal.300"
14+
color="teal.800"
15+
p="3"
16+
rounded="md"
17+
bl="4px"
18+
font-family="body"
19+
transition="all 0.2s ease-in-out"
20+
:_hover="{
21+
bg: 'red.200',
22+
color: 'red.700'
23+
}"
24+
:_focus="{
25+
bg: 'indigo.200',
26+
color: 'indigo.700'
27+
}"
28+
>
29+
Pseudobox here
30+
</PseudoBox>
3431
</theme-provider>
3532
</template>
3633

3734
<script>
3835
import ThemeProvider from './components/ThemeProvider'
3936
import Button from './components/Button'
40-
import { Box } from './lib/core/'
37+
import { Box, PseudoBox } from './lib/core/'
4138
import theme from './lib/theme'
4239
import { useIncrement } from './use-increment'
4340
44-
const Anchor = Box.withComponent('a')
45-
4641
export default {
4742
setup () {
4843
const { state, increment } = useIncrement()
@@ -58,7 +53,7 @@ export default {
5853
Button,
5954
ThemeProvider,
6055
Box,
61-
Anchor
56+
PseudoBox
6257
}
6358
}
6459
</script>

Diff for: src/components/Box/index.js

+3-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import styled from 'vue-styled-components'
2-
import pickBy from 'lodash-es/pickBy'
32
import { background, border, color, borderRadius, flexbox, grid, layout, position, shadow, space, typography, compose } from 'styled-system'
43
import { baseProps, propsConfig } from '../../lib/config/props'
4+
import { cleanProps } from '../../lib/utils/'
55

66
const baseEllipsis = {
77
overflow: 'hidden',
@@ -35,7 +35,6 @@ const clamp = props => {
3535
}
3636
}
3737

38-
// Compose @style-system style functions
3938
const system = compose(
4039
layout,
4140
color,
@@ -54,21 +53,8 @@ const system = compose(
5453
)
5554

5655
/**
57-
* @description Clears out all undefined props that are undefined from the props object
58-
* @param {Object} props
59-
* @returns {Object} Sanitized props object with defined values.
60-
*/
61-
function cleanProps (props) {
62-
const pure = pickBy(props, (prop) => !!prop)
63-
return pure
64-
}
65-
66-
/**
67-
* Note: All styled components in vue-styled-components forward all their props.
68-
* If the prop is not registered in the component, it is then it is bound as a native
69-
* HTML attribute
70-
* @see https://github.com/styled-components/vue-styled-components#passed-props
71-
* TODO: Will need to revisit this for Image component.
56+
* The Box component is the base reusable component which is the building block for all other Kiwi UI components.
57+
* The Box component by default renders a `<div/>` element.
7258
*/
7359
const Box = styled('div', {
7460
...baseProps

Diff for: src/components/PseudoBox/index.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import styled from 'vue-styled-components'
2+
import css from '@styled-system/css'
3+
import { Box } from '../../lib/core/'
4+
import { pseudoProps } from '../../lib/config/props'
5+
import { parsePseudoStyles } from './utils'
6+
7+
/**
8+
* 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
9+
*/
10+
const PseudoBox = styled(Box, {
11+
...pseudoProps
12+
})`
13+
${(props) => {
14+
const styles = parsePseudoStyles(props)
15+
return css(styles)
16+
}
17+
}`
18+
19+
export default PseudoBox

Diff for: src/components/PseudoBox/props.js

Whitespace-only changes.

Diff for: src/components/PseudoBox/utils.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import map from 'lodash-es/map'
2+
import { cleanProps, filterPseudo, tx } from '../../lib/utils/'
3+
4+
/**
5+
* PseudoBox pseudo selectors
6+
*/
7+
export const selectors = {
8+
_hover: '&:hover',
9+
_active: '&:active, &[data-active=true]',
10+
_focus: '&:focus',
11+
_visited: '&:visited',
12+
_even: '&:nth-of-type(even)',
13+
_odd: '&:nth-of-type(odd)',
14+
_disabled: '&:disabled, &:disabled:focus, &:disabled:hover, &[aria-disabled=true], &[aria-disabled=true]:focus, &[aria-disabled=true]:hover',
15+
_checked: '&[aria-checked=true]',
16+
_mixed: '&[aria-checked=mixed]',
17+
_selected: '&[aria-selected=true]',
18+
_invalid: '&[aria-invalid=true]',
19+
_pressed: '&[aria-pressed=true]',
20+
_readOnly: '&[aria-readonly=true], &[readonly]',
21+
_first: '&:first-of-type',
22+
_last: '&:last-of-type',
23+
_expanded: '&[aria-expanded=true]',
24+
_grabbed: '&[aria-grabbed=true]',
25+
_notFirst: '&:not(:first-of-type)',
26+
_notLast: '&:not(:last-of-type)',
27+
_groupHover: '[role=group]:hover &',
28+
_before: '&:before',
29+
_after: '&:after',
30+
_focusWithin: '&:focus-within',
31+
_placeholder: '&::placeholder'
32+
}
33+
34+
/**
35+
* Filter undefined props and parse pseudo style props to generate css styles object
36+
* @param {Object} props - Props
37+
* @returns {Object} Parsed pseudo styles object
38+
*/
39+
export function parsePseudoStyles (props) {
40+
const styles = {}
41+
const clean = cleanProps(props)
42+
const pseudoProps = filterPseudo(clean)
43+
const result = map(pseudoProps, (value, prop) => ({ prop, value }))
44+
result.forEach((pair) => {
45+
if (selectors[pair.prop]) {
46+
styles[selectors[pair.prop]] = tx(pair.value)
47+
}
48+
})
49+
return styles
50+
}

Diff for: src/lib/config/props/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { default as baseProps } from './props'
22
export { default as propsConfig } from './props.config'
3+
export { default as pseudoProps } from './pseudo'

Diff for: src/lib/config/props/pseudo.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const pseudoProps = {
2+
_hover: [Object, String, Array],
3+
_active: [Object, String, Array],
4+
_focus: [Object, String, Array]
5+
}
6+
7+
export default pseudoProps

Diff for: src/lib/core/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { default as Box } from '../../components/Box'
2+
export { default as PseudoBox } from '../../components/PseudoBox'

Diff for: src/lib/utils/index.js

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import Logger from './logger'
2-
import { provideTheme } from './provide-theme'
3-
4-
export {
5-
Logger,
6-
provideTheme
7-
}
1+
export { default as Logger } from './logger'
2+
export { provideTheme } from './provide-theme'
3+
export { transformAlias as tx } from './transform'
4+
export { pickProperty as cleanProps, filterPseudo } from './object'

Diff for: src/lib/utils/object.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import pickBy from 'lodash-es/pickBy'
2+
import startsWith from 'lodash-es/startsWith'
3+
4+
/**
5+
* @description Clears out all undefined properties from an object.
6+
* @param {Object} props
7+
* @returns {Object} Sanitized object with defined values.
8+
*/
9+
export function pickProperty (props) {
10+
const pure = pickBy(props, (prop) => !!prop)
11+
return pure
12+
}
13+
14+
export function filterPseudo (props) {
15+
const pseudos = pickBy(props, (_value, key) => {
16+
return startsWith(key, '_')
17+
})
18+
return pseudos
19+
}

Diff for: src/lib/utils/transform.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { propsConfig as config } from '../config/props'
2+
3+
/**
4+
* @description Transforms the custom prop alias to a format that styled-system CSS supports
5+
* @param {*} prop - Prop
6+
* @param {*} propValue - Prop value
7+
* @returns {Object} Style object with transformed alias.
8+
* @see chakra-ui PseudoBox tx_ method.
9+
*/
10+
function normalizeAlias (prop, propValue) {
11+
const configKeys = Object.keys(config)
12+
let result = {}
13+
14+
if (configKeys.includes(prop)) {
15+
const { properties, property } = config[prop]
16+
if (properties) {
17+
properties.forEach(_cssProp => (result[_cssProp] = propValue))
18+
}
19+
if (property) {
20+
result[property] = propValue
21+
}
22+
if (config[prop] === true) {
23+
result[prop] = propValue
24+
}
25+
} else {
26+
result[prop] = propValue
27+
}
28+
return result
29+
}
30+
31+
/**
32+
* @description Transforms the alias prop object to style-system supported syntax
33+
* @param {Object} props - Props object
34+
* @returns {Object} Normalized Props object
35+
*/
36+
export const transformAlias = props => {
37+
let result = {}
38+
for (let prop in props) {
39+
if (typeof props[prop] === 'object') {
40+
result = { ...result, [prop]: transformAlias(props[prop]) }
41+
} else {
42+
result = { ...result, ...normalizeAlias(prop, props[prop]) }
43+
}
44+
}
45+
return result
46+
}

0 commit comments

Comments
 (0)