Cooper Component Library
A Vue 3 component library built with TypeScript, Vite, and Tailwind CSS. Published as @cooperco/cooper-component-library and designed for integration with Contentful CMS via GraphQL.
Tech Stack
- Vue 3.5+ - Composition API with
<script setup> - TypeScript 5.3+ - Strict mode enabled
- Tailwind CSS 3.4+ - Utility-first styling
- Vite 5.2+ - Library build mode
- Storybook 8.2+ - Component documentation
- GraphQL - Contentful CMS integration
- pnpm - Package manager
Recommended IDE Setup
- VS Code + Vue - Official (previously Volar) and disable Vetur
Development
# Install dependencies
pnpm install
# Start Storybook dev server
pnpm run dev
# Run linter
pnpm run lint
# Fix linting issues
pnpm run lint:fix
# Type check
pnpm run check-types
Testing Locally
To test the component library in a consuming project before publishing:
# 1. Build and pack the library
pnpm run local-test
This creates a .tgz file in the root directory (e.g., cooperco-cooper-component-library-0.1.61.tgz)
# 2. In the consuming project, install the local package
pnpm add /path/to/cooperco-cooper-component-library-0.1.61.tgz
This allows you to test changes locally before publishing to npm.
Building and Publishing
The build and publish process needs to happen manually when changes are merged to main:
Workflow
- Merge to main - Merge your feature branch to
main - Patch version - Update version number using
npm version patch(orminor/major) - Publish - Run
npm publishto publish to npm registry - Push - Push changes and tags to GitHub
Hotfix releases
If one urgent fix must reach an environment that is pinned to an older library
version, and the fix touches nothing under cms/, see
docs/hotfix-release.md for publishing "old tag + this
fix only" as a pre-release without dragging in intermediate migrations.
Build Process
When you run pnpm run build, the following happens in order:
build:types- Compiles Vue component TypeScript definitionsbuild:cms- Compiles GraphQL queries for Contentfulvite build- Builds the component library bundle
All build artifacts are output to the dist/ directory.
Package Exports
The package exports multiple entry points:
- Components:
@cooperco/cooper-component-library- Main component library - Styles:
@cooperco/cooper-component-library/css/main.css- Main styles - Theme:
@cooperco/cooper-component-library/css/theme.css- Theme variables - Queries:
@cooperco/cooper-component-library/cms/contentful/graphql- GraphQL queries
Project Structure
├── src/
│ ├── components/ # Vue components
│ │ ├── ComponentName/
│ │ │ ├── ComponentName.vue
│ │ │ └── ComponentName.ts
│ │ ├── components.ts # Component exports
│ │ └── types.ts # Type exports
│ ├── config/ # Configuration (color palettes, passthroughs)
│ └── utils/ # Utility functions
├── cms/
│ └── contentful/
│ └── queries/ # GraphQL queries (see cms/contentful/queries/README.md)
├── .storybook/ # Storybook configuration
│ └── components/ # Component stories
└── dist/ # Build output (generated)
Documentation
- Component Documentation: Run
pnpm run devto view Storybook - GraphQL Queries: See cms/contentful/queries/README.md
- Hotfix releases: See docs/hotfix-release.md
TODO Issues
- There are many places where
classis not recognized by TypeScript. Examples are "start"/"end" in ContainerModule. This is because we are not definingclasson the component types. Defining them explicitly overrides the default Attribute Inheritance behavior of Vue. Need to find a way to get around this