Commit graph

67 commits

Author SHA1 Message Date
Jon Robson 5fdd66fa3b Disable table of contents toggle on VE activation
While the table of contents is not updated by VisualEditor
we should hide it.

Bug: T307900
Change-Id: I246fbe0069329ef78735147b8d3f280433155158
2022-06-10 15:39:21 -07:00
Jon Robson deb54f9452 Correctly hide the sticky header when it is not in use
When the  vector-sticky-header-enabled class is removed from the body
it means the feature is not enabled, it doesn't mean the sticky header
should be invisible.

Call the hide method instead, and move it out of the function given
its a side effect

Bug: T308343
Change-Id: I4ecd6524146f203af926847812e20275c9573cab
2022-06-01 19:07:49 +00:00
Jan Drewniak d7e6690b52 Sticky header edit button A/B test bucketing (updated)
Adds behaviour for conditionally adding the edit button
to the sticky-header based on A/B test bucketing.

This behaviour depends on having the `$wgVectorStickyHeaderEdit` config
set to true for logged-in users:

    $wgVectorStickyHeaderEdit = [
        "logged_in" => true,
        "logged_out" => false
    ];

as well as an AB test configured with the following buckets:

    $wgVectorWebABTestEnrollment = [
        'name' => 'vector.sticky_header_edit',
        'enabled' => true,
        'buckets' => [
            'unsampled' => [
                'samplingRate' => 0
            ],
            'stickyHeaderEditButtonControl' => [
                'samplingRate' => 0
            ],
            'stickyHeaderEditButtonTreatment' => [
                'samplingRate' => 1
            ]
        ]
    ];

With that config, this change hides the sticky header for all users
except those in the stickyHeaderEditButtonTreatment bucket.

NOTE: This patch address the sticky header being visible on incorrect
namespaces when the AB test is enabled and the revert of
42b808738a.

Bug: T299959
Bug: T309370
Change-Id: I3effbb3e5f0bb1c8663255936458e3849511dfca
2022-05-31 15:58:35 -07:00
Jdlrobson 0df8d35b43 Revert "Sticky header edit button A/B test bucketing"
This reverts commit 42b808738a.

Reason for revert: The sticky header is now showing up in unexpected
places e.g. special pages.

Bug: T299959
Bug: T309370
Change-Id: Ie7f224d84440279ba28e031e13d05984c81a3ad4
2022-05-27 18:10:29 +00:00
Jan Drewniak 42b808738a Sticky header edit button A/B test bucketing
Adds behaviour for conditionally adding the edit button
to the sticky-header based on A/B test bucketing.

This behaviour depends on having the `$wgVectorStickyHeaderEdit` config
set to true for logged-in users:

    $wgVectorStickyHeaderEdit = [
        "logged_in" => true,
        "logged_out" => false
    ];

as well as an AB test configured with the following buckets:

    $wgVectorWebABTestEnrollment = [
        'name' => 'vector.sticky_header_edit',
        'enabled' => true,
        'buckets' => [
            'unsampled' => [
                'samplingRate' => 0
            ],
            'stickyHeaderEditButtonControl' => [
                'samplingRate' => 0
            ],
            'stickyHeaderEditButtonTreatment' => [
                'samplingRate' => 1
            ]
        ]
    ];

With that config, this change hides the sticky header for all users
except those in the stickyHeaderEditButtonTreatment bucket.

Bug: T299959
Change-Id: If252956bc530d8ce54eeda61f42a93ffa48255cb
2022-05-25 10:15:47 -04:00
bwang 91e2e55a10 Simplify TOC spacing styles/logic by reusing the visible sticky header class
- Remove the 'vector-scrolled-below-table-of-contents' class, reducing the number of classes added with JS and simplifying the scrollObserver logic
- Move the 'vector-sticky-header-visible' class from the sticky header element to the body element. Hopefully, this is where other feature specific classes can go in the future
- This approach means the TOC will not need JS to update it's spacing when the sticky header is not enabled

