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

Commit 93aa1cc

Browse files
committed
feat(iconbutton): created icon button component
1 parent 45f3987 commit 93aa1cc

File tree

14 files changed

+290
-104
lines changed

14 files changed

+290
-104
lines changed

Diff for: src/App.vue

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
<template>
22
<theme-provider :theme="theme" :icons="$kiwi.icons">
33
<div class="root">
4-
<Button size="sm" variant-color="blue" left-icon="coffee" @click="setLoading" :is-loading="loading"> Buy Coffee </Button>
4+
<Button size="md" variant-color="indigo" mr="3" left-icon="search" @click="setLoading" :is-loading="loading"> Search </Button>
5+
<IconButton _aria-label="Search" size="sm" variant-color="blue" :is-round="true" icon="search" />
6+
<IconButton _aria-label="Search" variant-color="blue" :is-round="true" size="md" icon="search" />
7+
<IconButton _aria-label="Search" size="lg" variant-color="blue" :is-round="true" icon="search" />
58
</div>
69
</theme-provider>
710
</template>
811

912
<script>
1013
import ThemeProvider from './components/ThemeProvider'
11-
import { Button } from './lib/core/'
14+
import { Button, IconButton } from './lib/core/'
1215
import Badge from './components/Badge'
1316
import theme from './lib/theme'
1417
import { setTimeout } from 'timers'
@@ -25,7 +28,8 @@ export default {
2528
name: 'App',
2629
components: {
2730
ThemeProvider,
28-
Button
31+
Button,
32+
IconButton
2933
},
3034
methods: {
3135
toggle () {

Diff for: src/components/Button/button.props.js

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
export const buttonProps = {
2+
as: {
3+
type: [String, Object],
4+
default: 'button'
5+
},
6+
type: {
7+
type: String,
8+
default: 'button'
9+
},
10+
cast: {
11+
type: String,
12+
default: 'primary',
13+
validator: (value) =>
14+
value.match(/^(primary|secondary|success|warning|danger)$/)
15+
},
16+
variant: {
17+
type: String,
18+
default: 'solid',
19+
validator: (value) =>
20+
value.match(/^(solid|outline|ghost|flat|link)$/)
21+
},
22+
variantColor: {
23+
type: [String, Array],
24+
default: 'gray'
25+
},
26+
disabled: {
27+
type: Boolean,
28+
default: false
29+
},
30+
isLoading: {
31+
type: Boolean,
32+
default: false
33+
},
34+
isActive: {
35+
type: Boolean,
36+
default: false
37+
},
38+
size: {
39+
type: String,
40+
default: 'md',
41+
validator: (value) => value.match(/^(sm|md|lg)$/)
42+
},
43+
loadingText: {
44+
type: String,
45+
default: 'Loading',
46+
validator: (value) => typeof value === 'string'
47+
},
48+
iconSpacing: {
49+
type: [String, Number],
50+
default: 2,
51+
validator: (value) => value >= 0
52+
},
53+
leftIcon: {
54+
type: String,
55+
default: null
56+
},
57+
rightIcon: {
58+
type: String,
59+
default: null
60+
},
61+
rounded: {
62+
type: Boolean,
63+
default: false
64+
},
65+
ripple: {
66+
type: [String, Boolean],
67+
default: true
68+
},
69+
_ref: Object
70+
}

Diff for: src/components/Button/button.styles.js

+12-16
Original file line numberDiff line numberDiff line change
@@ -56,32 +56,28 @@ export const setIconSizes = (props) => {
5656
*/
5757
const sizes = {
5858
lg: {
59-
height: 12,
60-
minWidth: 12,
59+
h: 12,
60+
minW: 12,
6161
fontSize: 'lg',
62-
px: 6,
63-
py: 4
62+
px: 6
6463
},
6564
md: {
66-
height: 10,
67-
minWidth: 10,
65+
h: 10,
66+
minW: 10,
6867
fontSize: 'md',
69-
px: 4,
70-
py: 3
68+
px: 4
7169
},
7270
sm: {
73-
height: 8,
74-
minWidth: 8,
71+
h: 8,
72+
minW: 8,
7573
fontSize: 'sm',
76-
px: 3,
77-
py: 2
74+
px: 3
7875
},
7976
xs: {
80-
height: 6,
81-
minWidth: 6,
77+
h: 6,
78+
minW: 6,
8279
fontSize: 'xs',
83-
px: 2,
84-
py: 1
80+
px: 2
8581
}
8682
}
8783

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

+4-74
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import styleProps from '../../lib/config/props'
2+
import { buttonProps } from './button.props'
23
import { forwardProps } from '../../lib/utils'
34
import createButtonStyles, { setIconSizes } from './button.styles'
45
import { Box, PseudoBox, Spinner, Icon } from '../../lib/core'
@@ -24,7 +25,6 @@ const ButtonIcon = {
2425
focusable: false,
2526
name: this.icon,
2627
color: 'currentColor',
27-
mb: '-2px',
2828
...setIconSizes(this.$props),
2929
...forwardProps(this.$props)
3030
}
@@ -35,7 +35,6 @@ const ButtonIcon = {
3535
as: this.icon,
3636
focusable: false,
3737
color: 'currentColor',
38-
mb: '-2px',
3938
...setIconSizes(this.$props)
4039
},
4140
attrs: {
@@ -51,78 +50,9 @@ const ButtonIcon = {
5150
*/
5251
export default {
5352
name: 'Button',
54-
components: {
55-
PseudoBox
56-
},
5753
inject: ['$theme', '$colorMode'],
5854
props: {
59-
as: {
60-
type: [String, Object],
61-
default: 'button'
62-
},
63-
type: {
64-
type: String,
65-
default: 'button'
66-
},
67-
cast: {
68-
type: String,
69-
default: 'primary',
70-
validator: (value) =>
71-
value.match(/^(primary|secondary|success|warning|danger)$/)
72-
},
73-
variant: {
74-
type: String,
75-
default: 'solid',
76-
validator: (value) =>
77-
value.match(/^(solid|outline|ghost|flat|link)$/)
78-
},
79-
variantColor: {
80-
type: [String, Array],
81-
default: 'gray'
82-
},
83-
disabled: {
84-
type: Boolean,
85-
default: false
86-
},
87-
isLoading: {
88-
type: Boolean,
89-
default: false
90-
},
91-
isActive: {
92-
type: Boolean,
93-
default: false
94-
},
95-
size: {
96-
type: String,
97-
default: 'md',
98-
validator: (value) => value.match(/^(sm|md|lg)$/)
99-
},
100-
loadingText: {
101-
type: String,
102-
default: 'Loading',
103-
validator: (value) => typeof value === 'string'
104-
},
105-
iconSpacing: {
106-
type: [String, Number],
107-
default: 2,
108-
validator: (value) => value >= 0
109-
},
110-
leftIcon: {
111-
type: String,
112-
default: null
113-
},
114-
rightIcon: {
115-
type: String,
116-
default: null
117-
},
118-
rounded: {
119-
type: Boolean,
120-
default: false
121-
},
122-
ripple: {
123-
type: [String, Boolean],
124-
default: true
125-
},
55+
...buttonProps,
12656
...styleProps
12757
},
12858
render (h) {
@@ -134,6 +64,7 @@ export default {
13464
colorMode: this.$colorMode,
13565
size: this.size || 'md'
13666
})
67+
13768
return h(PseudoBox, {
13869
props: {
13970
as: this.as,
@@ -144,6 +75,7 @@ export default {
14475
border: 'none',
14576
transition: 'all 0.2s ease-in',
14677
rounded: 'md',
78+
width: this.isFullWidth ? 'full' : undefined,
14779
...buttonStyles,
14880
...forwardProps(this.$props)
14981
},
@@ -160,7 +92,6 @@ export default {
16092
}, [
16193
this.leftIcon && !this.isLoading && h(ButtonIcon, {
16294
props: {
163-
ml: -1,
16495
mr: this.iconSpacing,
16596
icon: this.leftIcon,
16697
size: '1em'
@@ -178,7 +109,6 @@ export default {
178109
this.isLoading ? this.loadingText : this.$slots.default,
179110
this.rightIcon && !this.isLoading && h(ButtonIcon, {
180111
props: {
181-
mr: -1,
182112
ml: this.iconSpacing,
183113
icon: this.rightIcon,
184114
size: '1em'

Diff for: src/components/Icon/index.d.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as Vue from 'vue';
2+
3+
/**
4+
* Icon component for UI representations
5+
*/
6+
declare const IconButton: Vue.Component<{
7+
name?: [String, Array<String>],
8+
use?: [String, Array<String>],
9+
pack?: String,
10+
size?: [String, Number, Array<String>],
11+
color?: [String, Array<String>],
12+
}>;
13+
export default IconButton;

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import styled from 'vue-styled-components'
12
import { Box } from '../../lib/core/'
23
import iconPaths from '../../lib/plugin/iconsPaths'
34
import { forwardProps } from '../../lib/utils'
@@ -6,6 +7,14 @@ import { baseProps } from '../../lib/config/props'
67

78
const fallbackIcon = iconPaths['question-outline']
89

10+
const Svg = styled(Box)`
11+
flex-shrink: 0;
12+
backface-visibility: hidden;
13+
&:not(:root) {
14+
overflow: hidden;
15+
}
16+
`
17+
918
/**
1019
* The Icon component renders SVGs for visual aid
1120
*/
@@ -56,7 +65,7 @@ export default {
5665
theme: this.$theme
5766
})
5867

59-
return h(Box, {
68+
return h(Svg, {
6069
props: {
6170
as: 'svg',
6271
color: this.color,

Diff for: src/components/IconButton/icon-button.utils.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const iconSizes = {
2+
xs: {
3+
w: '0.75rem',
4+
h: '0.75rem'
5+
},
6+
sm: {
7+
w: '0.8rem',
8+
h: '0.8rem'
9+
},
10+
md: {
11+
w: '1.0rem',
12+
h: '1.0rem'
13+
},
14+
lg: {
15+
w: '2rem',
16+
h: '2rem'
17+
},
18+
xl: {
19+
w: '3rem',
20+
h: '3rem'
21+
}
22+
}
23+
24+
const createCustomSize = (size) => {
25+
return {
26+
w: size,
27+
h: size
28+
}
29+
}
30+
31+
/**
32+
* @description Evaluates button icon sizes and returns wight and height parameters
33+
* @param {Object} props
34+
*/
35+
export const setButtonIconSize = (props) => {
36+
return iconSizes[props.size] || createCustomSize(props.size)
37+
}

Diff for: src/components/IconButton/index.d.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as Vue from 'vue';
2+
3+
/**
4+
* Icon Button component for UI interactions
5+
*/
6+
declare const IconButton: Vue.Component<{
7+
icon?: String,
8+
isRound?: Boolean,
9+
_ariaLabel?: String,
10+
_ref?: HTMLElement
11+
}>;
12+
export default IconButton;

0 commit comments

Comments
 (0)