Skip to content
This repository has been archived by the owner on Aug 2, 2024. It is now read-only.

Commit

Permalink
feat: added split button component
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianKienle committed Jun 15, 2019
1 parent bb4e5eb commit b4783c7
Show file tree
Hide file tree
Showing 12 changed files with 522 additions and 2 deletions.
88 changes: 88 additions & 0 deletions src/components/SplitButton/SplitButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<div class="fd-button-split" role="group">
<!-- Provide a custom action button. The action button is bigger button with the text that should trigger some kind of action. You can use fd-split-button-action to render the default auxiliary-button and customize it. -->
<slot v-bind="slotProps" name="action">
<fd-split-button-action @click="$emit('click')">
<!-- Provide a title. This is rendered inside the 'action' part of the split button (big area on the left). -->
<slot />
</fd-split-button-action>
</slot>
<!-- Provide a custom auxiliary button. The auxiliary button should bring up some kind of menu/popover. You can use fd-split-button-auxiliary to render the default auxiliary-button and customize it. -->
<slot v-bind="slotProps" name="auxiliary">
<fd-split-button-auxiliary @click="$emit('click:auxiliary')" />
</slot>
</div>
</template>

<script>
import FdSplitButtonAuxiliary from "./../SplitButtonAuxiliary/SplitButtonAuxiliary.vue";
import FdSplitButtonAction from "./../SplitButtonAction/SplitButtonAction.vue";
import Vue from "vue";
import ButtonTypes from "./../Button/ButtonTypes";
import IconMixin from "./../../mixins/Icon";
export default {
name: "FdSplitButton",
mixins: [IconMixin],
components: {
FdSplitButtonAction,
FdSplitButtonAuxiliary
},
provide() {
return {
splitButton: this.splitButton
};
},
computed: {
slotProps() {
return this.splitButton;
}
},
props: {
compact: Boolean,
styling: {
type: String,
default: null,
validator: value => ["emphasized", "light"].indexOf(value) >= 0
},
state: {
type: String,
default: "normal",
validator: value => ["normal", "selected", "disabled"].indexOf(value) >= 0
},
type: {
type: String,
default: null,
validator: value => ButtonTypes.indexOf(value) >= 0
}
},
watch: {
state(state) {
this.splitButton.state = state;
},
type(type) {
this.splitButton.type = type;
},
styling(styling) {
this.splitButton.styling = styling;
},
compact(compact) {
this.splitButton.compact = compact;
},
icon(icon) {
this.splitButton.icon = icon;
}
},
data() {
return {
splitButton: Vue.observable({
state: this.state,
type: this.type,
styling: this.styling,
compact: this.compact,
icon: this.icon
})
};
}
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Split Button renders correctly 1`] = `
<div
class="fd-button-split"
role="group"
>
<button
class="fd-button"
>
Hello World
</button>
<button
aria-label="More"
class="fd-button sap-icon--slim-arrow-down fd-button"
/>
</div>
`;

exports[`Split Button when disabled renders correctly 1`] = `
<div
class="fd-button-split"
role="group"
>
<button
class="fd-button is-disabled"
disabled="disabled"
>
Hello World
</button>
<button
aria-label="More"
class="fd-button sap-icon--slim-arrow-down fd-button is-disabled"
disabled="disabled"
/>
</div>
`;
74 changes: 74 additions & 0 deletions src/components/SplitButton/__tests__/split-button.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { mount, createLocalVue } from "@vue/test-utils";
import FundamentalVue from "./../../../";
import FdSplitButton from "./../SplitButton.vue";
import FdSplitButtonAction from "./../../SplitButtonAction/SplitButtonAction.vue";
import FdSplitButtonAuxiliary from "./../../SplitButtonAuxiliary/SplitButtonAuxiliary.vue";

const createSplitButton = ({ propsData } = { propsData: {} }) => {
const localVue = createLocalVue();
localVue.use(FundamentalVue);
return mount(FdSplitButton, {
localVue,
propsData,
slots: {
default: "Hello World"
}
});
};

describe("Split Button", () => {
test("renders correctly", () => {
expect(createSplitButton().element).toMatchSnapshot();
});

test("emits click-event when action-button is clicked", () => {
const wrapper = createSplitButton();
const actionButtonWrapper = wrapper.find(FdSplitButtonAction);
expect(actionButtonWrapper.exists()).toBe(true);
actionButtonWrapper.trigger("click");
expect(wrapper.emitted("click")).toHaveLength(1);
});

test("emits click:auxiliary-event when auxiliary-button is clicked", () => {
const wrapper = createSplitButton();
const auxiliaryButtonWrapper = wrapper.find(FdSplitButtonAuxiliary);
expect(auxiliaryButtonWrapper.exists()).toBe(true);
auxiliaryButtonWrapper.trigger("click");
expect(wrapper.emitted("click:auxiliary")).toHaveLength(1);
expect(wrapper.emitted("click")).toBeUndefined();
});

describe("when disabled", () => {
/** @type {import("@vue/test-utils").Wrapper<Vue>} */
let disabledWrapper;
beforeEach(() => {
disabledWrapper = createSplitButton({
propsData: {
state: "disabled"
}
});
});

test("renders correctly", () => {
expect(disabledWrapper.element).toMatchSnapshot();
});

test("click:auxiliary-event is not emitted when auxiliary-button is clicked", () => {
const auxiliaryButtonWrapper = disabledWrapper.find(
FdSplitButtonAuxiliary
);
expect(auxiliaryButtonWrapper.exists()).toBe(true);
auxiliaryButtonWrapper.trigger("click");
expect(disabledWrapper.emitted("click:auxiliary")).toBeUndefined();
expect(disabledWrapper.emitted("click")).toBeUndefined();
});

test("click-event is not emitted when action-button is clicked", () => {
const actionButtonWrapper = disabledWrapper.find(FdSplitButtonAction);
expect(actionButtonWrapper.exists()).toBe(true);
actionButtonWrapper.trigger("click");
expect(disabledWrapper.emitted("click:auxiliary")).toBeUndefined();
expect(disabledWrapper.emitted("click")).toBeUndefined();
});
});
});
4 changes: 4 additions & 0 deletions src/components/SplitButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SplitButton from "./SplitButton.vue";
import { pluginify } from "./../../util";
export default pluginify(SplitButton);
export { SplitButton };
40 changes: 40 additions & 0 deletions src/components/SplitButtonAction/SplitButtonAction.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<fd-button
v-bind="$attrs"
v-on="$listeners"
:state="state"
:type="type"
:styling="styling"
:compact="compact"
:icon="icon"
>
<slot />
</fd-button>
</template>

<script>
import FdButton from "./../Button/Button.vue";
export default {
name: "FdSplitButtonAction",
components: { FdButton },
inject: ["splitButton"],
computed: {
state() {
return this.splitButton.state;
},
type() {
return this.splitButton.type;
},
styling() {
return this.splitButton.styling;
},
compact() {
return this.splitButton.disacompactbled;
},
icon() {
return this.splitButton.icon;
}
}
};
</script>
4 changes: 4 additions & 0 deletions src/components/SplitButtonAction/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SplitButtonAction from "./SplitButtonAction.vue";
import { pluginify } from "./../../util";
export default pluginify(SplitButtonAction);
export { SplitButtonAction };
37 changes: 37 additions & 0 deletions src/components/SplitButtonAuxiliary/SplitButtonAuxiliary.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<template>
<fd-button
class="fd-button sap-icon--slim-arrow-down"
aria-label="More"
:state="state"
:type="type"
:styling="styling"
:compact="compact"
v-bind="$attrs"
v-on="$listeners"
><slot
/></fd-button>
</template>

<script>
import FdButton from "./../Button/Button.vue";
export default {
name: "FdSplitButtonAuxiliary",
components: { FdButton },
inject: ["splitButton"],
computed: {
state() {
return this.splitButton.state;
},
type() {
return this.splitButton.type;
},
styling() {
return this.splitButton.styling;
},
compact() {
return this.splitButton.disacompactbled;
}
}
};
</script>
4 changes: 4 additions & 0 deletions src/components/SplitButtonAuxiliary/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import SplitButtonAuxiliary from "./SplitButtonAuxiliary.vue";
import { pluginify } from "./../../util";
export default pluginify(SplitButtonAuxiliary);
export { SplitButtonAuxiliary };
6 changes: 6 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import SearchInput from "./SearchInput";
import SideNav from "./SideNav";
import Spinner from "./Spinner";
import Status from "./Status";
import SplitButton from "./SplitButton";
import SplitButtonAuxiliary from "./SplitButtonAuxiliary";
import SplitButtonAction from "./SplitButtonAction";
import Table from "./Table";
import Tabs from "./Tabs";
import Tile from "./Tile";
Expand Down Expand Up @@ -75,6 +78,9 @@ const plugin = {
SideNav,
Spinner,
Status,
SplitButton,
SplitButtonAuxiliary,
SplitButtonAction,
Table,
Tabs,
Tile,
Expand Down
Loading

0 comments on commit b4783c7

Please sign in to comment.