@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add support for aural-only and visual-only elements

Summary:
Ref T4843. This adds support to `javelin_tag()` for an `aural` attribute. When specified, `true` values mean "this content is aural-only", while `false` values mean "this content is not aural".

- I've attempted to find the best modern approaches for marking this content, but the `aural` attribute should let us change the mechanism later.
- Make the "beta" markers on application navigation visual only (see T4843). This information is of very low importance, the application navigation is accessed frequently, and the information is available on the application list.
- Partially convert the main navigation. This is mostly to test things, since I want to get more concrete feedback about approaches here.
- Add a `?__aural__=1` attribute, which renders the page with aural-only elements visible and visual-only elements colored.

Test Plan: {F146476}

Reviewers: btrahan, scp, chad

Reviewed By: chad

Subscribers: aklapper, qgil, epriestley

Maniphest Tasks: T4843

Differential Revision: https://secure.phabricator.com/D8830

+171 -20
+5 -5
resources/celerity/map.php
··· 7 7 return array( 8 8 'names' => 9 9 array( 10 - 'core.pkg.css' => 'b7ba02ba', 10 + 'core.pkg.css' => 'cc50ddf5', 11 11 'core.pkg.js' => '417722ff', 12 12 'darkconsole.pkg.js' => 'ca8671ce', 13 13 'differential.pkg.css' => '8a064eb7', ··· 105 105 'rsrc/css/application/subscriptions/subscribers-list.css' => '5bb30c78', 106 106 'rsrc/css/application/tokens/tokens.css' => '5f7bca25', 107 107 'rsrc/css/application/uiexample/example.css' => '528b19de', 108 - 'rsrc/css/core/core.css' => 'da26ddb2', 108 + 'rsrc/css/core/core.css' => '7dff07c3', 109 109 'rsrc/css/core/remarkup.css' => '98a7627b', 110 110 'rsrc/css/core/syntax.css' => '3c18c1cb', 111 - 'rsrc/css/core/z-index.css' => '0d89d53c', 111 + 'rsrc/css/core/z-index.css' => '7e4989ed', 112 112 'rsrc/css/diviner/diviner-shared.css' => '38813222', 113 113 'rsrc/css/font/font-awesome.css' => '62bc244d', 114 114 'rsrc/css/font/font-glyphicons-halflings.css' => 'c4c1c6b6', ··· 686 686 'phabricator-busy' => '6453c869', 687 687 'phabricator-chatlog-css' => '852140ff', 688 688 'phabricator-content-source-view-css' => '4b8b05d4', 689 - 'phabricator-core-css' => 'da26ddb2', 689 + 'phabricator-core-css' => '7dff07c3', 690 690 'phabricator-countdown-css' => '86b7b0a0', 691 691 'phabricator-crumbs-view-css' => '0222cbe0', 692 692 'phabricator-drag-and-drop-file-upload' => 'ae6abfba', ··· 735 735 'phabricator-uiexample-reactor-select' => '189e4fe3', 736 736 'phabricator-uiexample-reactor-sendclass' => 'bf97561d', 737 737 'phabricator-uiexample-reactor-sendproperties' => '551add57', 738 - 'phabricator-zindex-css' => '0d89d53c', 738 + 'phabricator-zindex-css' => '7e4989ed', 739 739 'phame-css' => '19ecc703', 740 740 'pholio-css' => '2fa97dbe', 741 741 'pholio-edit-css' => 'b9e59b6d',
+2
src/applications/auth/application/PhabricatorApplicationAuth.php
··· 40 40 ->setWorkflow(true) 41 41 ->setHref('/logout/') 42 42 ->setSelected(($controller instanceof PhabricatorLogoutController)) 43 + ->setAural(pht('Log Out')) 43 44 ->setOrder(900); 44 45 $items[] = $item; 45 46 } else { ··· 53 54 // TODO: Login icon? 54 55 ->setIcon('power') 55 56 ->setHref('/auth/start/') 57 + ->setAural(pht('Log In')) 56 58 ->setOrder(900); 57 59 $items[] = $item; 58 60 }
+4 -1
src/applications/help/application/PhabricatorApplicationHelp.php
··· 31 31 } 32 32 33 33 if ($application && $application->getHelpURI()) { 34 + $help_name = pht('%s Help', $application->getName()); 35 + 34 36 $item = id(new PHUIListItemView()) 35 - ->setName(pht('%s Help', $application->getName())) 37 + ->setName($help_name) 36 38 ->addClass('core-menu-item') 37 39 ->setIcon('info-sm') 40 + ->setAural($help_name) 38 41 ->setOrder(200) 39 42 ->setHref($application->getHelpURI()); 40 43 $items[] = $item;
+1
src/applications/home/application/PhabricatorApplicationHome.php
··· 60 60 ->setHref('/home/create/') 61 61 ->addSigil('quick-create-menu') 62 62 ->setID($create_id) 63 + ->setAural(pht('Quick Create')) 63 64 ->setOrder(300); 64 65 $items[] = $item; 65 66 }
+1 -1
src/applications/home/controller/PhabricatorHomeController.php
··· 167 167 } 168 168 } 169 169 170 - $nav->addFilter( 170 + $nav->addFilter( 171 171 '', 172 172 pht('Customize Applications...'), 173 173 '/settings/panel/home/');
+2 -1
src/applications/meta/view/PhabricatorApplicationLaunchView.php
··· 39 39 $application->getName()); 40 40 41 41 if ($application->isBeta()) { 42 - $content[] = phutil_tag( 42 + $content[] = javelin_tag( 43 43 'span', 44 44 array( 45 + 'aural' => false, 45 46 'class' => 'phabricator-application-beta', 46 47 ), 47 48 "\xCE\xB2");
+1
src/applications/people/application/PhabricatorApplicationPeople.php
··· 120 120 ->setName($user->getUsername()) 121 121 ->setHref('/p/'.$user->getUsername().'/') 122 122 ->addClass('core-menu-item') 123 + ->setAural(pht('Profile')) 123 124 ->setOrder(100); 124 125 125 126 $classes = array(
+1
src/applications/settings/application/PhabricatorApplicationSettings.php
··· 46 46 ->addClass('core-menu-item') 47 47 ->setSelected($selected) 48 48 ->setHref('/settings/') 49 + ->setAural(pht('Settings')) 49 50 ->setOrder(400); 50 51 $items[] = $item; 51 52 }
+14
src/infrastructure/javelin/markup.php
··· 36 36 } 37 37 } 38 38 39 + if (isset($attributes['aural'])) { 40 + if ($attributes['aural']) { 41 + $class = idx($attributes, 'class', ''); 42 + $class = rtrim('aural-only '.$class); 43 + $attributes['class'] = $class; 44 + } else { 45 + $class = idx($attributes, 'class', ''); 46 + $class = rtrim('visual-only '.$class); 47 + $attributes['class'] = $class; 48 + $attributes['aria-hidden'] = 'true'; 49 + } 50 + unset($attributes['aural']); 51 + } 52 + 39 53 return phutil_tag($tag, $attributes, $content); 40 54 } 41 55
+10 -1
src/view/form/control/PhabricatorRemarkupControl.php
··· 133 133 $target = '_blank'; 134 134 } 135 135 136 + $content = null; 137 + 136 138 $tip = idx($spec, 'tip'); 137 139 if ($tip) { 138 140 $meta['tip'] = $tip; 141 + $content = phutil_tag( 142 + 'span', 143 + array( 144 + 'class' => 'aural-only', 145 + ), 146 + $tip); 139 147 } 140 148 141 149 require_celerity_resource('sprite-icons-css'); 150 + 142 151 143 152 $buttons[] = javelin_tag( 144 153 'a', ··· 156 165 array( 157 166 'class' => 'remarkup-assist sprite-icons remarkup-assist-'.$action, 158 167 ), 159 - '')); 168 + $content)); 160 169 } 161 170 162 171 $buttons = phutil_tag(
+4
src/view/page/PhabricatorStandardPageView.php
··· 430 430 $classes[] = 'printable'; 431 431 } 432 432 433 + if ($this->getRequest()->getStr('__aural__')) { 434 + $classes[] = 'audible'; 435 + } 436 + 433 437 return implode(' ', $classes); 434 438 } 435 439
+63 -10
src/view/page/menu/PhabricatorMainMenuView.php
··· 34 34 $alerts = array(); 35 35 $search_button = ''; 36 36 $app_button = ''; 37 + $aural = null; 37 38 38 39 if ($user->isLoggedIn() && $user->isUserActivated()) { 39 - list($menu, $dropdowns) = $this->renderNotificationMenu(); 40 + list($menu, $dropdowns, $aural) = $this->renderNotificationMenu(); 40 41 $alerts[] = $menu; 41 42 $menus = array_merge($menus, $dropdowns); 42 43 $app_button = $this->renderApplicationMenuButton($header_id); ··· 51 52 $search_menu = $this->renderPhabricatorSearchMenu(); 52 53 53 54 if ($alerts) { 54 - $alerts = phutil_tag( 55 + $alerts = javelin_tag( 55 56 'div', 56 57 array( 57 58 'class' => 'phabricator-main-menu-alerts', 59 + 'aural' => false, 58 60 ), 59 61 $alerts); 60 62 } 61 63 64 + if ($aural) { 65 + $aural = javelin_tag( 66 + 'span', 67 + array( 68 + 'aural' => true, 69 + ), 70 + phutil_implode_html(' ', $aural)); 71 + } 72 + 62 73 $application_menu = $this->renderApplicationMenu(); 63 74 $classes = array(); 64 75 $classes[] = 'phabricator-main-menu'; ··· 76 87 $search_button, 77 88 $this->renderPhabricatorLogo(), 78 89 $alerts, 90 + $aural, 79 91 $application_menu, 80 92 $search_menu, 81 93 $menus, ··· 236 248 'class' => 'phabricator-main-menu-logo', 237 249 'href' => '/', 238 250 ), 239 - phutil_tag( 240 - 'span', 241 - array( 242 - 'class' => 'sprite-menu menu-logo-image '.$class, 243 - ), 244 - '')); 251 + array( 252 + javelin_tag( 253 + 'span', 254 + array( 255 + 'aural' => true, 256 + ), 257 + pht('Home')), 258 + phutil_tag( 259 + 'span', 260 + array( 261 + 'class' => 'sprite-menu menu-logo-image '.$class, 262 + ), 263 + ''), 264 + )); 245 265 } 246 266 247 267 private function renderNotificationMenu() { ··· 256 276 'alert-notifications', 257 277 ); 258 278 279 + $aural = array(); 280 + 259 281 $message_tag = ''; 260 282 $message_notification_dropdown = ''; 261 283 $conpherence = 'PhabricatorApplicationConpherence'; ··· 270 292 ->withParticipationStatus($unread_status) 271 293 ->execute(); 272 294 $message_count_number = idx($unread, $user->getPHID(), 0); 295 + 296 + if ($message_count_number) { 297 + $aural[] = phutil_tag( 298 + 'a', 299 + array( 300 + 'href' => '/conpherence/', 301 + ), 302 + pht( 303 + '%s unread messages.', 304 + new PhutilNumber($message_count_number))); 305 + } else { 306 + $aural[] = pht('No messages.'); 307 + } 308 + 273 309 if ($message_count_number > 999) { 274 310 $message_count_number = "\xE2\x88\x9E"; 275 311 } ··· 333 369 $count_number = id(new PhabricatorFeedStoryNotification()) 334 370 ->countUnread($user); 335 371 372 + if ($count_number) { 373 + $aural[] = phutil_tag( 374 + 'a', 375 + array( 376 + 'href' => '/notification/', 377 + ), 378 + pht( 379 + '%s unread notifications.', 380 + new PhutilNumber($count_number))); 381 + } else { 382 + $aural[] = pht('No notifications.'); 383 + } 384 + 336 385 if ($count_number > 999) { 337 386 $count_number = "\xE2\x88\x9E"; 338 387 } ··· 397 446 } 398 447 399 448 return array( 400 - hsprintf('%s%s', $bubble_tag, $message_tag), 401 - $dropdowns 449 + array( 450 + $bubble_tag, 451 + $message_tag, 452 + ), 453 + $dropdowns, 454 + $aural, 402 455 ); 403 456 } 404 457
+33 -1
src/view/phui/PHUIListItemView.php
··· 25 25 private $renderNameAsTooltip; 26 26 private $statusColor; 27 27 private $order; 28 + private $aural; 29 + 30 + public function setAural($aural) { 31 + $this->aural = $aural; 32 + return $this; 33 + } 34 + 35 + public function getAural() { 36 + return $this->aural; 37 + } 28 38 29 39 public function setOrder($order) { 30 40 $this->order = $order; ··· 170 180 $external = " \xE2\x86\x97"; 171 181 } 172 182 183 + // If this element has an aural representation, make any name visual 184 + // only. This is primarily dealing with the links in the main menu like 185 + // "Profile" and "Logout". If we don't hide the name, the mobile 186 + // version of these elements will have two redundant names. 187 + 188 + $classes = array(); 189 + $classes[] = 'phui-list-item-name'; 190 + if ($this->aural !== null) { 191 + $classes[] = 'visual-only'; 192 + } 193 + 173 194 $name = phutil_tag( 174 195 'span', 175 196 array( 176 - 'class' => 'phui-list-item-name', 197 + 'class' => implode(' ', $classes), 177 198 ), 178 199 array( 179 200 $this->name, 180 201 $external, 181 202 )); 182 203 } 204 + } 205 + 206 + $aural = null; 207 + if ($this->aural !== null) { 208 + $aural = phutil_tag( 209 + 'span', 210 + array( 211 + 'class' => 'aural-only', 212 + ), 213 + $this->aural); 183 214 } 184 215 185 216 if ($this->icon) { ··· 210 241 'sigil' => $sigil, 211 242 ), 212 243 array( 244 + $aural, 213 245 $icon, 214 246 $this->renderChildren(), 215 247 $name,
+26
webroot/rsrc/css/core/core.css
··· 123 123 background: #bbbbbb; 124 124 border: none; 125 125 } 126 + 127 + .aural-only { 128 + position: absolute !important; 129 + clip: rect(1px, 1px, 1px, 1px); 130 + } 131 + 132 + .visual-only { 133 + /* These elements are hidden by the 'aria-hidden' attribute. */ 134 + } 135 + 136 + .audible .aural-only { 137 + clip: auto; 138 + background: #006699; 139 + color: #ffffff; 140 + } 141 + 142 + .audible .aural-only a { 143 + color: #ffffff; 144 + font-weight: bold; 145 + } 146 + 147 + .audible .visual-only { 148 + position: absolute !important; 149 + background: #990066; 150 + opacity: 0.25; 151 + }
+4
webroot/rsrc/css/core/z-index.css
··· 148 148 .jx-tooltip-container { 149 149 z-index: 51; 150 150 } 151 + 152 + .audible .aural-only { 153 + z-index: 100; 154 + }