-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Core: Draw highlights on top of canvas and add various new features #30894
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
+1,407
−181
Merged
Changes from 14 commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
806a8a9
Implement highlights using overlay
ghengeveld 861a80a
Handle dynamically created elements
ghengeveld 082035f
Implement popover
ghengeveld a4be866
Handle scrolling
ghengeveld ae6e959
Refactor and add support for menu items
ghengeveld 4c33573
Update highlight preview code to render new HighlightOverlay
ghengeveld 0d3cb76
Fix stories
ghengeveld 72626c3
Merge branch 'a11y-polish' into highlight-overlay
ghengeveld ecfdab7
Merge branch 'next' into highlight-overlay
ghengeveld 010a353
Handle highlights inside scrollable containers
ghengeveld c419ce8
Remove unused story
ghengeveld 3aa7687
Merge branch 'next' into highlight-overlay
ghengeveld 841dcc1
Reimplement advanced highlighting using vanilla JS (no React)
ghengeveld a31c955
Merge branch 'next' into highlight-overlay
ghengeveld a3f571b
Clean up existing instance of useHighlights if there is one
ghengeveld d040e26
Highlight style tweaks
ghengeveld 85ec1f4
Always reset styles
ghengeveld 8ad7f10
Rename menuListItems to just menuItems
ghengeveld 45700a9
Merge branch 'next' into highlight-overlay
ghengeveld ed29b4a
Rename HighlightInfo to HighlightOptions
ghengeveld 85147e9
Add support for popovers, fixed and sticky elements
ghengeveld 2f95396
Add support for hover styles
ghengeveld 430ae58
Rename selectedStyles to focusStyles and apply hover style when hover…
ghengeveld f3b3e2e
Add basic support for hints
ghengeveld a7d11e3
Remove hint feature for now
ghengeveld a8f6aad
Improve types/docs
ghengeveld c5ad8b2
Update menu property to new API
ghengeveld 4be0ed0
Ensure highlights render on top of content
ghengeveld 056dbb5
Warn when attempting to scroll to nonexistent element
ghengeveld a9b3f50
Render highlights as a popover
ghengeveld 158712b
Fix unsubscribe logic
ghengeveld 32ed2e4
Clear interval after 60 seconds
ghengeveld 04652c6
Merge branch 'next' into highlight-overlay
ghengeveld 747952c
Linting
ghengeveld 090dc59
Fix eslint env
ghengeveld 57e8b72
Rename element IDs
ghengeveld 77f508b
Avoid global references to browser APIs, and other test fixes
ghengeveld 8477b54
Fix E2E tests for A11y addon and fix menu styling
ghengeveld 1627899
Merge branch 'next' into highlight-overlay
ghengeveld 7c80a76
Update snapshots
ghengeveld f5a3e13
Avoid using random ids
ghengeveld 7a9d1a0
Only create the root element when first highlights are added
ghengeveld 78ae3fb
Only highlight selected items from the active tab
ghengeveld 0e58134
Ensure root exists before rendering menu, and avoid event listener on…
ghengeveld 31ccf9f
Merge branch 'next' into highlight-overlay
ghengeveld 1557a12
Merge branch 'next' into highlight-overlay
ghengeveld 4cc0c39
Loosen selector
ghengeveld 996904e
Simplify assertion
ghengeveld b5dbd5a
Reset selection when switching stories
ghengeveld 493b525
Redraw boxes when the viewport resizes, not just when storybook-root …
ghengeveld 68a2fb0
Avoid emitting FORCE_REMOUNT in story, use globalThis rather than win…
ghengeveld File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export const ADDON_ID = 'storybook/highlight'; | ||
|
||
export const HIGHLIGHT = `${ADDON_ID}/add`; | ||
export const REMOVE_HIGHLIGHT = `${ADDON_ID}/remove`; | ||
export const RESET_HIGHLIGHT = `${ADDON_ID}/reset`; | ||
export const SCROLL_INTO_VIEW = `${ADDON_ID}/scroll-into-view`; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,119 +1,13 @@ | ||
/* eslint-env browser */ | ||
import { STORY_CHANGED } from 'storybook/internal/core-events'; | ||
|
||
import { global } from '@storybook/global'; | ||
|
||
import { addons, definePreview } from 'storybook/preview-api'; | ||
|
||
import { HIGHLIGHT, RESET_HIGHLIGHT, SCROLL_INTO_VIEW } from './constants'; | ||
|
||
const { document } = global; | ||
|
||
interface HighlightOptions { | ||
/** HTML selectors of the elements */ | ||
elements: string[]; | ||
/** Color of the outline */ | ||
color?: string; | ||
/** Style of the outline */ | ||
style?: 'dotted' | 'dashed' | 'solid' | 'double'; | ||
/** Width of the outline */ | ||
width?: string; | ||
/** Offset of the outline */ | ||
offset?: string; | ||
/** | ||
* Duration in milliseconds of the fade out animation. Note you must use a 6-character hex color | ||
* to use this option. | ||
*/ | ||
fadeOut?: number; | ||
/** | ||
* Duration in milliseconds of the pulse out animation. Note you must use a 6-character hex color | ||
* to use this option. | ||
*/ | ||
pulseOut?: number; | ||
} | ||
|
||
const highlightStyle = ( | ||
selectors: string[], | ||
{ | ||
color = '#FF4785', | ||
style = 'solid', | ||
width = '1px', | ||
offset = '2px', | ||
fadeOut = 0, | ||
pulseOut = 0, | ||
}: HighlightOptions | ||
) => { | ||
const animationName = Math.random().toString(36).substring(2, 15); | ||
let keyframes = ''; | ||
if (pulseOut) { | ||
keyframes = `@keyframes ${animationName} { | ||
0% { outline: ${width} ${style} ${color}; } | ||
20% { outline: ${width} ${style} ${color}00; } | ||
40% { outline: ${width} ${style} ${color}; } | ||
60% { outline: ${width} ${style} ${color}00; } | ||
80% { outline: ${width} ${style} ${color}; } | ||
100% { outline: ${width} ${style} ${color}00; } | ||
}\n`; | ||
} else if (fadeOut) { | ||
keyframes = `@keyframes ${animationName} { | ||
0% { outline: ${width} ${style} ${color}; } | ||
100% { outline: ${width} ${style} ${color}00; } | ||
}\n`; | ||
} | ||
|
||
return `${keyframes}${selectors.join(', ')} { | ||
outline: ${width} ${style} ${color}; | ||
outline-offset: ${offset}; | ||
${pulseOut || fadeOut ? `animation: ${animationName} ${pulseOut || fadeOut}ms linear forwards;` : ''} | ||
}`; | ||
}; | ||
import { useHighlights } from './useHighlights'; | ||
|
||
if (addons && addons.ready) { | ||
addons.ready().then(() => { | ||
const channel = addons.getChannel(); | ||
const sheetIds = new Set<string>(); | ||
|
||
const highlight = (options: HighlightOptions) => { | ||
const sheetId = Math.random().toString(36).substring(2, 15); | ||
sheetIds.add(sheetId); | ||
|
||
const sheet = document.createElement('style'); | ||
sheet.innerHTML = highlightStyle(Array.from(new Set(options.elements)), options); | ||
sheet.setAttribute('id', sheetId); | ||
document.head.appendChild(sheet); | ||
|
||
const timeout = options.pulseOut || options.fadeOut; | ||
if (timeout) { | ||
setTimeout(() => removeHighlight(sheetId), timeout + 500); | ||
} | ||
}; | ||
|
||
const removeHighlight = (id: string) => { | ||
const sheetElement = document.getElementById(id); | ||
sheetElement?.parentNode?.removeChild(sheetElement); | ||
sheetIds.delete(id); | ||
}; | ||
|
||
const resetHighlight = () => { | ||
sheetIds.forEach(removeHighlight); | ||
}; | ||
|
||
const scrollIntoView = (target: string, options?: ScrollIntoViewOptions) => { | ||
const element = document.querySelector(target); | ||
element?.scrollIntoView({ behavior: 'smooth', block: 'center', ...options }); | ||
highlight({ | ||
elements: [target], | ||
color: '#1EA7FD', | ||
width: '2px', | ||
offset: '2px', | ||
pulseOut: 3000, | ||
}); | ||
}; | ||
|
||
channel.on(STORY_CHANGED, resetHighlight); | ||
channel.on(SCROLL_INTO_VIEW, scrollIntoView); | ||
channel.on(RESET_HIGHLIGHT, resetHighlight); | ||
channel.on(HIGHLIGHT, highlight); | ||
useHighlights({ channel }); | ||
}); | ||
} | ||
|
||
export default () => definePreview({}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.