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

Commit aafe5bf

Browse files
committed
feat(icon): implemented internal icons
refactor(themeprovider): made provider renderless docs(button): made button stories docs(icon): added icon stories
1 parent e760bd5 commit aafe5bf

File tree

14 files changed

+239
-73
lines changed

14 files changed

+239
-73
lines changed

src/App.vue

+10-18
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,33 @@
11
<template>
22
<theme-provider :theme="theme">
3-
<Box
4-
w="100vw"
5-
h="100vh"
6-
m="0"
7-
d="flex"
8-
justify-content="center"
9-
align-items="center"
10-
bg="gray.50"
3+
<Icon
4+
name="star"
5+
color="yellow.500"
6+
size="5"
117
>
12-
<Button mx="3" variant-color="blue">Solid</Button>
13-
<Button variant="outline" mx="3" variant-color="blue">Outlined</Button>
14-
<Button variant="ghost" mx="3" variant-color="blue">Ghost</Button>
15-
<Button variant="flat" mx="3" variant-color="blue">Flat</Button>
16-
<Button variant="link" mx="3" variant-color="blue">Link</Button>
17-
</Box>
8+
9+
</Icon>
1810
</theme-provider>
1911
</template>
2012

2113
<script>
2214
import ThemeProvider from './components/ThemeProvider'
23-
import { Box, Button } from './lib/core/'
15+
import { Icon } from './lib/core/'
16+
import Badge from './components/Badge'
2417
import theme from './lib/theme'
2518
2619
export default {
2720
data () {
2821
return {
2922
theme,
3023
element: true,
31-
Box
24+
Badge
3225
}
3326
},
3427
name: 'App',
3528
components: {
3629
ThemeProvider,
37-
Box,
38-
Button
30+
Icon
3931
},
4032
methods: {
4133
toggle () {

src/components/Badge/index.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="js">
22
export default {
33
name: 'Badge',
4-
render: h => h('div')
4+
render: h => h('div', 'Badge')
55
}
66
</script>

src/components/Button/button.styles.js

+1-43
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,6 @@ const baseStyles = {
1313
outline: 'none'
1414
}
1515

16-
/**
17-
* @description Determine whether button should ripple
18-
* @param {Object} props - Props object
19-
* @returns {Object} Ripple styles object
20-
*/
21-
const ripple = (props) => {
22-
console.log(props)
23-
if (props.ripple) {
24-
return {
25-
position: 'relative',
26-
overflow: 'hidden',
27-
transform: 'translate3d(0, 0, 0)',
28-
_after: {
29-
content: '',
30-
display: 'block',
31-
position: 'absolute',
32-
width: '100%',
33-
height: '100%',
34-
top: '0',
35-
left: '0',
36-
pointerEvents: 'none',
37-
backgroundImage: 'radial-gradient(circle, rgb(255, 255, 255) 10%, transparent 10.01%)',
38-
backgroundRepeat: 'no-repeat',
39-
backgroundPosition: '50%',
40-
transform: 'scale(10, 10)',
41-
opacity: '0',
42-
transition: 'transform .5s, opacity 1s'
43-
},
44-
_active: {
45-
_after: {
46-
transform: 'scale(0, 0)',
47-
opacity: '.2',
48-
transition: '0s'
49-
}
50-
}
51-
}
52-
} else {
53-
return {}
54-
}
55-
}
56-
5716
/**
5817
* Size values
5918
*/
@@ -264,8 +223,7 @@ const createButtonStyles = (props) => {
264223
...baseStyles,
265224
...focusStyles,
266225
...sizeProps(props),
267-
...getVariantStyles(props),
268-
...ripple(props)
226+
...getVariantStyles(props)
269227
}
270228
}
271229

src/components/Button/button.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { shallowMount } from '@vue/test-utils'
2-
import Button from './index.vue'
2+
import Button from '../../lib/core/'
33
import Theme from '../../../kiwi.config'
44

55
describe('===== Button Component =====', () => {

src/components/Button/index.d.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ import * as Vue from 'vue';
22

33
declare const Button: Vue.Component<{
44
as?: String,
5-
color?: String,
6-
variant?: String,
7-
active?: Boolean,
5+
type?: String,
6+
cast?: String,
7+
variant?: String
8+
variantColor?: [String, Array<String>],
89
disabled?: Boolean,
910
isLoading?: Boolean,
11+
isActive?: Boolean,
1012
size?: String,
1113
loadingText?: String,
12-
px?: String,
13-
py?: String,
1414
iconSpacing?: String,
1515
rounded?: Boolean,
16-
ripple?: Boolean,
17-
shadow?: Boolean
1816
}>;
1917
export default Button;

src/components/Button/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default {
1414
inject: ['$theme', '$colorMode'],
1515
props: {
1616
as: {
17-
type: String,
17+
type: [String, Object],
1818
default: 'button'
1919
},
2020
type: {

src/components/Icon/Search.vue

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<template>
2+
<path
3+
fill="currentColor"
4+
d="M23.384,21.619,16.855,15.09a9.284,9.284,0,1,0-1.768,1.768l6.529,6.529a1.266,1.266,0,0,0,1.768,0A1.251,1.251,0,0,0,23.384,21.619ZM2.75,9.5a6.75,6.75,0,1,1,6.75,6.75A6.758,6.758,0,0,1,2.75,9.5Z"
5+
/>
6+
</template>

src/components/Icon/icon.utils.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// @ts-check
2+
3+
/**
4+
* @description Evaluate icon size props
5+
* @param {Object} props - Props object
6+
* @property {String} size - Props object
7+
* @property {Object} theme - Props object
8+
* @returns {Object} Size style props object
9+
*/
10+
const sizeProps = ({ size, theme }) => {
11+
const _theme = theme()
12+
return {
13+
w: _theme.sizes[size],
14+
h: _theme.sizes[size]
15+
}
16+
}
17+
18+
/**
19+
* @description Evaluate icon style props
20+
* @param {Object} props - Props object
21+
*/
22+
export const iconStyles = (props) => {
23+
return {
24+
...sizeProps(props)
25+
}
26+
}
27+
28+
/**
29+
* @description Get reference to an Icon component if Font Awesome or MDI is used
30+
* @param {String} name - Name of the registered icon.
31+
* @returns {Object} Icon Component
32+
*/
33+
export const getIconComponent = (name) => {
34+
35+
}

src/components/Icon/index.js

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// import styled from 'vue-styled-components'
2+
import { Box } from '../../lib/core/'
3+
import iconPaths from '../../lib/plugin/iconsPaths'
4+
// import styleProps from '../../lib/config/props'
5+
import { cleanProps } from '../../lib/utils'
6+
import { iconStyles } from './icon.utils'
7+
8+
const fallbackIcon = iconPaths['question-outline']
9+
10+
/**
11+
* Features:
12+
* 1) Register custom icons
13+
* 2) Support Font Awesome icons.
14+
* 3) Support MD icons.
15+
*
16+
* CUSTOM ICONS:
17+
* - All icons exist as object.
18+
* - Load them in at project build time
19+
* - Should be extendable by users.
20+
* - If "name" prop is provided, search icons config for icon.
21+
*
22+
* SUPPORT FONTAWESOME/MDI
23+
* - Provide Object/Array of Fontawesome components
24+
* - Iterate over array of components to globally register sprites as components
25+
* - Accept "use" prop to calculate reference to globally registered component and feed it to Box component
26+
* - ^^ Use "as" prop to render component passed.
27+
*/
28+
29+
/**
30+
* The Icon component renders SVGs for visual aid
31+
*/
32+
export default {
33+
name: 'Icon',
34+
inject: ['$theme', '$colorMode'],
35+
props: {
36+
name: {
37+
type: [String, Array]
38+
},
39+
use: {
40+
type: [String, Array],
41+
required: false
42+
},
43+
pack: {
44+
type: String,
45+
required: false,
46+
default: 'fas',
47+
validator: (value) => value.match(/^(fas|fal|fad)$/)
48+
},
49+
size: {
50+
type: [String, Number, Array],
51+
default: '1em'
52+
},
53+
color: {
54+
type: [String, Array],
55+
default: 'currentColor'
56+
}
57+
},
58+
render (h) {
59+
let icon, viewBox
60+
if (this.name) {
61+
icon = iconPaths[this.name]
62+
} else if (this.use) {
63+
// icon =
64+
} else {
65+
console.warn(`[KiwiIcon]: You need to provide the "name" or "use" prop to for the Icon component`)
66+
}
67+
68+
if (!icon) {
69+
icon = fallbackIcon
70+
}
71+
72+
viewBox = icon.viewBox || '0 0 24 24'
73+
74+
// Evaluate icon size
75+
const iconSize = iconStyles({
76+
size: this.size,
77+
theme: this.$theme
78+
})
79+
80+
return h(Box, {
81+
props: {
82+
as: 'svg',
83+
color: this.color,
84+
d: 'inline-block',
85+
verticalAlign: 'middle',
86+
...iconSize,
87+
...cleanProps(this.$props)
88+
},
89+
attrs: {
90+
viewBox,
91+
role: 'presentation',
92+
focusable: false
93+
},
94+
domProps: {
95+
innerHTML: icon.path
96+
}
97+
})
98+
}
99+
}

src/components/ThemeProvider/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ const ThemeProvider = {
1919
$colorMode: this.colorMode
2020
}
2121
},
22-
render: function (createElement) {
23-
return createElement('div', {}, this.$slots.default)
22+
render: function () {
23+
return this.$slots.default
2424
}
2525
}
2626

src/lib/core/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { default as Box } from '../../components/Box'
22
export { default as PseudoBox } from '../../components/PseudoBox'
33
export { default as Button } from '../../components/Button'
4+
export { default as Icon } from '../../components/Icon'

src/lib/plugin/iconsPaths.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Internal icon paths
3+
*/
4+
const icons = {
5+
star: {
6+
path: `
7+
<path
8+
fill="currentColor"
9+
d="M23.555,8.729a1.505,1.505,0,0,0-1.406-.98H16.062a.5.5,0,0,1-.472-.334L13.405,1.222a1.5,1.5,0,0,0-2.81,0l-.005.016L8.41,7.415a.5.5,0,0,1-.471.334H1.85A1.5,1.5,0,0,0,.887,10.4l5.184,4.3a.5.5,0,0,1,.155.543L4.048,21.774a1.5,1.5,0,0,0,2.31,1.684l5.346-3.92a.5.5,0,0,1,.591,0l5.344,3.919a1.5,1.5,0,0,0,2.312-1.683l-2.178-6.535a.5.5,0,0,1,.155-.543l5.194-4.306A1.5,1.5,0,0,0,23.555,8.729Z"
10+
/>
11+
`
12+
},
13+
email: {
14+
path: `
15+
<g fill="currentColor">
16+
<path d="M11.114,14.556a1.252,1.252,0,0,0,1.768,0L22.568,4.87a.5.5,0,0,0-.281-.849A1.966,1.966,0,0,0,22,4H2a1.966,1.966,0,0,0-.289.021.5.5,0,0,0-.281.849Z" />
17+
<path d="M23.888,5.832a.182.182,0,0,0-.2.039l-6.2,6.2a.251.251,0,0,0,0,.354l5.043,5.043a.75.75,0,1,1-1.06,1.061l-5.043-5.043a.25.25,0,0,0-.354,0l-2.129,2.129a2.75,2.75,0,0,1-3.888,0L7.926,13.488a.251.251,0,0,0-.354,0L2.529,18.531a.75.75,0,0,1-1.06-1.061l5.043-5.043a.251.251,0,0,0,0-.354l-6.2-6.2a.18.18,0,0,0-.2-.039A.182.182,0,0,0,0,6V18a2,2,0,0,0,2,2H22a2,2,0,0,0,2-2V6A.181.181,0,0,0,23.888,5.832Z" />
18+
</g>
19+
`
20+
},
21+
phone: {
22+
viewBox: '0 0 14 14',
23+
path: `
24+
<path
25+
fill="currentColor"
26+
d="M2.20731,0.0127209 C2.1105,-0.0066419 1.99432,-0.00664663 1.91687,0.032079 C0.871279,0.438698 0.212942,1.92964 0.0580392,2.95587 C-0.426031,6.28627 2.20731,9.17133 4.62766,11.0689 C6.77694,12.7534 10.9012,15.5223 13.3409,12.8503 C13.6507,12.5211 14.0186,12.037 13.9993,11.553 C13.9412,10.7397 13.186,10.1588 12.6051,9.71349 C12.1598,9.38432 11.2304,8.47427 10.6495,8.49363 C10.1267,8.51299 9.79754,9.05515 9.46837,9.38432 L8.88748,9.96521 C8.79067,10.062 7.55145,9.24878 7.41591,9.15197 C6.91248,8.8228 6.4284,8.45491 6.00242,8.04829 C5.57644,7.64167 5.18919,7.19632 4.86002,6.73161 C4.7632,6.59607 3.96933,5.41495 4.04678,5.31813 C4.04678,5.31813 4.72448,4.58234 4.91811,4.2919 C5.32473,3.67229 5.63453,3.18822 5.16982,2.45243 C4.99556,2.18135 4.78257,1.96836 4.55021,1.73601 C4.14359,1.34875 3.73698,0.942131 3.27227,0.612963 C3.02055,0.419335 2.59457,0.0708094 2.20731,0.0127209 Z"
27+
/>
28+
`
29+
},
30+
'question-outline': {
31+
viewBox: '0 0 24 24',
32+
path: `
33+
<g stroke="currentColor" strokeWidth="1.5">
34+
<path
35+
strokeLinecap="full"
36+
fill="none"
37+
d="M9,9a3,3,0,1,1,4,2.829,1.5,1.5,0,0,0-1,1.415V14.25"
38+
/>
39+
<path
40+
fill="none"
41+
strokeLinecap="full"
42+
d="M12,17.25a.375.375,0,1,0,.375.375A.375.375,0,0,0,12,17.25h0"
43+
/>
44+
<circle fill="none" strokeMiterlimit="10" cx="12" cy="12" r="11.25" />
45+
</g>
46+
`
47+
}
48+
}
49+
50+
export default icons

stories/3-Button.stories.js

+3
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,7 @@ storiesOf('UI | Button', module)
6363
</div>
6464
`,
6565
methods: { action: action('Button Clicked') }
66+
// mounted () {
67+
// console.log({ instance: this.$options.components })
68+
// }
6669
}))

0 commit comments

Comments
 (0)