Skip to main content

Overview

The Tag component displays a label with an optional close button, perfect for showing selected items, filters, or removable categories.

Basic Usage

import Tag from '@newtonschool/grauity';

function MyComponent() {
  return (
    <Tag 
      onButtonClick={() => console.log('Tag removed')}
    >
      Selected Item
    </Tag>
  );
}

Props

children
React.ReactNode
required
Content to display in the tag.
onButtonClick
function
Callback function when the close button is clicked.Signature: (e: React.MouseEvent<HTMLButtonElement>) => void
buttonIcon
grauityIconName
default:"close"
Icon to display in the close button.
icon
grauityIconName
default:"null"
Icon to display at the start of the tag (always positioned left).
isDisabled
boolean
default:false
Disable the close button.
shouldTruncateText
boolean
default:true
Truncate text with ellipsis if it overflows.
truncateLength
string | number
default:"200px"
Maximum width before text truncation occurs.
className
string
Additional CSS class name.

Basic Tag

<Tag onButtonClick={() => handleRemove('tag1')}>
  Technology
</Tag>

With Icon

<Tag 
  icon="star" 
  onButtonClick={() => handleRemove('favorite')}
>
  Favorite
</Tag>

<Tag 
  icon="user" 
  onButtonClick={() => handleRemove('user')}
>
  John Doe
</Tag>

Disabled Close Button

<Tag 
  isDisabled={true}
  onButtonClick={() => console.log('Cannot remove')}
>
  Permanent Tag
</Tag>

Custom Close Icon

<Tag 
  buttonIcon="x"
  onButtonClick={() => handleRemove()}
>
  Custom Close Icon
</Tag>

Text Truncation

<Tag 
  shouldTruncateText={true}
  truncateLength="150px"
  onButtonClick={() => handleRemove()}
>
  This is a very long tag label that will be truncated with an ellipsis
</Tag>

<Tag 
  shouldTruncateText={false}
  onButtonClick={() => handleRemove()}
>
  This long text will not be truncated
</Tag>

Selected Items Example

function SelectedItemsExample() {
  const [selectedItems, setSelectedItems] = useState([
    { id: 1, label: 'React', icon: 'code' },
    { id: 2, label: 'TypeScript', icon: 'code' },
    { id: 3, label: 'JavaScript', icon: 'code' },
  ]);

  const handleRemove = (id: number) => {
    setSelectedItems(items => items.filter(item => item.id !== id));
  };

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
      {selectedItems.map(item => (
        <Tag
          key={item.id}
          icon={item.icon}
          onButtonClick={() => handleRemove(item.id)}
        >
          {item.label}
        </Tag>
      ))}
    </div>
  );
}

Filter Tags

function FilterTags() {
  const [filters, setFilters] = useState([
    'Active',
    'In Progress',
    'Completed',
  ]);

  const removeFilter = (filter: string) => {
    setFilters(filters => filters.filter(f => f !== filter));
  };

  return (
    <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
      {filters.map(filter => (
        <Tag
          key={filter}
          onButtonClick={() => removeFilter(filter)}
        >
          {filter}
        </Tag>
      ))}
    </div>
  );
}

Read-only Tags

For display-only tags without removal functionality, consider using the Chip component instead:
import Chip from '@newtonschool/grauity';

<Chip variant="brand">Read-only Label</Chip>

Build docs developers (and LLMs) love