Bug: T307345
Change-Id: I1084defc7025f5c946e22a36d373224fae6f8bd6
2022-05-10 11:39:05 -05:00
bwang 94be7578f5 Factor out a separate scroll observer for the TOC A/B test, which should be fired separately from the page title observer used by the sticky header and TOC
Bug: T307952
Bug: T307345
Change-Id: I3f247730fa1c399e6d2e4d866677703fc24e8c58
2022-05-09 20:44:54 +00:00
Jan Drewniak 7e81c26712 [TOC] Remove pointer-events:none on .sidebar-toc-link
Previously, we relied on setting pointer-events:none on all child
elements of ToC links.

This propagated the click event up to the link itself in Javascript
and allowed us check if an element with the class `.sidebar-toc-link`
was clicked.

Unfortunately as of Chromium 101 this approach causes the entire link
in the sidebar to be unclickable.

Instead, this patch checks if the ToC link or any of it's children
have been clicked (using the less efficient `Element.closest()` ).

Bug: T307271
Change-Id: I2264b7862f6e1ef50c5c722daee81acc39eea54e
2022-05-02 19:48:30 +00:00
bwang b075c90f60 Update TOC heading and link styles
Bug: T306562
Change-Id: Iafe335547a1e3c432efce303b5c0e5f8f5a23a15
2022-04-28 13:32:59 -05:00
bwang af8cf470fd Fix TOC bottom fade
Additional change: Fixes an eslint warning

Bug: T306893
Change-Id: I778470ec5fa2081e4412f40b0180efbff7013d1b
2022-04-27 19:07:17 +00:00
Jon Robson c269419af3 Disable animations when user prefers reduced motion
When browser preference for reduced motion is enabled:
* Disables bolding of table of contents
* Disables sticky header transition

Bug: T254399
Change-Id: I8ef9e59b258fed977ce370da352b1924832d842b
2022-04-26 23:31:38 +00:00
Clare Ming f12659fff6 Layout + visual style changes for sticky TOC
- Layout updates per design review.
- Visual updates per design review.

Bug: T304166
Bug: T305069
Change-Id: I2f95d5938674bb8263b6203c5f6a469762bf0cc2
2022-04-15 10:24:46 -06:00
bwang f1c70e99b7 Update sticky header to use ARIA attributes for section collapsing and add accessible label to toggle buttons
Bug: T303766
Change-Id: Idda4f286a42152af1d233588a1839ada5491ce95
2022-04-06 17:24:34 -05:00
jenkins-bot ec3b66e0ed Merge "Only track headings that are included in the table of contents" 2022-04-05 22:10:33 +00:00
Nicholas Ray 6fbf08a198 Build A/B test bucketing infrastructure for the table of contents.
* Bucket and sample on server by using the
  `WikimediaEvents.WebABTestArticleIdFactory` service from
  WikimediaEvents (soft dependency)
* Add linkHijack.js so that users bucketed in one group have the
  possibility of remaining in that group if they click a link to another
  page.

Bug: T302046
Depends-On: Ie6627de98effb3d37a3bedda5023d08af319837f
Change-Id: Iff231a976c473217b0fa4da1aa9a8d1c2a1a19f2
2022-04-04 17:06:29 -06:00
bwang 4a81d0e4eb Scroll active TOC links to midpoint when past threshold
Bug: T301150
Change-Id: I282dbeab8e0b121b71c04f921ab11311f1514da7
2022-03-31 15:50:54 -05:00
Jon Robson 94c7f31082 Only track headings that are included in the table of contents
Headings can also appear in templates inside divs and subtitles.
These do not
get rendered in the table of contents and should not be tracked.

This also excludes headings from the legacy table of contents which
may be in the article during the A/B test

See English Wikipedia examples [[Portal:Biography]] and [[Main page]]

Change-Id: I4ca8933a0e7736157f80e5e68077b153e5bfc81d
2022-03-31 17:35:00 +00:00
bwang 607f3279bd Move sticky header DOM queries into main.js
- Remove isStickyHeaderAllowed() from stickyHeader.js, move to main.js
- Rename variables in stickyHeader.js to be consistent

