Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/JaleelB/emblor

A fully-featured tag input component built with shadcn/ui
https://github.com/JaleelB/emblor

autocomplete input popover radix react-tag-input shadcn-ui tag-input

Last synced: 24 days ago
JSON representation

A fully-featured tag input component built with shadcn/ui

Awesome Lists containing this project

README

        

https://github.com/JaleelB/emblor/assets/78449846/7f678789-ef5e-4913-b26c-9317003d6dbc

[Emblor](https://emblor.jaleelbennett.com/) is a highly customizable, accessible, and fully-featured tag input component built with Shadcn UI.

## About

Emblor is built on top of the [Input](https://ui.shadcn.com/docs/components/input), [Popover](https://ui.shadcn.com/docs/components/popover), [Command](https://ui.shadcn.com/docs/components/command) and [Dialog](https://ui.shadcn.com/docs/components/dialog) components from [Shadcn UI](https://ui.shadcn.com/).

## Installation

To install Emblor, run the command:

```bash
pnpm add emblor
```

## Features

- **Autocomplete**: Enable autocomplete suggestions for tags.
- **Validation**: Validate tags based on custom rules.
- **Limit**: Set a maximum and minimum number of tags.
- **Duplication**: Allow or disallow duplicate tags.
- **Character Limit**: Define the maximum length of a tag.
- **Sorting**: Sort tags alphabetically.
- **Truncation**: Truncate tags that exceed a certain length.
- **Popovers**: Use popovers to display tags.
- **Keyboard Navigation**: Use keyboard shortcuts to interact with the tag input.
- **Customization**: Change the appearance and behavior of the tags by passing in a custom tag renderer.
- **Accessibility**: Ensure that the tag input is accessible to all users.
- **Drag and Drop**: Allow users to reorder tags using drag and drop.
- **Read-only Mode**: Prevent users from editing the tag input.
- **Delimiters**: Define custom delimiters for separating tags.
- **Add on Paste**: Automatically add tags when pasting text.

## Usage

Here's a sample implementation that initializes the component with a list of initial tags and suggestions list. Apart from this, there are multiple events, handlers for which need to be set.

The example below uses `tailwindcss` `@shadcn/ui` `tailwind-merge` `clsx`:

```tsx
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Tag, TagInput } from 'emblor';
import Link from 'next/link';
import { Button, buttonVariants } from '@/components/ui/button';
import { z } from 'zod';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import React from 'react';
import { toast } from '@/components/ui/use-toast';

const FormSchema = z.object({
topics: z.array(
z.object({
id: z.string(),
text: z.string(),
}),
),
});

export default function Hero() {
const form = useForm>({
resolver: zodResolver(FormSchema),
});

const [tags, setTags] = React.useState([]);

const { setValue } = form;

function onSubmit(data: z.infer) {
toast({
title: 'You submitted the following values:',
description: (


{JSON.stringify(data, null, 2)}

),
});
}

return (


Shadcn Tag Input



An implementation of a Tag Input component built on top of Shadcn UI's input component.




Try it out


Github







(

Topics

{
setTags(newTags);
setValue('topics', newTags as [Tag, ...Tag[]]);
}}
/>

These are the topics that you're interested in.


)}
/>
Submit






);
}
```

## API Reference

### TagInput

The primary component for user interaction. Configure the tag input behavior and appearance using these props, and manage tag data dynamically.

#### Props

```typescript
type TagInputProps = {
// Placeholder text for the input.
placeholder?: string; // default: ""

// Array of tags displayed as pre-selected.
tags: Array<{ id: string; text: string }>; // default: []

// Function to set the state of tags.
setTags: React.Dispatch>;

// Enable or disable the autocomplete feature.
enableAutocomplete?: boolean; // default: false

// List of autocomplete options.
autocompleteOptions?: Array<{ id: string; text: string }>; // default: []

// Maximum number of tags allowed.
maxTags?: number; // default: null

// Minimum number of tags required.
minTags?: number; // default: null

// Make the input read-only.
readOnly?: boolean; // default: false

// Disable the input.
disabled?: boolean; // default: false

// Callback function when a tag is added.
onTagAdd?: (tag: string) => void; // default: null

// Callback function when a tag is removed.
onTagRemove?: (tag: string) => void; // default: null

// Allow duplicate tags.
allowDuplicates?: boolean; // default: false

// Maximum length of a tag.
maxLength?: number; // default: null

// Minimum length of a tag.
minLength?: number; // default: null

// Function to validate a tag.
validateTag?: (tag: string) => boolean; // default: null

// Character used to separate tags.
delimiter?: Delimiter; // default: null

// Show the count of tags.
showCount?: boolean; // default: false

// Placeholder text when tag limit is reached.
placeholderWhenFull?: string; // default: ""

styleClasses?: {
// Class name styles for the tag input container (use when inlineTags is set to true).
inlineTagsContainer?: string;

// Class name styles for the tag popover sub components
tagPopover?: {
popoverTrigger?: string;
popoverContent?: string;
};

// Class name styles for the tag list sub components (the tag list renders the tags as a list)
tagList?: {
container?: string;
sortableList?: string;
};

// Class name styles for the autocomplete component sub components
autoComplete?: {
command?: string;
popoverTrigger?: string;
popoverContent?: string;
commandList?: string;
commandGroup?: string;
commandItem?: string;
};

// Class name styles for the tag
tag?: {
body?: string;
closeButton?: string;
};

// Class name styles for the main input field
input?: string;
}; // default: {}

// Sort tags alphabetically.
sortTags?: boolean; // default: false

// List of characters that can be used as delimiters.
delimiterList?: string[]; // default: []

// Truncate tag text to a certain length.
truncate?: number; // default: null

// Function to filter autocomplete options.
autocompleteFilter?: (option: string) => boolean; // default: null

// Layout direction of the tag inputs.
direction?: 'row' | 'column'; // default: 'row'

// A callback function that is called whenever the input value changes.
onInputChange?: (value: string) => void; // default: null

// A callback function that is used to render custom tag elements.
customTagRenderer?: (tag: { id: string; text: string }) => React.ReactElement; // default: null

// Function to be called when the input field gains focus.
onFocus?: React.FocusEventHandler; // default: null

// Function to be called when the input field loses focus.
onBlur?: React.FocusEventHandler; // default: null

// Only allow tags that are present in the autocomplete options.
restrictTagsToAutocompleteOptions?: boolean; // default: false

// A callback function to be called when a tag is clicked.
onTagClick?: (tag: { id: string; text: string }) => void; // default: null

// Enable drag and drop functionality.
draggable?: boolean; // default: false

// Position of the input field in relation to the tags.
inputFieldPosition?: 'bottom' | 'top' | 'inline'; // default: 'bottom'

// Show a button to clear all tags.
clearAll?: boolean; // default: false

// A callback function to be called when the clear all button is clicked.
onClearAll?: () => void; // default: null

// Additional props to be passed to the input field.
inputProps?: React.InputHTMLAttributes; // default: {}

// Use a popover to display tags instead of inline.
usePopoverForTags?: boolean; // default: false

// A callback function that generates an id for a newly created tag.
generateTagId?: () => string; // default: crypto.getRandomValues(new Uint32Array(1))[0].toString
};
```

### Delimiter

Define the delimiters that can be used to separate tags within the input.

```typescript
enum Delimiter {
Comma = ',',
Enter = 'Enter',
}
```

## Documentation

You can find out more about the API and implementation in the [Documentation](https://emblor.jaleelbennett.com/).