Skip to content

Channel Topic Bar

A header bar showing the channel name and a truncating topic description.

A header bar showing the channel name and a truncating topic description. 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-channel-topic
import {
  ChannelTopic,
  ChannelTopicDescription,
  ChannelTopicDivider,
  ChannelTopicIcon,
  ChannelTopicName,
} from "@/registry/bases/newt/ui/channel-topic"

export default function ChannelTopicDemo() {
  return (
    <ChannelTopic className="w-full max-w-md">
      <ChannelTopicIcon />
      <ChannelTopicName>channel-name</ChannelTopicName>
      <ChannelTopicDivider />
      <ChannelTopicDescription>
        Channel topic description goes here
      </ChannelTopicDescription>
    </ChannelTopic>
  )
}
<script setup lang="ts">
import {
  ChannelTopic,
  ChannelTopicDescription,
  ChannelTopicDivider,
  ChannelTopicIcon,
  ChannelTopicName,
} from "~~/registry/bases/newt/ui/channel-topic"
</script>

<template>
  <ChannelTopic class="w-full max-w-md">
    <ChannelTopicIcon />
    <ChannelTopicName>channel-name</ChannelTopicName>
    <ChannelTopicDivider />
    <ChannelTopicDescription
      >Channel topic description goes here</ChannelTopicDescription
    >
  </ChannelTopic>
</template>

Installation

pnpm dlx newtui@latest add channel-topic
npx newtui@latest add channel-topic
yarn dlx newtui@latest add channel-topic
bunx newtui@latest add channel-topic

Copy the source into your project

import * as React from "react"

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

const ChannelTopic = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div">
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn(
      "flex min-w-0 items-center gap-2 border-b border-newt-border px-4 py-3 text-sm",
      className
    )}
    {...props}
  />
))
ChannelTopic.displayName = "ChannelTopic"

const ChannelTopicIcon = React.forwardRef<
  HTMLSpanElement,
  React.ComponentProps<"span">
>(({ className, children = "#", ...props }, ref) => (
  <span
    ref={ref}
    aria-hidden="true"
    className={cn("shrink-0 font-bold text-newt-text-muted", className)}
    {...props}
  >
    {children}
  </span>
))
ChannelTopicIcon.displayName = "ChannelTopicIcon"

const ChannelTopicName = React.forwardRef<
  HTMLSpanElement,
  React.ComponentProps<"span">
>(({ className, ...props }, ref) => (
  <span
    ref={ref}
    className={cn(
      "shrink-0 whitespace-nowrap font-bold text-newt-text-primary",
      className
    )}
    {...props}
  />
))
ChannelTopicName.displayName = "ChannelTopicName"

const ChannelTopicDivider = React.forwardRef<
  HTMLSpanElement,
  React.ComponentProps<"span">
>(({ className, ...props }, ref) => (
  <span
    ref={ref}
    aria-hidden="true"
    className={cn("h-[18px] w-px shrink-0 bg-newt-border", className)}
    {...props}
  />
))
ChannelTopicDivider.displayName = "ChannelTopicDivider"

const ChannelTopicDescription = React.forwardRef<
  HTMLSpanElement,
  React.ComponentProps<"span">
>(({ className, ...props }, ref) => (
  <span
    ref={ref}
    className={cn(
      "overflow-hidden text-ellipsis whitespace-nowrap text-[13px] text-newt-text-muted",
      className
    )}
    {...props}
  />
))
ChannelTopicDescription.displayName = "ChannelTopicDescription"

export {
  ChannelTopic,
  ChannelTopicIcon,
  ChannelTopicName,
  ChannelTopicDivider,
  ChannelTopicDescription,
}
<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 min-w-0 items-center gap-2 border-b border-newt-border px-4 py-3 text-sm',
        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>
  <span
    aria-hidden="true"
    :class="cn('shrink-0 font-bold text-newt-text-muted', props.class)"
  >
    <slot>#</slot>
  </span>
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

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

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

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

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

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

<template>
  <span
    aria-hidden="true"
    :class="cn('h-[18px] w-px shrink-0 bg-newt-border', props.class)"
  />
</template>
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

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

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

<template>
  <span
    :class="
      cn(
        'overflow-hidden text-ellipsis whitespace-nowrap text-[13px] text-newt-text-muted',
        props.class
      )
    "
  >
    <slot />
  </span>
</template>
export { default as ChannelTopic } from "./ChannelTopic.vue"
export { default as ChannelTopicIcon } from "./ChannelTopicIcon.vue"
export { default as ChannelTopicName } from "./ChannelTopicName.vue"
export { default as ChannelTopicDivider } from "./ChannelTopicDivider.vue"
export { default as ChannelTopicDescription } from "./ChannelTopicDescription.vue"

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 { ChannelTopic } from "@/components/ui/channel-topic"

export function Example() {
  return <ChannelTopic />
}
<script setup lang="ts">
import { ChannelTopic, ChannelTopicIcon, ChannelTopicName, ChannelTopicDivider, ChannelTopicDescription } from "@/components/ui/channel-topic"
</script>

<template>
  <ChannelTopic />
</template>

API reference

ChannelTopic

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 ChannelTopic, ChannelTopicIcon, ChannelTopicName, ChannelTopicDivider, ChannelTopicDescription. 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

Channel Topic Bar 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-channel-topic.