Feature/onboarding slides (#4955)

# Description of Changes

- Added onboarding slides/upgrade banner conditions for all the
following cases
  - 'licensed'
  - 'no-login-user-under-limit-no-license'
  - 'no-login-admin-under-limit-no-license'
  - 'no-login-user-over-limit-no-license'
  - 'no-login-admin-over-limit-no-license'
  - 'login-user-under-limit-no-license'
  - 'login-admin-under-limit-no-license'
  - 'login-user-over-limit-no-license'
  - 'login-admin-over-limit-no-license';


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.

---------

Co-authored-by: Anthony Stirling <[email protected]>
Co-authored-by: Connor Yoh <[email protected]>
This commit is contained in:
EthanHealy01
2025-11-25 13:45:02 +00:00
committed by GitHub
co-authored by Anthony Stirling Connor Yoh
parent 80f2980755
commit a8db2fda18
66 changed files with 5641 additions and 1248 deletions
@@ -0,0 +1,207 @@
import WelcomeSlide from '@app/components/onboarding/slides/WelcomeSlide';
import DesktopInstallSlide from '@app/components/onboarding/slides/DesktopInstallSlide';
import SecurityCheckSlide from '@app/components/onboarding/slides/SecurityCheckSlide';
import PlanOverviewSlide from '@app/components/onboarding/slides/PlanOverviewSlide';
import ServerLicenseSlide from '@app/components/onboarding/slides/ServerLicenseSlide';
import { SlideConfig, LicenseNotice } from '@app/types/types';
export type SlideId =
| 'welcome'
| 'desktop-install'
| 'security-check'
| 'admin-overview'
| 'server-license';
export type HeroType = 'rocket' | 'dual-icon' | 'shield' | 'diamond' | 'logo';
export type ButtonAction =
| 'next'
| 'prev'
| 'close'
| 'complete-close'
| 'download-selected'
| 'security-next'
| 'launch-admin'
| 'launch-tools'
| 'launch-auto'
| 'see-plans'
| 'skip-to-license';
export interface FlowState {
selectedRole: 'admin' | 'user' | null;
}
export interface OSOption {
label: string;
url: string;
value: string;
}
export interface SlideFactoryParams {
osLabel: string;
osUrl: string;
osOptions?: OSOption[];
onDownloadUrlChange?: (url: string) => void;
selectedRole: 'admin' | 'user' | null;
onRoleSelect: (role: 'admin' | 'user' | null) => void;
licenseNotice?: LicenseNotice;
loginEnabled?: boolean;
}
export interface HeroDefinition {
type: HeroType;
}
export interface ButtonDefinition {
key: string;
type: 'button' | 'icon';
label?: string;
icon?: 'chevron-left';
variant?: 'primary' | 'secondary' | 'default';
group: 'left' | 'right';
action: ButtonAction;
disabledWhen?: (state: FlowState) => boolean;
}
export interface SlideDefinition {
id: SlideId;
createSlide: (params: SlideFactoryParams) => SlideConfig;
hero: HeroDefinition;
buttons: ButtonDefinition[];
}
export const SLIDE_DEFINITIONS: Record<SlideId, SlideDefinition> = {
'welcome': {
id: 'welcome',
createSlide: () => WelcomeSlide(),
hero: { type: 'rocket' },
buttons: [
{
key: 'welcome-next',
type: 'button',
label: 'onboarding.buttons.next',
variant: 'primary',
group: 'right',
action: 'next',
},
],
},
'desktop-install': {
id: 'desktop-install',
createSlide: ({ osLabel, osUrl, osOptions, onDownloadUrlChange }) => DesktopInstallSlide({ osLabel, osUrl, osOptions, onDownloadUrlChange }),
hero: { type: 'dual-icon' },
buttons: [
{
key: 'desktop-back',
type: 'icon',
icon: 'chevron-left',
group: 'left',
action: 'prev',
},
{
key: 'desktop-skip',
type: 'button',
label: 'onboarding.buttons.skipForNow',
variant: 'secondary',
group: 'left',
action: 'next',
},
{
key: 'desktop-download',
type: 'button',
label: 'onboarding.buttons.download',
variant: 'primary',
group: 'right',
action: 'download-selected',
},
],
},
'security-check': {
id: 'security-check',
createSlide: ({ selectedRole, onRoleSelect }) =>
SecurityCheckSlide({ selectedRole, onRoleSelect }),
hero: { type: 'shield' },
buttons: [
{
key: 'security-back',
type: 'button',
label: 'onboarding.buttons.back',
variant: 'secondary',
group: 'left',
action: 'prev',
},
{
key: 'security-next',
type: 'button',
label: 'onboarding.buttons.next',
variant: 'primary',
group: 'right',
action: 'security-next',
disabledWhen: (state) => !state.selectedRole,
},
],
},
'admin-overview': {
id: 'admin-overview',
createSlide: ({ licenseNotice, loginEnabled }) =>
PlanOverviewSlide({ isAdmin: true, licenseNotice, loginEnabled }),
hero: { type: 'diamond' },
buttons: [
{
key: 'admin-back',
type: 'icon',
icon: 'chevron-left',
group: 'left',
action: 'prev',
},
{
key: 'admin-show',
type: 'button',
label: 'onboarding.buttons.showMeAround',
variant: 'primary',
group: 'right',
action: 'launch-admin',
},
{
key: 'admin-skip',
type: 'button',
label: 'onboarding.buttons.skipTheTour',
variant: 'secondary',
group: 'left',
action: 'skip-to-license',
},
],
},
'server-license': {
id: 'server-license',
createSlide: ({ licenseNotice }) => ServerLicenseSlide({ licenseNotice }),
hero: { type: 'logo' },
buttons: [
{
key: 'license-close',
type: 'button',
label: 'onboarding.buttons.skipForNow',
variant: 'secondary',
group: 'left',
action: 'close',
},
{
key: 'license-see-plans',
type: 'button',
label: 'onboarding.serverLicense.seePlans',
variant: 'primary',
group: 'right',
action: 'see-plans',
},
],
},
};
export const FLOW_SEQUENCES = {
loginAdmin: ['welcome', 'desktop-install', 'admin-overview'] as SlideId[],
loginUser: ['welcome', 'desktop-install'] as SlideId[],
noLoginBase: ['welcome', 'desktop-install', 'security-check'] as SlideId[],
noLoginAdmin: ['admin-overview'] as SlideId[],
};