Skip to content

Role Tag

A compact bordered tag with a coloured dot for displaying a member's role.

A compact bordered tag with a coloured dot for displaying a member’s role. 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-role-tag
import { RoleTag, RoleTagDot } from "@/registry/bases/newt/ui/role-tag"

export default function RoleTagDemo() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <RoleTag>
        <RoleTagDot />
        Role name
      </RoleTag>
      <RoleTag color="#5865f2">
        <RoleTagDot />
        Admin
      </RoleTag>
      <RoleTag color="#23a55a">
        <RoleTagDot />
        Moderator
      </RoleTag>
    </div>
  )
}
<script setup lang="ts">
import { RoleTag, RoleTagDot } from "~~/registry/bases/newt/ui/role-tag"
</script>

<template>
  <div class="flex flex-wrap items-center gap-2">
    <RoleTag>
      <RoleTagDot />
      Role name
    </RoleTag>
    <RoleTag color="#5865f2">
      <RoleTagDot />
      Admin
    </RoleTag>
    <RoleTag color="#23a55a">
      <RoleTagDot />
      Moderator
    </RoleTag>
  </div>
</template>

Installation

pnpm dlx newtui@latest add role-tag
npx newtui@latest add role-tag
yarn dlx newtui@latest add role-tag
bunx newtui@latest add role-tag

Copy the source into your project

import * as React from "react"

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

export interface RoleTagProps extends React.ComponentProps<"span"> {
  /** Role colour applied to the tag; the dot inherits it via `currentColor`. */
  color?: string
}

const RoleTag = React.forwardRef<HTMLSpanElement, RoleTagProps>(
  ({ className, color, style, ...props }, ref) => (
    <span
      ref={ref}
      className={cn(
        "inline-flex items-center gap-1 rounded-sm border border-newt-border bg-newt-bg-elevated px-1.5 py-0.5 text-[11px] font-semibold",
        className
      )}
      style={color ? { color, ...style } : style}
      {...props}
    />
  )
)
RoleTag.displayName = "RoleTag"

const RoleTagDot = React.forwardRef<
  HTMLSpanElement,
  React.ComponentProps<"span">
>(({ className, ...props }, ref) => (
  <span
    ref={ref}
    aria-hidden="true"
    className={cn("h-2 w-2 rounded-full bg-current", className)}
    {...props}
  />
))
RoleTagDot.displayName = "RoleTagDot"

export { RoleTag, RoleTagDot }
<script setup lang="ts">
import type { HTMLAttributes } from "vue"

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

const props = defineProps<{
  /** Role colour applied to the tag; the dot inherits it via `currentColor`. */
  color?: string
  class?: HTMLAttributes["class"]
}>()
</script>

<template>
  <span
    :class="
      cn(
        'inline-flex items-center gap-1 rounded-sm border border-newt-border bg-newt-bg-elevated px-1.5 py-0.5 text-[11px] font-semibold',
        props.class
      )
    "
    :style="props.color ? { color: props.color } : undefined"
  >
    <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-2 w-2 rounded-full bg-current', props.class)"
  />
</template>
export { default as RoleTag } from "./RoleTag.vue"
export { default as RoleTagDot } from "./RoleTagDot.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 { RoleTag } from "@/components/ui/role-tag"

export function Example() {
  return <RoleTag />
}
<script setup lang="ts">
import { RoleTag, RoleTagDot } from "@/components/ui/role-tag"
</script>

<template>
  <RoleTag />
</template>

API reference

RoleTag

PropType
color?string | undefined

Role colour applied to the tag; the dot inherits it via `currentColor`.

Typestring | undefined

The registry exports RoleTag, RoleTagDot. 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

Role Tag 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-role-tag.