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

guide-kit

v1.1.1

Published

UI components library for user onboarding in engineering software

Readme

guide-kit

guide-kit is a UI components library for user onboarding in engineering software. It provides lightweight, accessible, and customizable components to guide users through complex workflows — from inline parameter hints with formula support to multi-step guided tours with spotlight overlays. Built with TypeScript and React, it integrates seamlessly into engineering dashboards, CAD tools, and technical web applications. All components are zero-dependency on the React side and rely only on @floating-ui/dom for precise positioning.

Installation

npm install guide-kit

React and ReactDOM are peer dependencies and must be installed separately:

npm install react react-dom

Quick Start

Hint

Wrap any element with <Hint> to show a contextual popover with parameter details:

import { Hint } from 'guide-kit/react'

function MyComponent() {
  return (
    <Hint
      content={{
        title: 'Коэффициент запаса',
        description: 'Отношение предельной нагрузки к расчётной.',
        range: '1.2 – 2.5',
        unit: 'безразмерный',
        norm: 'ГОСТ 27751-2014',
      }}
      placement="right"
      trigger="hover"
    >
      <span>K = 1.5</span>
    </Hint>
  )
}

Tour

Run a guided product tour across multiple DOM elements:

import { useRef } from 'react'
import { Tour, useTour } from 'guide-kit/react'
import type { TourHandle } from 'guide-kit/react'

function App() {
  const tourRef = useRef<TourHandle>(null)
  const { start } = useTour(tourRef)

  const steps = [
    {
      target: '#step-one',
      title: 'Шаг 1',
      content: 'Введите значение нагрузки.',
      placement: 'bottom',
    },
    {
      target: '#step-two',
      title: 'Шаг 2',
      content: 'Выберите материал из каталога.',
      placement: 'right',
    },
  ]

  return (
    <>
      <button onClick={start}>Начать тур</button>
      <Tour
        ref={tourRef}
        steps={steps}
        run={false}
        onComplete={() => console.log('Tour done')}
        onSkip={() => console.log('Tour skipped')}
      />
    </>
  )
}

Components

<Hint>

Shows a contextual popover anchored to a child element. Supports hover and click triggers.

| Prop | Type | Default | Description | |------|------|---------|-------------| | content | HintContent \| string | required | Popover content. Pass a string for simple text, or an object for structured content with title, range, norm, etc. | | trigger | 'hover' \| 'click' | 'hover' | How the popover is opened | | placement | Placement | 'right' | Preferred floating placement (from @floating-ui/dom) | | children | React.ReactElement | required | The element to anchor the hint to |

<Hint content="This field represents pipeline pressure in bar." placement="top">
  <label>Pressure</label>
</Hint>

<Tour>

A multi-step guided tour with a spotlight overlay. Uses forwardRef so you can control it imperatively.

| Prop | Type | Default | Description | |------|------|---------|-------------| | steps | TourStep[] | required | Array of tour steps | | run | boolean | required | Whether the tour is running | | onComplete | () => void | — | Called when the last step is finished | | onSkip | () => void | — | Called when the tour is dismissed | | onStepChange | (index: number) => void | — | Called on each step change | | spotlightPadding | number | 8 | Padding around the spotlight cutout (px) | | overlayOpacity | number | 0.65 | Opacity of the dark overlay | | locale | Partial<TourLocale> | — | Override button labels |

Use useTour(ref) for a convenience hook that exposes start, stop, and goTo.

const tourRef = useRef<TourHandle>(null)
const { start, goTo } = useTour(tourRef)

Keyboard shortcuts: / Enter — next, — back, Escape — skip.

<FormulaBlock>

Renders a mathematical formula inline with optional variable legend and source citation.

import { FormulaBlock } from 'guide-kit/react'

// Fraction mode
<FormulaBlock
  mode="fraction"
  numerator="F"
  denominator="A"
  result="σ"
  variables={[
    { symbol: 'F', description: 'Сила', unit: 'Н' },
    { symbol: 'A', description: 'Площадь сечения', unit: 'м²' },
    { symbol: 'σ', description: 'Нормальное напряжение', unit: 'Па' },
  ]}
  source="СП 20.13330.2017"
