Skip to content

Product tour#3065

Open
mnocon wants to merge 3 commits into4.6from
product-tour
Open

Product tour#3065
mnocon wants to merge 3 commits into4.6from
product-tour

Conversation

@mnocon
Copy link
Contributor

@mnocon mnocon commented Feb 18, 2026

Target: 4.6, 5.0

Documentation for the Product Tour feature - an extension of Integrated Help.

Contains still some TODOs, but initial feedback is welcome.

User doc PR: ibexa/documentation-user#390

alt_translation_key: tour.image.alt
- type: video
params:
# 'Big Buck Bunny' licensed under CC 3.0 by the Blender foundation. Hosted by archive.org
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ibexa/share": "~4.6.x-dev",
"ibexa/phpstan": "~4.6.-dev"
"ibexa/phpstan": "~4.6.-dev",
"ibexa/integrated-help": "dev-dev as 4.6.x-dev"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TMP branch to make PHPStan happy

With the following example, the scenario is modified to trigger only when certain conditions are matched. When the current user has a pending [notification]([[= user_doc =]]/getting_started/notifications/), a custom onboarding scenario is triggered.

First, define a custom product tour scenario.
It contains a placeholder step with a single block.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A scenario MUST have at least one step, with at least one block - that's why I need to add a placeholder step in Yaml and remove all of them in PHP code

@mnocon mnocon marked this pull request as ready for review February 18, 2026 08:05
@github-actions
Copy link

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/back_office/product_tour/config/general_scenario.yaml


code_samples/back_office/product_tour/config/general_scenario.yaml

docs/administration/back_office/configure_product_tour.md@118:```yaml hl_lines="6 10"
docs/administration/back_office/configure_product_tour.md@119:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 0, 14) =]]
docs/administration/back_office/configure_product_tour.md@120:```

001⫶ibexa:
002⫶ system:
003⫶ default:
004⫶ product_tour:
005⫶ my_general_scenario:
006❇️ type: 'general'
007⫶ steps:
008⫶ welcome_step:
009⫶ step_title_translation_key: title
010❇️ background_image: build/images/headless.png
011⫶ blocks:
012⫶ - type: title
013⫶ params:
014⫶ text_translation_key: subtitle

docs/administration/back_office/configure_product_tour.md@187:```yaml
docs/administration/back_office/configure_product_tour.md@188:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 11, 14) =]]
docs/administration/back_office/configure_product_tour.md@189:```

001⫶ - type: title
002⫶ params:
003⫶ text_translation_key: subtitle

docs/administration/back_office/configure_product_tour.md@195:```yaml
docs/administration/back_office/configure_product_tour.md@196:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 14, 17) =]]
docs/administration/back_office/configure_product_tour.md@197:```

001⫶ - type: text
002⫶ params:
003⫶ text_translation_key: tour.step.description

docs/administration/back_office/configure_product_tour.md@203:```yaml
docs/administration/back_office/configure_product_tour.md@204:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 17, 21) =]]
docs/administration/back_office/configure_product_tour.md@205:```

001⫶ - type: link
002⫶ params:
003⫶ url: https://doc.ibexa.co
004⫶ text_translation_key: tour.link.documentation

docs/administration/back_office/configure_product_tour.md@211:```yaml
docs/administration/back_office/configure_product_tour.md@212:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 29, 36) =]]
docs/administration/back_office/configure_product_tour.md@213:```

001⫶ - type: list
002⫶ params:
003⫶ title_translation_key: tour.list.title
004⫶ items_translation_keys:
005⫶ - tour.list.item1
006⫶ - tour.list.item2
007⫶ - tour.list.item3

docs/administration/back_office/configure_product_tour.md@229:```yaml
docs/administration/back_office/configure_product_tour.md@230:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 21, 25) =]]
docs/administration/back_office/configure_product_tour.md@231:```

001⫶ - type: image
002⫶ params:
003⫶ src: /bundles/ibexaadminui/img/feature-screenshot.jpg
004⫶ alt_translation_key: tour.image.alt

docs/administration/back_office/configure_product_tour.md@237:```yaml
docs/administration/back_office/configure_product_tour.md@238:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 25, 29) =]]
docs/administration/back_office/configure_product_tour.md@239:```

001⫶ - type: video
002⫶ params:
003⫶ # 'Big Buck Bunny' licensed under CC 3.0 by the Blender foundation. Hosted by archive.org
004⫶ url: https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4

docs/administration/back_office/configure_product_tour.md@245:```yaml
docs/administration/back_office/configure_product_tour.md@246:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 36, 39) =]]
docs/administration/back_office/configure_product_tour.md@247:```

001⫶ - type: twig_template
002⫶ params:
003⫶ template: custom_template.html.twig

docs/administration/back_office/configure_product_tour.md@269:```yaml
docs/administration/back_office/configure_product_tour.md@270:[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml') =]]
docs/administration/back_office/configure_product_tour.md@271:```

