A collection of components built with Vue3, TypeScript which we use when building the administration dashboards of our applications.
npm install
We use Storybook for visualizing and documenting components. To run a local instance of storybook run:
npm run storybook
You can also view them at https://salt-admin-component-library.netlify.app/
To run all tests:
npm run test:unit
To run a single test:
npm run test:single /path/to/test/file
npm run lint
Follow these steps when adding a new component to the library
The folder should start with 'Admin' and then the name of the component in camel case. E.g for a form input component,
the name would be AdminFormInput
.
Add a .vue
file in the newly created folder with the same name as the folder. There are 3 sections to add for each component. The first is a script
tag which exports the name of the component:
<script lang="ts">
export default {
name: "SltAdminFormInput",
};
</script>
The next section is the main script
element. This is where you define props, emits, reactive data, computed properties and methods used by the component. We use the composition API using script setup and typescript, so your script tag must start with this:
<script setup lang="ts">
Finally, we have the template itself at the bottom of the page.
<script lang="ts">
// Add a default export with the name of the component
</script>
<script setup lang="ts">
// Component logic and data goes here using composition API with script setup and TypeScript
</script>
<template>
<!-- Component HTML -->
</template>
In the same folder, add a file called index.ts
and add the following code:
import { App, Plugin } from "vue";
import AdminFormInput from "./AdminFormInput.vue";
import { registerComponent } from "@/utils/plugins";
export default {
install(app: App) {
registerComponent(app, AdminFormInput);
},
} as Plugin;
export { AdminFormInput as SltAdminFormInput };
The only part that changes is the name of the component.
There is a file in src/components
called admin.ts
. New components must be imported here and then exported. This file is used when the component library is installed to automatically register all components globally
import AdminFormInput from "./AdminFormInput";
export { AdminFormInput };
We use Storybook for visualizing and documenting the components in this library. Every new component must have at least one story added. You can add one by creating a new file in stories/admin
with the same name as the component and adding stories.js
at the end. A simplified version of a story looks a little like this:
import SltAdminFormInput from "../../src/components/AdminFormInput/AdminFormInput.vue";
export default {
title: "Admin/Forms/Input",
component: SltAdminFormInput,
};
const Template = (args) => ({
components: { SltAdminFormInput },
setup() {
return {
args,
};
},
template: `<slt-admin-form-input v-bind="args" />`,
});
export const Default = Template.bind({});
Default.args = {
inputId: "example_input",
label: "Name",
type: "text",
};
Once you've added your story, you should be able to see it in your browser when you run
npm run storybook
We currently use vue-test-utils along with Mocha and Chai for our unit tests. The test suite runs automatically when code is pushed up to the repo so we can ensure we don't have regressions after changes are made.
Create a new file in tests/unit
with the name of the component followed by .spec.js
. Here's an example of a simplified setup with one test:
import { mount } from "@vue/test-utils";
import { assert } from "chai";
import AdminFormInput from "@/components/AdminFormInput/AdminFormInput.vue";
describe("AdminFormInput.vue", () => {
it("displays an error message if an error is passed as a prop", async () => {
const wrapper = mount(AdminFormInput, {
props: { label, inputId, value, error: "Error message" },
components: { AdminFormItemWrapper },
});
const error = wrapper.find("[data-test='error'");
assert.isTrue(error.exists());
assert.equal(error.text(), "Error message");
});
});
In order for an app which installs this library to get IDE auto-completion and type inference when using the components, we need to augment Vue's GlobalComponents
interface. When you add a new component, you need to import the .vue
file of the component in src/global-components.d.ts
and add it to the interface
import SltAdminFormInput from "@pango-studio/salt-admin-component-library/src/components/AdminFormInput/AdminFormInput.vue";
declare module "@vue/runtime-core" {
export interface GlobalComponents {
SltAdminFormInput: typeof SltAdminFormInput;
}
Once you are ready to release a new version, you need to run the build steps to populate the dist
folder with:
npm run build:vue
Once that process is completed, ensure you are logged in with your npm account details:
npm login
Then set the new version number in package.json
and run:
npm publish