npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@harshiniravikumar/react-footnote-system

v1.0.0

Published

A fully featured, customizable, and accessible footnote management system for React applications with TypeScript support

Readme

React Footnote System

A fully featured, customizable, and accessible footnote management system for React applications. Provides automatic numbering, context-based management, and flexible rendering with TypeScript support for modern web development.

✨ Core Features

  • 🔢 Automatic Numbering – smart footnote numbering with context awareness
  • 📝 Context Management – centralized footnote state across components
  • 🎯 Flexible Rendering – customizable footnote references and lists
  • TypeScript Support – comprehensive type definitions included
  • 🎨 Customizable Styling – complete visual customization options
  • Accessible – ARIA support and semantic HTML structure
  • 🔄 Dynamic Registration – footnotes register automatically when mounted
  • 📱 Responsive Design – works seamlessly across all device sizes

📦 Installation

npm install "@harshiniravikumar/react-footnote-system"

🔧 Main Components

| Component | Type | Description | |-----------|------|-------------| | FootnoteContext | Provider | Context provider for footnote management | | FootnoteReference | Component | Creates footnote references with automatic numbering | | FootnoteList | Component | Renders all registered footnotes in list format | | Footnote | Component | Standalone footnote component for advanced use cases |

🎯 Component Props

FootnoteReference

| Prop | Type | Default | Description | |------|------|---------|-------------| | id | string | - | Unique identifier for the footnote (required) | | children | ReactNode | - | The footnote content | | className | string | '' | Additional CSS classes for the reference | | onClick | () => void | - | Custom click handler | | style | CSSProperties | {} | Inline styles for the reference | | renderReference | (number: number) => ReactNode | - | Custom reference renderer |

FootnoteList

| Prop | Type | Default | Description | |------|------|---------|-------------| | className | string | '' | CSS classes for the list container | | itemClassName | string | '' | CSS classes for footnote items | | title | string | "Footnotes" | Title for the footnote section | | showTitle | boolean | true | Whether to display the title | | orderBy | "appearance" \| "alphabetical" | "appearance" | Footnote ordering method | | renderItem | (footnote: FootnoteData) => ReactNode | - | Custom footnote item renderer |

Footnote

| Prop | Type | Default | Description | |------|------|---------|-------------| | id | string | - | Unique identifier (required) | | content | string \| ReactNode | - | Footnote content | | number | number | - | Manual footnote number override | | autoRegister | boolean | true | Automatically register with context |

⚙️ Footnote Context Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | startNumber | number | 1 | Starting number for footnote numbering | | numberingStyle | "numeric" \| "roman" \| "alpha" | "numeric" | Numbering style for footnotes | | allowDuplicates | boolean | false | Allow duplicate footnote IDs | | resetOnUnmount | boolean | false | Reset footnotes when context unmounts | | maxFootnotes | number | undefined | Maximum number of footnotes allowed |

🎨 Theme Configuration

Customize the visual appearance of your footnotes:

const footnoteTheme = {
  reference: {
    color: "#007bff",
    fontSize: "0.8em",
    verticalAlign: "super",
    textDecoration: "none",
    padding: "0 2px",
    borderRadius: "2px",
    backgroundColor: "transparent"
  },
  list: {
    borderTop: "1px solid #e0e0e0",
    marginTop: "2rem",
    paddingTop: "1rem",
    fontSize: "0.9em"
  },
  item: {
    marginBottom: "0.5rem",
    lineHeight: "1.4",
    color: "#666"
  },
  title: {
    fontSize: "1.1em",
    fontWeight: "bold",
    marginBottom: "1rem",
    color: "#333"
  }
};

🖼️ Basic Usage

import React from 'react';
import { 
  FootnoteContext, 
  FootnoteReference, 
  FootnoteList 
} from "@your-username/react-footnote-system";

function BasicExample() {
  return (
    <FootnoteContext>
      <article>
        <h1>Article Title</h1>
        <p>
          This is some content with a footnote
          <FootnoteReference id="note1">
            This appears as footnote #1 at the bottom of the page.
          </FootnoteReference>
          and more text continues here.
        </p>
        
        <p>
          Another paragraph with another reference
          <FootnoteReference id="note2">
            This becomes footnote #2 with automatic numbering.
          </FootnoteReference>
          in the middle of the sentence.
        </p>

        <FootnoteList />
      </article>
    </FootnoteContext>
  );
}

🔮 Advanced Usage with All Features

import React, { useRef, useContext } from 'react';
import { 
  FootnoteContext, 
  FootnoteReference, 
  FootnoteList,
  useFootnoteContext 
} from "@your-username/react-footnote-system";