/>

// HTML mode (for complex formulas)
<FormulaBlock
  mode="html"
  html="E = mc<sup>2</sup>"
/>

<DocButton>

A download button (or inline link) for one or more documents.

import { DocButton } from 'guide-kit/react'

// Single document
<DocButton
  docs={{ label: 'Руководство пользователя', url: '/docs/manual.pdf', fileType: 'pdf', size: '2.4 MB' }}
/>

// Multiple documents — renders a dropdown
<DocButton
  label="Нормативные документы"
  docs={[
    { label: 'ГОСТ 27751', url: '/docs/gost27751.pdf', fileType: 'pdf' },
    { label: 'Таблица нагрузок', url: '/docs/loads.xlsx', fileType: 'xlsx' },
  ]}
/>

// Inline link variant
<DocButton
  variant="inline"
  docs={{ label: 'Скачать отчёт', url: '/report.docx', fileType: 'docx' }}
/>

<VideoPanel>

Embeds a video or renders a clickable preview card.

import { VideoPanel } from 'guide-kit/react'

// Embed mode (default) — wraps an iframe with correct aspect ratio
<VideoPanel
  source={{
    url: 'https://www.youtube.com/embed/dQw4w9WgXcQ',
    title: 'Обзор системы',
    duration: '3:32',
  }}
  aspectRatio="16/9"
/>

// Link mode — preview card with thumbnail and external link
<VideoPanel
  mode="link"
  source={{
    url: 'https://youtu.be/dQw4w9WgXcQ',
    title: 'Видеоинструкция',
    duration: '3:32',
    thumbnail: '/images/video-thumb.jpg',
  }}
  linkText="Смотреть на YouTube"
/>

<SidebarOverlay>

A fixed sidebar that overlays the page. Renders via a portal — no host-app layout changes required.

import { useState } from 'react'
import { SidebarOverlay } from 'guide-kit/react'

function App() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <button onClick={() => setOpen(true)}>Открыть справку</button>
      <SidebarOverlay
        open={open}
        onClose={() => setOpen(false)}
        title="Учебные материалы"
        side="left"
        width={360}
        showToggleButton
        toggleButtonLabel="Справка"
        backdrop
        sections={[
          {
            type: 'text',
            title: 'Описание',
            content: 'Введите расчётную нагрузку в кН на погонный метр.',
          },
          {
            type: 'steps',
            title: 'Порядок работы',
            collapsible: true,
            steps: [
              { label: 'Выбрать схему нагружения' },
              { label: 'Ввести значения нагрузок', done: true },
              { label: 'Запустить расчёт' },
            ],
          },
        ]}
      />
    </>
  )
}

<SidebarPush>

A sidebar that pushes the main content aside. Requires a flex container in the host app. Does not use a portal — place it as a direct child of the flex container.

import { useState } from 'react'
import { SidebarPush } from 'guide-kit/react'

function App() {
  const [open, setOpen] = useState(true)

  return (
    <div data-gk-container style={{ display: 'flex', height: '100vh' }}>
      <SidebarPush
        open={open}
        onClose={() => setOpen(false)}
        title="Чек-лист"
        width={300}
        sections={[
          {
            type: 'checklist',
            title: 'Проверка перед расчётом',
            items: [
              { id: 'c1', label: 'Схема нагружения задана' },
              { id: 'c2', label: 'Материал выбран из каталога' },
              { id: 'c3', label: 'Граничные условия проверены' },
            ],
          },
        ]}
      />
      <main style={{ flex: 1, overflow: 'auto', padding: '24px' }}>
        {/* основной контент */}
      </main>
    </div>
  )
}

<HelpPanel>

A fixed floating button that opens a panel listing all registered help items. Each item can be toggled on/off; state is persisted in localStorage.

Simple mode — pass items directly via the items prop:

import { useRef } from 'react'
import { HelpPanel, Tour } from 'guide-kit/react'
import type { TourHandle } from 'guide-kit/react'

