Trees is our attempt at unifying the frontend code we've written to power a small handful of web applications. We prefer the slower method of walking the trails, smelling the trees, and staying closer to the dirt than something speedier on the road. This bad boy is just getting of the ground and will be in v0 for the foreseeable future.
- [x] Skeleton for NPM Component Library
- [x] Button component
- [x] Form input (checkbox, input, select, textarea) components
- [x] Nav component
- [x] DateRangePicker component
- [x] Paginator component
- [x] Table component
- [x] Layout component
- [x] Spinner component
- [x] Flash component
- [x] DetailList component
- [x] Components for basic text + layout (paragraphs, headers, subcontent, etc...)
- [x] Actions container component
- [ ] Initial UI kit website with deploy pipeline
- [ ] Table component scaffolded from trails defined struct
- [ ] Modal forms + regular defined on server component
- [ ] Get icon for project and make it home link
- [ ] Add emitted events to component detail view
- [ ] Make library types links in component detail view
- [ ] Add table component example that uses ActionsDropdown and handles emitted event
- [ ] Bump to new version of vue-cli and bump postcss -> 8
- [ ] Improve form element disabled and error states
- [ ] Line up buttons and badges with design system
- [x] Ensure flatpickr is picked up on build
- [ ] Select install for globally available components
- [ ] Make sure components have names in devtools
- [ ] Look into forcing tables to dropdown when actions open up in hidden area
- [ ] Fix select placeholder only showing up in dropdown
- [x] DateFilter input heights is not consistent. Make select match datepicker.
- [x] move to vite for building the dev site, library, and possible storybook
- [x] refactor componentes away from class decorators to setup sugar
- [ ] consider implementing storybook using vite as the bundler
Install trees into an existing Vue project - assumes npm version >= 7
npm i @xy-planning-network/trees
Additional peer dependecies will be installed by NPM. If you are using NPM < 7 you may need to explicitly install peer dependencies.
Initialize ESLint rules in .eslintrc.js
/* eslint-env node */
module.exports = {
extends: "./node_modules/@xy-planning-network/trees/config/eslint.js",
}
Initialize Prettier rules in .prettierrc.json
"@xy-planning-network/trees/config/prettier.js"
Include Font Families in html template
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Work+Sans:ital,wght@0,300..800;1,300..800&display=swap"
rel="stylesheet"
/>
</head>
Initialize styles in main.css
/* main.css */
/* import trees base styles */
@import "@xy-planning-network/trees/src/index.css";
/* additional tailwind styles */
@layer components {
.xy-example {
@apply inline-flex justify-center items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-800;
}
}
Merge with the trees tailwind.cofig.js
Note you may need a deep merge utility depending on the depth of properties you plan to override.
/* eslint-disable */
const treesConfig = require("@xy-planning-network/trees/config/tailwind.config")
module.exports = {
...treesConfig,
content: [...treesConfig.content, ...["./src/**/*.vue"]],
}
This is the best option when tree shaking and final bundle size is important to you.
Initialize trees dependencies in your application root
// main.ts
import Vue, { createApp } from "vue"
import App from "./App.vue"
// import your project's main stylesheet
import "@/main.css"
// initialize the app
const app = createApp(App)
app.mount("#vue-app")
Use Trees components as needed in your components
<script setup lang="ts">
import { ref } from "vue"
import { BaseInput} from "@xy-planning-network/trees"
const myInputVal = ref("")
</script>
<template>
<form>
<BaseInput
v-model="myInputVal"
type="text"
label="What's on your mind"
help="Don't over think it!"
/>
</form>
</template>
This example installs all components of Trees globally so you don't need to import them in your components. Useful for hitting the ground running with as little friction as possible. Bundles size will suffer as tree shaking optimizations will be limited.
Install all Trees components as a Vue plugin in your project root
// main.ts
// include the type interfaces for Trees components installed globally on the Vue instance
/// <reference types="@xy-planning-network/trees/types/components" />
import Vue, { createApp } from "vue"
import Trees from "@xy-planning-network/trees"
import App from "./App.vue"
// import your project's main stylesheet
import "@/main.css"
// initialize the app
const app = createApp(App)
// use all of Trees as a vue plugin
app.use(Trees)
// mount the application
app.mount("#vue-app")
Use Trees components as globally in your components
<script setup lang="ts">
import { ref } from "vue"
const myInputVal = ref("")
</script>
<template>
<form>
<!-- BaseInput is globally available -->
<BaseInput
v-model="myInputVal"
type="text"
label="What's on your mind"
help="Don't over think it!"
/>
</form>
</template>
This example selectively installs the Form components of Trees globally so you don't need to import them in your components. All other Trees components need to be explicitly imported.
Create a project based plugin for just the Trees form components
// plugins/trees.ts
// plugins/trees.ts
import { App } from "vue"
import {
BaseInput,
Checkbox,
DateRangePicker,
InputHelp,
InputLabel,
MultiCheckboxes,
Radio,
Select,
TextArea,
YesOrNoRadio,
} from "@xy-planning-network/trees"
/**
* declare the global component types
* should provide code completiong support in your editor - milage may vary
* provides proper type checking on the components declared props
*/
declare module "vue" {
interface GlobalComponents {
BaseInput: typeof BaseInput
Checkbox: typeof Checkbox
DateRangePicker: typeof DateRangePicker
InputHelp: typeof InputHelp
InputLabel: typeof InputLabel
MultiCheckboxes: typeof MultiCheckboxes
Radio: typeof Radio
Select: typeof Select
TextArea: typeof TextArea
YesOrNoRadio: typeof YesOrNoRadio
}
}
/**
* export a plugin object with an install method
*/
export default {
install(app: App) {
app.component("BaseInput", BaseInput)
app.component("Checkbox", Checkbox)
app.component("DateRangePicker", DateRangePicker)
app.component("InputHelp", InputHelp)
app.component("InputLabel", InputLabel)
app.component("MultiCheckboxes", MultiCheckboxes)
app.component("Radio", Radio)
app.component("Select", Select)
app.component("TextArea", TextArea)
app.component("YesOrNoRadio", YesOrNoRadio)
},
}
// main.ts
import Vue, { createApp } from "vue"
import App from "./App.vue"
import TreesFormComponents from "./plugins/trees"
// import your project's main stylesheet
import "@/main.css"
// initialize the app
const app = createApp(App)
// use cherry picked Form components of Trees globally
app.use(TreesFormComponents)
// mount the application
app.mount("#vue-app")
Use Trees components as globally in your components
<script setup lang="ts">
import { ref } from "vue"
import { Cards } from "@xy-planning-network/trees"
const myInputVal = ref("")
const cardsList = [
{ primary: "Get Some", secondary: "You are gonna do well." },
{ primary: "Try It", secondary: "I'm proud of how far you've come." },
{ primary: "Nice Info", secondary: "Never stop trying." },
]
</script>
<template>
<!--Cards needed to be imported -->
<Cards :cards="cardsList" />
<form>
<!-- BaseInput is globally available -->
<BaseInput
v-model="myInputVal"
type="text"
label="What's on your mind"
help="Don't over think it!"
/>
</form>
</template>