npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nonsuch/component-library

v0.11.0

Published

A Vue 3 component library built on Quasar with opinionated defaults and custom components.

Readme

@nonsuch/component-library

A Vue 3 component library built on top of Quasar, providing customized components with opinionated defaults.

Quasar components you haven't customized are used directly — this library only adds or overrides the ones with Nonsuch-specific styling and behavior. Tree-shaking is fully preserved.

Installation

# Install the library and its peer dependencies
pnpm add @nonsuch/component-library
pnpm add quasar @quasar/extras @quasar/vite-plugin

Quick Start (Recommended)

Vite Configuration

import { quasar, transformAssetUrls } from '@quasar/vite-plugin'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue({ template: { transformAssetUrls } }), quasar()],
})

App Entry

import { createApp } from 'vue'
import { Quasar } from 'quasar'
import { createNonsuch, createQuasarConfig } from '@nonsuch/component-library'
import '@nonsuch/component-library/tokens.css'
import 'quasar/src/css/index.sass'

const app = createApp(App)
app.use(Quasar, createQuasarConfig()) // Token-aligned Quasar brand colours
app.use(createNonsuch()) // Locale + library setup
app.mount('#app')

That's it — components, tokens, locale (defaults to en-CA), and Quasar brand colours are all wired up.

Use Components

<script setup>
import { NsButton, NsInput, NsCard } from '@nonsuch/component-library'
</script>

<template>
  <NsCard title="Welcome">
    <NsInput v-model="name" label="Your name" />
    <template #actions>
      <NsButton label="Submit" />
    </template>
  </NsCard>
</template>

Plugin Options

createNonsuch() accepts options for locale:

import { createNonsuch, nsLocaleFrCA } from '@nonsuch/component-library'

app.use(createNonsuch({ locale: nsLocaleFrCA }))

createQuasarConfig() accepts brand colour overrides and extra Quasar config:

import { createQuasarConfig } from '@nonsuch/component-library'

app.use(
  Quasar,
  createQuasarConfig({
    brand: { primary: '#1a73e8' },
    plugins: { Notify: {} },
  }),
)

Dark Mode

import { useNsDarkMode } from '@nonsuch/component-library'

const { isDark, toggle, useSystem } = useNsDarkMode()

The composable persists the user's choice to localStorage and syncs with prefers-color-scheme. Design tokens switch automatically via the dark class on <html>.

NsThemeProvider

For section-level locale overrides without a plugin:

<script setup>
import { NsThemeProvider, nsLocaleFrCA } from '@nonsuch/component-library'
</script>

<template>
  <NsThemeProvider :locale="nsLocaleFrCA">
    <!-- All Ns components here use French strings -->
  </NsThemeProvider>
</template>

Manual Setup (Advanced)

Fonts (Optional)

The library ships Fixel as the Nonsuch brand font with Roboto as a fallback. Three integration options:

Option 1: Global CSS (recommended) — makes Fixel the default for your entire app:

import '@nonsuch/component-library/fonts/global.css'

This loads all @font-face declarations and sets Fixel Text on body and Fixel Display on headings.

Option 2: Font faces only — load the fonts without applying them globally, then use them where you choose:

import '@nonsuch/component-library/fonts.css'
.my-element {
  font-family: 'Fixel Text', 'Roboto', sans-serif;
}

Option 3: Quasar Sass variables — integrates with Quasar's typography system:

// src/quasar-variables.sass
@use '@nonsuch/component-library/fonts/quasar-overrides' as *
// vite.config.ts
quasar({ sassVariables: 'src/quasar-variables.sass' })

Or use Quasar components directly — they aren't re-exported through this library, so you import them from quasar as normal:

import { QInput, QSelect } from 'quasar'

Translations (i18n)

The library ships its own locale system — no dependency on vue-i18n. Components that render user-visible text accept optional string props with built-in defaults from the active locale.

Built-in locales: en-CA (default) and fr-CA.

Option 1: Use the defaults — components use English (Canada) strings out of the box with no setup:

<NsButton>Add to cart</NsButton>
<!-- internal labels like loading text already default to English -->

Option 2: Switch locale globally — provide a locale pack at the app root:

import { createApp } from 'vue'
import { provideNsLocale, nsLocaleFrCA } from '@nonsuch/component-library'

const app = createApp(App)

// Inside your root component's setup():
provideNsLocale(nsLocaleFrCA)

Option 3: Custom / partial locale — supply your own translations by implementing the NsLocaleMessages interface:

import type { NsLocaleMessages } from '@nonsuch/component-library'
import { nsLocaleEnCA, provideNsLocale } from '@nonsuch/component-library'

const myLocale: NsLocaleMessages = {
  ...nsLocaleEnCA,
  product: {
    ...nsLocaleEnCA.product,
    addToCart: 'Add to bag', // override just what you need
  },
}

provideNsLocale(myLocale)

Option 4: Override per-component — pass a string prop directly to bypass the locale:

<!-- This label is always "Ajouter" regardless of the active locale -->
<NsButton label="Ajouter" />

The locale interface covers four sections: common, product, media, and validation. See the full type in NsLocaleMessages.

Design Tokens (Optional)

Import CSS custom properties for colours, typography, spacing, border-radius, shadows, and motion:

import '@nonsuch/component-library/tokens.css'

All tokens use the --ns- prefix and support light/dark mode automatically. Current values are placeholders — token names are stable.

.my-card {
  border-radius: var(--ns-radius-md);
  box-shadow: var(--ns-shadow-sm);
  padding: var(--ns-space-4);
}

