UIPackage
Menu

Framework

Change language

Boilerplate repo

Feature Visual Changelog Diff

blockfeature

Visual semantic git changelog with unified code diff highlighting and commit verification.

Also available for React ->

Installation

$npx shadcn-vue@latest add https://uipkge.dev/r/vue/feature-visual-changelog-diff.json
Named registry:npx shadcn-vue@latest add @uipkge/feature-visual-changelog-diffInstalls to:app/components/blocks/feature-visual-changelog-diff/

Variants

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
titlestring'Continuous evolution with transparent source-level chang…optional
descriptionstring'Every architectural improvementoptional
releasesChangelogRelease[]optional
classstringoptional

Schema

Type aliases exported from this item's source. Use these to shape the data you pass in.

ChangelogRelease
interface ChangelogRelease {
  version: string
  date: string
  title: string
  description: string
  commitSha: string
  diffLines: {
    type: 'add' | 'delete' | 'context'
    content: string
  }[]
}

npm dependencies

Includes

Files installed (2)

  • app/components/blocks/feature-visual-changelog-diff/FeatureVisualChangelogDiff.vue6.6 kB
    <script setup lang="ts">
    import { computed, ref } from 'vue'
    import { ArrowRight, Check, Copy, GitCommit, GitPullRequest } from 'lucide-vue-next'
    import { Badge } from '@/components/ui/badge'
    import { Card, CardContent } from '@/components/ui/card'
    import { cn } from '@/lib/utils'
    
    export interface ChangelogRelease {
      version: string
      date: string
      title: string
      description: string
      commitSha: string
      diffLines: {
        type: 'add' | 'delete' | 'context'
        content: string
      }[]
    }
    
    export interface FeatureVisualChangelogDiffProps {
      title?: string
      description?: string
      releases?: ChangelogRelease[]
      class?: string
    }
    
    const DEFAULT_RELEASES: ChangelogRelease[] = [
      {
        version: 'v2.4.0',
        date: 'August 2026',
        title: 'Tailwind CSS v4 & OKLCH Semantic Color Spaces',
        description:
          'Upgraded all cross-framework tokens to direct @theme inline CSS bindings. Eliminates legacy postcss configs.',
        commitSha: '7f9a2b1',
        diffLines: [
          { type: 'delete', content: '- module.exports = { theme: { extend: { colors: { ... } } } }' },
          { type: 'add', content: '+ @theme inline {' },
          { type: 'add', content: '+   --color-background: oklch(1 0 0);' },
          { type: 'add', content: '+   --color-primary: oklch(0.205 0 0);' },
          { type: 'add', content: '+ }' },
          { type: 'context', content: '  // Zero JavaScript compilation overhead in production bundles' },
        ],
      },
      {
        version: 'v2.3.0',
        date: 'July 2026',
        title: 'Headless Polymorphic Primitive Architecture',
        description: 'Unified Reka UI and Radix UI state machines across Vue 3.5 and React 19 mirrors.',
        commitSha: '4c8e1d9',
        diffLines: [
          { type: 'delete', content: '- import { Dialog } from "legacy-untyped-modal"' },
          { type: 'add', content: '+ import { DialogRoot, DialogPortal } from "reka-ui"' },
          { type: 'add', content: '+ <Primitive data-slot="dialog" :as="as">' },
          { type: 'context', content: '  // Full WCAG AA focus trapping and keyboard navigation' },
        ],
      },
    ]
    
    const props = withDefaults(defineProps<FeatureVisualChangelogDiffProps>(), {
      title: 'Continuous evolution with transparent source-level changelogs.',
      description:
        'Every architectural improvement, performance optimization, and token adjustment documented with precise git diffs.',
    })
    
    const activeReleases = computed(() => props.releases ?? DEFAULT_RELEASES)
    
    const copiedSha = ref<string | null>(null)
    
    async function copySha(sha: string) {
      try {
        await navigator.clipboard.writeText(sha)
        copiedSha.value = sha
        setTimeout(() => {
          copiedSha.value = null
        }, 2000)
      } catch {
        // fallback
      }
    }
    </script>
    
    <template>
      <section
        data-slot="feature-visual-changelog-diff"
        :class="cn('bg-background relative overflow-hidden py-16 sm:py-24', props.class)"
      >
        <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
          <!-- Section Header -->
          <div class="mx-auto max-w-3xl space-y-4 text-center">
            <a
              href="#changelog"
              class="group border-border/80 bg-secondary/60 hover:bg-secondary text-foreground inline-flex items-center gap-2 rounded-full border px-3.5 py-1 text-xs font-medium shadow-2xs transition-colors"
            >
              <GitPullRequest class="text-primary size-3.5" />
              <span>Continuous Release Ledger</span>
              <ArrowRight class="text-muted-foreground size-3 transition-transform group-hover:translate-x-0.5" />
            </a>
    
            <h2 class="text-foreground text-3xl font-bold tracking-tight sm:text-4xl">
              {{ title }}
            </h2>
    
            <p class="text-muted-foreground text-base sm:text-lg">
              {{ description }}
            </p>
          </div>
    
          <!-- Changelog Timeline Entries -->
          <div class="mx-auto mt-12 max-w-4xl space-y-8">
            <Card
              v-for="rel in activeReleases"
              :key="rel.version"
              class="border-border bg-card/80 overflow-hidden shadow-xs backdrop-blur-xs"
            >
              <CardContent class="space-y-5 p-6">
                <!-- Header Bar -->
                <div class="border-border flex flex-wrap items-center justify-between gap-2 border-b pb-3">
                  <div class="flex items-center gap-2.5">
                    <Badge
                      variant="outline"
                      class="border-primary/40 bg-primary/10 text-primary font-mono text-xs font-bold"
                    >
                      {{ rel.version }}
                    </Badge>
                    <span class="text-foreground text-sm font-bold">{{ rel.title }}</span>
                  </div>
    
                  <div class="flex items-center gap-2">
                    <span class="text-muted-foreground font-mono text-xs">{{ rel.date }}</span>
                    <button
                      type="button"
                      class="border-border bg-muted/30 text-muted-foreground hover:text-foreground inline-flex items-center gap-1 rounded border px-2 py-0.5 font-mono text-xs transition-colors"
                      @click="copySha(rel.commitSha)"
                    >
                      <GitCommit class="text-primary size-3" />
                      <span>{{ rel.commitSha }}</span>
                      <Check v-if="copiedSha === rel.commitSha" class="text-success ml-0.5 size-3" />
                      <Copy v-else class="ml-0.5 size-3" />
                    </button>
                  </div>
                </div>
    
                <p class="text-muted-foreground text-xs leading-relaxed">
                  {{ rel.description }}
                </p>
    
                <!-- Code Diff Box -->
                <div class="border-border bg-muted/40 overflow-hidden rounded-lg border font-mono text-xs">
                  <div
                    class="border-border/80 bg-muted/60 text-muted-foreground flex items-center justify-between border-b px-3 py-1.5 text-xs font-bold"
                  >
                    <span>Unified Source Diff</span>
                    <span class="text-success text-xs font-normal">Git verified</span>
                  </div>
                  <div class="space-y-1 overflow-x-auto p-3 text-xs">
                    <div
                      v-for="(line, lIdx) in rel.diffLines"
                      :key="lIdx"
                      :class="
                        cn(
                          'rounded px-2 py-0.5 leading-relaxed',
                          line.type === 'add'
                            ? 'bg-success/10 text-success font-medium'
                            : line.type === 'delete'
                              ? 'bg-destructive/10 text-destructive text-destructive line-through opacity-80'
                              : 'text-muted-foreground',
                        )
                      "
                    >
                      {{ line.content }}
                    </div>
                  </div>
                </div>
              </CardContent>
            </Card>
          </div>
        </div>
      </section>
    </template>
    
  • app/components/blocks/feature-visual-changelog-diff/index.ts0.2 kB

Raw manifest:https://uipkge.dev/r/vue/feature-visual-changelog-diff.json