Skip to content

Server Banner

Invite-style card with a server icon, name, live member counts and a join button.

Invite-style card with a server icon, name, live member counts and a join button. Compose it from the exported registry parts so local content and behaviour stay in the application while the visual contract stays token-driven.

Root class newt-server-banner
import { Button } from "@/registry/bases/newt/ui/button"
import {
  ServerBanner,
  ServerBannerIcon,
  ServerBannerInfo,
  ServerBannerMeta,
  ServerBannerMetaItem,
  ServerBannerName,
} from "@/registry/bases/newt/ui/server-banner"

export default function ServerBannerDemo() {
  return (
    <ServerBanner>
      <ServerBannerIcon>N</ServerBannerIcon>
      <ServerBannerInfo>
        <ServerBannerName>Server name</ServerBannerName>
        <ServerBannerMeta>
          <ServerBannerMetaItem status="online">
            142 Online
          </ServerBannerMetaItem>
          <ServerBannerMetaItem status="offline">
            1,024 Members
          </ServerBannerMetaItem>
        </ServerBannerMeta>
      </ServerBannerInfo>
      <Button variant="primary">Join</Button>
    </ServerBanner>
  )
}
<script setup lang="ts">
import { Button } from "~~/registry/bases/newt/ui/button"
import {
  ServerBanner,
  ServerBannerIcon,
  ServerBannerInfo,
  ServerBannerMeta,
  ServerBannerMetaItem,
  ServerBannerName,
} from "~~/registry/bases/newt/ui/server-banner"
</script>

<template>
  <ServerBanner>
    <ServerBannerIcon>N</ServerBannerIcon>
    <ServerBannerInfo>
      <ServerBannerName>Server name</ServerBannerName>
      <ServerBannerMeta>
        <ServerBannerMetaItem status="online">142 Online</ServerBannerMetaItem>
        <ServerBannerMetaItem status="offline"
          >1,024 Members</ServerBannerMetaItem
        >
      </ServerBannerMeta>
    </ServerBannerInfo>
    <Button variant="primary">Join</Button>
  </ServerBanner>
</template>

Installation

pnpm dlx newtui@latest add server-banner
npx newtui@latest add server-banner
yarn dlx newtui@latest add server-banner
bunx newtui@latest add server-banner

Install the dependencies

pnpm dlx --yes class-variance-authority
npx --yes class-variance-authority
yarn dlx --yes class-variance-authority
bunx --yes class-variance-authority

Add the components it builds on

Copy the source into your project

import { cva, type VariantProps } from "class-variance-authority"
import * as React from "react"

import { cn } from "@/lib/utils"

const ServerBanner = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn(
      "flex max-w-[480px] items-center gap-4 rounded-lg border border-newt-border bg-newt-bg-elevated px-5 py-4",
      className
    )}
    {...props}
  />
))
ServerBanner.displayName = "ServerBanner"

const ServerBannerIcon = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    aria-hidden="true"
    className={cn(
      "flex h-14 w-14 shrink-0 items-center justify-center rounded-lg bg-newt-brand text-[22px] font-bold text-white",
      className
    )}
    {...props}
  />
))
ServerBannerIcon.displayName = "ServerBannerIcon"

const ServerBannerInfo = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div ref={ref} className={cn("min-w-0 flex-1", className)} {...props} />
))
ServerBannerInfo.displayName = "ServerBannerInfo"

const ServerBannerName = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("text-base font-bold text-newt-text-primary", className)}
    {...props}
  />
))
ServerBannerName.displayName = "ServerBannerName"

const ServerBannerMeta = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn(
      "mt-[2px] flex items-center gap-3 text-[13px] text-newt-text-muted",
      className
    )}
    {...props}
  />
))
ServerBannerMeta.displayName = "ServerBannerMeta"

const serverBannerDotVariants = cva("h-2 w-2 shrink-0 rounded-full", {
  variants: {
    status: {
      online: "bg-newt-online",
      offline: "bg-newt-offline",
    },
  },
  defaultVariants: {
    status: "offline",
  },
})

export interface ServerBannerMetaItemProps
  extends
    React.HTMLAttributes<HTMLSpanElement>,
    VariantProps<typeof serverBannerDotVariants> {}

const ServerBannerMetaItem = React.forwardRef<
  HTMLSpanElement,
  ServerBannerMetaItemProps
