Appearance
Button #
This is a simple button.
Usage #
This is a basic button, which defaults to a filled primary button. Try changing the props and slots to see how it reacts.
Props #
ButtonColor
colorAllows to change the mode the button is displayed Default value: ButtonColor.PRIMARY
ButtonMode
modeMakes the HTML to be a "router-link" instead of a "button" Default value: ButtonMode.NORMAL
ComponentSkin
skinIndicates which skin should be used for the component Default value: ComponentSkin.DESIGN_SYSTEM
panda
ds
string
toIndicates the route to which the button should redirect when clickedstring
hrefIndicates the URL to which the button should redirect when clickedTIP
When the to
prop is set, the button element will render as a <router-link>
instead of a <button>
. This prop has priority over the href
prop if both are set.
When the href
prop is set, the button element will render as a <a>
instead of a <button>
.
Options #
Make it disabledDisable the button to not allow user interaction
Slots #
defaultThe content of the button, usually a text
iconAn icon prepending the button content. It can be a svg, a component, an image or whatever
icon-onlyIf you want the button to only have an icon, you should use this slot instead of the "icon" one
WARNING
The icon-only
slot should be used with no content in the default slot, as it may cause the button to look weird. This is not the case with the example as the icon-only
example is detached with no possibility of using the default slot.
Implementation details #
Ripple effect #
The button has a ripple effect when clicked. This is done by creating a span
element with the class ripple
and appending it to the button.
js
const element = ref();
function createRippleEffect(event: MouseEvent) {
if(!element.value) { return; }
const button = (props.to) ? element.value.$el : element.value;
if(!button) { return; }
const circle = document.createElement('span');
const diameter = Math.max(button.clientWidth, button.clientHeight);
const radius = diameter / 2;
circle.style.width = circle.style.height = `${diameter}px`;
const buttonPosition = button.getBoundingClientRect();
circle.style.left = `${event.clientX - buttonPosition.left - radius}px`;
circle.style.top = `${event.clientY - buttonPosition.top - radius}px`;
circle.classList.add('ripple');
const ripple = button.getElementsByClassName('ripple')[0];
if (ripple) {
ripple.remove();
}
button.appendChild(circle);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
The ripple
element is then animated with CSS. The animation is done by setting the transform
property to scale(1)
and opacity
to 0
.
This effect needs the button to have a position
property set to relative
or absolute
so that the ripple
element can be positioned absolutely, as well as hiding the overflow of the button.
js
<style lang="scss">
.ripple {
position: absolute;
border-radius: 50%;
transform: scale(0);
animation: ripple 600ms linear;
background-color: rgba(255, 255, 255, .3);
}
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Type declarations #
ButtonSize #
ts
export enum ButtonSize {
DEFAULT = 'default',
SMALL = 'small',
}
1
2
3
2
3
ButtonMode #
ts
export enum ButtonMode {
NORMAL = 'normal',
OUTLINE = 'outline',
CLEAR = 'clear',
LINK = 'link',
}
1
2
3
4
5
2
3
4
5
ButtonColor #
ts
export enum ButtonColor {
PRIMARY = 'primary',
SECONDARY = 'secondary',
TERTIARY = 'tertiary',
DANGER = 'danger',
WARNING = 'warning',
SUCCESS = 'success',
LIGHT = 'light',
MEDIUM = 'medium',
DARK = 'dark',
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
ComponentSkin #
ts
export enum ComponentSkin {
PANDA = 'panda',
DESIGN_SYSTEM = 'ds',
}
1
2
3
2
3