function App() {
  const tourRef = useRef<TourHandle>(null)

  return (
    <>
      <Tour ref={tourRef} steps={steps} run={false} onComplete={() => {}} onSkip={() => {}} />

      <HelpPanel
        position="bottom-right"
        label="Помощь"
        items={[
          {
            id: 'main-tour',
            type: 'tour',
            label: 'Обзорный тур',
            description: 'Пошаговое знакомство с интерфейсом',
            action: () => tourRef.current?.start(),
          },
        ]}
      />
    </>
  )
}

Provider mode — register items dynamically with useHelpRegistry:

import { useRef } from 'react'
import { HelpPanel, HelpPanelProvider, Tour, useHelpRegistry } from 'guide-kit/react'
import type { TourHandle } from 'guide-kit/react'

function Calculator() {
  const tourRef = useRef<TourHandle>(null)

  useHelpRegistry({
    id: 'calc-tour',
    type: 'tour',
    label: 'Тур по калькулятору',
    description: 'Знакомство с полями ввода',
    action: () => tourRef.current?.start(),
  })

  return <Tour ref={tourRef} steps={steps} run={false} onComplete={() => {}} onSkip={() => {}} />
}

function App() {
  return (
    <HelpPanelProvider storageKey="my-app-help">
      <Calculator />
      <HelpPanel position="bottom-right" />
    </HelpPanelProvider>
  )
}

useHelpRegistry automatically registers the item on mount and unregisters on unmount.

Persistence. By default (persistState={true}) the enabled/disabled state of each item is saved to localStorage under storageKey (default "guide-kit-help"). Pass persistState={false} to disable.

| Prop | Type | Default | Description | |------|------|---------|-------------| | items | HelpItemRegistration[] | — | Static list; bypasses registry | | position | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Corner of the screen | | label | string | 'Помощь' | Button label | | storageKey | string | 'guide-kit-help' | localStorage key | | persistState | boolean | true | Save toggle state | | onOpen | () => void | — | Panel opened | | onClose | () => void | — | Panel closed | | onItemToggle | (id, enabled) => void | — | Toggle changed | | onItemActivate | (id) => void | — | Item row clicked |

Vanilla JS

For projects without React, use the guide-kit/vanilla entry point:

import { createHint, createTour, createSidebar } from 'guide-kit/vanilla'

// Hint
const hint = createHint(document.getElementById('mass-input'), {
  content: {
    title: 'Масса состава',
    description: 'Полная масса вагонов без локомотива.',
    range: '100–6000',
    unit: 'т',
    norm: 'ГОСТ 22235-2010',
  },
  trigger: 'hover',
})

// Tour
const tour = createTour({
  steps: [
    { target: '#step-1', title: 'Шаг 1', content: 'Выберите локомотив' },
    { target: '#step-2', title: 'Шаг 2', content: 'Введите массу состава' },
  ],
  onComplete: () => console.log('Тур завершён'),
})
tour.start()

// Sidebar
const sidebar = createSidebar({
  title: 'Инструкция',
  sections: [
    { type: 'text', title: 'Введение', content: 'Порядок выполнения расчёта...' },
    { type: 'steps', steps: [{ label: 'Шаг 1' }, { label: 'Шаг 2' }] },
  ],
})
sidebar.open()

Each function returns an instance object with control methods and a destroy() for cleanup. All seven functions follow the same pattern: create*(target?, options) → instance.

Note: SidebarPush is not available in the vanilla adapter — it requires React's component model for layout integration. Use createSidebar (overlay mode) or the React version instead.


Vue 3

For Vue 3 projects, use the guide-kit/vue entry point:

import {
  GkHint, GkTour, GkFormulaBlock, GkDocButton,
  GkVideoPanel, GkSidebarOverlay, GkHelpPanel,
  useHelpRegistry,
} from 'guide-kit/vue'

All components are implemented as render-function components (defineComponent + setup) and work without SFC files or @vitejs/plugin-vue.

GkHint

<template>
  <GkHint
    :content="{
      title: 'Масса состава',
      description: 'Полная масса вагонов без локомотива.',
      range: '100–6000',
      unit: 'т',
    }"
    placement="right"
    trigger="hover"
  >
    <label>Масса состава</label>
  </GkHint>