Dark mode activates via class="dark", data-theme="dark", Quasar's .q-dark, or prefers-color-scheme: dark.

Breakpoints

The library ships Quasar-aligned breakpoint values and media-query helpers:

import {
  nsBreakpoints,
  nsMediaUp,
  nsMediaDown,
  nsMediaOnly,
  nsMediaBetween,
} from '@nonsuch/component-library'

| Name | Min-width | Range | Note | | ---- | --------- | -------------- | ----- | | xs | 0 | 0 – 599 px | | | sm | 600 | 600 – 1023 px | | | md | 1024 | 1024 – 1439 px | | | lg | 1440 | 1440 – 1919 px | | | xl | 1920 | 1920 – 2559 px | | | xxl | 2560 | 2560 – 3839 px | 1440p | | xxxl | 3840 | 3840 px + | 4K |

Media-query helpers return matchMedia()-ready strings:

nsMediaUp('md') // '(min-width: 1024px)'
nsMediaDown('md') // '(max-width: 1023px)'
nsMediaOnly('md') // '(min-width: 1024px) and (max-width: 1439px)'
nsMediaBetween('sm', 'lg') // '(min-width: 600px) and (max-width: 1919px)'

To customize in the future, spread and override:

const custom = { ...nsBreakpoints, lg: 1280 }

Development

# Install dependencies
pnpm install

# Run Storybook (dev mode)
pnpm dev

# Run tests
pnpm test
pnpm test:watch

# Build the library
pnpm build

# Build Storybook for deployment
pnpm build:storybook

Project Structure

src/
  index.ts                # Library entry — exports all public API
  manifest.ts             # Quasar → Ns component mapping for sync enforcement
  plugin.ts               # createNonsuch() Vue plugin
  quasarConfig.ts         # createQuasarConfig() helper
  components/
    NsAvatar/             # Avatar with size presets
    NsBadge/              # Styled QBadge wrapper
    NsBanner/             # Info/success/warning/error banners
    NsBreadcrumbs/        # Breadcrumb navigation
    NsBreadcrumbElement/  # Individual breadcrumb item
    NsButton/             # Styled QBtn wrapper
    NsButtonToggle/       # Toggle between button options
    NsCard/               # Card with title/subtitle/actions slots
    NsCardActions/        # Card action bar
    NsCardSection/        # Card content section
    NsCheckbox/           # Styled QCheckbox wrapper
    NsChip/               # Tag/filter chip
    NsDialog/             # Modal dialog with header/body/actions
    NsDrawer/             # Side drawer (within NsLayout)
    NsExpansionItem/      # Collapsible list item
    NsFooter/             # App footer (within NsLayout)
    NsForm/               # Form wrapper with validation
    NsHeader/             # App header (within NsLayout)
    NsIcon/               # Styled QIcon wrapper
    NsImage/              # Styled QImg wrapper
    NsInnerLoading/       # Overlay loading indicator
    NsInput/              # Styled QInput wrapper
    NsItem/               # List item
    NsItemLabel/          # List item label
    NsItemSection/        # List item section
    NsLayout/             # App layout container
    NsLinearProgress/     # Linear progress bar
    NsList/               # List with separator defaults
    NsMenu/               # Dropdown/context menu
    NsPage/               # Page content area
    NsPageContainer/      # Page container (within NsLayout)
    NsPagination/         # Page navigation controls
    NsSelect/             # Styled QSelect dropdown
    NsSeparator/          # Horizontal/vertical separator
    NsSkeleton/           # Loading skeleton with animation
    NsSpace/              # Flex spacer
    NsSpinner/            # Circular spinner
    NsSpinnerDots/        # Dot-style spinner
    NsTab/                # Tab item (within NsTabs)
    NsTabPanel/           # Tab panel content
    NsTabPanels/          # Tab panels container
    NsTable/              # Data table
    NsTableCell/          # Table cell
    NsTabs/               # Tab navigation bar
    NsThemeProvider/      # Renderless locale provider
    NsTimeline/           # Timeline container
    NsTimelineEntry/      # Timeline entry item
    NsToggle/             # Styled QToggle switch
    NsToolbar/            # Toolbar container
    NsToolbarTitle/       # Toolbar title
    NsTooltip/            # Tooltip with consistent delays
  composables/
    useNsLocale.ts        # Locale injection/provision
    useNsDarkMode.ts      # Dark mode with persistence
    useNsDefaults.ts      # Default value helper
  locale/                 # en-CA, fr-CA string packs
  breakpoints/            # Breakpoint values + media query helpers
  tokens/                 # Design token CSS + TS helpers
  fonts/                  # Fixel font files + CSS

Each custom component lives in its own directory with co-located story and test files. The Ns prefix distinguishes library components from Quasar's Q prefix.

Adding a New Component

  1. Create src/components/NsMyComponent/NsMyComponent.vue
  2. Add a story: NsMyComponent.stories.ts
  3. Add tests: NsMyComponent.test.ts
  4. Add a re-export: index.ts
  5. Export from src/index.ts

Architecture

  • Quasar is a peer dependency — consumers install it normally and get full tree-shaking via @quasar/vite-plugin
  • Custom components compose Quasar — they wrap or extend Quasar components with opinionated defaults
  • Vite library mode — builds to ES modules with externalized vue and quasar
  • TypeScript — strict mode with emitted .d.ts declarations

Contributing

Want to add or improve components? Check out CONTRIBUTING.md for a friendly step-by-step guide — no deep Vue experience required!

License

MIT — see LICENSE