This single page application (SPA) is for the food pilot program with Trupanion and Royal Canin. The application is primarily built with the following technologies:
- TypeScript - Language
- Vue 3 - Framework
- Vue Router - Routing
- Pinia - State Management
- Vite - Build Tool
- UnoCSS - CSS Framework
- Vitest - Testing
- @vue/test-utils - Testing Utilities
Work on this project was initially conducted by Chuck Taylor (chuck@preventivevet.com) at Preventive Vet.
The CSS for this application is assembled using UnoCSS, an instant on-demand atomic css engine. UnoCSS will generate css based on the configurations. As a convention these classes are similar compatible with TailwindCSS. Tailwind is a good reference for the available classes and their usage.
UnoCSS goes a step further in that is has powerful configuration options which can be adjusted in uno.config.ts. The main changes made in the configuration have been the addition of brand colors, brand shadows, fonts, and added support for container queries.
The colors added in the configuration file will permeate to any class that references them in the same style as Tailwind utility classes. For example, in Tailwind you can use bg-blue-500 to set the background color to the blue-500 color. With the configuration, you can use bg-tru-blue-500 to set the background color to the tru-blue-500 color. The same would be true for text or borders, etc. text-tru-blue-500 or border-tru-blue-500. Most of the brand colors have increments sarting at 50 for the lightest and going to 950 for the darkest. There are a few exceptions like charcoal. Check the configuration file for the full list of colors.
All stylesheets are imported in main.ts.
The project makes use of some container queries. Since UnoCSS is being used, these can be accessed using the classes generated. These classes match those in the TailwindCSS Container Queries Plugin. Check their documentation for more information.
While container queries are very well supported, there are some users who may not be using a supported browser. To account for this, the project uses the container query polyfill by Google Chrome Labs. This polyfill is only loaded if the browser does not support container queries. The polyfill is loaded in index.html.
TypeScript cannot handle type information for .vue imports by default, so we replace the tsc CLI with vue-tsc for type checking. In editors, we need TypeScript Vue Plugin (Volar) to make the TypeScript language service aware of .vue types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a Take Over Mode that is more performant. You can enable it by the following steps:
- Disable the built-in TypeScript Extension
- Run
Extensions: Show Built-in Extensionsfrom VSCode's command palette - Find
TypeScript and JavaScript Language Features, right click and selectDisable (Workspace)
- Run
- Reload the VSCode window by running
Developer: Reload Windowfrom the command palette.
This project was updated to use the presetWind4 preset for UnoCSS. This preset provides better compatibility with TailwindCSS v4 and newer features.
The uno.config.ts file needed to be rewritten.
Variants were added to support container queries and pointer variants.
The difference between pointer and any-pointer is about which pointing devices they detect:
pointer variants - Checks the primary pointing device:
pointer-fine: - Primary device is accurate (mouse/trackpad)
pointer-coarse: - Primary device is less accurate (touchscreen)
pointer-none: - No primary pointing device
any-pointer variants - Checks if ANY pointing device meets the criteria:
any-pointer-fine: - At least one connected device is accurate
any-pointer-coarse: - At least one connected device is less accurate
any-pointer-none: - No pointing devices at all
Example scenario: A laptop with a trackpad (fine) also has a touchscreen (coarse):
pointer-fine: would match (trackpad is primary)
pointer-coarse: would NOT match
any-pointer-fine: would match (trackpad exists)
any-pointer-coarse: would ALSO match (touchscreen exists)
When to use which:
Use pointer-* when you want to optimize for the primary input method
Use any-pointer-* when you want to accommodate all possible input methods on a device
For example, any-pointer-coarse:p-4 could add extra padding if ANY touch capability exists, even if the user is currently using a mouse.
To install all the dependencies run
npm installTo run the project locally run
npm run devTo build the project run
npm run buildWhen deploying the application, the dist folder is the only folder that needs to be deployed. The dist folder contains all the files needed to run the application.
A thorough guide for deployment can be found in the Vite documentation.
On that page is a section for Azure Static Web Apps