</template>

Props: content (HintContent | string, required), placement (Placement, default 'right'), trigger ('hover' | 'click' | 'focus', default 'hover').

GkTour

<script setup lang="ts">
import { ref } from 'vue'
const tourRef = ref()
</script>

<template>
  <button @click="tourRef.start()">Начать тур</button>
  <GkTour
    ref="tourRef"
    :steps="[
      { target: '#step-1', title: 'Шаг 1', content: 'Выберите локомотив' },
      { target: '#step-2', title: 'Шаг 2', content: 'Введите массу' },
    ]"
    :run="false"
    @complete="console.log('done')"
  />
</template>

Props: steps (TourStep[], required), run (boolean, default false). Emits: complete, skip. Exposed: start(), stop(), goTo(index).

GkSidebarOverlay

<script setup lang="ts">
const sidebarRef = ref()
</script>

<template>
  <button @click="sidebarRef.open()">Открыть инструкцию</button>
  <GkSidebarOverlay
    ref="sidebarRef"
    title="Порядок расчёта"
    :sections="[
      { type: 'text', title: 'Введение', content: 'Порядок выполнения...' },
      { type: 'steps', steps: [{ label: 'Шаг 1' }, { label: 'Шаг 2' }] },
    ]"
    side="right"
    :show-toggle-button="true"
  />
</template>

Props: title (string, required), sections (SidebarSection[], required), side ('left' | 'right', default 'right'), showToggleButton (boolean, default true), width (string, default '360px'). Exposed: open(), close(), toggle().

GkHelpPanel + useHelpRegistry

<script setup lang="ts">
import { ref } from 'vue'
import { GkHelpPanel, useHelpRegistry, GkTour } from 'guide-kit/vue'

const tourRef = ref()

// Register the tour in the global HelpRegistry
useHelpRegistry({
  id: 'main-tour',
  label: 'Обучающий тур',
  type: 'tour',
  action: () => tourRef.value?.start(),
})
</script>

<template>
  <GkTour ref="tourRef" :steps="[...]" />

  <!-- Floating help button + panel (reads from HelpRegistry automatically) -->
  <GkHelpPanel
    :items="[
      { id: 'main-tour', label: 'Обучающий тур', type: 'tour', action: () => tourRef.start() },
    ]"
    position="bottom-right"
    label="Помощь"
    storage-key="my-app-help"
  />
</template>

useHelpRegistry registers an item on mount and unregisters on unmount. GkHelpPanel renders a floating button that opens a panel listing all registered items with enable/disable toggles. State is persisted to localStorage via storageKey.

Note: GkSidebarPush is not implemented in the Vue adapter. Use GkSidebarOverlay (overlay/portal mode) for sidebars in Vue projects.


Theming

All components use CSS custom properties for visual customisation. Override them globally or scoped to a container:

:root {
  --gk-primary: #0f62fe;       /* Accent color (buttons, links, markers) */
  --gk-bg: #ffffff;            /* Popover / card background */
  --gk-text: #161616;          /* Primary text color */
  --gk-text-muted: #6f6f6f;    /* Secondary / muted text */
  --gk-border: #e0e0e0;        /* Border and formula background */
  --gk-radius: 6px;            /* Border radius */
  --gk-shadow: 0 2px 16px rgba(0, 0, 0, 0.16); /* Popover shadow */
  --gk-font: 'IBM Plex Sans', sans-serif; /* Font family */
}

Dark mode example:

[data-theme="dark"] {
  --gk-bg: #1c1c1c;
  --gk-text: #f4f4f4;
  --gk-text-muted: #a8a8a8;
  --gk-border: #3d3d3d;
}

TypeScript

All components and types are fully typed. Import types from guide-kit/react or from guide-kit (core/utility types only):

import type { HintContent, TourStep, TourHandle, FormulaBlockProps, DocItem } from 'guide-kit/react'
import type { HelpPanelProps, HelpItemRegistration } from 'guide-kit'
import { HelpRegistry, HelpStorage } from 'guide-kit'

License

MIT