Integrations — Logo Grid
blockmarketingIntegration marquee grid: category chips filter a wall of square logo tiles with hover labels, over a count line and a request-an-integration prompt.
Installation
$pnpm dlx uipkge-ng@latest add integrations-logo-grid$npx uipkge-ng@latest add integrations-logo-grid$yarn dlx uipkge-ng@latest add integrations-logo-grid$bunx uipkge-ng@latest add integrations-logo-gridManifest:
https://uipkge.dev/r/angular/integrations-logo-grid.jsonInstalls to:src/app/components/blocks/integrations-logo-grid/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
LogoIntegrationinterface LogoIntegration {
name: string
mark: string
category: string
}npm dependencies
Includes
Files installed (2)
src/app/components/blocks/integrations-logo-grid/integrations-logo-grid.component.ts5.7 kB
// 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. // Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core' import { ArrowRight, LucideAngularModule } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiToggleGroupComponent, UiToggleGroupItemComponent } from '@/ui/toggle-group/toggle-group.component' interface LogoIntegration { name: string mark: string category: string } // Monogram stand-ins: swap the `mark` for a real logo file per integration. const integrations: LogoIntegration[] = [ { name: 'Snowflake', mark: 'SF', category: 'Warehouses' }, { name: 'BigQuery', mark: 'BQ', category: 'Warehouses' }, { name: 'Redshift', mark: 'RS', category: 'Warehouses' }, { name: 'Databricks', mark: 'DB', category: 'Warehouses' }, { name: 'Postgres', mark: 'PG', category: 'Warehouses' }, { name: 'Okta', mark: 'OK', category: 'Identity' }, { name: 'Entra ID', mark: 'EI', category: 'Identity' }, { name: 'Google Workspace', mark: 'GW', category: 'Identity' }, { name: 'Slack', mark: 'SL', category: 'Alerting' }, { name: 'PagerDuty', mark: 'PD', category: 'Alerting' }, { name: 'Opsgenie', mark: 'OG', category: 'Alerting' }, { name: 'dbt', mark: 'DT', category: 'Modelling' }, { name: 'Airflow', mark: 'AF', category: 'Modelling' }, { name: 'Dagster', mark: 'DG', category: 'Modelling' }, { name: 'Fivetran', mark: 'FT', category: 'Modelling' }, { name: 'Looker', mark: 'LK', category: 'Downstream' }, { name: 'Hex', mark: 'HX', category: 'Downstream' }, { name: 'Sigma', mark: 'SG', category: 'Downstream' }, ] const ALL = 'All' const categories: string[] = [ALL, ...new Set(integrations.map((i) => i.category))] @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-integrations-logo-grid, [ui-integrations-logo-grid]', standalone: true, // React renders the root <section> itself: the host stays out of layout and `class` goes to the root. host: { '[attr.class]': '"contents"' }, imports: [ LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiToggleGroupComponent, UiToggleGroupItemComponent, ], template: ` <section data-slot="integrations-logo-grid" [class]="rootClass"> <div class="mx-auto max-w-6xl px-6 py-20 lg:py-28"> <div class="flex flex-wrap items-end justify-between gap-6"> <div class="max-w-2xl"> <span ui-badge variant="secondary">Integrations</span> <h2 class="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">Works with what you already run</h2> <p class="text-muted-foreground mt-3 text-lg"> Read-only connections, configured once. Nothing here needs an agent installed on your side. </p> </div> <div ui-toggle-group type="single" variant="outline" size="sm" class="flex-nowrap overflow-x-auto" aria-label="Filter integrations by category" [value]="active()" (valueChange)="onCategory($event)" > @for (category of allCategories; track category) { <button ui-toggle-group-item [value]="category">{{ category }}</button> } </div> </div> <div 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" > @for (integration of visible(); track integration.name) { <div class="bg-background hover:bg-muted/60 group flex aspect-square flex-col items-center justify-center gap-2 p-4 transition-colors" > <span 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" aria-hidden="true" > {{ integration.mark }} </span> <span class="text-muted-foreground group-hover:text-foreground text-center text-xs transition-colors"> {{ integration.name }} </span> </div> } </div> <div class="border-border mt-6 flex flex-wrap items-center justify-between gap-4 border-t pt-5"> <p class="text-muted-foreground text-sm"> {{ visible().length }} of {{ total }} integrations shown · more added every release. </p> <button ui-button variant="ghost" size="sm"> Request an integration <lucide-icon [img]="ArrowRight" class="ml-1.5 size-3.5" aria-hidden="true" /> </button> </div> </div> </section> `, }) export class UiIntegrationsLogoGridComponent { protected readonly ArrowRight = ArrowRight protected readonly allCategories = categories protected readonly total = integrations.length @Input('class') className?: string readonly active = signal<string>(ALL) readonly visible = computed(() => { const current = this.active() return current === ALL ? integrations : integrations.filter((i) => i.category === current) }) get rootClass(): string { return cn('bg-background', this.className) } onCategory(value: string | string[]): void { const next = Array.isArray(value) ? value[0] : value // Single-select emits '' when the pressed item is pressed again; // fall back to ALL so the wall is never empty. this.active.set(next || ALL) } }src/app/components/blocks/integrations-logo-grid/index.ts0.1 kB
export { UiIntegrationsLogoGridComponent } from './integrations-logo-grid.component'
Raw manifest:https://uipkge.dev/r/angular/integrations-logo-grid.json