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.PRIMARYButtonMode modeMakes the HTML to be a "router-link" instead of a "button" Default value: ButtonMode.NORMALComponentSkin skinIndicates which skin should be used for the component Default value: ComponentSkin.DESIGN_SYSTEMpandadsstring 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