001⫶ibexa:
002⫶ system:
003⫶ default:
004⫶ product_tour:
005⫶ my_general_scenario:
006⫶ type: 'general'
007⫶ steps:
008⫶ welcome_step:
009⫶ step_title_translation_key: title
010⫶ background_image: build/images/headless.png
011⫶ blocks:
012⫶ - type: title
013⫶ params:
014⫶ text_translation_key: subtitle
015⫶ - type: text
016⫶ params:
017⫶ text_translation_key: tour.step.description
018⫶ - type: link
019⫶ params:
020⫶ url: https://doc.ibexa.co
021⫶ text_translation_key: tour.link.documentation
022⫶ - type: image
023⫶ params:
024⫶ src: /bundles/ibexaadminui/img/feature-screenshot.jpg
025⫶ alt_translation_key: tour.image.alt
026⫶ - type: video
027⫶ params:
028⫶ # 'Big Buck Bunny' licensed under CC 3.0 by the Blender foundation. Hosted by archive.org
029⫶ url: https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4
030⫶ - type: list
031⫶ params:
032⫶ title_translation_key: tour.list.title
033⫶ items_translation_keys:
034⫶ - tour.list.item1
035⫶ - tour.list.item2
036⫶ - tour.list.item3
037⫶ - type: twig_template
038⫶ params:
039⫶ template: custom_template.html.twig


code_samples/back_office/product_tour/config/targetable_scenario.yaml


code_samples/back_office/product_tour/config/targetable_scenario.yaml

docs/administration/back_office/configure_product_tour.md@127:```yaml hl_lines="6 10"
docs/administration/back_office/configure_product_tour.md@128:[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 0, 15) =]]
docs/administration/back_office/configure_product_tour.md@129:```

001⫶ibexa:
002⫶ system:
003⫶ default:
004⫶ product_tour:
005⫶ targetable_dashboard_scenario:
006❇️ type: 'targetable'
007⫶ steps:
008⫶ dashboard_options:
009⫶ step_title_translation_key: Open Dashboard options
010❇️ target: ".ibexa-db-header__more"
011⫶ # No interaction_mode specified or the value is set to null
012⫶ blocks:
013⫶ - type: text
014⫶ params:
015⫶ text_translation_key: Learn how to customize the blocks displayed on your dashboard

docs/administration/back_office/configure_product_tour.md@153:```yaml
docs/administration/back_office/configure_product_tour.md@154:[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 7, 15) =]]
docs/administration/back_office/configure_product_tour.md@155:```

001⫶ dashboard_options:
002⫶ step_title_translation_key: Open Dashboard options
003⫶ target: ".ibexa-db-header__more"
004⫶ # No interaction_mode specified or the value is set to null
005⫶ blocks:
006⫶ - type: text
007⫶ params:
008⫶ text_translation_key: Learn how to customize the blocks displayed on your dashboard

docs/administration/back_office/configure_product_tour.md@162:```yaml
docs/administration/back_office/configure_product_tour.md@163:[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 15, 23) =]]
docs/administration/back_office/configure_product_tour.md@164:```

001⫶ open_dashboard_options:
002⫶ step_title_translation_key: Open Dashboard options
003⫶ target: '.ibexa-db-header__more'
004⫶ interaction_mode: clickable
005⫶ blocks:
006⫶ - type: text
007⫶ params:
008⫶ text_translation_key: Click here to customize your dashboard

docs/administration/back_office/configure_product_tour.md@171:```yaml
docs/administration/back_office/configure_product_tour.md@172:[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 31, 39) =]]
docs/administration/back_office/configure_product_tour.md@173:```

001⫶ drag_and_drop_step:
002⫶ step_title_translation_key: Drag-and-drop blocks
003⫶ target: ".c-pb-toolbox-blocks-group__blocks > * .c-pb-toolbox-block__content:first-of-type"
004⫶ interaction_mode: draggable
005⫶ blocks:
006⫶ - type: text
007⫶ params:
008⫶ text_translation_key: Drag-and-drop blocks from the sidebar to the dashboard to customize it

docs/administration/back_office/configure_product_tour.md@277:```yaml
docs/administration/back_office/configure_product_tour.md@278:[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml') =]]
docs/administration/back_office/configure_product_tour.md@279:```

001⫶ibexa:
002⫶ system:
003⫶ default:
004⫶ product_tour:
005⫶ targetable_dashboard_scenario:
006⫶ type: 'targetable'
007⫶ steps:
008⫶ dashboard_options:
009⫶ step_title_translation_key: Open Dashboard options
010⫶ target: ".ibexa-db-header__more"
011⫶ # No interaction_mode specified or the value is set to null
012⫶ blocks:
013⫶ - type: text
014⫶ params:
015⫶ text_translation_key: Learn how to customize the blocks displayed on your dashboard
016⫶ open_dashboard_options:
017⫶ step_title_translation_key: Open Dashboard options
018⫶ target: '.ibexa-db-header__more'
019⫶ interaction_mode: clickable
020⫶ blocks:
021⫶ - type: text
022⫶ params:
023⫶ text_translation_key: Click here to customize your dashboard
024⫶ customize_dashboard:
025⫶ step_title_translation_key: Customize Dashboard
026⫶ target: '.ibexa-db-actions-popup-menu'
027⫶ interaction_mode: clickable
028⫶ blocks:
029⫶ - type: text
030⫶ params:
031⫶ text_translation_key: Choose "Customize dashboard"
032⫶ drag_and_drop_step:
033⫶ step_title_translation_key: Drag-and-drop blocks
034⫶ target: ".c-pb-toolbox-blocks-group__blocks > * .c-pb-toolbox-block__content:first-of-type"
035⫶ interaction_mode: draggable
036⫶ blocks:
037⫶ - type: text
038⫶ params:
039⫶ text_translation_key: Drag-and-drop blocks from the sidebar to the dashboard to customize it


