@juanitte/inoui 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,8 @@ A modern, lightweight React component library with built-in theming support.
16
16
  - [useTheme Hook](#usetheme-hook)
17
17
  - [Color System](#color-system)
18
18
  - [Theme Tokens](#theme-tokens)
19
+ - [Semantic DOM Styling](#semantic-dom-styling)
20
+ - [CSS Class Customization](#css-class-customization)
19
21
  - [Utils](#utils)
20
22
  - [DOM Utilities](#dom-utilities)
21
23
  - [Object Utilities](#object-utilities)
@@ -80,6 +82,7 @@ A modern, lightweight React component library with built-in theming support.
80
82
  - [TimePicker](#timepicker)
81
83
  - [Timeline](#timeline)
82
84
  - [Toggle](#toggle)
85
+ - [Tooltip](#tooltip)
83
86
  - [Tour](#tour)
84
87
  - [Transfer](#transfer)
85
88
  - [Tree](#tree)
@@ -87,7 +90,6 @@ A modern, lightweight React component library with built-in theming support.
87
90
  - [Upload](#upload)
88
91
  - [Waterfall](#waterfall)
89
92
  - [Watermark](#watermark)
90
- - [Tooltip](#tooltip)
91
93
 
92
94
  ## Features
93
95
 
@@ -113,9 +115,10 @@ pnpm add @juanitte/inoui
113
115
 
114
116
  ## Quick Start
115
117
 
116
- Wrap your application with `ThemeProvider` and start using components:
118
+ Import the stylesheet once in your app entry point, wrap your application with `ThemeProvider`, and start using components:
117
119
 
118
120
  ```tsx
121
+ import '@juanitte/inoui/styles.css'
119
122
  import { ThemeProvider, Button, Tooltip } from '@juanitte/inoui'
120
123
 
121
124
  function App() {
@@ -404,6 +407,43 @@ For `className`, the component-level `className` prop and `classNames.root` are
404
407
  | Tooltip | `root`, `popup`, `arrow` |
405
408
  | Waterfall | `root`, `column`, `item` |
406
409
 
410
+ ### CSS Class Customization
411
+
412
+ All components use [BEM](https://getbem.com/) class names with the `ino-` prefix, which you can target directly in your stylesheets.
413
+
414
+ **Naming convention:**
415
+
416
+ | Pattern | Example | Description |
417
+ |---------|---------|-------------|
418
+ | `ino-{block}` | `ino-btn` | Component root |
419
+ | `ino-{block}--{modifier}` | `ino-btn--primary`, `ino-btn--sm` | Variant, size, or state |
420
+ | `ino-{block}__{element}` | `ino-btn__icon` | Internal part |
421
+
422
+ **Example — custom button styles:**
423
+
424
+ ```css
425
+ /* Your stylesheet — loaded after ino-ui */
426
+ .ino-btn--primary {
427
+ border-radius: 999px;
428
+ }
429
+
430
+ .ino-tag--sm {
431
+ font-size: 0.7rem;
432
+ }
433
+ ```
434
+
435
+ You can combine this with the `classNames` prop for scoped overrides:
436
+
437
+ ```tsx
438
+ <Button classNames={{ root: 'my-btn' }}>Click</Button>
439
+ ```
440
+
441
+ ```css
442
+ .my-btn {
443
+ border-radius: 999px;
444
+ }
445
+ ```
446
+
407
447
  ---
408
448
 
409
449
  ## Utils
@@ -14530,188 +14570,441 @@ function ProductCatalog() {
14530
14570
  ---
14531
14571
 
14532
14572
  <details>
14533
- <summary><strong>Tour</strong> - Step-by-step guided walkthrough with spotlight overlay</summary>
14573
+ <summary><strong>Tooltip</strong> - Lightweight hover tooltips with 12 placements and color presets</summary>
14534
14574
 
14535
- ### Tour
14575
+ ### Tooltip
14536
14576
 
14537
- `Tour` is a guided walkthrough component that highlights UI elements one by one using an SVG spotlight mask. It is ideal for onboarding flows, feature discovery, and interactive product demos. The popup card follows the highlighted element with 13 placement options, supports two visual themes, and offers full control over step navigation, indicators, and action buttons.
14577
+ A lightweight tooltip component for displaying additional information on hover or focus. Renders into a portal (`document.body`), supports 12 placements, auto-flip on viewport overflow, an optional arrow with `pointAtCenter` mode, and colorful presets.
14578
+
14579
+ #### Import
14538
14580
 
14539
14581
  ```tsx
14540
- import { Tour } from '@juanitte/inoui'
14582
+ import { Tooltip } from '@juanitte/inoui'
14541
14583
  ```
14542
14584
 
14543
14585
  #### Props
14544
14586
 
14545
14587
  | Prop | Type | Default | Description |
14546
14588
  |------|------|---------|-------------|
14547
- | `steps` | `TourStepConfig[]` | — | Array of step configurations |
14548
- | `open` | `boolean` | — | Whether the tour is visible (controlled) |
14549
- | `current` | `number` | | Active step index (controlled) |
14550
- | `onChange` | `(current: number) => void` | — | Called on step change |
14551
- | `onClose` | `() => void` | | Called when the tour closes |
14552
- | `onFinish` | `() => void` | — | Called when the last step's Next button is clicked |
14553
- | `mask` | `boolean` | `true` | Show SVG spotlight mask |
14554
- | `arrow` | `boolean` | `true` | Show arrow pointing at the target |
14555
- | `type` | `TourType` | `'default'` | Card visual theme |
14556
- | `placement` | `TourPlacement` | `'bottom'` | Default popup placement (overridden per step) |
14557
- | `gap` | `{ offset?: number; radius?: number }` | `{ offset: 6, radius: 2 }` | Spotlight padding (px) and corner radius (px) |
14558
- | `closeIcon` | `ReactNode \| false` | — | Custom close icon; `false` hides it entirely |
14559
- | `disabledInteraction` | `boolean` | — | Block pointer events on the highlighted element |
14560
- | `scrollIntoViewOptions` | `boolean \| ScrollIntoViewOptions` | `true` | Auto-scroll target into view; `true` uses `{ block: 'center', behavior: 'instant' }` |
14561
- | `indicatorsRender` | `(current: number, total: number) => ReactNode` | — | Custom step indicator renderer |
14562
- | `actionsRender` | `(actions: ReactNode, info: ActionsInfo) => ReactNode` | — | Custom action buttons renderer (replaces footer buttons) |
14563
- | `zIndex` | `number` | `1001` | z-index for overlay and popup |
14564
- | `className` | `string` | — | CSS class on the popup card |
14565
- | `style` | `CSSProperties` | — | Inline style on the popup card |
14566
- | `classNames` | `TourClassNames` | — | Semantic class names per slot |
14567
- | `styles` | `TourStyles` | — | Semantic inline styles per slot |
14568
-
14569
- #### TourStepConfig
14570
-
14571
- | Prop | Type | Default | Description |
14572
- |------|------|---------|-------------|
14573
- | `target` | `HTMLElement \| (() => HTMLElement \| null) \| null` | — | Element to highlight; `null` centers the popup |
14574
- | `title` | `ReactNode` | — | Step title |
14575
- | `description` | `ReactNode` | — | Step body text |
14576
- | `cover` | `ReactNode` | — | Media content above the title (e.g. an image) |
14577
- | `placement` | `TourPlacement` | inherited | Override placement for this step |
14578
- | `arrow` | `boolean` | inherited | Override arrow visibility for this step |
14579
- | `mask` | `boolean` | inherited | Override mask visibility for this step |
14580
- | `type` | `TourType` | inherited | Override card theme for this step |
14581
- | `nextButtonProps` | `{ children?: ReactNode; onClick?: () => void }` | — | Customize the Next / Finish button |
14582
- | `prevButtonProps` | `{ children?: ReactNode; onClick?: () => void }` | — | Customize the Previous button |
14583
- | `scrollIntoViewOptions` | `boolean \| ScrollIntoViewOptions` | inherited | Override scroll behavior for this step |
14589
+ | `content` | `ReactNode` | — | **Required.** Tooltip content |
14590
+ | `children` | `ReactNode` | — | **Required.** Trigger element |
14591
+ | `placement` | `TooltipPlacement` | `'top'` | Preferred placement 12 options |
14592
+ | `position` | `TooltipPlacement` | — | **Deprecated.** Use `placement` instead |
14593
+ | `arrow` | `boolean \| { pointAtCenter: boolean }` | `true` | Show arrow; pass `{ pointAtCenter: true }` to center it on corner placements |
14594
+ | `color` | `string` | — | Preset color name or any CSS color colorizes the tooltip background |
14595
+ | `autoAdjustOverflow` | `boolean` | `true` | Flip to the opposite side when the tooltip overflows the viewport |
14596
+ | `delay` | `number` | `200` | Delay before showing (ms) |
14597
+ | `disabled` | `boolean` | `false` | Disable tooltip |
14598
+ | `className` | `string` | | Root CSS class |
14599
+ | `style` | `CSSProperties` | | Root inline style |
14600
+ | `classNames` | `TooltipClassNames` | — | Semantic class names per slot |
14601
+ | `styles` | `TooltipStyles` | — | Semantic inline styles per slot |
14584
14602
 
14585
- #### Types
14603
+ #### Type Definitions
14586
14604
 
14587
14605
  ```ts
14588
- type TourPlacement =
14589
- | 'center'
14606
+ type TooltipPlacement =
14590
14607
  | 'top' | 'topLeft' | 'topRight'
14591
14608
  | 'bottom' | 'bottomLeft' | 'bottomRight'
14592
14609
  | 'left' | 'leftTop' | 'leftBottom'
14593
14610
  | 'right' | 'rightTop' | 'rightBottom'
14594
14611
 
14595
- type TourType = 'default' | 'primary'
14612
+ type TooltipSemanticSlot = 'root' | 'popup' | 'arrow'
14613
+ type TooltipClassNames = SemanticClassNames<TooltipSemanticSlot>
14614
+ type TooltipStyles = SemanticStyles<TooltipSemanticSlot>
14615
+ ```
14596
14616
 
14597
- // actionsRender info argument
14598
- interface ActionsInfo {
14599
- current: number
14600
- total: number
14601
- goTo: (step: number) => void
14602
- close: () => void
14603
- }
14617
+ #### Placements
14604
14618
 
14605
- // Semantic slots
14606
- type TourSemanticSlot =
14607
- | 'root' | 'mask' | 'popup' | 'header'
14608
- | 'title' | 'description' | 'footer'
14609
- | 'arrow' | 'close' | 'cover' | 'indicators'
14619
+ All 12 placements relative to the trigger element:
14610
14620
 
14611
- type TourClassNames = SemanticClassNames<TourSemanticSlot>
14612
- type TourStyles = SemanticStyles<TourSemanticSlot>
14621
+ ```
14622
+ topLeft top topRight
14623
+ leftTop ┌─────────────────┐ rightTop
14624
+ left │ trigger │ right
14625
+ leftBottom └─────────────────┘ rightBottom
14626
+ bottomLeft bottom bottomRight
14613
14627
  ```
14614
14628
 
14615
- #### Examples
14629
+ #### Preset Colors
14616
14630
 
14617
- **1. Basic guided tour**
14618
- ```tsx
14619
- import { useRef, useState } from 'react'
14620
- import { Tour } from '@juanitte/inoui'
14631
+ | Name | Hex |
14632
+ |------|-----|
14633
+ | `'blue'` | `#1677ff` |
14634
+ | `'geekblue'` | `#2f54eb` |
14635
+ | `'purple'` | `#722ed1` |
14636
+ | `'cyan'` | `#13c2c2` |
14637
+ | `'green'` | `#52c41a` |
14638
+ | `'lime'` | `#a0d911` |
14639
+ | `'yellow'` | `#fadb14` |
14640
+ | `'gold'` | `#faad14` |
14641
+ | `'orange'` | `#fa8c16` |
14642
+ | `'volcano'` | `#fa541c` |
14643
+ | `'red'` | `#f5222d` |
14644
+ | `'pink'` / `'magenta'` | `#eb2f96` |
14621
14645
 
14622
- function App() {
14623
- const btnRef = useRef<HTMLButtonElement>(null)
14624
- const cardRef = useRef<HTMLDivElement>(null)
14625
- const [open, setOpen] = useState(false)
14646
+ Any other string is used as-is (hex, rgb, hsl…).
14626
14647
 
14627
- const steps = [
14628
- {
14629
- target: () => btnRef.current,
14630
- title: 'Create a new item',
14631
- description: 'Click here to start creating a new entry.',
14632
- },
14633
- {
14634
- target: () => cardRef.current,
14635
- title: 'Your results appear here',
14636
- description: 'This card shows the output of your actions.',
14637
- placement: 'right' as const,
14638
- },
14639
- ]
14648
+ #### Semantic DOM
14640
14649
 
14641
- return (
14642
- <>
14643
- <button ref={btnRef} onClick={() => {}}>New item</button>
14644
- <div ref={cardRef} style={{ marginTop: 24 }}>Result card</div>
14645
- <button onClick={() => setOpen(true)}>Start Tour</button>
14650
+ | Slot | Element | Description |
14651
+ |------|---------|-------------|
14652
+ | `root` | `<div>` | Inline wrapper around the trigger element |
14653
+ | `popup` | `<div>` | Tooltip popup portaled to `document.body` |
14654
+ | `arrow` | `<div>` | Arrow pointing at the trigger |
14646
14655
 
14647
- <Tour
14648
- steps={steps}
14649
- open={open}
14650
- onClose={() => setOpen(false)}
14651
- onFinish={() => setOpen(false)}
14652
- />
14653
- </>
14654
- )
14655
- }
14656
- ```
14656
+ #### Examples
14657
+
14658
+ **1. Basic**
14657
14659
 
14658
- **2. Primary theme**
14659
14660
  ```tsx
14660
- <Tour
14661
- steps={steps}
14662
- open={open}
14663
- type="primary"
14664
- onClose={() => setOpen(false)}
14665
- onFinish={() => setOpen(false)}
14666
- />
14661
+ <Tooltip content="This is a tooltip">
14662
+ <Button>Hover me</Button>
14663
+ </Tooltip>
14667
14664
  ```
14668
14665
 
14669
- **3. No mask (transparent overlay)**
14666
+ ---
14667
+
14668
+ **2. All 12 placements**
14669
+
14670
14670
  ```tsx
14671
- <Tour steps={steps} open={open} mask={false} onClose={() => setOpen(false)} onFinish={() => setOpen(false)} />
14671
+ <Tooltip content="Top center" placement="top"> <Button>top</Button> </Tooltip>
14672
+ <Tooltip content="Top left" placement="topLeft"> <Button>topLeft</Button> </Tooltip>
14673
+ <Tooltip content="Top right" placement="topRight"> <Button>topRight</Button> </Tooltip>
14674
+ <Tooltip content="Bottom center" placement="bottom"> <Button>bottom</Button> </Tooltip>
14675
+ <Tooltip content="Bottom left" placement="bottomLeft"> <Button>bottomLeft</Button> </Tooltip>
14676
+ <Tooltip content="Bottom right" placement="bottomRight"> <Button>bottomRight</Button> </Tooltip>
14677
+ <Tooltip content="Left center" placement="left"> <Button>left</Button> </Tooltip>
14678
+ <Tooltip content="Left top" placement="leftTop"> <Button>leftTop</Button> </Tooltip>
14679
+ <Tooltip content="Left bottom" placement="leftBottom"> <Button>leftBottom</Button> </Tooltip>
14680
+ <Tooltip content="Right center" placement="right"> <Button>right</Button> </Tooltip>
14681
+ <Tooltip content="Right top" placement="rightTop"> <Button>rightTop</Button> </Tooltip>
14682
+ <Tooltip content="Right bottom" placement="rightBottom"> <Button>rightBottom</Button> </Tooltip>
14672
14683
  ```
14673
14684
 
14674
- **4. Center placement — no target element**
14685
+ ---
14686
+
14687
+ **3. No arrow**
14688
+
14675
14689
  ```tsx
14676
- const steps = [
14677
- {
14678
- target: null, // null → popup centers on the viewport
14679
- title: 'Welcome to the App',
14680
- description: 'This quick tour will walk you through the key features.',
14681
- placement: 'center' as const,
14682
- },
14683
- ]
14690
+ <Tooltip content="No arrow" arrow={false}>
14691
+ <Button>Hover</Button>
14692
+ </Tooltip>
14684
14693
  ```
14685
14694
 
14686
- **5. Per-step overrides**
14687
- ```tsx
14688
- const steps = [
14689
- {
14690
- target: () => step1Ref.current,
14691
- title: 'Step 1 — Default',
14692
- description: 'Uses the global type and mask settings.',
14693
- },
14694
- {
14695
- target: () => step2Ref.current,
14696
- title: 'Step 2 — Primary',
14697
- description: 'This step overrides the card theme.',
14698
- type: 'primary' as const,
14699
- mask: false,
14700
- arrow: false,
14701
- },
14702
- ]
14695
+ ---
14703
14696
 
14704
- <Tour steps={steps} open={open} type="default" mask onClose={close} onFinish={close} />
14697
+ **4. Arrow pointing at center (corner placements)**
14698
+
14699
+ ```tsx
14700
+ <Tooltip content="Centered arrow" placement="topLeft" arrow={{ pointAtCenter: true }}>
14701
+ <Button>topLeft + pointAtCenter</Button>
14702
+ </Tooltip>
14705
14703
  ```
14706
14704
 
14707
- **6. Custom button labels per step**
14705
+ ---
14706
+
14707
+ **5. Preset color**
14708
+
14708
14709
  ```tsx
14709
- const steps = [
14710
- {
14711
- target: () => ref1.current,
14712
- title: 'Introduction',
14713
- nextButtonProps: { children: 'Get Started →' },
14714
- },
14710
+ <Tooltip content="Success action" color="green">
14711
+ <Button>Green</Button>
14712
+ </Tooltip>
14713
+
14714
+ <Tooltip content="Danger zone" color="red">
14715
+ <Button>Red</Button>
14716
+ </Tooltip>
14717
+
14718
+ <Tooltip content="Information" color="blue">
14719
+ <Button>Blue</Button>
14720
+ </Tooltip>
14721
+ ```
14722
+
14723
+ ---
14724
+
14725
+ **6. Custom CSS color**
14726
+
14727
+ ```tsx
14728
+ <Tooltip content="Brand tooltip" color="#722ed1">
14729
+ <Button>Custom purple</Button>
14730
+ </Tooltip>
14731
+ ```
14732
+
14733
+ ---
14734
+
14735
+ **7. Disable auto-flip**
14736
+
14737
+ ```tsx
14738
+ <Tooltip content="Always on top" placement="top" autoAdjustOverflow={false}>
14739
+ <Button>No flip</Button>
14740
+ </Tooltip>
14741
+ ```
14742
+
14743
+ ---
14744
+
14745
+ **8. Custom delay**
14746
+
14747
+ ```tsx
14748
+ <Tooltip content="Instant" delay={0}>
14749
+ <Button>No delay</Button>
14750
+ </Tooltip>
14751
+
14752
+ <Tooltip content="Slow reveal" delay={800}>
14753
+ <Button>800 ms delay</Button>
14754
+ </Tooltip>
14755
+ ```
14756
+
14757
+ ---
14758
+
14759
+ **9. Disabled**
14760
+
14761
+ ```tsx
14762
+ <Tooltip content="Won't show" disabled>
14763
+ <Button>Disabled tooltip</Button>
14764
+ </Tooltip>
14765
+ ```
14766
+
14767
+ ---
14768
+
14769
+ **10. Rich content**
14770
+
14771
+ ```tsx
14772
+ <Tooltip
14773
+ content={
14774
+ <div>
14775
+ <strong>Keyboard shortcut</strong>
14776
+ <p style={{ margin: '0.25rem 0 0', opacity: 0.85 }}>⌘ + K to open command palette</p>
14777
+ </div>
14778
+ }
14779
+ placement="bottom"
14780
+ >
14781
+ <Button>Hover for shortcut</Button>
14782
+ </Tooltip>
14783
+ ```
14784
+
14785
+ ---
14786
+
14787
+ **11. Semantic style customization**
14788
+
14789
+ ```tsx
14790
+ <Tooltip
14791
+ content="Styled tooltip"
14792
+ styles={{
14793
+ popup: { borderRadius: '0.75rem', fontSize: '0.75rem', padding: '0.375rem 0.625rem' },
14794
+ }}
14795
+ >
14796
+ <Button>Custom style</Button>
14797
+ </Tooltip>
14798
+ ```
14799
+
14800
+ ---
14801
+
14802
+ **12. Wrapping a disabled element**
14803
+
14804
+ Disabled elements do not fire mouse events. Wrap them in a `<span>` so the Tooltip trigger receives events correctly.
14805
+
14806
+ ```tsx
14807
+ <Tooltip content="Button is disabled">
14808
+ <span style={{ display: 'inline-flex' }}>
14809
+ <Button disabled>Submit</Button>
14810
+ </span>
14811
+ </Tooltip>
14812
+ ```
14813
+
14814
+ #### Accessibility
14815
+
14816
+ - Shows on `mouseenter` and `focus`
14817
+ - Hides on `mouseleave` and `blur`
14818
+ - Popup has `role="tooltip"`
14819
+ - Repositions on scroll and window resize while visible
14820
+
14821
+ </details>
14822
+
14823
+ ---
14824
+
14825
+ <details>
14826
+ <summary><strong>Tour</strong> - Step-by-step guided walkthrough with spotlight overlay</summary>
14827
+
14828
+ ### Tour
14829
+
14830
+ `Tour` is a guided walkthrough component that highlights UI elements one by one using an SVG spotlight mask. It is ideal for onboarding flows, feature discovery, and interactive product demos. The popup card follows the highlighted element with 13 placement options, supports two visual themes, and offers full control over step navigation, indicators, and action buttons.
14831
+
14832
+ ```tsx
14833
+ import { Tour } from '@juanitte/inoui'
14834
+ ```
14835
+
14836
+ #### Props
14837
+
14838
+ | Prop | Type | Default | Description |
14839
+ |------|------|---------|-------------|
14840
+ | `steps` | `TourStepConfig[]` | — | Array of step configurations |
14841
+ | `open` | `boolean` | — | Whether the tour is visible (controlled) |
14842
+ | `current` | `number` | — | Active step index (controlled) |
14843
+ | `onChange` | `(current: number) => void` | — | Called on step change |
14844
+ | `onClose` | `() => void` | — | Called when the tour closes |
14845
+ | `onFinish` | `() => void` | — | Called when the last step's Next button is clicked |
14846
+ | `mask` | `boolean` | `true` | Show SVG spotlight mask |
14847
+ | `arrow` | `boolean` | `true` | Show arrow pointing at the target |
14848
+ | `type` | `TourType` | `'default'` | Card visual theme |
14849
+ | `placement` | `TourPlacement` | `'bottom'` | Default popup placement (overridden per step) |
14850
+ | `gap` | `{ offset?: number; radius?: number }` | `{ offset: 6, radius: 2 }` | Spotlight padding (px) and corner radius (px) |
14851
+ | `closeIcon` | `ReactNode \| false` | — | Custom close icon; `false` hides it entirely |
14852
+ | `disabledInteraction` | `boolean` | — | Block pointer events on the highlighted element |
14853
+ | `scrollIntoViewOptions` | `boolean \| ScrollIntoViewOptions` | `true` | Auto-scroll target into view; `true` uses `{ block: 'center', behavior: 'instant' }` |
14854
+ | `indicatorsRender` | `(current: number, total: number) => ReactNode` | — | Custom step indicator renderer |
14855
+ | `actionsRender` | `(actions: ReactNode, info: ActionsInfo) => ReactNode` | — | Custom action buttons renderer (replaces footer buttons) |
14856
+ | `zIndex` | `number` | `1001` | z-index for overlay and popup |
14857
+ | `className` | `string` | — | CSS class on the popup card |
14858
+ | `style` | `CSSProperties` | — | Inline style on the popup card |
14859
+ | `classNames` | `TourClassNames` | — | Semantic class names per slot |
14860
+ | `styles` | `TourStyles` | — | Semantic inline styles per slot |
14861
+
14862
+ #### TourStepConfig
14863
+
14864
+ | Prop | Type | Default | Description |
14865
+ |------|------|---------|-------------|
14866
+ | `target` | `HTMLElement \| (() => HTMLElement \| null) \| null` | — | Element to highlight; `null` centers the popup |
14867
+ | `title` | `ReactNode` | — | Step title |
14868
+ | `description` | `ReactNode` | — | Step body text |
14869
+ | `cover` | `ReactNode` | — | Media content above the title (e.g. an image) |
14870
+ | `placement` | `TourPlacement` | inherited | Override placement for this step |
14871
+ | `arrow` | `boolean` | inherited | Override arrow visibility for this step |
14872
+ | `mask` | `boolean` | inherited | Override mask visibility for this step |
14873
+ | `type` | `TourType` | inherited | Override card theme for this step |
14874
+ | `nextButtonProps` | `{ children?: ReactNode; onClick?: () => void }` | — | Customize the Next / Finish button |
14875
+ | `prevButtonProps` | `{ children?: ReactNode; onClick?: () => void }` | — | Customize the Previous button |
14876
+ | `scrollIntoViewOptions` | `boolean \| ScrollIntoViewOptions` | inherited | Override scroll behavior for this step |
14877
+
14878
+ #### Types
14879
+
14880
+ ```ts
14881
+ type TourPlacement =
14882
+ | 'center'
14883
+ | 'top' | 'topLeft' | 'topRight'
14884
+ | 'bottom' | 'bottomLeft' | 'bottomRight'
14885
+ | 'left' | 'leftTop' | 'leftBottom'
14886
+ | 'right' | 'rightTop' | 'rightBottom'
14887
+
14888
+ type TourType = 'default' | 'primary'
14889
+
14890
+ // actionsRender info argument
14891
+ interface ActionsInfo {
14892
+ current: number
14893
+ total: number
14894
+ goTo: (step: number) => void
14895
+ close: () => void
14896
+ }
14897
+
14898
+ // Semantic slots
14899
+ type TourSemanticSlot =
14900
+ | 'root' | 'mask' | 'popup' | 'header'
14901
+ | 'title' | 'description' | 'footer'
14902
+ | 'arrow' | 'close' | 'cover' | 'indicators'
14903
+
14904
+ type TourClassNames = SemanticClassNames<TourSemanticSlot>
14905
+ type TourStyles = SemanticStyles<TourSemanticSlot>
14906
+ ```
14907
+
14908
+ #### Examples
14909
+
14910
+ **1. Basic guided tour**
14911
+ ```tsx
14912
+ import { useRef, useState } from 'react'
14913
+ import { Tour } from '@juanitte/inoui'
14914
+
14915
+ function App() {
14916
+ const btnRef = useRef<HTMLButtonElement>(null)
14917
+ const cardRef = useRef<HTMLDivElement>(null)
14918
+ const [open, setOpen] = useState(false)
14919
+
14920
+ const steps = [
14921
+ {
14922
+ target: () => btnRef.current,
14923
+ title: 'Create a new item',
14924
+ description: 'Click here to start creating a new entry.',
14925
+ },
14926
+ {
14927
+ target: () => cardRef.current,
14928
+ title: 'Your results appear here',
14929
+ description: 'This card shows the output of your actions.',
14930
+ placement: 'right' as const,
14931
+ },
14932
+ ]
14933
+
14934
+ return (
14935
+ <>
14936
+ <button ref={btnRef} onClick={() => {}}>New item</button>
14937
+ <div ref={cardRef} style={{ marginTop: 24 }}>Result card</div>
14938
+ <button onClick={() => setOpen(true)}>Start Tour</button>
14939
+
14940
+ <Tour
14941
+ steps={steps}
14942
+ open={open}
14943
+ onClose={() => setOpen(false)}
14944
+ onFinish={() => setOpen(false)}
14945
+ />
14946
+ </>
14947
+ )
14948
+ }
14949
+ ```
14950
+
14951
+ **2. Primary theme**
14952
+ ```tsx
14953
+ <Tour
14954
+ steps={steps}
14955
+ open={open}
14956
+ type="primary"
14957
+ onClose={() => setOpen(false)}
14958
+ onFinish={() => setOpen(false)}
14959
+ />
14960
+ ```
14961
+
14962
+ **3. No mask (transparent overlay)**
14963
+ ```tsx
14964
+ <Tour steps={steps} open={open} mask={false} onClose={() => setOpen(false)} onFinish={() => setOpen(false)} />
14965
+ ```
14966
+
14967
+ **4. Center placement — no target element**
14968
+ ```tsx
14969
+ const steps = [
14970
+ {
14971
+ target: null, // null → popup centers on the viewport
14972
+ title: 'Welcome to the App',
14973
+ description: 'This quick tour will walk you through the key features.',
14974
+ placement: 'center' as const,
14975
+ },
14976
+ ]
14977
+ ```
14978
+
14979
+ **5. Per-step overrides**
14980
+ ```tsx
14981
+ const steps = [
14982
+ {
14983
+ target: () => step1Ref.current,
14984
+ title: 'Step 1 — Default',
14985
+ description: 'Uses the global type and mask settings.',
14986
+ },
14987
+ {
14988
+ target: () => step2Ref.current,
14989
+ title: 'Step 2 — Primary',
14990
+ description: 'This step overrides the card theme.',
14991
+ type: 'primary' as const,
14992
+ mask: false,
14993
+ arrow: false,
14994
+ },
14995
+ ]
14996
+
14997
+ <Tour steps={steps} open={open} type="default" mask onClose={close} onFinish={close} />
14998
+ ```
14999
+
15000
+ **6. Custom button labels per step**
15001
+ ```tsx
15002
+ const steps = [
15003
+ {
15004
+ target: () => ref1.current,
15005
+ title: 'Introduction',
15006
+ nextButtonProps: { children: 'Get Started →' },
15007
+ },
14715
15008
  {
14716
15009
  target: () => ref2.current,
14717
15010
  title: 'Final Step',
@@ -16586,259 +16879,6 @@ type WatermarkStyles = SemanticStyles<WatermarkSemanticSlot>
16586
16879
 
16587
16880
  ---
16588
16881
 
16589
- <details>
16590
- <summary><strong>Tooltip</strong> - Lightweight hover tooltips with 12 placements and color presets</summary>
16591
-
16592
- ### Tooltip
16593
-
16594
- A lightweight tooltip component for displaying additional information on hover or focus. Renders into a portal (`document.body`), supports 12 placements, auto-flip on viewport overflow, an optional arrow with `pointAtCenter` mode, and colorful presets.
16595
-
16596
- #### Import
16597
-
16598
- ```tsx
16599
- import { Tooltip } from '@juanitte/inoui'
16600
- ```
16601
-
16602
- #### Props
16603
-
16604
- | Prop | Type | Default | Description |
16605
- |------|------|---------|-------------|
16606
- | `content` | `ReactNode` | — | **Required.** Tooltip content |
16607
- | `children` | `ReactNode` | — | **Required.** Trigger element |
16608
- | `placement` | `TooltipPlacement` | `'top'` | Preferred placement — 12 options |
16609
- | `position` | `TooltipPlacement` | — | **Deprecated.** Use `placement` instead |
16610
- | `arrow` | `boolean \| { pointAtCenter: boolean }` | `true` | Show arrow; pass `{ pointAtCenter: true }` to center it on corner placements |
16611
- | `color` | `string` | — | Preset color name or any CSS color — colorizes the tooltip background |
16612
- | `autoAdjustOverflow` | `boolean` | `true` | Flip to the opposite side when the tooltip overflows the viewport |
16613
- | `delay` | `number` | `200` | Delay before showing (ms) |
16614
- | `disabled` | `boolean` | `false` | Disable tooltip |
16615
- | `className` | `string` | — | Root CSS class |
16616
- | `style` | `CSSProperties` | — | Root inline style |
16617
- | `classNames` | `TooltipClassNames` | — | Semantic class names per slot |
16618
- | `styles` | `TooltipStyles` | — | Semantic inline styles per slot |
16619
-
16620
- #### Type Definitions
16621
-
16622
- ```ts
16623
- type TooltipPlacement =
16624
- | 'top' | 'topLeft' | 'topRight'
16625
- | 'bottom' | 'bottomLeft' | 'bottomRight'
16626
- | 'left' | 'leftTop' | 'leftBottom'
16627
- | 'right' | 'rightTop' | 'rightBottom'
16628
-
16629
- type TooltipSemanticSlot = 'root' | 'popup' | 'arrow'
16630
- type TooltipClassNames = SemanticClassNames<TooltipSemanticSlot>
16631
- type TooltipStyles = SemanticStyles<TooltipSemanticSlot>
16632
- ```
16633
-
16634
- #### Placements
16635
-
16636
- All 12 placements relative to the trigger element:
16637
-
16638
- ```
16639
- topLeft top topRight
16640
- leftTop ┌─────────────────┐ rightTop
16641
- left │ trigger │ right
16642
- leftBottom └─────────────────┘ rightBottom
16643
- bottomLeft bottom bottomRight
16644
- ```
16645
-
16646
- #### Preset Colors
16647
-
16648
- | Name | Hex |
16649
- |------|-----|
16650
- | `'blue'` | `#1677ff` |
16651
- | `'geekblue'` | `#2f54eb` |
16652
- | `'purple'` | `#722ed1` |
16653
- | `'cyan'` | `#13c2c2` |
16654
- | `'green'` | `#52c41a` |
16655
- | `'lime'` | `#a0d911` |
16656
- | `'yellow'` | `#fadb14` |
16657
- | `'gold'` | `#faad14` |
16658
- | `'orange'` | `#fa8c16` |
16659
- | `'volcano'` | `#fa541c` |
16660
- | `'red'` | `#f5222d` |
16661
- | `'pink'` / `'magenta'` | `#eb2f96` |
16662
-
16663
- Any other string is used as-is (hex, rgb, hsl…).
16664
-
16665
- #### Semantic DOM
16666
-
16667
- | Slot | Element | Description |
16668
- |------|---------|-------------|
16669
- | `root` | `<div>` | Inline wrapper around the trigger element |
16670
- | `popup` | `<div>` | Tooltip popup — portaled to `document.body` |
16671
- | `arrow` | `<div>` | Arrow pointing at the trigger |
16672
-
16673
- #### Examples
16674
-
16675
- **1. Basic**
16676
-
16677
- ```tsx
16678
- <Tooltip content="This is a tooltip">
16679
- <Button>Hover me</Button>
16680
- </Tooltip>
16681
- ```
16682
-
16683
- ---
16684
-
16685
- **2. All 12 placements**
16686
-
16687
- ```tsx
16688
- <Tooltip content="Top center" placement="top"> <Button>top</Button> </Tooltip>
16689
- <Tooltip content="Top left" placement="topLeft"> <Button>topLeft</Button> </Tooltip>
16690
- <Tooltip content="Top right" placement="topRight"> <Button>topRight</Button> </Tooltip>
16691
- <Tooltip content="Bottom center" placement="bottom"> <Button>bottom</Button> </Tooltip>
16692
- <Tooltip content="Bottom left" placement="bottomLeft"> <Button>bottomLeft</Button> </Tooltip>
16693
- <Tooltip content="Bottom right" placement="bottomRight"> <Button>bottomRight</Button> </Tooltip>
16694
- <Tooltip content="Left center" placement="left"> <Button>left</Button> </Tooltip>
16695
- <Tooltip content="Left top" placement="leftTop"> <Button>leftTop</Button> </Tooltip>
16696
- <Tooltip content="Left bottom" placement="leftBottom"> <Button>leftBottom</Button> </Tooltip>
16697
- <Tooltip content="Right center" placement="right"> <Button>right</Button> </Tooltip>
16698
- <Tooltip content="Right top" placement="rightTop"> <Button>rightTop</Button> </Tooltip>
16699
- <Tooltip content="Right bottom" placement="rightBottom"> <Button>rightBottom</Button> </Tooltip>
16700
- ```
16701
-
16702
- ---
16703
-
16704
- **3. No arrow**
16705
-
16706
- ```tsx
16707
- <Tooltip content="No arrow" arrow={false}>
16708
- <Button>Hover</Button>
16709
- </Tooltip>
16710
- ```
16711
-
16712
- ---
16713
-
16714
- **4. Arrow pointing at center (corner placements)**
16715
-
16716
- ```tsx
16717
- <Tooltip content="Centered arrow" placement="topLeft" arrow={{ pointAtCenter: true }}>
16718
- <Button>topLeft + pointAtCenter</Button>
16719
- </Tooltip>
16720
- ```
16721
-
16722
- ---
16723
-
16724
- **5. Preset color**
16725
-
16726
- ```tsx
16727
- <Tooltip content="Success action" color="green">
16728
- <Button>Green</Button>
16729
- </Tooltip>
16730
-
16731
- <Tooltip content="Danger zone" color="red">
16732
- <Button>Red</Button>
16733
- </Tooltip>
16734
-
16735
- <Tooltip content="Information" color="blue">
16736
- <Button>Blue</Button>
16737
- </Tooltip>
16738
- ```
16739
-
16740
- ---
16741
-
16742
- **6. Custom CSS color**
16743
-
16744
- ```tsx
16745
- <Tooltip content="Brand tooltip" color="#722ed1">
16746
- <Button>Custom purple</Button>
16747
- </Tooltip>
16748
- ```
16749
-
16750
- ---
16751
-
16752
- **7. Disable auto-flip**
16753
-
16754
- ```tsx
16755
- <Tooltip content="Always on top" placement="top" autoAdjustOverflow={false}>
16756
- <Button>No flip</Button>
16757
- </Tooltip>
16758
- ```
16759
-
16760
- ---
16761
-
16762
- **8. Custom delay**
16763
-
16764
- ```tsx
16765
- <Tooltip content="Instant" delay={0}>
16766
- <Button>No delay</Button>
16767
- </Tooltip>
16768
-
16769
- <Tooltip content="Slow reveal" delay={800}>
16770
- <Button>800 ms delay</Button>
16771
- </Tooltip>
16772
- ```
16773
-
16774
- ---
16775
-
16776
- **9. Disabled**
16777
-
16778
- ```tsx
16779
- <Tooltip content="Won't show" disabled>
16780
- <Button>Disabled tooltip</Button>
16781
- </Tooltip>
16782
- ```
16783
-
16784
- ---
16785
-
16786
- **10. Rich content**
16787
-
16788
- ```tsx
16789
- <Tooltip
16790
- content={
16791
- <div>
16792
- <strong>Keyboard shortcut</strong>
16793
- <p style={{ margin: '0.25rem 0 0', opacity: 0.85 }}>⌘ + K to open command palette</p>
16794
- </div>
16795
- }
16796
- placement="bottom"
16797
- >
16798
- <Button>Hover for shortcut</Button>
16799
- </Tooltip>
16800
- ```
16801
-
16802
- ---
16803
-
16804
- **11. Semantic style customization**
16805
-
16806
- ```tsx
16807
- <Tooltip
16808
- content="Styled tooltip"
16809
- styles={{
16810
- popup: { borderRadius: '0.75rem', fontSize: '0.75rem', padding: '0.375rem 0.625rem' },
16811
- }}
16812
- >
16813
- <Button>Custom style</Button>
16814
- </Tooltip>
16815
- ```
16816
-
16817
- ---
16818
-
16819
- **12. Wrapping a disabled element**
16820
-
16821
- Disabled elements do not fire mouse events. Wrap them in a `<span>` so the Tooltip trigger receives events correctly.
16822
-
16823
- ```tsx
16824
- <Tooltip content="Button is disabled">
16825
- <span style={{ display: 'inline-flex' }}>
16826
- <Button disabled>Submit</Button>
16827
- </span>
16828
- </Tooltip>
16829
- ```
16830
-
16831
- #### Accessibility
16832
-
16833
- - Shows on `mouseenter` and `focus`
16834
- - Hides on `mouseleave` and `blur`
16835
- - Popup has `role="tooltip"`
16836
- - Repositions on scroll and window resize while visible
16837
-
16838
- </details>
16839
-
16840
- ---
16841
-
16842
16882
  ## License
16843
16883
 
16844
16884
  MIT License - see [LICENSE](./LICENSE) for details.