>(({ className, status, children, ...props }, ref) => (
  <span
    ref={ref}
    className={cn("flex items-center gap-[5px]", className)}
    {...props}
  >
    <span className={serverBannerDotVariants({ status })} aria-hidden="true" />
    {children}
  </span>
))
ServerBannerMetaItem.displayName = "ServerBannerMetaItem"

export {
  ServerBanner,
  ServerBannerIcon,
  ServerBannerInfo,
  ServerBannerName,
  ServerBannerMeta,
  ServerBannerMetaItem,
  serverBannerDotVariants,
}
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>

<template>
  <div
    :class="
      cn(
        'flex max-w-[480px] items-center gap-4 rounded-lg border border-newt-border bg-newt-bg-elevated px-5 py-4',
        props.class
      )
    "
  >
    <slot />
  </div>
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>

<template>
  <div
    aria-hidden="true"
    :class="
      cn(
        'flex h-14 w-14 shrink-0 items-center justify-center rounded-lg bg-newt-brand text-[22px] font-bold text-white',
        props.class
      )
    "
  >
    <slot />
  </div>
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>

<template>
  <div :class="cn('min-w-0 flex-1', props.class)">
    <slot />
  </div>
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>

<template>
  <div :class="cn('text-base font-bold text-newt-text-primary', props.class)">
    <slot />
  </div>
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>

<template>
  <div
    :class="
      cn(
        'mt-[2px] flex items-center gap-3 text-[13px] text-newt-text-muted',
        props.class
      )
    "
  >
    <slot />
  </div>
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

import { cn } from "@/lib/utils"

import { serverBannerDotVariants, type ServerBannerDotVariants } from "."

const props = defineProps<{
  class?: HTMLAttributes["class"]
  status?: ServerBannerDotVariants["status"]
}>()
</script>

<template>
  <span :class="cn('flex items-center gap-[5px]', props.class)">
    <span :class="serverBannerDotVariants({ status })" aria-hidden="true" />
    <slot />
  </span>
</template>
import { cva, type VariantProps } from "class-variance-authority"

export { default as ServerBanner } from "./ServerBanner.vue"
export { default as ServerBannerIcon } from "./ServerBannerIcon.vue"
export { default as ServerBannerInfo } from "./ServerBannerInfo.vue"
export { default as ServerBannerName } from "./ServerBannerName.vue"
export { default as ServerBannerMeta } from "./ServerBannerMeta.vue"
export { default as ServerBannerMetaItem } from "./ServerBannerMetaItem.vue"

export const serverBannerDotVariants = cva("h-2 w-2 shrink-0 rounded-full", {
  variants: {
    status: {
      online: "bg-newt-online",
      offline: "bg-newt-offline",
    },
  },
  defaultVariants: {
    status: "offline",
  },
})

export type ServerBannerDotVariants = VariantProps<
  typeof serverBannerDotVariants
>

Update the import paths

The files import @/lib/utils and sibling components through the aliases in your components.json. Point them at wherever those live in your project.

Usage

import { ServerBanner } from "@/components/ui/server-banner"

export function Example() {
  return <ServerBanner />
}
<script setup lang="ts">
import { ServerBanner, ServerBannerIcon, ServerBannerInfo, ServerBannerName, ServerBannerMeta, ServerBannerMetaItem } from "@/components/ui/server-banner"
</script>

<template>
  <ServerBanner />
</template>

API reference

ServerBanner

PropType
children / default slot?React.ReactNode / Vue slot

Content rendered inside the component.

TypeReact.ReactNode / Vue slot
className / class?string

Additional classes merged with the component defaults.

Typestring

The registry exports ServerBanner, ServerBannerIcon, ServerBannerInfo, ServerBannerName, ServerBannerMeta, ServerBannerMetaItem. Parts without a table accept the native attributes for the element they render; React uses className, while Vue uses class and fallthrough attributes.

Accessibility

Preserve the native semantics of the rendered elements and pass through ARIA attributes when the surrounding context needs a label or description. Any interactive child needs a visible focus indicator, and meaning must not rely on colour alone.

Tokens

Server Banner reads its colours, radii and motion from the --newt-* tokens installed with the library. Override a token and every component that reads it follows, including this one — see the token layer. In the plain HTML and CSS distribution the same component is newt-server-banner.