Skip to content

feat(s2): coachmarks #7590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Apr 22, 2025
Merged

feat(s2): coachmarks #7590

merged 21 commits into from
Apr 22, 2025

Conversation

jluyau
Copy link
Member

@jluyau jluyau commented Jan 9, 2025

Closes

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@rspbot
Copy link

rspbot commented Jan 9, 2025

@rspbot
Copy link

rspbot commented Jan 9, 2025

@rspbot
Copy link

rspbot commented Jan 15, 2025

Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

I think the Coachmark should be a Focus trap. Probably just need to include a Dialog inside the Popover.

Coachmarks and indicator look pretty :) have a couple initial big points

export default meta;

export const CoachMarkExample = (args) => (
<CoachMarkTrigger isOpen>
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is the API we want. Otherwise Coachmarks are always in the JSX and it becomes hard to disentangle them or coordinate over an entire application for a tour. For instance, a Coachmark may not be rendered until a lazy component has loaded or maybe a view is swapped out part way through the tour.

Instead, we should use the same strategy from v2 and attach to selectors with a retry pattern for finding the current step.

import TextBold from '../s2wf-icons/S2_Icon_TextBold_20_N.svg';
import TextIcon from '../s2wf-icons/S2_Icon_Text_20_N.svg';
import {Toolbar} from 'react-aria-components';

Copy link
Member

Choose a reason for hiding this comment

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

stories should all have a button to start the tour, I don't think the tour should auto start when you enter the docs otherwise there could be multiple tours at once

@jluyau
Copy link
Member Author

jluyau commented Jan 15, 2025

I think the Coachmark should be a Focus trap. Probably just need to include a Dialog inside the Popover.

yeah i initially went with a focus trap, but looking at the Spectrum design docs, there's a type of coach mark that will only advance if the element it's modifying is interacted with (e.g. a button is pressed), and i wasn't able to tap the element with the coach mark focusables.

@snowystinger
Copy link
Member

I think the Coachmark should be a Focus trap. Probably just need to include a Dialog inside the Popover.

yeah i initially went with a focus trap, but looking at the Spectrum design docs, there's a type of coach mark that will only advance if the element it's modifying is interacted with (e.g. a button is pressed), and i wasn't able to tap the element with the coach mark focusables.

oh... no....

That would be difficult to detect from a global coordination standpoint, so I see why you opted to try and place the coachmark using the target as the trigger element.

Would all the "clickable" things even be buttons? What if it's telling you how to paint on a canvas?

If we tried to do that, we'd need something better than a capturing click listener since we stop propagation and we also will be moving to firing onPress in the click event IF it even exists. Different forms of interaction may not even fire click, for instance keyboard.

I think the better thing to do would be to have the UI update state in response to the tour moving along, regardless of clicking on a button or canvas.

Maybe bring these different use cases to an Otters time, I suspect there will be opinions.

placement="left top"
{...otherTourProps}
description="This is the Apply button. Press it to continue the tour."
hasPressAction />
Copy link
Member

Choose a reason for hiding this comment

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

This is really strange IMO. I guess it's overriding the press events on the button? Does the button also do its normal action?

Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

Notes for future work:
Add docs to use https://react-spectrum.adobe.com/react-aria/Popover.html#controlled-open-state to organise a tour or A/B testing more easily. Otherwise default usage of CoachmarkTrigger is fine.

# Conflicts:
#	packages/@react-spectrum/s2/package.json
#	yarn.lock
@rspbot
Copy link

rspbot commented Mar 11, 2025

@snowystinger snowystinger changed the title feat(s2): coachmarks [WIP] feat(s2): coachmarks Apr 10, 2025
@snowystinger
Copy link
Member

I've added UNSTABLE prefix and removed it from the auto docs so we can get this merged

@rspbot
Copy link

rspbot commented Apr 10, 2025

@rspbot
Copy link

rspbot commented Apr 10, 2025

@rspbot
Copy link

rspbot commented Apr 11, 2025

# Conflicts:
#	packages/@react-spectrum/s2/package.json
#	yarn.lock
@rspbot
Copy link

rspbot commented Apr 15, 2025

"@react-aria/utils": "^3.28.2",
"@react-spectrum/utils": "^3.12.4",
"@react-stately/layout": "^4.2.2",
"@react-stately/menu": "^3.9.3",
Copy link
Member

Choose a reason for hiding this comment

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

Looks like these dependencies aren't used anywhere?

Copy link
Member

Choose a reason for hiding this comment

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

https://github.com/adobe/react-spectrum/pull/7590/files#diff-8cd68236c9fcef8c0976a16402d56ed41af3bbdac40c17b02ff088920c1d51deR52

wanted to revisit this in followup because I'm not sure we should allow menus in a coachmark

Copy link
Member

Choose a reason for hiding this comment

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

sorry, wrong one, @react-aria/overlays is unused.

size?: 'S' | 'M' | 'L' | 'XL'
}