function AdvancedExample() {
  const footnoteContext = useFootnoteContext();

  const handleFootnoteClick = (id: string) => {
    console.log('Footnote clicked:', id);
  };

  return (
    <FootnoteContext
      options={{
        startNumber: 1,
        numberingStyle: "numeric",
        allowDuplicates: false,
        resetOnUnmount: true,
        maxFootnotes: 50
      }}
      theme={{
        reference: {
          color: "#0066cc",
          backgroundColor: "#f0f8ff",
          borderRadius: "4px",
          padding: "2px 4px"
        },
        list: {
          borderTop: "2px solid #0066cc",
          backgroundColor: "#fafafa"
        }
      }}
    >
      <main>
        <section>
          <h1>Research Paper</h1>
          <p>
            Recent studies show significant findings
            <FootnoteReference 
              id="study-2024"
              onClick={() => handleFootnoteClick("study-2024")}
              className="custom-reference"
            >
              Smith, J., & Johnson, A. (2024). "Advanced Research Methods in Modern Science." 
              <em>Journal of Scientific Discovery</em>, 42(3), 123-145. 
              DOI: 10.1000/journal.2024.123
            </FootnoteReference>
            that support our hypothesis.
          </p>

          <p>
            The methodology employed
            <FootnoteReference id="methodology">
              Our research methodology followed the guidelines established by 
              the International Research Standards Committee (IRSC).
            </FootnoteReference>
            ensures reliable results across multiple scenarios.
          </p>
        </section>

        <footer>
          <FootnoteList 
            title="References & Notes"
            className="research-footnotes"
            itemClassName="footnote-item"
            showTitle={true}
            orderBy="appearance"
            renderItem={(footnote) => (
              <div className="custom-footnote">
                <span className="footnote-number">{footnote.number}.</span>
                <span className="footnote-content">{footnote.content}</span>
              </div>
            )}
          />
        </footer>
      </main>
    </FootnoteContext>
  );
}

📱 Multiple Contexts & Sections

function MultiSectionDocument() {
  return (
    <div>
      {/* Chapter 1 with independent footnotes */}
      <FootnoteContext options={{ startNumber: 1 }}>
        <section>
          <h2>Chapter 1: Introduction</h2>
          <p>
            Content with footnotes
            <FootnoteReference id="ch1-intro">
              Introduction footnote content here.
            </FootnoteReference>
            specific to this chapter.
          </p>
          <FootnoteList title="Chapter 1 Notes" />
        </section>
      </FootnoteContext>

      <FootnoteContext options={{ startNumber: 1, numberingStyle: "roman" }}>
        <section>
          <h2>Chapter 2: Methodology</h2>
          <p>
            Different chapter content
            <FootnoteReference id="ch2-method">
              Methodology footnote with roman numerals.
            </FootnoteReference>
            with separate footnote numbering.
          </p>
          <FootnoteList title="Chapter 2 Notes" />
        </section>
      </FootnoteContext>
    </div>
  );
}

🎬 Custom Renderers & Animations

function CustomFootnoteExample() {
  return (
    <FootnoteContext>
      <div>
        <p>
          Text with custom reference
          <FootnoteReference 
            id="custom"
            renderReference={(number) => (
              <span className="custom-ref">
                [{number}]
              </span>
            )}
          >
            Custom styled footnote content
          </FootnoteReference>
        </p>

        <FootnoteList 
          renderItem={(footnote) => (
            <div className="animated-footnote">
              <strong>{footnote.number}.</strong>
              <span>{footnote.content}</span>
            </div>
          )}
        />
      </div>
    </FootnoteContext>
  );
}

🔄 Callbacks & Events

| Callback | Type | Description | |----------|------|-------------| | onFootnoteRegister | (id: string, content: ReactNode) => void | Called when footnote is registered | | onFootnoteUnregister | (id: string) => void | Called when footnote is unregistered | | onFootnoteClick | (id: string, number: number) => void | Called when footnote reference is clicked | | onListRender | (footnotes: FootnoteData[]) => void | Called when footnote list renders | | onMaxFootnotesReached | () => void | Called when max footnotes limit is reached |

🛠️ Hook: useFootnoteContext

Access footnote context methods and state:

| Method/Property | Type | Description | |-----------------|------|-------------| | footnotes | FootnoteData[] | Array of all registered footnotes | | register | (id: string, content: ReactNode) => void | Register a new footnote | | unregister | (id: string) => void | Unregister a footnote | | getFootnote | (id: string) => FootnoteData \| undefined | Get footnote by ID | | getFootnoteNumber | (id: string) => number \| undefined | Get footnote number by ID | | reset | () => void | Clear all footnotes | | count | number | Total number of registered footnotes |

import { useFootnoteContext } from "@your-username/react-footnote-system";

function FootnoteStats() {
  const { footnotes, count, reset } = useFootnoteContext();
  
  return (
    <div>
      <p>Total footnotes: {count}</p>
      <button onClick={reset}>Clear All Footnotes</button>
    </div>
  );
}

