Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/examples/basic.less
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}

// Wrapper for the tour content
.@{tour-prefix-cls}-inner {
.@{tour-prefix-cls}-body {
text-align: left;
text-decoration: none;
border-radius: 6px;;
Expand Down
12 changes: 9 additions & 3 deletions src/Mask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import classNames from 'classnames';
import Portal from '@rc-component/portal';
import type { PosInfo } from './hooks/useTarget';
import useId from 'rc-util/lib/hooks/useId';
import { SemanticName } from './interface';

const COVER_PROPS = {
fill: 'transparent',
Expand All @@ -21,6 +22,8 @@ export interface MaskProps {
animated?: boolean | { placeholder: boolean };
zIndex?: number;
disabledInteraction?: boolean;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
}

const Mask = (props: MaskProps) => {
Expand All @@ -34,7 +37,9 @@ const Mask = (props: MaskProps) => {
open,
animated,
zIndex,
disabledInteraction
disabledInteraction,
styles,
classNames: tourClassNames,
} = props;

const id = useId();
Expand All @@ -48,7 +53,7 @@ const Mask = (props: MaskProps) => {
return (
<Portal open={open} autoLock>
<div
className={classNames(`${prefixCls}-mask`, rootClassName)}
className={classNames(`${prefixCls}-mask`, rootClassName, tourClassNames?.mask)}
style={{
position: 'fixed',
left: 0,
Expand All @@ -57,7 +62,8 @@ const Mask = (props: MaskProps) => {
bottom: 0,
zIndex,
pointerEvents: pos && !disabledInteraction ? 'none' : 'auto',
...style
...style,
...styles?.mask,
}}
>
{showMask ? (
Expand Down
12 changes: 11 additions & 1 deletion src/Tour.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ const Tour: React.FC<TourProps> = props => {
closable,
builtinPlacements,
disabledInteraction,
styles,
classNames: tourClassNames,
className,
style,
...restProps
} = props;

Expand All @@ -66,7 +70,7 @@ const Tour: React.FC<TourProps> = props => {
postState: origin =>
mergedCurrent < 0 || mergedCurrent >= steps.length
? false
: origin ?? true,
: (origin ?? true),
});

// Record if already rended in the DOM to avoid `findDOMNode` issue
Expand Down Expand Up @@ -157,6 +161,8 @@ const Tour: React.FC<TourProps> = props => {

const getPopupElement = () => (
<TourStep
styles={styles}
classNames={tourClassNames}
arrow={mergedArrow}
key="content"
prefixCls={prefixCls}
Expand Down Expand Up @@ -192,6 +198,8 @@ const Tour: React.FC<TourProps> = props => {
return (
<>
<Mask
styles={styles}
classNames={tourClassNames}
zIndex={zIndex}
prefixCls={prefixCls}
pos={posInfo}
Expand Down Expand Up @@ -222,13 +230,15 @@ const Tour: React.FC<TourProps> = props => {
<Portal open={mergedOpen} autoLock>
<div
className={classNames(
className,
rootClassName,
`${prefixCls}-target-placeholder`,
)}
style={{
...(posInfo || CENTER_PLACEHOLDER),
position: 'fixed',
pointerEvents: 'none',
...style,
}}
/>
</Portal>
Expand Down
73 changes: 56 additions & 17 deletions src/TourStep/DefaultPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import type { TourStepProps } from '../interface';
import classNames from 'classnames';
import pickAttrs from 'rc-util/lib/pickAttrs';

export type DefaultPanelProps = Exclude<TourStepProps, "closable"> & {
closable: Exclude<TourStepProps["closable"], boolean>;
export type DefaultPanelProps = Exclude<TourStepProps, 'closable'> & {
closable: Exclude<TourStepProps['closable'], boolean>;
};

export default function DefaultPanel(props: DefaultPanelProps) {
Expand All @@ -20,14 +20,28 @@ export default function DefaultPanel(props: DefaultPanelProps) {
onFinish,
className,
closable,
classNames: tourClassNames,
styles,
} = props;
const ariaProps = pickAttrs(closable || {}, true);
const closeIcon = closable?.closeIcon ?? <span className={`${prefixCls}-close-x`}>&times;</span>;
const closeIcon = closable?.closeIcon ?? (
<span className={`${prefixCls}-close-x`}>&times;</span>
);
const mergedClosable = !!closable;

return (
<div className={classNames(`${prefixCls}-content`, className)}>
<div className={`${prefixCls}-inner`}>
<div
className={classNames(
`${prefixCls}-section`,
tourClassNames?.section,
className,
)}
style={styles?.section}
>
<div
className={classNames(`${prefixCls}-body`, tourClassNames?.body)}
Copy link
Member

Choose a reason for hiding this comment

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

这个不太对,body 下面不应该包含 header 的。

style={styles?.body}
>
{mergedClosable && (
<button
type="button"
Expand All @@ -39,24 +53,49 @@ export default function DefaultPanel(props: DefaultPanelProps) {
{closeIcon}
</button>
)}
<div className={`${prefixCls}-header`}>
<div className={`${prefixCls}-title`}>{title}</div>
<div
className={classNames(`${prefixCls}-header`, tourClassNames?.header)}
style={styles?.header}
>
<div
className={classNames(`${prefixCls}-title`, tourClassNames?.title)}
style={styles?.title}
>
{title}
</div>
</div>
<div className={`${prefixCls}-description`}>{description}</div>
<div className={`${prefixCls}-footer`}>
<div
className={classNames(
`${prefixCls}-description`,
tourClassNames?.description,
)}
style={styles?.description}
>
{description}
</div>
<div
className={classNames(`${prefixCls}-footer`, tourClassNames?.footer)}
style={styles?.footer}
>
<div className={`${prefixCls}-sliders`}>
{total > 1
? [...Array.from({ length: total }).keys()].map((item, index) => {
return (
<span
key={item}
className={index === current ? 'active' : ''}
/>
);
})
return (
<span
key={item}
className={index === current ? 'active' : ''}
/>
);
})
: null}
</div>
<div className={`${prefixCls}-buttons`}>
<div
className={classNames(
`${prefixCls}-actions`,
tourClassNames?.actions,
)}
style={styles?.actions}
>
{current !== 0 ? (
<button className={`${prefixCls}-prev-btn`} onClick={onPrev}>
Prev
Expand Down
16 changes: 16 additions & 0 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ import type { CSSProperties, ReactNode } from 'react';
import type { Gap } from './hooks/useTarget';
import { type DefaultPanelProps } from './TourStep/DefaultPanel';

export type SemanticName =
| 'body'
| 'section'
| 'footer'
| 'actions'
| 'header'
| 'title'
| 'description'
| 'mask';

export interface TourStepInfo {
arrow?: boolean | { pointAtCenter: boolean };
target?: HTMLElement | (() => HTMLElement) | null | (() => null);
Expand Down Expand Up @@ -33,9 +43,15 @@ export interface TourStepProps extends TourStepInfo {
renderPanel?: (step: TourStepProps, current: number) => ReactNode;
onPrev?: () => void;
onNext?: () => void;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
}

export interface TourProps extends Pick<TriggerProps, 'onPopupAlign'> {
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
className?: string;
style?: React.CSSProperties;
steps?: TourStepInfo[];
open?: boolean;
defaultCurrent?: number;
Expand Down
Loading