code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php


code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php

docs/administration/back_office/customize_product_tour.md@42:```php hl_lines="35-37 39-41 43-45 47-58"
docs/administration/back_office/customize_product_tour.md@43:[[= include_file('code_samples/back_office/product_tour/src/EventSubscriber/NotificationScenarioSubscriber.php') =]]
docs/administration/back_office/customize_product_tour.md@44:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\EventSubscriber;
006⫶
007⫶use Ibexa\Contracts\Core\Repository\NotificationService;
008⫶use Ibexa\Contracts\IntegratedHelp\Event\RenderProductTourScenarioEvent;
009⫶use Ibexa\IntegratedHelp\ProductTour\Block\LinkBlock;
010⫶use Ibexa\IntegratedHelp\ProductTour\Block\TextBlock;
011⫶use Ibexa\IntegratedHelp\ProductTour\ProductTourStep;
012⫶use Symfony\Component\EventDispatcher\EventSubscriberInterface;
013⫶
014⫶final class NotificationScenarioSubscriber implements EventSubscriberInterface
015⫶{
016⫶ private NotificationService $notificationService;
017⫶
018⫶ public function __construct(NotificationService $notificationService)
019⫶ {
020⫶ $this->notificationService = $notificationService;
021⫶ }
022⫶
023⫶ public static function getSubscribedEvents(): array
024⫶ {
025⫶ return [
026⫶ RenderProductTourScenarioEvent::class => ['onRenderScenario'],
027⫶ ];
028⫶ }
029⫶
030⫶ public function onRenderScenario(RenderProductTourScenarioEvent $event): void
031⫶ {
032⫶ $scenario = $event->getScenario();
033⫶ $steps = $scenario->getSteps();
034⫶
035❇️ if ($scenario->getIdentifier() !== 'notifications') {
036❇️ return;
037❇️ }
038⫶
039❇️ foreach ($steps as $step) {
040❇️ $scenario->removeStep($step);
041❇️ }
042⫶
043❇️ if (!$this->hasUnreadNotifications()) {
044❇️ return;
045❇️ }
046⫶
047❇️ $customStep = new ProductTourStep();
048❇️ $customStep->setIdentifier('custom_step_identifier');
049❇️ $customStep->setInteractionMode('clickable');
050❇️ $customStep->setTarget('.ibexa-header-user-menu__notifications-toggler');
051❇️ $customStep->setTitle('You have unread notifications');
052❇️ $customStep->addBlock(new TextBlock('Click here to preview your unread notifications.'));
053❇️ $customStep->addBlock(new LinkBlock(
054❇️ 'https://doc.ibexa.co/projects/userguide/en/latest/getting_started/notifications/',
055❇️ 'Learn more about notifications'
056❇️ ));
057❇️
058❇️ $scenario->addStep($customStep);
059⫶ }
060⫶
061⫶ private function hasUnreadNotifications(): bool
062⫶ {
063⫶ return $this->notificationService->getPendingNotificationCount() > 0;
064⫶ }
065⫶}

Download colorized diff

@sonarqubecloud
Copy link


Clickable and draggable modes are designed for single actions only (buttons, links).
You can't select an entire form.
If the interaction with the highlighted element results in redirection to a new page or opening a modal window where the previous target element can't be found, the "Previous" navigation step will be disabled.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the "Previous" navigation step will not be disabled.

Embed images with alternative text:

```yaml
[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 21, 25) =]]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't be better to give a example with asset added to public folder. Before block give example that 'I add a photo public/img/welcome.jpg and in config put img/welcome.jpg

``` yaml
ibexa:
system:
default:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here can also be changed to admin_group

@@ -0,0 +1,39 @@
ibexa:
system:
default:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here can also be changed to admin_group

@@ -0,0 +1,39 @@
ibexa:
system:
default:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here can also be changed to admin_group


For **general scenario**, the scenario appears at the earliest opportunity (on any page after logging in), with an exception of the user settings area.

For **targeted scenarios**, the scenario begins if the target element is found in the DOM.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too, with the exception of the user settings area.

The steps building the scenario support three interaction modes:

- Standard - Users navigate between steps using "Previous" and "Next" buttons
- Clickable - Users must click the highlighted element to proceed to the next step
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an idea: we can mention, that if someone would want to go to prev step in clickable or draggable mode it is possible only by restarting tour (for example via user setting after finishing tour)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments