Aller au contenu

Tour

Visite guidée avec mise en évidence par projecteur et navigation par étapes.

import { Tour } from 'asterui'

Tour basique

Une visite guidée simple avec plusieurs étapes.

import { Tour, Button, Input, Card } from 'asterui'
import { useState, useRef } from 'react'

function App() {
  const [open, setOpen] = useState(false);
  const searchRef = useRef<HTMLInputElement>(null);
  const profileRef = useRef<HTMLButtonElement>(null);
  const settingsRef = useRef<HTMLButtonElement>(null);
  
  const steps = [
    {
      target: searchRef,
      title: 'Search',
      description: 'Use the search bar to find content quickly.',
      placement: 'bottom' as const,
    },
    {
      target: profileRef,
      title: 'Profile',
      description: 'Click here to view and edit your profile.',
      placement: 'bottom' as const,
    },
    {
      target: settingsRef,
      title: 'Settings',
      description: 'Customize your experience in settings.',
      placement: 'left' as const,
    },
  ];
  
  return (
      <Card className="p-4">
        <div className="flex gap-4 items-center mb-4">
          <Input ref={searchRef} placeholder="Search..." className="flex-1" />
          <Button ref={profileRef}>Profile</Button>
          <Button ref={settingsRef}>Settings</Button>
        </div>
        <Button color="primary" onClick={() => setOpen(true)}>
          Start Tour
        </Button>
        <Tour
          open={open}
          steps={steps}
          onClose={() => setOpen(false)}
          onFinish={() => setOpen(false)}
        />
      </Card>
    )
}

export default App

Tour sans cible

Les étapes sans cible apparaissent centrées à l'écran.

import { Tour, Button } from 'asterui'
import { useState } from 'react'

function App() {
  const [open, setOpen] = useState(false);
  
  const steps = [
    {
      title: 'Welcome!',
      description: 'This tour will guide you through the main features.',
    },
    {
      title: 'Getting Started',
      description: 'Follow along to learn how to use this application.',
    },
    {
      title: 'All Done!',
      description: 'You are ready to start using the app.',
    },
  ];
  
  return (
      <Button color="primary" onClick={() => setOpen(true)}>
        Start Intro
      </Button>
      <Tour
        open={open}
        steps={steps}
        onClose={() => setOpen(false)}
        type="primary"
      />
    )
}

export default App

Avec image de couverture

Ajoutez des images ou du contenu personnalisé au-dessus du titre de l'étape.

import { Tour, Button } from 'asterui'
import { useState, useRef } from 'react'

function App() {
  const [open, setOpen] = useState(false);
  const buttonRef = useRef<HTMLButtonElement>(null);
  
  const steps = [
    {
      target: buttonRef,
      title: 'New Feature',
      description: 'Check out this amazing new feature we just added!',
      cover: (
        <img
          src="https://picsum.photos/320/160"
          alt="Feature preview"
          className="w-full h-40 object-cover"
        />
      ),
      placement: 'right' as const,
    },
  ];
  
  return (
      <Button ref={buttonRef} color="primary" onClick={() => setOpen(true)}>
        View Feature
      </Button>
      <Tour
        open={open}
        steps={steps}
        onClose={() => setOpen(false)}
        showSkip={false}
      />
    )
}

export default App

Placements

Contrôlez l'emplacement du popover par rapport à la cible.

Target
import { Tour, Button, Space } from 'asterui'
import { useState, useRef } from 'react'

function App() {
  const [open, setOpen] = useState(false);
  const targetRef = useRef<HTMLDivElement>(null);
  const placements = ['top', 'right', 'bottom', 'left'] as const;
  const [placementIndex, setPlacementIndex] = useState(0);
  
  const steps = [
    {
      target: targetRef,
      title: `Placement: ${placements[placementIndex]}`,
      description: 'The popover can appear on any side of the target.',
      placement: placements[placementIndex],
    },
  ];
  
  return (
      <div className="flex flex-col items-center gap-4">
        <div
          ref={targetRef}
          className="w-24 h-24 bg-primary text-primary-content flex items-center justify-center rounded-lg"
        >
          Target
        </div>
        <Space>
          <Button onClick={() => setPlacementIndex((i) => (i + 1) % 4)}>
            Change Placement
          </Button>
          <Button color="primary" onClick={() => setOpen(true)}>
            Show Tour
          </Button>
        </Space>
        <Tour
          open={open}
          steps={steps}
          onClose={() => setOpen(false)}
          showIndicators={false}
        />
      </div>
    )
}

export default App
PropriétéDescriptionTypeDéfaut
openSi le tour est visiblebooleanfalse
stepsConfiguration des étapes du tourTourStepProps[]-
currentIndice de l’étape actuelle (contrôlé)number-
onChangeCallback lorsque l’étape change(current: number) => void-
onCloseCallback lorsque le tour se ferme() => void-
onFinishCallback lorsque le tour se termine() => void-
maskAfficher le masque de superposition avec projecteurbooleantrue
typeType de style de bouton'default' | 'primary''default'
gapÉcart entre le projecteur et la cible [rayon, décalage] ou nombrenumber | [number, number]8
showSkipAfficher le bouton ignorerbooleantrue
showIndicatorsAfficher les indicateurs d’étapebooleantrue
closeOnMaskClickFermer au clic sur le masquebooleantrue
closeOnEscapeFermer avec la touche Échapbooleantrue
scrollIntoViewFaire défiler la cible dans la vuebooleantrue
prevButtonTextTexte pour le bouton précédentReact.ReactNode'Previous'
nextButtonTextTexte pour le bouton suivantReact.ReactNode'Next'
finishButtonTextTexte pour le bouton terminerReact.ReactNode'Finish'
skipButtonTextTexte pour le bouton ignorerReact.ReactNode'Skip'
zIndexZ-index pour la superposition du tournumber1000
PropriétéDescriptionTypeDéfaut
targetRéférence de l’élément cible ou fonction retournant l’élémentRefObject<HTMLElement> | (() => HTMLElement | null) | null-
titleTitre de l’étapeReact.ReactNode-
descriptionDescription de l’étapeReact.ReactNode-
coverImage de couverture ou contenu au-dessus du titreReact.ReactNode-
placementPlacement du popover par rapport à la cibleTourPlacement'bottom'
classNameClasse personnalisée pour le popover de l’étapestring-
onOpenAppelé lorsque l’étape devient active() => void-
onCloseAppelé lors de la sortie de l’étape() => void-
  • La boîte de dialogue du tour a role=“dialog” et aria-modal=“true”
  • Les touches fléchées permettent de naviguer entre les étapes
  • La touche Échap ferme le tour
  • Les indicateurs d’étape sont accessibles au clavier
  • Le focus est piégé dans le tour lorsqu’il est ouvert