dragon-eye
v2.0.1
Published
A lightweight, accessible React eye icon and password visibility toggle component library.
Maintainers
Readme
dragon-eye 👁️
A lightweight, accessible, and fully typed React eye icon & password visibility toggle library.
dragon-eye provides ready-to-use components for password visibility toggles, authentication forms, and any UI that requires eye / eye-off icons.
Preview
Author
✨ Features
- ✅ TypeScript support included
- ✅ Accessible keyboard interactions (Enter / Space)
- ✅ React 16.8+ compatible
- ✅ Lightweight & tree-shakeable
- ✅ ForwardRef support
- ✅ Memoized components for performance
- ✅ Custom size, color, and stroke width
- ✅ Animated hover interactions
- ✅ Built-in password input component
- ✅ Built-in visibility toggle component
- ✅
usePasswordTogglehook included - ✅ Supports both
colorandcolourprops
📦 Installation
Install with npm:
npm install dragon-eyeor with yarn:
yarn add dragon-eyeor with pnpm:
pnpm add dragon-eye📋 Requirements
- React 16.8 or higher
- ReactDOM 16.8 or higher
🚀 Quick Start
import { Eye, EyeOff } from "dragon-eye";
function App() {
return (
<div style={{ display: "flex", gap: 16 }}>
<Eye size={32} color="purple" />
<EyeOff size={32} color="tomato" />
</div>
);
}
export default App;📚 Exports
import {
Eye,
EyeOff,
EyeToggle,
PasswordInput,
usePasswordToggle,
} from "dragon-eye";Components
Eye– visible eye iconEyeOff– hidden eye iconEyeToggle– controlled visibility toggle iconPasswordInput– ready-to-use password field with toggle
Hooks
usePasswordToggle– state helper for password visibility
👁️ Eye Component
Eye renders an open eye icon that is commonly used for password visibility toggles, visibility indicators, and custom UI controls.
Import
import { Eye } from "dragon-eye";Basic Usage
<Eye />Custom Size
<Eye size={32} />or
<Eye
width={32}
height={32}
/>Custom Color
Preferred:
<Eye color="royalblue" />Backward compatible:
<Eye colour="royalblue" />Clickable Icon
<Eye
color="tomato"
onClick={() => alert("Clicked!")}
/>Animated Icon
<Eye
animated
size={30}
/>Disabled Icon
<Eye
disabled
color="gray"
/>Accessibility
<Eye
ariaLabel="Show password"
title="Show password"
/>Eye Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| size | number \| string | 20 | Sets both width and height |
| width | number \| string | size | Custom width |
| height | number \| string | size | Custom height |
| color | string | currentColor | Preferred icon color |
| colour | string | — | Backward compatible color prop |
| strokeWidth | number | 2 | SVG stroke width |
| animated | boolean | false | Enables hover animation |
| disabled | boolean | false | Disables interaction |
| title | string | "Show password" | SVG title |
| ariaLabel | string | "Show password" | Accessibility label |
| className | string | — | Custom CSS class |
| style | CSSProperties | — | Inline styles |
| onClick | (event) => void | — | Click handler |
Example
import { Eye } from "dragon-eye";
export default function Example() {
return (
<Eye
size={36}
color="#6C63FF"
strokeWidth={2.5}
animated
ariaLabel="Show password"
onClick={() => console.log("Eye clicked")}
/>
);
}🙈 EyeOff Component
EyeOff renders a crossed eye icon, commonly used to indicate hidden content such as concealed passwords or disabled visibility states.
Import
import { EyeOff } from "dragon-eye";Basic Usage
<EyeOff />Custom Size
<EyeOff size={32} />or
<EyeOff
width={32}
height={32}
/>Custom Color
Preferred:
<EyeOff color="crimson" />Backward compatible:
<EyeOff colour="crimson" />Clickable Icon
<EyeOff
color="tomato"
onClick={() => alert("Clicked!")}
/>Animated Icon
<EyeOff
animated
size={30}
/>Disabled Icon
<EyeOff
disabled
color="gray"
/>Accessibility
<EyeOff
ariaLabel="Hide password"
title="Hide password"
/>EyeOff Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| size | number \| string | 20 | Sets both width and height |
| width | number \| string | size | Custom width |
| height | number \| string | size | Custom height |
| color | string | currentColor | Preferred icon color |
| colour | string | — | Backward compatible color prop |
| strokeWidth | number | 2 | SVG stroke width |
| animated | boolean | false | Enables hover animation |
| disabled | boolean | false | Disables interaction |
| title | string | "Hide password" | SVG title |
| ariaLabel | string | "Hide password" | Accessibility label |
| className | string | — | Custom CSS class |
| style | CSSProperties | — | Inline styles |
| onClick | (event) => void | — | Click handler |
Example
import { EyeOff } from "dragon-eye";
export default function Example() {
return (
<EyeOff
size={36}
color="#E63946"
strokeWidth={2.5}
animated
ariaLabel="Hide password"
onClick={() => console.log("EyeOff clicked")}
/>
);
}Common Use Cases
- Password visibility toggle
- Hide confidential information
- Toggle sensitive form fields
- Authentication interfaces
- Login and signup forms
- Custom visibility controls
🔄 EyeToggle Component
EyeToggle is a ready-to-use visibility toggle component that automatically switches between the Eye and EyeOff icons.
It is ideal for password visibility toggles and any UI that needs to switch between visible and hidden states.
Import
import { EyeToggle } from "dragon-eye";Basic Usage
import { useState } from "react";
import { EyeToggle } from "dragon-eye";
export default function Example() {
const [visible, setVisible] = useState(false);
return (
<EyeToggle
visible={visible}
onToggle={setVisible}
/>
);
}Password Toggle Example
import { useState } from "react";
import { EyeToggle } from "dragon-eye";
export default function PasswordField() {
const [visible, setVisible] = useState(false);
return (
<div
style={{
display: "flex",
alignItems: "center",
gap: 8,
}}
>
<input
type={visible ? "text" : "password"}
placeholder="Password"
/>
<EyeToggle
visible={visible}
onToggle={setVisible}
/>
</div>
);
}Controlled Component
EyeToggle is a controlled component.
You manage the visibility state.
const [visible, setVisible] = useState(false);
<EyeToggle
visible={visible}
onToggle={setVisible}
/>Event Handling
The onToggle callback receives the next visibility state.
<EyeToggle
visible={visible}
onToggle={(nextVisible) => {
console.log(nextVisible);
setVisible(nextVisible);
}}
/>Custom Color
Preferred:
<EyeToggle
visible={visible}
onToggle={setVisible}
color="royalblue"
/>Backward compatible:
<EyeToggle
visible={visible}
onToggle={setVisible}
colour="royalblue"
/>Custom Size
<EyeToggle
visible={visible}
onToggle={setVisible}
size={30}
/>or
<EyeToggle
visible={visible}
onToggle={setVisible}
width={30}
height={30}
/>Stroke Width
<EyeToggle
visible={visible}
onToggle={setVisible}
strokeWidth={2.5}
/>Animated Toggle
<EyeToggle
visible={visible}
onToggle={setVisible}
animated
/>Disabled Toggle
<EyeToggle
visible={visible}
onToggle={setVisible}
disabled
/>Accessibility
<EyeToggle
visible={visible}
onToggle={setVisible}
ariaLabel="Toggle password visibility"
title="Toggle password visibility"
/>EyeToggle Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| visible | boolean | Required | Current visibility state |
| onToggle | (visible: boolean) => void | Required | Called with the next visibility state |
| size | number \| string | 20 | Sets icon size |
| width | number \| string | size | Custom width |
| height | number \| string | size | Custom height |
| color | string | currentColor | Preferred icon color |
| colour | string | — | Backward compatible color prop |
| strokeWidth | number | 2 | SVG stroke width |
| animated | boolean | false | Enables hover animation |
| disabled | boolean | false | Disables interaction |
| title | string | Auto generated | SVG title |
| ariaLabel | string | Auto generated | Accessibility label |
| className | string | — | Custom CSS class |
| style | CSSProperties | — | Inline styles |
Default Behaviour
When:
visible={false}the component renders:
<Eye />When:
visible={true}the component renders:
<EyeOff />Clicking the component automatically calls:
onToggle(!visible)so you only need to update your state.
Complete Example
import { useState } from "react";
import { EyeToggle } from "dragon-eye";
export default function Example() {
const [visible, setVisible] = useState(false);
return (
<EyeToggle
visible={visible}
onToggle={setVisible}
size={32}
color="#7C3AED"
animated
strokeWidth={2.5}
/>
);
}🔐 PasswordInput Component
PasswordInput is a ready-to-use password field with built-in visibility toggle functionality.
It automatically manages password visibility state, renders the appropriate eye icon, and supports customization of the icon appearance.
Import
import { PasswordInput } from "dragon-eye";Basic Usage
<PasswordInput
placeholder="Enter password"
/>Default Behaviour
The component automatically:
- Starts with the password hidden
- Switches between
passwordandtext - Displays the correct icon
- Supports keyboard accessibility
- Disables the toggle when the input is disabled
No additional state management is required.
Custom Icon Color
Preferred:
<PasswordInput
iconColor="royalblue"
/>Backward compatible:
<PasswordInput
iconColour="royalblue"
/>Custom Icon Size
<PasswordInput
iconSize={28}
/>Custom Stroke Width
<PasswordInput
strokeWidth={2.5}
/>Animated Icon
<PasswordInput
animated
/>Disabled Input
<PasswordInput
disabled
/>When disabled:
- Input cannot be edited
- Eye icon cannot be clicked
- Visibility cannot be changed
Custom Placeholder
<PasswordInput
placeholder="Create password"
/>Default Value
<PasswordInput
defaultValue="secret123"
/>Controlled Value
const [password, setPassword] = useState("");
<PasswordInput
value={password}
onChange={(e) => setPassword(e.target.value)}
/>Custom Classes
<PasswordInput
wrapperClassName="password-wrapper"
inputClassName="password-input"
/>Styling Example
.password-wrapper {
border: 1px solid #ccc;
border-radius: 8px;
padding: 6px 10px;
}
.password-input {
border: none;
outline: none;
width: 100%;
}Using Standard Input Props
Since PasswordInput extends React's native input attributes, you can use all standard input properties.
<PasswordInput
placeholder="Password"
autoComplete="current-password"
required
maxLength={32}
autoFocus
/>PasswordInput Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| iconSize | number \| string | 24 | Toggle icon size |
| iconColor | string | currentColor | Preferred icon color |
| iconColour | string | — | Backward compatible icon color |
| strokeWidth | number | 2 | Icon stroke width |
| animated | boolean | true | Enables icon animation |
| wrapperClassName | string | — | Wrapper class |
| inputClassName | string | — | Input class |
| disabled | boolean | false | Disables input and toggle |
| placeholder | string | — | Input placeholder |
| defaultValue | string | — | Initial value |
| value | string | — | Controlled input value |
| onChange | (event) => void | — | Input change handler |
| ...rest | InputHTMLAttributes | — | All native input props |
Complete Example
import { PasswordInput } from "dragon-eye";
export default function Example() {
return (
<PasswordInput
placeholder="Enter your password"
iconSize={26}
iconColor="#7C3AED"
strokeWidth={2.2}
animated
/>
);
}Why Use PasswordInput?
✅ No state management required
✅ Built-in visibility toggle
✅ Accessible keyboard interaction
✅ Supports all native React input props
✅ Fully customizable icon
✅ TypeScript support
✅ Lightweight
✅ Production ready
Part 6 – usePasswordToggle Hook
usePasswordToggle is a lightweight React hook that manages password visibility state.
It eliminates repetitive useState logic and provides helper functions for showing, hiding, toggling, and manually controlling password visibility.
Import
import { usePasswordToggle } from "dragon-eye";Basic Example
Instead of writing:
const [visible, setVisible] = useState(false);you can simply use:
const {
visible,
inputType,
toggle,
} = usePasswordToggle();Complete example:
import { EyeToggle, usePasswordToggle } from "dragon-eye";
function Login() {
const {
visible,
inputType,
toggle,
} = usePasswordToggle();
return (
<div>
<input
type={inputType}
placeholder="Password"
/>
<EyeToggle
visible={visible}
onToggle={toggle}
/>
</div>
);
}Start Visible
You may choose the initial visibility state.
const password = usePasswordToggle(true);or
const password = usePasswordToggle(false);Returned Values
const {
visible,
inputType,
show,
hide,
toggle,
setVisible,
} = usePasswordToggle();| Property | Type | Description |
|-----------|------|-------------|
| visible | boolean | Current visibility state |
| inputType | "password" \| "text" | Derived input type |
| show() | () => void | Show password |
| hide() | () => void | Hide password |
| toggle() | () => void | Toggle visibility |
| setVisible() | Dispatch<SetStateAction<boolean>> | Manually control visibility |
API
usePasswordToggle(
initialVisible?: boolean
)Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| initialVisible | boolean | false | Initial visibility state |
Example – Toggle Button
import {
EyeToggle,
usePasswordToggle,
} from "dragon-eye";
export default function Example() {
const password =
usePasswordToggle();
return (
<>
<input
type={password.inputType}
/>
<EyeToggle
visible={password.visible}
onToggle={password.toggle}
/>
</>
);
}Example – Show Button
const password =
usePasswordToggle();
<button
onClick={password.show}
>
Show Password
</button>Example – Hide Button
const password =
usePasswordToggle();
<button
onClick={password.hide}
>
Hide Password
</button>Example – Manual Control
const password =
usePasswordToggle();
<button
onClick={() =>
password.setVisible(true)
}
>
Always Show
</button>
<button
onClick={() =>
password.setVisible(false)
}
>
Always Hide
</button>Example – Multiple Password Fields
Each hook instance maintains its own independent state.
const loginPassword =
usePasswordToggle();
const confirmPassword =
usePasswordToggle();<input
type={loginPassword.inputType}
/>
<EyeToggle
visible={loginPassword.visible}
onToggle={loginPassword.toggle}
/>
<input
type={confirmPassword.inputType}
/>
<EyeToggle
visible={confirmPassword.visible}
onToggle={confirmPassword.toggle}
/>Using with PasswordInput
If you're using the built-in PasswordInput component, you usually don't need this hook, because PasswordInput manages visibility internally.
Use the hook when you're building your own password field.
Best Practices
✅ Use one hook instance per password field.
✅ Prefer inputType instead of manually checking visible.
<input
type={password.inputType}
/>instead of
<input
type={
password.visible
? "text"
: "password"
}
/>✅ Use toggle() with EyeToggle.
<EyeToggle
visible={password.visible}
onToggle={password.toggle}
/>✅ Use show() and hide() when explicit actions are required.
password.show();
password.hide();TypeScript
The hook is fully typed.
import {
usePasswordToggle,
UsePasswordToggleReturn,
} from "dragon-eye";
const password:
UsePasswordToggleReturn =
usePasswordToggle();Summary
The usePasswordToggle hook provides a simple, reusable way to manage password visibility in React applications.
It is ideal for custom password inputs and works seamlessly with the Eye and EyeToggle components while remaining fully typed, lightweight, and framework-friendly.
Part 7 – Styling & CSS
dragon-eye ships with a lightweight stylesheet that provides sensible defaults for hover effects, transitions, cursor styles, keyboard focus, and disabled states.
The CSS file is automatically included when using the package with most modern bundlers such as Vite, Rollup, and Webpack.
Default Styling
Icons are rendered as inline-flex elements with smooth transitions.
Features include:
- Hover animation
- Keyboard focus support
- Disabled appearance
- Pointer cursor for clickable icons
- Consistent sizing
No additional configuration is required.
CSS Classes
The library uses the following internal CSS classes.
| Class | Description |
|---------|-------------|
| dragon-eye-icon | Base icon class |
| dragon-eye-icon--animated | Enables hover animation |
| dragon-eye-icon--clickable | Applied when onClick exists |
| dragon-eye-icon--disabled | Applied when disabled |
Animated Icons
Animation is enabled by default on components that support it.
<Eye
animated
/>Disable animations if preferred.
<Eye
animated={false}
/>The same option is available for:
- Eye
- EyeOff
- EyeToggle
- PasswordInput
Custom Styling
Every component accepts standard React HTML attributes.
Example:
<Eye
className="my-icon"
/>.my-icon {
color: royalblue;
transition: transform .2s ease;
}
.my-icon:hover {
transform: scale(1.15);
}Inline Styles
Inline styles are also supported.
<Eye
style={{
color: "purple",
marginLeft: 8,
}}
/>PasswordInput Styling
Customize wrapper and input independently.
<PasswordInput
wrapperClassName="password-wrapper"
inputClassName="password-input"
/>Example CSS:
.password-wrapper {
display: flex;
align-items: center;
gap: 8px;
}
.password-input {
width: 100%;
padding: 10px;
border-radius: 6px;
}Disabled State
Disabled icons automatically:
- ignore clicks
- remove pointer cursor
- reduce opacity
- disable keyboard activation
<EyeToggle
visible={false}
disabled
/>Responsive Sizing
Icons support numbers or CSS values.
<Eye
size={20}
/>
<Eye
width="2rem"
height="2rem"
/>
<Eye
width="100%"
height="100%"
/>Best Practices
✅ Prefer the size prop when width and height are equal.
<Eye size={24} />✅ Use width and height when different dimensions are required.
<Eye
width={32}
height={20}
/>✅ Customize appearance with your own CSS classes instead of editing library styles.
Summary
dragon-eye includes minimal default styling while remaining fully customizable through CSS classes, inline styles, and component props.
Part 8 – Accessibility
Accessibility is a core feature of dragon-eye.
All interactive components are designed to work with keyboards, assistive technologies, and modern accessibility standards.
Keyboard Support
Clickable icons can be activated using:
- Tab to focus
- Enter to activate
- Space to activate
Example:
<EyeToggle
visible={visible}
onToggle={toggle}
/>No additional keyboard handlers are required.
Focus Management
Interactive icons automatically become keyboard focusable.
<Eye
onClick={handleClick}
/>The component receives:
tabIndex=0automatically.
Non-clickable icons are excluded from keyboard navigation.
Screen Reader Support
Provide meaningful labels using ariaLabel.
<Eye
ariaLabel="Show password"
/><EyeOff
ariaLabel="Hide password"
/>SVG Titles
Use the title prop to provide accessible SVG descriptions.
<Eye
title="Password visible"
/>This is useful for browser tooltips and assistive technologies.
Disabled Accessibility
Disabled components automatically receive:
aria-disabled="true"and ignore:
- mouse clicks
- keyboard activation
Example:
<EyeToggle
visible={false}
disabled
/>Semantic Roles
Interactive icons use:
role="button"Static icons use:
role="img"These roles are managed automatically.
PasswordInput Accessibility
The built-in PasswordInput preserves all native input accessibility features.
Example:
<PasswordInput
placeholder="Password"
aria-label="Password"
/>You may also combine it with labels.
<label htmlFor="password">
Password
</label>
<PasswordInput
id="password"
/>Best Practices
✅ Always provide an ariaLabel for interactive icons.
<EyeToggle
ariaLabel="Toggle password visibility"
visible={visible}
onToggle={toggle}
/>✅ Use descriptive title values.
<Eye
title="Show password"
/>✅ Prefer native <button> elements when wrapping icons inside larger controls.
✅ Pair password inputs with <label> elements whenever possible.
Summary
dragon-eye is built with accessibility in mind, offering keyboard navigation, ARIA support, semantic roles, focus management, and screen reader compatibility out of the box.
Part 9 – TypeScript
dragon-eye is written entirely in TypeScript and ships with built-in type declarations.
No additional typings are required.
Installation
Simply install the package.
npm install dragon-eyeTypeScript definitions are included automatically.
Importing Types
All public types are exported from the package.
import type {
IconProps,
IconBaseProps,
PasswordInputProps,
UsePasswordToggleReturn,
} from "dragon-eye";IconProps
Used by:
- Eye
- EyeOff
- EyeToggle
Example:
import type { IconProps } from "dragon-eye";
const props: IconProps = {
size: 24,
color: "royalblue",
animated: true,
};PasswordInputProps
Useful when creating wrapper components.
import type {
PasswordInputProps,
} from "dragon-eye";
interface LoginPasswordProps
extends PasswordInputProps {}Example:
function LoginPassword(
props: PasswordInputProps
) {
return (
<PasswordInput
{...props}
/>
);
}UsePasswordToggleReturn
The hook exports its return type.
import {
usePasswordToggle,
UsePasswordToggleReturn,
} from "dragon-eye";
const password:
UsePasswordToggleReturn =
usePasswordToggle();Component Refs
All components support React refs.
Eye:
const ref =
useRef<HTMLSpanElement>(null);
<Eye ref={ref} />EyeToggle:
const ref =
useRef<HTMLSpanElement>(null);
<EyeToggle
ref={ref}
visible={visible}
onToggle={toggle}
/>PasswordInput:
const inputRef =
useRef<HTMLInputElement>(null);
<PasswordInput
ref={inputRef}
/>Generic Wrapper Example
import {
Eye,
IconProps,
} from "dragon-eye";
function BlueEye(
props: IconProps
) {
return (
<Eye
color="royalblue"
{...props}
/>
);
}Full Type Exports
The library exports:
| Type | Description |
|------|-------------|
| IconProps | Shared icon props |
| IconBaseProps | Base icon component props |
| PasswordInputProps | PasswordInput props |
| UsePasswordToggleReturn | Hook return type |
Type Safety
The compiler validates props automatically.
Correct:
<Eye
size={24}
color="red"
/>Incorrect:
<Eye
size="large"
/>TypeScript will report an error because size accepts only:
number | stringIntelliSense Support
Modern editors provide:
- Auto-completion
- Prop documentation
- Type checking
- Hover information
- Ref types
- Event types
without any additional configuration.
Summary
dragon-eye is fully typed, providing first-class TypeScript support with exported interfaces, strongly typed hooks, component refs, and editor IntelliSense.
Part 10 – Complete API Reference
This section summarizes every public export available in dragon-eye.
Exports
import {
Eye,
EyeOff,
EyeToggle,
PasswordInput,
usePasswordToggle,
} from "dragon-eye";Eye Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| size | number \| string | 20 | Icon size |
| width | number \| string | size | Custom width |
| height | number \| string | size | Custom height |
| color | string | currentColor | Icon color |
| colour | string | currentColor | Backward compatible color |
| strokeWidth | number | 2 | SVG stroke width |
| animated | boolean | false | Enable hover animation |
| disabled | boolean | false | Disable interaction |
| title | string | — | SVG title |
| ariaLabel | string | — | Accessibility label |
| onClick | MouseEventHandler | — | Click handler |
| className | string | — | CSS class |
| style | CSSProperties | — | Inline styles |
EyeOff Props
Supports exactly the same props as Eye.
EyeToggle Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| visible | boolean | — | Current visibility |
| onToggle | (visible:boolean,event?)=>void | — | Toggle callback |
| All IconProps | — | — | All icon props are supported |
PasswordInput Props
| Prop | Type | Default |
|------|------|---------|
| iconSize | number \| string | 20 |
| iconColor | string | currentColor |
| iconColour | string | currentColor |
| strokeWidth | number | 2 |
| animated | boolean | true |
| wrapperClassName | string | "" |
| inputClassName | string | "" |
| defaultVisible | boolean | false |
| All native input props | ✓ | Supported |
usePasswordToggle
const password =
usePasswordToggle(
initialVisible?
);Returns:
| Property | Type |
|-----------|------|
| visible | boolean |
| inputType | "password" \| "text" |
| show() | () => void |
| hide() | () => void |
| toggle() | () => void |
| setVisible() | Dispatch<SetStateAction<boolean>> |
Browser Support
Compatible with all modern browsers supporting:
- ES2020
- SVG
- React 16.8+
- React 17
- React 18
- React 19
Bundle Formats
The package includes:
- ES Module (ESM)
- UMD
- TypeScript declarations
- Source maps
Tree Shaking
Only the components you import are included in your bundle.
import { Eye } from "dragon-eye";This helps keep production bundle sizes small.
Summary
The API is intentionally small, strongly typed, and easy to learn, making dragon-eye suitable for projects ranging from simple forms to large-scale React applications.
Part 11 – Migration Guide
This section explains how to migrate from earlier versions of dragon-eye to the latest release.
Upgrading
Install the latest version:
npm install dragon-eye@latestor
yarn add dragon-eye@latestWhat's New
The latest version introduces:
- ✅
EyeTogglecomponent - ✅
PasswordInputcomponent - ✅
usePasswordTogglehook - ✅ Better accessibility
- ✅ Better keyboard support
- ✅ Improved TypeScript types
- ✅ React 19 compatibility
- ✅ Improved tree shaking
- ✅ Forward ref support
Existing Eye Component
Old usage:
<Eye colour="blue" />Still works.
New usage:
<Eye color="blue" />Both are fully supported.
Existing EyeOff Component
No changes are required.
Old code:
<EyeOff
width={24}
height={24}
/>continues to work.
New EyeToggle Component
Instead of manually writing:
{
visible
? <EyeOff />
: <Eye />
}You can now write:
<EyeToggle
visible={visible}
onToggle={toggle}
/>This simplifies password visibility logic.
New PasswordInput Component
Previously you had to build your own password field.
Example:
<input
type={
visible
? "text"
: "password"
}
/>
<EyeToggle
visible={visible}
onToggle={toggle}
/>Now you can simply use:
<PasswordInput />New Hook
Instead of:
const [visible, setVisible] =
useState(false);Use:
const password =
usePasswordToggle();Deprecated Patterns
Prefer:
colorinstead of
colourThe colour prop is still supported for backward compatibility but color is recommended for new projects.
No Breaking Changes
Version 2 maintains compatibility with existing icon usage.
Existing projects using:
- Eye
- EyeOff
- colour
will continue to work without modification.
Summary
Migrating to the latest version is straightforward. Existing applications continue to work while gaining access to new components, improved accessibility, stronger TypeScript support, and simplified password visibility management.
Part 12 – Frequently Asked Questions (FAQ)
Does this library work with React 16?
Yes.
Minimum supported version:
React 16.8+because Hooks require React 16.8 or newer.
Does it support React 17?
Yes.
Does it support React 18?
Yes.
Does it support React 19?
Yes.
The library is compatible with React 19.
Does it work with TypeScript?
Yes.
TypeScript declarations are included in the package.
No additional typings are required.
Can I use JavaScript instead?
Absolutely.
The package works with both JavaScript and TypeScript projects.
Can I change the icon color?
Yes.
<Eye color="tomato" />or
<Eye colour="tomato" />Can I change the size?
Yes.
<Eye size={28} />or
<Eye
width={32}
height={20}
/>Does it support custom CSS?
Yes.
<Eye
className="my-icon"
/>Can I disable animations?
Yes.
<Eye
animated={false}
/>Is the library accessible?
Yes.
Features include:
- Keyboard navigation
- ARIA labels
- SVG titles
- Screen reader support
- Focus management
Is SSR supported?
Yes.
The package works with server-side rendering frameworks such as:
- Next.js
- Remix
- Gatsby
Does it work with Vite?
Yes.
It is built with Vite and works seamlessly in Vite projects.
Does it work with Create React App?
Yes.
Can I use only one component?
Yes.
Example:
import { Eye } from "dragon-eye";Only the imported component is bundled.
Does it support tree shaking?
Yes.
Unused components are removed by modern bundlers.
Can I use the icons outside password fields?
Yes.
The icons are generic SVG React components and can be used anywhere.
Example:
<Eye
color="green"
size={30}
/>Is CSS required?
No.
The components work without custom CSS.
The included stylesheet only provides improved hover effects, focus styles, and transitions.
How can I report a bug?
Please open an issue on the GitHub repository.
Include:
- React version
- Browser
- Package version
- Steps to reproduce
Can I contribute?
Yes.
Contributions are welcome through GitHub pull requests and issue reports.
Summary
If your question isn't covered here, please check the GitHub repository or open an issue. Feedback and contributions are always appreciated.
Part 13 – Contributing
Contributions are welcome and greatly appreciated!
Whether you'd like to fix a bug, improve documentation, add a feature, or optimize performance, your help is always welcome.
Ways to Contribute
You can contribute by:
- Reporting bugs
- Suggesting new features
- Improving documentation
- Optimizing performance
- Improving accessibility
- Fixing TypeScript definitions
- Writing tests
- Improving examples
Reporting Issues
If you discover a bug, please create a GitHub issue and include:
- Package version
- React version
- Operating system
- Browser (if applicable)
- Expected behavior
- Actual behavior
- Steps to reproduce
- Screenshots (if helpful)
Development Setup
Clone the repository.
git clone https://github.com/iamxerrycan/dragon-eye.gitEnter the project.
cd dragon-eyeInstall dependencies.
npm installRun the build.
npm run buildRun tests.
npm testPull Requests
Before submitting a pull request:
- Keep changes focused
- Update documentation if needed
- Ensure the project builds successfully
- Follow the existing coding style
- Add tests when introducing new features
Code Style
Please follow the project's conventions:
- TypeScript
- Functional React components
- Hooks over class components
- Strong typing
- Meaningful comments
- Consistent formatting
Feature Requests
Have an idea?
Open a GitHub discussion or issue describing:
- The problem
- Your proposed solution
- Example usage
- Any alternatives you've considered
Community Guidelines
Please be respectful and constructive.
We aim to maintain a welcoming environment for everyone.
Thank You ❤️
Every contribution—large or small—helps make dragon-eye better for the React community.
Thank you for your support!
Part 14 – License
MIT License
Copyright (c) 2026 iamxerrycan
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to:
- Use
- Copy
- Modify
- Merge
- Publish
- Distribute
- Sublicense
- Sell copies of the Software
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For the complete license text, see the project's LICENSE file.
Part 15 – Author & Links
Author
Rajshish Singh Rajput (iamxerrycan)
A passionate software developer focused on building modern, reusable, and developer-friendly open-source tools for the React ecosystem.
Connect
GitHub
https://github.com/iamxerrycan
https://www.linkedin.com/in/iamxerrycan/
https://www.instagram.com/rajshishsinghrajput/
Project Links
npm Package
https://www.npmjs.com/package/dragon-eye
GitHub Repository
https://github.com/iamxerrycan/dragon-eye
Issue Tracker
https://github.com/iamxerrycan/dragon-eye/issues
Support
If you find this project useful, consider:
- ⭐ Starring the GitHub repository
- 🐛 Reporting bugs
- 💡 Suggesting new features
- 📢 Sharing the package with others
- 🤝 Contributing to the project
Your support helps improve the library and keeps the project growing.
Changelog
For release history and updates, see:
- GitHub Releases
- npm Version History
Acknowledgements
Thanks to:
- The React team
- The TypeScript team
- The Vite team
- Every contributor and user of dragon-eye
Made with ❤️
Built with React, TypeScript, and Vite to provide lightweight, accessible, and customizable eye icons and password visibility components for modern web applications.
⭐ If you like this project...
Please consider giving the repository a Star on GitHub.
It helps others discover the project and motivates continued development.
Thank you for using dragon-eye! 👁️