const fadeKeyframes = keyframes(`
Copy link
Member

Choose a reason for hiding this comment

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

Assuming all of this will change in a future PR, but we shouldn't need these anymore now that popover supports CSS transitions. Popover in S2 was updated in the meantime.

Copy link
Member

Choose a reason for hiding this comment

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

}
`);

let popover = style({
Copy link
Member

Choose a reason for hiding this comment

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

Would be nice to avoid duplicating this...

Copy link
Member

Choose a reason for hiding this comment

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

yeah, i got it a lot smaller in my followup, can see about getting rid of it there

zIndex: undefined
}}
className={(renderProps) => mergeStyles(popover({...renderProps, colorScheme}))}>
<Card>
Copy link
Member

Choose a reason for hiding this comment

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

I guess you're planning to change this later?

Copy link
Member

Choose a reason for hiding this comment

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

value: {
default: '[-2px]',
':has([data-trigger=checkbox])': '[-6px]',
':has([data-trigger=slider])': '[-8px]',
Copy link
Member

Choose a reason for hiding this comment

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

I guess we probably want to avoid special values for specific components.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I haven't thought of a good way to do this yet. I was going to do like we discussed and search for the first border radius, but that had problems. See https://github.com/adobe/react-spectrum/pull/8095/files#diff-8cd68236c9fcef8c0976a16402d56ed41af3bbdac40c17b02ff088920c1d51deR264

}
});

const pulse = raw(`&:before { content: ""; display: inline-block; position: absolute; top: var(--borderOffset); bottom: var(--borderOffset); left: var(--borderOffset); right: var(--borderOffset); border-radius: var(--ringRadius); outline-style: solid; outline-color: var(--activeElement); outline-width: 4px; animation-duration: 2s; animation-iteration-count: infinite; animation-timing-function: ease-in-out; animation-fill-mode: forwards; animation-name: ${pulseAnimation}}`);
Copy link
Member

Choose a reason for hiding this comment

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

Can it be an actual element? Why is it a before?

@@ -27,6 +27,7 @@ export {CardView, CardViewContext} from './CardView';
export {Checkbox, CheckboxContext} from './Checkbox';
export {CheckboxGroup, CheckboxGroupContext} from './CheckboxGroup';
export {CloseButton} from './CloseButton';
export {CoachMark as UNSTABLE_CoachMark, CoachMarkTrigger as UNSTABLE_CoachMarkTrigger} from './CoachMark';
Copy link
Member

Choose a reason for hiding this comment

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

Let's not export it for now. This seems like pre-unstable :D

@rspbot
Copy link

rspbot commented Apr 18, 2025

@rspbot
Copy link

rspbot commented Apr 18, 2025

@snowystinger snowystinger added this pull request to the merge queue Apr 22, 2025
Merged via the queue into main with commit f76c445 Apr 22, 2025
30 checks passed
@snowystinger snowystinger deleted the coachmarks branch April 22, 2025 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants