Attachment Card
File card showing a type icon, file name, size and a download action.
File card showing a type icon, file name, size and a download action. Compose it from the exported registry parts so local content and behaviour stay in the application while the visual contract stays token-driven.
newt-attachmentimport {
Attachment,
AttachmentIcon,
AttachmentMeta,
AttachmentName,
AttachmentSize,
} from "@/registry/bases/newt/ui/attachment"
import { Button } from "@/registry/bases/newt/ui/button"
export default function AttachmentDemo() {
return (
<Attachment>
<AttachmentIcon>FILE</AttachmentIcon>
<AttachmentMeta>
<AttachmentName>filename.ext</AttachmentName>
<AttachmentSize>1.2 MB</AttachmentSize>
</AttachmentMeta>
<Button variant="secondary" size="icon" aria-label="Download file">
⬇
</Button>
</Attachment>
)
}<script setup lang="ts">
import {
Attachment,
AttachmentIcon,
AttachmentMeta,
AttachmentName,
AttachmentSize,
} from "~~/registry/bases/newt/ui/attachment"
import { Button } from "~~/registry/bases/newt/ui/button"
</script>
<template>
<Attachment>
<AttachmentIcon>FILE</AttachmentIcon>
<AttachmentMeta>
<AttachmentName>filename.ext</AttachmentName>
<AttachmentSize>1.2 MB</AttachmentSize>
</AttachmentMeta>
<Button variant="secondary" size="icon" aria-label="Download file"
>⬇</Button
>
</Attachment>
</template>Installation
pnpm dlx newtui@latest add attachmentnpx newtui@latest add attachmentyarn dlx newtui@latest add attachmentbunx newtui@latest add attachmentAdd the components it builds on
Copy the source into your project
import * as React from "react"
import { cn } from "@/lib/utils"
const Attachment = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"flex max-w-[360px] items-center gap-3 rounded-md border border-newt-border bg-newt-bg-surface px-3 py-[10px]",
className
)}
{...props}
/>
))
Attachment.displayName = "Attachment"
const AttachmentIcon = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
aria-hidden="true"
className={cn(
"flex h-9 w-9 shrink-0 items-center justify-center rounded-sm bg-newt-brand font-mono text-xs font-bold text-white",
className
)}
{...props}
/>
))
AttachmentIcon.displayName = "AttachmentIcon"
const AttachmentMeta = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("min-w-0 flex-1", className)} {...props} />
))
AttachmentMeta.displayName = "AttachmentMeta"
const AttachmentName = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"truncate text-sm font-medium text-newt-text-link",
className
)}
{...props}
/>
))
AttachmentName.displayName = "AttachmentName"
const AttachmentSize = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-xs text-newt-text-muted", className)}
{...props}
/>
))
AttachmentSize.displayName = "AttachmentSize"
export {
Attachment,
AttachmentIcon,
AttachmentMeta,
AttachmentName,
AttachmentSize,
}<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-[360px] items-center gap-3 rounded-md border border-newt-border bg-newt-bg-surface px-3 py-[10px]',
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-9 w-9 shrink-0 items-center justify-center rounded-sm bg-newt-brand font-mono text-xs 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('truncate text-sm font-medium text-newt-text-link', 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-xs text-newt-text-muted', props.class)">
<slot />
</div>
</template>export { default as Attachment } from "./Attachment.vue"
export { default as AttachmentIcon } from "./AttachmentIcon.vue"
export { default as AttachmentMeta } from "./AttachmentMeta.vue"
export { default as AttachmentName } from "./AttachmentName.vue"
export { default as AttachmentSize } from "./AttachmentSize.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 { Attachment } from "@/components/ui/attachment"
export function Example() {
return <Attachment />
}<script setup lang="ts">
import { Attachment, AttachmentIcon, AttachmentMeta, AttachmentName, AttachmentSize } from "@/components/ui/attachment"
</script>
<template>
<Attachment />
</template>API reference
Attachment
children / default slot?React.ReactNode / Vue slot
Content rendered inside the component.
React.ReactNode / Vue slotclassName / class?string
Additional classes merged with the component defaults.
stringThe registry exports Attachment, AttachmentIcon, AttachmentMeta, AttachmentName, AttachmentSize. 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
Attachment Card 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-attachment.