Bug: T301429
Change-Id: Ib445a19cbfab52a008b749ea63cef178d6288e6a
2022-03-30 09:21:25 -05:00
jenkins-bot 0529f8cb26 Merge "Update scroll instrument for TOC" 2022-03-29 21:43:41 +00:00
jenkins-bot 056b242682 Merge "Make beginning bold on scroll" 2022-03-29 16:05:39 +00:00
Clare Ming f2c60983bb Update scroll instrument for TOC
- Leverage scrollObserver to use for TOC scroll events.
- Add new hooks to target legacy TOC intersection.
- See corresponding changes (not strict dependency) in related
WME patch 773628 for capturing scroll events from Vector TOC:
https://gerrit.wikimedia.org/r/c/mediawiki/extensions/WikimediaEvents/+/773628
- Dependency on https://github.com/wikimedia/typescript-types/pull/30
which updates mwHookInstance interface with fire property to prevent
TS error on fire method of mw.hook in scrollObserver.

Bug: T303297
Change-Id: I5c2dd5f3a25ffcb0ed03b76ae28e65eb18ad8d33
2022-03-29 09:45:30 -06:00
Clare Ming ccdfbf2e58 Update @wikimedia/types-wikimedia to latest version
- Remove some @ts-ignore statements.
- Update invocation of mw.util.debounce to have correct order of
parameters.

Bug: T303297
Change-Id: I4bb795fbd4d026c21c66e9a3d161afff4d7ef09f
2022-03-28 23:33:50 +00:00
Jon Robson a2c7c024df Make beginning bold on scroll
Bug: T301254
Change-Id: I4469575ea8590ae22023b98c3dbd31bc672d5766
2022-03-25 01:13:42 +00:00
jenkins-bot 1b8ee10357 Merge "Add data-event-name attributes to legacy and sidebar TOC" 2022-03-23 22:00:45 +00:00
Nicholas Ray d01dead5a7 Revise AB.js to handle other features + server sampling/bucketing
* Eliminates AB.js dependency on sticky header
* Code coverage has been raised to 100%
* Instead of importing ABTestConfig, these props are now passed into the
  function along with a token.
* WikimediaEvents hook is now fired when experiment is initialized. The
  experiment should not be initialized if it is not enabled.
* Removes several methods (e.g. initAB, getEnabledExperiment) due to the
  preceeding changes.
* Adds `isInSample` and `isInTreatmentBucket` methods so that the client
  has less work.

Treatment buckets now follow a naming convention so that the client can
do less work querying if the subject is part of the treatment:

* Treatment buckets should have the case-insensitive `treatment`
  substring somewhere in their name (e.g. 'treatment',
  'stickyHeaderTreatment', 'sticky-header-treatment' )

Bug: T302046
Change-Id: I4febec42b4c471b2f2ef02be2e334bd6d2c31eec
2022-03-22 11:58:48 -06:00
bwang ac54984d75 Add data-event-name attributes to legacy and sidebar TOC
Bug: T302934
Depends-on: I5ef98d5f5713d3d99bc5f7f8112ba2d1e0f62e22
Change-Id: I5806c346abf0375c85248659c636ae3b2d73f661
2022-03-21 22:32:56 +00:00
Jdlrobson f7a859bac5 Revert "build: Update eslint-config-wikimedia to 0.22.1"
This reverts commit b72c648d21.