🎯 Real-World Examples

Academic Paper

<FootnoteContext options={{ numberingStyle: "numeric" }}>
  <article className="academic-paper">
    <h1>The Impact of Climate Change on Marine Ecosystems</h1>
    <p>
      Recent oceanographic studies
      <FootnoteReference id="ocean-study-2024">
        Martinez, C., et al. (2024). "Ocean Temperature Variations and Marine Biodiversity." 
        <em>Marine Biology Quarterly</em>, 78(2), 45-67.
      </FootnoteReference>
      indicate significant temperature variations in coastal waters.
    </p>
    
    <p>
      These findings corroborate earlier research
      <FootnoteReference id="previous-research">
        See Thompson, R. (2022) and Williams, S. (2023) for comprehensive 
        reviews of historical temperature data.
      </FootnoteReference>
      from the past decade.
    </p>

    <FootnoteList title="References" className="academic-references" />
  </article>
</FootnoteContext>

Blog Post with Explanatory Notes

<FootnoteContext options={{ numberingStyle: "alpha" }}>
  <article className="blog-post">
    <h1>Understanding React Hooks</h1>
    <p>
      React Hooks revolutionized functional components
      <FootnoteReference id="hooks-intro">
        Hooks were introduced in React 16.8 (February 2019) and allow you to 
        use state and other React features in functional components.
      </FootnoteReference>
      by enabling state management without classes.
    </p>

    <p>
      The useState hook
      <FootnoteReference id="usestate-example">
        <code>const [state, setState] = useState(initialValue)</code> is the 
        most commonly used hook for managing component state.
      </FootnoteReference>
      is fundamental to modern React development.
    </p>

    <FootnoteList 
      title="Additional Information" 
      className="blog-footnotes"
      showTitle={true}
    />
  </article>
</FootnoteContext>

Legal Document with Roman Numerals

<FootnoteContext options={{ numberingStyle: "roman" }}>
  <div className="legal-document">
    <h1>Terms of Service</h1>
    <section>
      <h2>Section 1: Definitions</h2>
      <p>
        "Service" refers to the platform
        <FootnoteReference id="service-definition">
          As defined under applicable consumer protection laws and regulations 
          in the jurisdiction where the service is provided.
        </FootnoteReference>
        provided by the Company.
      </p>
    </section>

    <FootnoteList 
      title="Legal References"
      className="legal-footnotes"
      itemClassName="legal-footnote-item"
    />
  </div>
</FootnoteContext>

🎨 Custom Styling Examples

Modern Glass Effect

.modern-footnotes .footnote-reference {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  padding: 2px 6px;
  color: #007bff;
  text-decoration: none;
  transition: all 0.2s ease;
}

.modern-footnotes .footnote-reference:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-1px);
}

.modern-footnotes .footnote-list {
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  border-radius: 12px;
  padding: 1.5rem;
  margin-top: 2rem;
}

Academic Style

.academic-footnotes .footnote-reference {
  color: #d32f2f;
  font-weight: 500;
  vertical-align: super;
  font-size: 0.75em;
  text-decoration: none;
  border-bottom: 1px dotted #d32f2f;
}

.academic-footnotes .footnote-list {
  border-top: 2px solid #333;
  margin-top: 3rem;
  padding-top: 1rem;
  font-family: 'Times New Roman', serif;
}

.academic-footnotes .footnote-item {
  text-indent: -1em;
  padding-left: 1em;
  margin-bottom: 0.8rem;
}

📱 Responsive Behavior

function ResponsiveFootnotes() {
  return (
    <FootnoteContext>
      <div className="responsive-content">
        <p>
          Mobile-optimized footnotes
          <FootnoteReference 
            id="mobile-note"
            className="responsive-reference"
          >
            On mobile devices, footnotes adapt to smaller screens with 
            optimized touch targets and readable font sizes.
          </FootnoteReference>
          work seamlessly across devices.
        </p>

        <FootnoteList className="responsive-footnote-list" />
      </div>
    </FootnoteContext>
  );
}
@media (max-width: 768px) {
  .responsive-reference {
    font-size: 0.9em !important;
    padding: 4px 6px !important;
  }
  
  .responsive-footnote-list {
    font-size: 0.85em;
    padding: 1rem 0.5rem;
  }
}

♿ Accessibility Features

  • ARIA Labels: Proper labeling for screen readers
  • Keyboard Navigation: Tab and Enter key support
  • Semantic HTML: Uses appropriate HTML elements
  • High Contrast: Works with high contrast modes
  • Screen Reader Support: Announces footnote numbers and content
  • Focus Management: Proper focus indicators and management
<FootnoteReference 
  id="accessible-note"
  aria-label="Footnote reference 1"
  role="doc-noteref"
