{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "integrations-logo-grid",
  "title": "Integrations — Logo Grid",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/integrations-logo-grid/IntegrationsLogoGrid.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { ArrowRight } from 'lucide-vue-next'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'\n\n// Monogram stand-ins: swap the `mark` for a real logo file per integration.\nconst integrations = [\n  { name: 'Snowflake', mark: 'SF', category: 'Warehouses' },\n  { name: 'BigQuery', mark: 'BQ', category: 'Warehouses' },\n  { name: 'Redshift', mark: 'RS', category: 'Warehouses' },\n  { name: 'Databricks', mark: 'DB', category: 'Warehouses' },\n  { name: 'Postgres', mark: 'PG', category: 'Warehouses' },\n  { name: 'Okta', mark: 'OK', category: 'Identity' },\n  { name: 'Entra ID', mark: 'EI', category: 'Identity' },\n  { name: 'Google Workspace', mark: 'GW', category: 'Identity' },\n  { name: 'Slack', mark: 'SL', category: 'Alerting' },\n  { name: 'PagerDuty', mark: 'PD', category: 'Alerting' },\n  { name: 'Opsgenie', mark: 'OG', category: 'Alerting' },\n  { name: 'dbt', mark: 'DT', category: 'Modelling' },\n  { name: 'Airflow', mark: 'AF', category: 'Modelling' },\n  { name: 'Dagster', mark: 'DG', category: 'Modelling' },\n  { name: 'Fivetran', mark: 'FT', category: 'Modelling' },\n  { name: 'Looker', mark: 'LK', category: 'Downstream' },\n  { name: 'Hex', mark: 'HX', category: 'Downstream' },\n  { name: 'Sigma', mark: 'SG', category: 'Downstream' },\n]\n\nconst ALL = 'All'\nconst categories = computed(() => [ALL, ...new Set(integrations.map((i) => i.category))])\nconst active = ref(ALL)\nconst visible = computed(() =>\n  active.value === ALL ? integrations : integrations.filter((i) => i.category === active.value),\n)\n\n// Single-select emits '' when the pressed item is pressed again; fall back to\n// ALL so the wall is never empty.\nfunction onChange(value: unknown) {\n  active.value = typeof value === 'string' && value ? value : ALL\n}\n</script>\n\n<template>\n  <section data-slot=\"integrations-logo-grid\" class=\"bg-background\">\n    <div class=\"mx-auto max-w-6xl px-6 py-20 lg:py-28\">\n      <div class=\"flex flex-wrap items-end justify-between gap-6\">\n        <div class=\"max-w-2xl\">\n          <Badge variant=\"secondary\">Integrations</Badge>\n          <h2 class=\"mt-4 text-3xl font-semibold tracking-tight sm:text-4xl\">Works with what you already run</h2>\n          <p class=\"text-muted-foreground mt-3 text-lg\">\n            Read-only connections, configured once. Nothing here needs an agent installed on your side.\n          </p>\n        </div>\n\n        <ToggleGroup\n          :model-value=\"active\"\n          type=\"single\"\n          variant=\"outline\"\n          size=\"sm\"\n          class=\"flex-nowrap overflow-x-auto\"\n          aria-label=\"Filter integrations by category\"\n          @update:model-value=\"onChange\"\n        >\n          <ToggleGroupItem v-for=\"category in categories\" :key=\"category\" :value=\"category\">\n            {{ category }}\n          </ToggleGroupItem>\n        </ToggleGroup>\n      </div>\n\n      <div\n        class=\"bg-border border-border mt-10 grid grid-cols-2 gap-px overflow-hidden rounded-xl border sm:grid-cols-4 lg:grid-cols-6\"\n      >\n        <div\n          v-for=\"integration in visible\"\n          :key=\"integration.name\"\n          class=\"bg-background hover:bg-muted/60 group flex aspect-square flex-col items-center justify-center gap-2 p-4 transition-colors\"\n        >\n          <span\n            class=\"border-border text-muted-foreground group-hover:text-foreground flex size-11 items-center justify-center rounded-lg border font-mono text-sm font-semibold transition-colors\"\n            aria-hidden=\"true\"\n          >\n            {{ integration.mark }}\n          </span>\n          <span class=\"text-muted-foreground group-hover:text-foreground text-center text-xs transition-colors\">\n            {{ integration.name }}\n          </span>\n        </div>\n      </div>\n\n      <div class=\"border-border mt-6 flex flex-wrap items-center justify-between gap-4 border-t pt-5\">\n        <p class=\"text-muted-foreground text-sm\">\n          {{ visible.length }} of {{ integrations.length }} integrations shown · more added every release.\n        </p>\n        <Button variant=\"ghost\" size=\"sm\">\n          Request an integration\n          <ArrowRight class=\"ml-1.5 size-3.5\" aria-hidden=\"true\" />\n        </Button>\n      </div>\n    </div>\n  </section>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/IntegrationsLogoGrid.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/toggle-group.json"
  ],
  "description": "Integration marquee grid: category chips filter a wall of square logo tiles with hover labels, over a count line and a request-an-integration prompt.",
  "categories": [
    "marketing"
  ]
}