Reason for revert: Causes an issue with the search
(See https://phabricator.wikimedia.org/F35009362)

Change-Id: I09f7e5c9eab677bfd5a92cf2d8389d20a2d6e87a
2022-03-16 23:40:42 +00:00
Ed Sanders b72c648d21 build: Update eslint-config-wikimedia to 0.22.1
Change-Id: If632697f7c3bb3fad6668d791d9408f7b7a3590b
2022-03-16 15:42:07 +00:00
jenkins-bot 11b968cf18 Merge "Clean up: Remove ts-ignores in stickyheader.js" 2022-02-23 16:18:06 +00:00
jenkins-bot d93f9e9bed Merge "Use TOC template data for showing collapsible section arrows" 2022-02-22 22:16:18 +00:00
bwang 5f0c0cb294 Use TOC template data for showing collapsible section arrows
Bug: T299361
Depends-on: I8ab5c0543b898d1df9399a1cb39672c45daf2acd
Change-Id: Ib68de8cd97cc1111a5a33e100e688d6832fc7e6e
2022-02-22 15:47:23 -06:00
Nicholas Ray 27939ac6c9 Revert "Improve jsdoc for tableOfContents.js and sectionObserver.js"
This mostly reverts commit f5ad6fe78a but
keeps the SectionObserverProps typedef.

Instead, we will use @module introduced in
Ib68de8cd97cc1111a5a33e100e688d6832fc7e6e.

Change-Id: I7aff49a3d922889cc99bc4313a6cb416410a7a0d
2022-02-22 12:36:35 -07:00
Nicholas Ray f5ad6fe78a Improve jsdoc for tableOfContents.js and sectionObserver.js
Switch to using @namespace which seems to have the best jsdoc support
for the revealing module pattern [1] that these two files use.

Additionally:

* Add typedef for section observer props

[1] https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch09s03.html

Change-Id: I3eeda191e5da0294ad40533053adb57e1fc9c8e9
2022-02-21 17:40:10 -07:00
Nicholas Ray 6e9506dcad Dynamically expand/collapse sub-sections in ToC based on # of headings
Server render the table of contents in a collapsed state when the total
number of headings is equal or greater than the value of
`$wgVectorTableOfContentsCollapseAtCount`. Otherwise, the table of
contents will be server rendered in its "expanded" state.

In addition:

* Revise table of contents tests to call one `assertion` per element so
  that it is easier to see the exact element that may fail an assertion.
* Revise table of contents tests to call a mount function that can merge
  props to allow for a more flexible set of tests.
* Revise table of contents tests by wrapping a `describe` around tests
  that expect the same prop state.
* Adds typedef for table of sections props

Bug: T300973
Depends-On: Ifaee451e1903f2accd0ada2f2ed6dfa3f83037b6
Change-Id: I382200bc603b6abf757a91f14a8a55a6581969bd
2022-02-21 14:58:51 -07:00
bwang 48f1f1355b Clean up: Remove ts-ignores in stickyheader.js
From what I could tell, most instances of `toHTMLElement` or @ts-ignore could be fixed by using typeguards or using Element over HTMLElement.
Element is a looser typing than HTMLElement, but given `querySelector` returns `Element|null` and the fact that we were already inconsistently using both Element and HTMLElement in this file, I feel it was a worthwhile tradeoff

Change-Id: I3512a98fa67c13a4383b9497e8588960259b5b68
2022-02-21 11:41:12 -06:00
Jon Robson 2dcd99ed21 Sticky header dropdown should not contain gadgets in personal menu
Bug: T302087
Change-Id: Iae1f42c3c526398d7dea038786ae9001e118307b
2022-02-18 21:30:29 +00:00
bwang 301e09916d Toggle ToC sections when clicking toggle button
Bug: T300167
Change-Id: If1150a9e018b232da900187383aaee9c9cf331a1
2022-02-16 15:48:28 -06:00
jenkins-bot 0f49a257d1 Merge "Collapse ToC by default & expand sections when clicking section headings" 2022-02-15 19:31:18 +00:00
Jan Drewniak 7d32ec80d3 Collapse ToC by default & expand sections when clicking section headings
Collapses sub-sections in the new table of contents by default
(except for non-js and reduced-motion users) and expands the
sections when the top-level section link has been clicked.

Refactors the `activateSection` TableOfContents methods into separate
`activateSection` and `deactivateSection` functions.
Adds `expandSection` and `collapseSection` methods.

Adds triangle icon as a visual expand/collapsed indicator
next to all ToC section headings and are hidden via CSS based on
whether or not the section contains subsections.

Adds test for tableOfContents.

Bug: T299361
Change-Id: I36b3ae7f9f633877683bc17a9444c970d7fa7293
2022-02-15 00:09:50 -05:00
jenkins-bot 4557c0910b Merge "Use new ve.activationStart hook to hide header earlier when loading editor" 2022-02-14 18:33:19 +00:00
jenkins-bot a541859743 Merge "[eslint] Disable mediawiki/class-doc" 2022-02-14 16:15:34 +00:00
Nicholas Ray 6b73bd2b41 Fix jsdoc comments for sectionObserver.js
Move jsdoc comment closer to the methods they are describing. This also
enables better typehint support.

I36b3ae7f9f633877683bc17a9444c970d7fa7293 will handle revising tableOfContents.js.

Change-Id: Ifcac7cfd88cd3f1c0405611c880a0d101d2aed3b
2022-02-11 12:17:38 -07:00
bwang 52c7c2ee75 [eslint] Disable mediawiki/class-doc
Given our use of constants for tracking classes this eslint rule
is more an annoyance than helpful.

Change-Id: I37570e3e851997d058f2d93777990dddb3d04089
2022-02-11 16:31:33 +00:00
jenkins-bot 306dc89bf8 Merge "Limit WVUI search to ES6 browsers" 2022-02-09 23:01:03 +00:00
Jon Robson 0c2981d772 Limit WVUI search to ES6 browsers
Rather than test for fetch, limit the code to ES6 browsers.

Depends-On: I96a03796628a74ace93579d45a582711400c09c1
Change-Id: I4ca10182491118e61e155f99c713d4cb1b4fc7f0
2022-02-09 22:10:11 +00:00
Nicholas Ray 80a111d0e4 Fix TOC section activation on link click bug
We want the link that the user has clicked inside the TOC to be "active"
(e.g. bolded) regardless of whether the browser's scroll position
corresponds to that section. Therefore, we need to temporarily ignore
section observer until the browser has finished scrolling to the section
(if needed).

However, because the scroll event happens asyncronously after the user
clicks on a link and may not even happen at all (e.g. the user has
scrolled all the way to the bottom and clicks a section that is already
in the viewport), determining when we should resume section observer is
a bit tricky.

Because a scroll event may not even be triggered after clicking the
link, we instead allow the browser to perform a maximum number of
repaints before resuming sectionObserver. Per T297614#7687656, Firefox
wasn't consistently activating the table of contents section that the
user clicked even after waiting 2 frames. After further investigation,
it sometimes waits up to 3 frames before painting the new scroll
position so we have that as the limit.

Bug: T297614
Change-Id: If3632529f58c15348a7200258f4f5999ea0dadc4
2022-02-08 14:45:16 -07:00
Nicholas Ray 4d2ad52374 Remove getElementsByClassName usage from sectionObserver
Based on prior discussion [1], using getElementsByClassName probably
isn't worth it.

[1] https://gerrit.wikimedia.org/r/c/mediawiki/skins/Vector/+/756675/8..13/resources/skins.vector.es6/main.js#104

Change-Id: Id7f8aff73a1d2082ebfeaa9488a815d96317c156
2022-02-03 17:33:42 -07:00
bwang 66359e8fa5 Setup jest unit tests and add basic test cases for AB.js and App.vue
Bug: T300561
Change-Id: Ib7c314b094bd823ae233374f63c9094724d6c06f
2022-01-31 20:50:33 +00:00
Ed Sanders 1cd5bf4d41 Use new ve.activationStart hook to hide header earlier when loading editor
Bug: T299907
Depends-On: I0eaeb98719bf7a43e4a87366cfcd204f35b74650
Change-Id: I8e8b635b46e79c63c4dafbd2418c9be94528ec06
2022-01-31 18:32:55 +00:00
Nicholas Ray 3c433a5315 Add sectionObserver and tableOfContents component JS to respond to intersection changes
This commits sets up the Table of Contents to bold the active section
when the section is scrolled.

Unfortunately, because our content does not have actual sections but
instead has a flat list of headings and paragraphs, we can't use
IntersectionObserver in the conventional way as it is optimized to find
intersections of elements that are *within* the viewport and the
callback will not reliably fire during certain scenarios (e.g. with fast
scrolling or when the headings are not currently within the viewport).
Furthermore, iterating through a list of elements and calling
`getBoundingClientRect()` can be expensive and can also cause
significant forced synchronous layouts that block the main thread.

The best compromise in terms of performance and function that I've found
is to use a combination of a throttled scroll event listener and
IntersectionObserver's ability to asyncronously find the
boundingClientRect of all elements off the main thread when `.observe`
is called which is the approach this patch takes. Although this is an
unorthodox way to use IntersectionObserver, performance profiles
recorded while holding the "down" arrow and scrolling for 10 seconds
with a 6x CPU throttle are comparable between master and this patch:

master: https://phabricator.wikimedia.org/F34930737
this patch:  https://phabricator.wikimedia.org/F34930738

Bug: T297614
Change-Id: I4077d86a1786cc1f4a7d85b20b7cf402960940e7
2022-01-26 14:11:43 -07:00