Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/docs/contributor/assistive_technologies.diviner b/src/docs/contributor/assistive_technologies.diviner
new file mode 100644
index 0000000000..a519bde881
--- /dev/null
+++ b/src/docs/contributor/assistive_technologies.diviner
@@ -0,0 +1,76 @@
+@title Assistive Technologies
+@group developer
+
+Information about making Phabricator accessible to assistive technologies.
+
+Overview
+========
+
+Assistive technologies help people with disabilities use the web. For example,
+screen readers can assist people with limited or no eyesight by reading the
+contents of pages aloud.
+
+Phabricator has some support for assistive technologies, and we'd like to have
+more support. This document describes how to use the currently available
+features to improve the accessibility of Phabricator.
+
+
+Aural-Only Elements
+===================
+
+The most common issue assistive technologies encounter is buttons, links, or
+other elements which only convey information visually (usually through an icon
+or image).
+
+These elements can be made more accessible by providing an aural-only label.
+This label will not be displayed by visual browsers, but will be read by screen
+readers.
+
+To add an aural-only label to an element, use `javelin_tag()` with the
+`aural` attribute:
+
+ javelin_tag(
+ 'span',
+ array(
+ 'aural' => true,
+ ),
+ pht('Aural Label Here'));
+
+This label should be placed inside the button or link that you are labeling.
+
+You can also use `aural` on a container to provide an entirely different
+replacement element, but should be cautious about doing this.
+
+NOTE: You must use `javelin_tag()`, not `phutil_tag()`, to get support for
+this attribute.
+
+
+Visual-Only Elements
+====================
+
+Occasionally, a visual element should be hidden from screen readers. This should
+be rare, but some textual elements convey very little information or are
+otherwise disruptive for aural users.
+
+This technique can also be used to offer a visual alternative of an element
+and a different aural alternative element. However, this should be rare: it is
+usually better to adapt a single element to work well for both visual and aural
+users.
+
+You can mark an element as visual-only by using `javelin_tag()` with the
+`aural` attribute:
+
+ javelin_tag(
+ 'span',
+ array(
+ 'aural' => false,
+ ),
+ $ascii_art);
+
+
+Previewing Aural Pages
+======================
+
+To verify aural markup, you can add `?__aural__=1` to any page URI. This will
+make Phabricator render the page with styles that reveal aural-only elements and
+mute visual-only elements.
diff --git a/src/view/form/control/PhabricatorRemarkupControl.php b/src/view/form/control/PhabricatorRemarkupControl.php
index b4dc6fb09e..1f98ad6da7 100644
--- a/src/view/form/control/PhabricatorRemarkupControl.php
+++ b/src/view/form/control/PhabricatorRemarkupControl.php
@@ -1,206 +1,206 @@
<?php
final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl {
private $disableMacro = false;
public function setDisableMacros($disable) {
$this->disableMacro = $disable;
return $this;
}
protected function renderInput() {
$id = $this->getID();
if (!$id) {
$id = celerity_generate_unique_node_id();
$this->setID($id);
}
// We need to have this if previews render images, since Ajax can not
// currently ship JS or CSS.
require_celerity_resource('lightbox-attachment-css');
Javelin::initBehavior(
'aphront-drag-and-drop-textarea',
array(
'target' => $id,
'activatedClass' => 'aphront-textarea-drag-and-drop',
'uri' => '/file/dropupload/',
));
Javelin::initBehavior(
'phabricator-remarkup-assist',
array(
'pht' => array(
'bold text' => pht('bold text'),
'italic text' => pht('italic text'),
'monospaced text' => pht('monospaced text'),
'List Item' => pht('List Item'),
'data' => pht('data'),
'name' => pht('name'),
'URL' => pht('URL'),
),
));
Javelin::initBehavior('phabricator-tooltips', array());
$actions = array(
'b' => array(
'tip' => pht('Bold'),
),
'i' => array(
'tip' => pht('Italics'),
),
'tt' => array(
'tip' => pht('Monospaced'),
),
'link' => array(
'tip' => pht('Link'),
),
array(
'spacer' => true,
),
'ul' => array(
'tip' => pht('Bulleted List'),
),
'ol' => array(
'tip' => pht('Numbered List'),
),
'code' => array(
'tip' => pht('Code Block'),
),
'table' => array(
'tip' => pht('Table'),
),
'image' => array(
'tip' => pht('Upload File'),
),
);
if (!$this->disableMacro and function_exists('imagettftext')) {
$actions[] = array(
'spacer' => true,
);
$actions['meme'] = array(
'tip' => pht('Meme'),
);
}
$actions['help'] = array(
'tip' => pht('Help'),
'align' => 'right',
'href' => PhabricatorEnv::getDoclink('Remarkup Reference'),
);
$actions[] = array(
'spacer' => true,
'align' => 'right',
);
$actions['fullscreen'] = array(
'tip' => pht('Fullscreen Mode'),
'align' => 'right',
);
$buttons = array();
foreach ($actions as $action => $spec) {
$classes = array();
if (idx($spec, 'align') == 'right') {
$classes[] = 'remarkup-assist-right';
}
if (idx($spec, 'spacer')) {
$classes[] = 'remarkup-assist-separator';
$buttons[] = phutil_tag(
'span',
array(
'class' => implode(' ', $classes),
),
'');
continue;
} else {
$classes[] = 'remarkup-assist-button';
}
$href = idx($spec, 'href', '#');
if ($href == '#') {
$meta = array('action' => $action);
$mustcapture = true;
$target = null;
} else {
$meta = array();
$mustcapture = null;
$target = '_blank';
}
$content = null;
$tip = idx($spec, 'tip');
if ($tip) {
$meta['tip'] = $tip;
- $content = phutil_tag(
+ $content = javelin_tag(
'span',
array(
- 'class' => 'aural-only',
+ 'aural' => true,
),
$tip);
}
require_celerity_resource('sprite-icons-css');
$buttons[] = javelin_tag(
'a',
array(
'class' => implode(' ', $classes),
'href' => $href,
'sigil' => 'remarkup-assist has-tooltip',
'meta' => $meta,
'mustcapture' => $mustcapture,
'target' => $target,
'tabindex' => -1,
),
phutil_tag(
'div',
array(
'class' => 'remarkup-assist sprite-icons remarkup-assist-'.$action,
),
$content));
}
$buttons = phutil_tag(
'div',
array(
'class' => 'remarkup-assist-bar',
),
$buttons);
$monospaced_textareas = null;
$monospaced_textareas_class = null;
$user = $this->getUser();
if ($user) {
$monospaced_textareas = $user
->loadPreferences()
->getPreference(
PhabricatorUserPreferences::PREFERENCE_MONOSPACED_TEXTAREAS);
if ($monospaced_textareas == 'enabled') {
$monospaced_textareas_class = 'PhabricatorMonospaced';
}
}
$this->setCustomClass(
'remarkup-assist-textarea '.$monospaced_textareas_class);
return javelin_tag(
'div',
array(
'sigil' => 'remarkup-assist-control',
),
array(
$buttons,
parent::renderInput(),
));
}
}
diff --git a/src/view/phui/PHUIListItemView.php b/src/view/phui/PHUIListItemView.php
index 5360771e3c..399b27ac98 100644
--- a/src/view/phui/PHUIListItemView.php
+++ b/src/view/phui/PHUIListItemView.php
@@ -1,251 +1,251 @@
<?php
final class PHUIListItemView extends AphrontTagView {
const TYPE_LINK = 'type-link';
const TYPE_SPACER = 'type-spacer';
const TYPE_LABEL = 'type-label';
const TYPE_BUTTON = 'type-button';
const TYPE_CUSTOM = 'type-custom';
const TYPE_DIVIDER = 'type-divider';
const TYPE_ICON = 'type-icon';
const STATUS_WARN = 'phui-list-item-warn';
const STATUS_FAIL = 'phui-list-item-fail';
private $name;
private $href;
private $type = self::TYPE_LINK;
private $isExternal;
private $key;
private $icon;
private $appIcon;
private $selected;
private $disabled;
private $renderNameAsTooltip;
private $statusColor;
private $order;
private $aural;
public function setAural($aural) {
$this->aural = $aural;
return $this;
}
public function getAural() {
return $this->aural;
}
public function setOrder($order) {
$this->order = $order;
return $this;
}
public function getOrder() {
return $this->order;
}
public function setRenderNameAsTooltip($render_name_as_tooltip) {
$this->renderNameAsTooltip = $render_name_as_tooltip;
return $this;
}
public function getRenderNameAsTooltip() {
return $this->renderNameAsTooltip;
}
public function setSelected($selected) {
$this->selected = $selected;
return $this;
}
public function getSelected() {
return $this->selected;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function setAppIcon($icon) {
$this->appIcon = $icon;
return $this;
}
public function getIcon() {
return $this->icon;
}
public function setKey($key) {
$this->key = (string)$key;
return $this;
}
public function getKey() {
return $this->key;
}
public function setType($type) {
$this->type = $type;
return $this;
}
public function getType() {
return $this->type;
}
public function setHref($href) {
$this->href = $href;
return $this;
}
public function getHref() {
return $this->href;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public function setIsExternal($is_external) {
$this->isExternal = $is_external;
return $this;
}
public function getIsExternal() {
return $this->isExternal;
}
public function setStatusColor($color) {
$this->statusColor = $color;
return $this;
}
protected function getTagName() {
return 'li';
}
protected function getTagAttributes() {
$classes = array();
$classes[] = 'phui-list-item-view';
$classes[] = 'phui-list-item-'.$this->type;
if ($this->icon || $this->appIcon) {
$classes[] = 'phui-list-item-has-icon';
}
if ($this->selected) {
$classes[] = 'phui-list-item-selected';
}
if ($this->statusColor) {
$classes[] = $this->statusColor;
}
return array(
'class' => $classes,
);
}
public function setDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function getDisabled() {
return $this->disabled;
}
protected function getTagContent() {
$name = null;
$icon = null;
$meta = null;
$sigil = null;
if ($this->name) {
if ($this->getRenderNameAsTooltip()) {
$sigil = 'has-tooltip';
$meta = array(
'tip' => $this->name,
);
} else {
$external = null;
if ($this->isExternal) {
$external = " \xE2\x86\x97";
}
// If this element has an aural representation, make any name visual
// only. This is primarily dealing with the links in the main menu like
// "Profile" and "Logout". If we don't hide the name, the mobile
// version of these elements will have two redundant names.
$classes = array();
$classes[] = 'phui-list-item-name';
if ($this->aural !== null) {
$classes[] = 'visual-only';
}
$name = phutil_tag(
'span',
array(
'class' => implode(' ', $classes),
),
array(
$this->name,
$external,
));
}
}
$aural = null;
if ($this->aural !== null) {
- $aural = phutil_tag(
+ $aural = javelin_tag(
'span',
array(
- 'class' => 'aural-only',
+ 'aural' => true,
),
$this->aural);
}
if ($this->icon) {
$icon_name = $this->icon;
if ($this->getDisabled()) {
$icon_name .= '-grey';
}
$icon = id(new PHUIIconView())
->addClass('phui-list-item-icon')
->setSpriteSheet(PHUIIconView::SPRITE_ICONS)
->setSpriteIcon($icon_name);
}
if ($this->appIcon) {
$icon = id(new PHUIIconView())
->addClass('phui-list-item-icon')
->setSpriteSheet(PHUIIconView::SPRITE_APPS)
->setSpriteIcon($this->appIcon);
}
return javelin_tag(
$this->href ? 'a' : 'div',
array(
'href' => $this->href,
'class' => $this->href ? 'phui-list-item-href' : null,
'meta' => $meta,
'sigil' => $sigil,
),
array(
$aural,
$icon,
$this->renderChildren(),
$name,
));
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Aug 15, 7:14 AM (6 d, 6 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
188827
Default Alt Text
(13 KB)

Event Timeline