>
  Accessible footnote content
</FootnoteReference>

🚀 Performance Features

  • Lazy Registration: Footnotes register only when needed
  • Efficient Re-renders: Optimized with React.memo and context optimization
  • Memory Management: Automatic cleanup on unmount
  • Minimal Bundle Size: Tree-shakeable components
  • No Dependencies: Pure React implementation

📄 TypeScript Support

Comprehensive TypeScript definitions included:

import type { 
  Footnotes,
  FootnoteProps,
  FootnoteContextType,
  FootnoteRefProps,
  FootnoteListProps,
  FootnoteData,
  FootnoteOptions,
  FootnoteTheme
} from "@your-username/react-footnote-system";

interface CustomFootnoteData {
  id: string;
  content: string;
  category: 'reference' | 'explanation' | 'source';
}

const MyComponent: React.FC = () => {
  const [footnotes, setFootnotes] = useState<CustomFootnoteData[]>([]);
  
  return (
    <FootnoteContext>
      {/* Your footnote implementation */}
    </FootnoteContext>
  );
};

🔧 Configuration Examples

Numbered Footnotes (Default)

<FootnoteContext options={{ numberingStyle: "numeric" }}>
  {/* Footnotes appear as: 1, 2, 3, ... */}
</FootnoteContext>

Roman Numeral Footnotes

<FootnoteContext options={{ numberingStyle: "roman" }}>
  {/* Footnotes appear as: i, ii, iii, ... */}
</FootnoteContext>

Alphabetical Footnotes

<FootnoteContext options={{ numberingStyle: "alpha" }}>
  {/* Footnotes appear as: a, b, c, ... */}
</FootnoteContext>

Custom Starting Number

<FootnoteContext options={{ startNumber: 10 }}>
  {/* Footnotes start from: 10, 11, 12, ... */}
</FootnoteContext>

🎪 Interactive Examples

Footnotes with Custom Actions

function InteractiveFootnotes() {
  const [selectedFootnote, setSelectedFootnote] = useState<string | null>(null);

  return (
    <FootnoteContext>
      <div>
        <p>
          Click this footnote
          <FootnoteReference 
            id="interactive"
            onClick={() => setSelectedFootnote("interactive")}
          >
            This footnote has custom click behavior and can trigger actions 
            in your application.
          </FootnoteReference>
          to see custom behavior.
        </p>

        {selectedFootnote && (
          <div className="footnote-popup">
            <p>You clicked footnote: {selectedFootnote}</p>
            <button onClick={() => setSelectedFootnote(null)}>Close</button>
          </div>
        )}

        <FootnoteList />
      </div>
    </FootnoteContext>
  );
}

Dynamic Footnote Management

function DynamicFootnotes() {
  const { register, unregister, footnotes, reset } = useFootnoteContext();

  const addDynamicFootnote = () => {
    const id = `dynamic-${Date.now()}`;
    register(id, `Dynamic footnote added at ${new Date().toLocaleTimeString()}`);
  };

  return (
    <div>
      <button onClick={addDynamicFootnote}>Add Footnote</button>
      <button onClick={reset}>Clear All</button>
      <p>Current footnotes: {footnotes.length}</p>
      <FootnoteList />
    </div>
  );
}

🔮 Integration with Other Libraries

With Markdown Processors

import ReactMarkdown from 'react-markdown';

function MarkdownWithFootnotes({ content }: { content: string }) {
  return (
    <FootnoteContext>
      <ReactMarkdown 
        components={{
          sup: ({ children }) => (
            <FootnoteReference id={`md-${children}`}>
              Markdown footnote content
            </FootnoteReference>
          )
        }}
      >
        {content}
      </ReactMarkdown>
      <FootnoteList />
    </FootnoteContext>
  );
}

With Content Management Systems

function CMSContent({ content }: { content: any[] }) {
  return (
    <FootnoteContext>
      {content.map((block, index) => {
        if (block.type === 'footnote') {
          return (
            <FootnoteReference key={index} id={block.id}>
              {block.content}
            </FootnoteReference>
          );
        }
        return <div key={index}>{block.content}</div>;
      })}
      <FootnoteList />
    </FootnoteContext>
  );
}

🧪 Testing Support

import { render, screen } from '@testing-library/react';
import { FootnoteContext, FootnoteReference, FootnoteList } from 'your-library';

test('footnotes render correctly', () => {
  render(
    <FootnoteContext>
      <FootnoteReference id="test">Test footnote</FootnoteReference>
      <FootnoteList />
    </FootnoteContext>
  );
  
  expect(screen.getByText('1')).toBeInTheDocument();
  expect(screen.getByText('Test footnote')).toBeInTheDocument();
});

📄 License

MIT License - feel free to use in your projects!