Skip to content

Components Reference

Vue component patterns and reference for ZapTracker.

Component Structure

All components use Vue 3 Composition API with <script setup>:

vue
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useComposable } from '../../composables/feature/useComposable.js'

// Props
const props = defineProps({
  propName: {
    type: String,
    required: true
  }
})

// Emits
const emit = defineEmits(['eventName'])

// Composables
const { data, loading } = useComposable()

// Local state
const localValue = ref('')

// Computed
const derivedValue = computed(() => {
  return localValue.value.toUpperCase()
})

// Methods
function handleAction() {
  emit('eventName', localValue.value)
}

// Lifecycle
onMounted(() => {
  // Initialize
})
</script>

<template>
  <div class="component-wrapper">
    <!-- Template -->
  </div>
</template>

<style scoped>
/* Component styles */
</style>

Analytics Components

Analytics.vue

Main analytics dashboard page.

Location: src/components/analytics/Analytics.vue

Features:

  • Time period selection
  • Zap volume charts
  • Top supporters list
  • Content performance

StatsCards.vue

Grid of statistic cards.

Props:

PropTypeDescription
statsArrayStats to display
loadingBooleanLoading state

Usage:

vue
<StatsCards :stats="statsArray" :loading="isLoading" />

Wallet Components

NWCConnection.vue

Nostr Wallet Connect setup component.

Location: src/components/wallet/NWCConnection.vue

Features:

  • NWC URL input
  • Connection status
  • Balance display
  • Error handling

Events:

EventPayloadDescription
connected{ pubkey }Wallet connected
error{ message }Connection error

Content Components

BlogEditor.vue

Rich text editor for long-form content.

Location: src/components/content/BlogEditor.vue

Props:

PropTypeDescription
initialContentStringStarting content
titleStringArticle title

Events:

EventPayloadDescription
publish{ title, content }Content published
save{ title, content }Draft saved

ContentList.vue

Displays list of user's content.

Props:

PropTypeDescription
itemsArrayContent items
filterStringFilter type

MentionInput.vue

Text input with @mention support.

Usage:

vue
<MentionInput
  v-model="text"
  @mention="handleMention"
  placeholder="Write something..."
/>

Audience Components

FollowListManager.vue

Manage follow lists (create, edit, delete).

Location: src/components/audience/FollowListManager.vue

FollowListCard.vue

Display a follow list.

Props:

PropTypeDescription
listObjectFollow list data
editableBooleanAllow editing

Campaign Components

CampaignCard.vue

Display campaign summary.

Props:

PropTypeDescription
campaignObjectCampaign data
compactBooleanCompact mode

CampaignCreateModal.vue

Modal for creating campaigns.

Events:

EventPayloadDescription
created{ campaign }Campaign created
close-Modal closed

ProfileModal.vue

View user profile in modal.

Props:

PropTypeDescription
pubkeyStringUser's public key
showBooleanShow/hide modal

ZapEventModal.vue

View zap details.

Props:

PropTypeDescription
zapObjectZap event data

Shared Components

EmptyStateDashboard.vue

Empty state display.

Props:

PropTypeDescription
messageStringDisplay message
iconStringIcon name

LoadingStateDashboard.vue

Loading skeleton display.

SkeletonCard.vue / SkeletonChart.vue

Skeleton loading states.

Usage:

vue
<SkeletonCard v-if="loading" />
<ActualContent v-else :data="data" />

Layout Components

Main navigation sidebar.

Features:

  • Navigation links
  • Active state
  • Collapse support

TopBar.vue

Top navigation bar.

Features:

  • User profile
  • Notifications
  • Quick actions

Component Patterns

Loading States

Always handle loading:

vue
<template>
  <SkeletonCard v-if="loading" />
  <div v-else-if="error" class="error">
    {{ error }}
  </div>
  <div v-else>
    <!-- Content -->
  </div>
</template>

Props Validation

Use detailed prop definitions:

javascript
const props = defineProps({
  amount: {
    type: Number,
    required: true,
    validator: (value) => value >= 0
  },
  status: {
    type: String,
    default: 'pending',
    validator: (value) => ['pending', 'active', 'complete'].includes(value)
  }
})

Event Handling

Use typed emits:

javascript
const emit = defineEmits({
  update: (value) => typeof value === 'string',
  submit: (data) => data && typeof data.id === 'string'
})

Styling

Tailwind Utilities

Use utility classes:

vue
<template>
  <div class="flex items-center gap-4 p-4 bg-orange-50 rounded-lg">
    <span class="text-lg font-semibold text-orange-700">
      {{ title }}
    </span>
  </div>
</template>

Scoped Styles

For complex styles:

vue
<style scoped>
.component-wrapper {
  /* Component-specific styles */
}
</style>