Skip to content

V2 Container

The Components V2 block that groups text, separators and action rows behind one accent bar.

The Components V2 block that groups text, separators and action rows behind one accent bar. Compose it from the exported registry parts so local content and behaviour stay in the application while the visual contract stays token-driven.

import { ActionRow } from "@/registry/bases/newt/ui/action-row"
import { Button } from "@/registry/bases/newt/ui/button"
import { Divider } from "@/registry/bases/newt/ui/divider"
import { V2Container } from "@/registry/bases/newt/ui/v2-container"

export default function V2ContainerDemo() {
  return (
    <V2Container accentColor="var(--newt-brand)">
      <strong>Server rules</strong>
      <Divider spacing="sm" />
      <span>
        Be kind, keep it on topic, and read the pinned messages before asking.
      </span>
      <ActionRow aria-label="Rules actions">
        <Button variant="primary">I agree</Button>
        <Button variant="link">Read more</Button>
      </ActionRow>
    </V2Container>
  )
}
<script setup lang="ts">
import { ActionRow } from "~~/registry/bases/newt/ui/action-row"
import { Button } from "~~/registry/bases/newt/ui/button"
import { Divider } from "~~/registry/bases/newt/ui/divider"
import { V2Container } from "~~/registry/bases/newt/ui/v2-container"
</script>

<template>
  <V2Container accent-color="var(--newt-brand)">
    <strong>Server rules</strong>
    <Divider spacing="sm" />
    <span>
      Be kind, keep it on topic, and read the pinned messages before asking.
    </span>
    <ActionRow aria-label="Rules actions">
      <Button variant="primary">I agree</Button>
      <Button variant="link">Read more</Button>
    </ActionRow>
  </V2Container>
</template>

Installation

pnpm dlx newtui@latest add v2-container
npx newtui@latest add v2-container
yarn dlx newtui@latest add v2-container
bunx newtui@latest add v2-container

Copy the source into your project

import * as React from "react"

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

export interface V2ContainerProps extends React.ComponentProps<"div"> {
  /** Accent colour of the left bar; defaults to the surface border. */
  accentColor?: string
}

/*
 * The Components V2 container: an accent-barred block that groups text,
 * separators and action rows inside a single message.
 */
const V2Container = React.forwardRef<HTMLDivElement, V2ContainerProps>(
  ({ className, accentColor, style, ...props }, ref) => (
    <div
      ref={ref}
      className={cn(
        "mt-1 flex max-w-[520px] flex-col gap-2 rounded-sm border-s-4 border-[var(--newt-v2-accent)] bg-newt-bg-surface p-3 text-sm leading-relaxed text-newt-text-primary",
        className
      )}
      /*
       * SAFETY: `CSSProperties` has no index signature for custom properties,
       * but React forwards unknown `--*` keys to the style attribute verbatim,
       * so the extra key is written out exactly as spelled here.
       */
      style={
        {
          ...style,
          "--newt-v2-accent": accentColor ?? "var(--newt-border)",
        } as React.CSSProperties
      }
      {...props}
    />
  )
)
V2Container.displayName = "V2Container"

export { V2Container }
<script setup lang="ts">
import type { CSSProperties, HTMLAttributes } from "vue"
import { computed } from "vue"

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

const props = defineProps<{
  class?: HTMLAttributes["class"]
  /** Accent colour of the left bar; defaults to the surface border. */
  accentColor?: string
}>()

const style = computed(
  () =>
    // SAFETY: Vue forwards unknown `--*` keys to the DOM verbatim, so a custom
    // property is a valid style entry even though the type omits it.
    ({
      "--newt-v2-accent": props.accentColor ?? "var(--newt-border)",
    }) as CSSProperties
)
</script>

<template>
  <!--
    The Components V2 container: an accent-barred block that groups text,
    separators and action rows inside a single message.
  -->
  <div
    :style="style"
    :class="
      cn(
        'mt-1 flex max-w-[520px] flex-col gap-2 rounded-sm border-s-4 border-[var(--newt-v2-accent)] bg-newt-bg-surface p-3 text-sm leading-relaxed text-newt-text-primary',
        props.class
      )
    "
  >
    <slot />
  </div>
</template>
export { default as V2Container } from "./V2Container.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 { V2Container } from "@/components/ui/v2-container"

export function Example() {
  return <V2Container />
}
<script setup lang="ts">
import { V2Container } from "@/components/ui/v2-container"
</script>

<template>
  <V2Container />
</template>

API reference

V2Container

PropType
accentColor?string | undefined

Accent colour of the left bar; defaults to the surface border.

Typestring | undefined

The registry exports V2Container. 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

V2 Container 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.