From 49af92e903252c3e833267a9520779fa47710aad Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 17 Jul 2020 11:57:10 -0700 Subject: [PATCH] Improve commit action item layout on mobile Summary: Ref T13552. Build the "commit list" elements so that the menu action items collapse under the element on mobile. Also change the mobile breakpoint to 512px because my Safari window can't go any narrower than 508px. Future changes to responsive design will be more content-aware anyway. Test Plan: Looked at commits in various interfaces, at desktop and mobile widths. Maniphest Tasks: T13552 Differential Revision: https://secure.phabricator.com/D21430 --- resources/celerity/map.php | 32 ++--- src/__phutil_library_map__.php | 6 +- .../view/DiffusionCommitGraphView.php | 33 +++-- src/view/fuel/FuelGridCellView.php | 4 +- src/view/fuel/FuelMenuItemView.php | 114 ++++++++++++++++++ src/view/fuel/FuelMenuView.php | 38 ++++++ src/view/phui/PHUIIconView.php | 5 + src/view/phui/PHUIObjectItemView.php | 47 ++++---- webroot/rsrc/css/fuel/fuel-grid.css | 18 +-- webroot/rsrc/css/fuel/fuel-menu.css | 52 ++++++++ .../phui/object-item/phui-oi-list-view.css | 16 ++- webroot/rsrc/js/core/behavior-device.js | 2 +- 12 files changed, 303 insertions(+), 64 deletions(-) create mode 100644 src/view/fuel/FuelMenuItemView.php create mode 100644 src/view/fuel/FuelMenuView.php create mode 100644 webroot/rsrc/css/fuel/fuel-menu.css diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 447d96d7e1..91e875769d 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,8 +9,8 @@ return array( 'names' => array( 'conpherence.pkg.css' => '0e3cf785', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '9cb7cb3f', - 'core.pkg.js' => '845355f4', + 'core.pkg.css' => '2ffd6897', + 'core.pkg.js' => 'adc34883', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '5c459f92', 'differential.pkg.js' => '218fda21', @@ -121,8 +121,9 @@ return array( 'rsrc/css/font/font-awesome.css' => '3883938a', 'rsrc/css/font/font-lato.css' => '23631304', 'rsrc/css/font/phui-font-icon-base.css' => '303c9b87', - 'rsrc/css/fuel/fuel-grid.css' => 'd87031e7', + 'rsrc/css/fuel/fuel-grid.css' => '66697240', 'rsrc/css/fuel/fuel-map.css' => 'd6e31510', + 'rsrc/css/fuel/fuel-menu.css' => 'cb35abe3', 'rsrc/css/layout/phabricator-source-code-view.css' => '03d7ac28', 'rsrc/css/phui/button/phui-button-bar.css' => 'a4aa75c4', 'rsrc/css/phui/button/phui-button-simple.css' => '1ff278aa', @@ -135,7 +136,7 @@ return array( 'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0', 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc', 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e', - 'rsrc/css/phui/object-item/phui-oi-list-view.css' => '4b0def39', + 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'ecd651d5', 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46', 'rsrc/css/phui/phui-action-list.css' => '1b0085b2', 'rsrc/css/phui/phui-action-panel.css' => '6c386cbf', @@ -475,7 +476,7 @@ return array( 'rsrc/js/core/behavior-choose-control.js' => '04f8a1e3', 'rsrc/js/core/behavior-copy.js' => 'cf32921f', 'rsrc/js/core/behavior-detect-timezone.js' => '78bc5d94', - 'rsrc/js/core/behavior-device.js' => '0cf79f45', + 'rsrc/js/core/behavior-device.js' => 'ac2b1e01', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '7ad020a5', 'rsrc/js/core/behavior-fancy-datepicker.js' => '956f3eeb', 'rsrc/js/core/behavior-form.js' => '55d7b788', @@ -576,8 +577,9 @@ return array( 'diviner-shared-css' => '4bd263b0', 'font-fontawesome' => '3883938a', 'font-lato' => '23631304', - 'fuel-grid-css' => 'd87031e7', + 'fuel-grid-css' => '66697240', 'fuel-map-css' => 'd6e31510', + 'fuel-menu-css' => 'cb35abe3', 'global-drag-and-drop-css' => '1d2713a4', 'harbormaster-css' => '8dfe16b2', 'herald-css' => '648d39e2', @@ -615,7 +617,7 @@ return array( 'javelin-behavior-day-view' => '727a5a61', 'javelin-behavior-desktop-notifications-control' => '070679fe', 'javelin-behavior-detect-timezone' => '78bc5d94', - 'javelin-behavior-device' => '0cf79f45', + 'javelin-behavior-device' => 'ac2b1e01', 'javelin-behavior-differential-diff-radios' => '925fe8cd', 'javelin-behavior-differential-populate' => 'b86ef6c2', 'javelin-behavior-diffusion-commit-branches' => '4b671572', @@ -870,7 +872,7 @@ return array( 'phui-oi-color-css' => 'b517bfa0', 'phui-oi-drag-ui-css' => 'da15d3dc', 'phui-oi-flush-ui-css' => '490e2e2e', - 'phui-oi-list-view-css' => '4b0def39', + 'phui-oi-list-view-css' => 'ecd651d5', 'phui-oi-simple-ui-css' => '6a30fa46', 'phui-pager-css' => 'd022c7ad', 'phui-pinboard-view-css' => '1f08f5d8', @@ -1006,13 +1008,6 @@ return array( 'javelin-dom', 'phabricator-draggable-list', ), - '0cf79f45' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-dom', - 'javelin-vector', - 'javelin-install', - ), '0d2490ce' => array( 'javelin-install', ), @@ -1930,6 +1925,13 @@ return array( 'javelin-dom', 'phabricator-notification', ), + 'ac2b1e01' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-dom', + 'javelin-vector', + 'javelin-install', + ), 'ad258e28' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 1578a69868..79d51c46fc 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1311,6 +1311,8 @@ phutil_register_library_map(array( 'FuelGridView' => 'view/fuel/FuelGridView.php', 'FuelMapItemView' => 'view/fuel/FuelMapItemView.php', 'FuelMapView' => 'view/fuel/FuelMapView.php', + 'FuelMenuItemView' => 'view/fuel/FuelMenuItemView.php', + 'FuelMenuView' => 'view/fuel/FuelMenuView.php', 'FuelView' => 'view/fuel/FuelView.php', 'FundBacker' => 'applications/fund/storage/FundBacker.php', 'FundBackerCart' => 'applications/fund/phortune/FundBackerCart.php', @@ -7447,11 +7449,13 @@ phutil_register_library_map(array( 'FlagEditConduitAPIMethod' => 'FlagConduitAPIMethod', 'FlagQueryConduitAPIMethod' => 'FlagConduitAPIMethod', 'FuelComponentView' => 'FuelView', - 'FuelGridCellView' => 'FuelView', + 'FuelGridCellView' => 'FuelComponentView', 'FuelGridRowView' => 'FuelView', 'FuelGridView' => 'FuelComponentView', 'FuelMapItemView' => 'AphrontView', 'FuelMapView' => 'FuelComponentView', + 'FuelMenuItemView' => 'FuelView', + 'FuelMenuView' => 'FuelComponentView', 'FuelView' => 'AphrontView', 'FundBacker' => array( 'FundDAO', diff --git a/src/applications/diffusion/view/DiffusionCommitGraphView.php b/src/applications/diffusion/view/DiffusionCommitGraphView.php index 6682e1bf66..abfd5da349 100644 --- a/src/applications/diffusion/view/DiffusionCommitGraphView.php +++ b/src/applications/diffusion/view/DiffusionCommitGraphView.php @@ -452,13 +452,17 @@ final class DiffusionCommitGraphView $uri = $drequest->generateURI( array( 'action' => 'browse', - 'path' => $path, + 'path' => $path, + 'commit' => $hash, )); - $item->newAction() - ->setIcon('fa-folder-open-o bluegrey') + $menu_item = $item->newMenuItem() ->setName(pht('Browse Repository')) - ->setHref($uri); + ->setURI($uri); + + $menu_item->newIcon() + ->setIcon('fa-folder-open-o') + ->setColor('bluegrey'); } private function addBuildAction(PHUIObjectItemView $item, $hash) { @@ -483,11 +487,14 @@ final class DiffusionCommitGraphView $uri = null; } - $item->newAction() - ->setIcon($icon.' '.$color) + $menu_item = $item->newMenuItem() ->setName($name) - ->setHref($uri) + ->setURI($uri) ->setDisabled(($uri === null)); + + $menu_item->newIcon() + ->setIcon($icon) + ->setColor($color); } private function addAuditAction(PHUIObjectItemView $item_view, $hash) { @@ -502,7 +509,7 @@ final class DiffusionCommitGraphView $uri = $commit->getURI(); - $is_disabled = $status->isNoAudit(); + $is_disabled = false; } else { $text = pht('No Audit'); $color = 'grey'; @@ -512,11 +519,15 @@ final class DiffusionCommitGraphView $is_disabled = true; } - $item_view->newAction() - ->setIcon($icon.' '.$color) + $menu_item = $item_view->newMenuItem() ->setName($text) - ->setHref($uri) + ->setURI($uri) + ->setBackgroundColor($color) ->setDisabled($is_disabled); + + $menu_item->newIcon() + ->setIcon($icon) + ->setColor($color); } private function getBuildable(PhabricatorRepositoryCommit $commit) { diff --git a/src/view/fuel/FuelGridCellView.php b/src/view/fuel/FuelGridCellView.php index edb6391843..b4e4b6ef5a 100644 --- a/src/view/fuel/FuelGridCellView.php +++ b/src/view/fuel/FuelGridCellView.php @@ -1,7 +1,7 @@ getContent(); - return phutil_tag( + return $this->newComponentTag( 'div', array( 'class' => 'fuel-grid-cell', diff --git a/src/view/fuel/FuelMenuItemView.php b/src/view/fuel/FuelMenuItemView.php new file mode 100644 index 0000000000..70799b6630 --- /dev/null +++ b/src/view/fuel/FuelMenuItemView.php @@ -0,0 +1,114 @@ +uri = $uri; + return $this; + } + + public function getURI() { + return $this->uri; + } + + public function setName($name) { + $this->name = $name; + return $this; + } + + public function getName() { + return $this->name; + } + + public function setIcon(PHUIIconView $icon) { + $this->icon = $icon; + return $this; + } + + public function getIcon() { + return $this->icon; + } + + public function newIcon() { + $icon = new PHUIIconView(); + $this->setIcon($icon); + return $icon; + } + + public function setDisabled($disabled) { + $this->disabled = $disabled; + return $this; + } + + public function getDisabled() { + return $this->disabled; + } + + public function setBackgroundColor($background_color) { + $this->backgroundColor = $background_color; + return $this; + } + + public function getBackgroundColor() { + return $this->backgroundColor; + } + + public function render() { + $icon = $this->getIcon(); + + $name = $this->getName(); + $uri = $this->getURI(); + + $icon = phutil_tag( + 'span', + array( + 'class' => 'fuel-menu-item-icon', + ), + $icon); + + $item_link = phutil_tag( + 'a', + array( + 'href' => $uri, + 'class' => 'fuel-menu-item-link', + ), + array( + $icon, + $name, + )); + + $classes = array(); + $classes[] = 'fuel-menu-item'; + + if ($this->getDisabled()) { + $classes[] = 'disabled'; + } + + $background_color = $this->getBackgroundColor(); + if ($background_color !== null) { + $classes[] = 'fuel-menu-item-background-color-'.$background_color; + } + + + if ($uri !== null) { + $classes[] = 'has-link'; + } + + $classes = implode(' ', $classes); + + return phutil_tag( + 'div', + array( + 'class' => $classes, + ), + $item_link); + } + +} diff --git a/src/view/fuel/FuelMenuView.php b/src/view/fuel/FuelMenuView.php new file mode 100644 index 0000000000..5b35aeae09 --- /dev/null +++ b/src/view/fuel/FuelMenuView.php @@ -0,0 +1,38 @@ +items[] = $item; + return $item; + } + + public function render() { + require_celerity_resource('fuel-menu-css'); + + $items = $this->items; + + if (!$items) { + return null; + } + + $list = phutil_tag( + 'div', + array( + 'class' => 'fuel-menu', + ), + $items); + + return $this->newComponentTag( + 'div', + array( + 'class' => 'fuel-menu-component', + ), + $list); + } + +} diff --git a/src/view/phui/PHUIIconView.php b/src/view/phui/PHUIIconView.php index e3f9f076c2..a5897e02d6 100644 --- a/src/view/phui/PHUIIconView.php +++ b/src/view/phui/PHUIIconView.php @@ -57,6 +57,11 @@ final class PHUIIconView extends AphrontTagView { return $this; } + public function setColor($color) { + $this->iconColor = $color; + return $this; + } + public function getIconName() { return $this->iconFont; } diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php index 86c8d8d380..1dfa1a198e 100644 --- a/src/view/phui/PHUIObjectItemView.php +++ b/src/view/phui/PHUIObjectItemView.php @@ -16,7 +16,6 @@ final class PHUIObjectItemView extends AphrontTagView { private $bylines = array(); private $grippable; private $actions = array(); - private $actionItems = array(); private $headIcons = array(); private $disabled; private $imageURI; @@ -31,6 +30,7 @@ final class PHUIObjectItemView extends AphrontTagView { private $description; private $clickable; private $mapViews = array(); + private $menu; private $selectableName; private $selectableValue; @@ -214,10 +214,12 @@ final class PHUIObjectItemView extends AphrontTagView { return $this; } - public function newAction() { - $action = new PhabricatorActionView(); - $this->actionItems[] = $action; - return $action; + public function newMenuItem() { + if (!$this->menu) { + $this->menu = new FuelMenuView(); + } + + return $this->menu->newItem(); } public function newMapView() { @@ -763,23 +765,6 @@ final class PHUIObjectItemView extends AphrontTagView { )); } - $column4 = null; - if ($this->actionItems) { - $action_list = id(new PhabricatorActionListView()) - ->setViewer($viewer); - - foreach ($this->actionItems as $action_item) { - $action_list->addAction($action_item); - } - - $column4 = phutil_tag( - 'div', - array( - 'class' => 'phui-oi-col2 phui-oi-action-list', - ), - $action_list); - } - $table = phutil_tag( 'div', array( @@ -792,7 +777,6 @@ final class PHUIObjectItemView extends AphrontTagView { $column1, $column2, $column3, - $column4, ))); $box = phutil_tag( @@ -859,7 +843,22 @@ final class PHUIObjectItemView extends AphrontTagView { $frame_content, )); - return $frame; + $grid_view = id(new FuelGridView()) + ->addClass('fuel-grid-tablet'); + $grid_row = $grid_view->newRow(); + + $grid_row->newCell() + ->setContent($frame); + + if ($this->menu) { + $menu = $this->menu; + + $grid_row->newCell() + ->addClass('phui-oi-menu') + ->setContent($menu); + } + + return $grid_view; } private function renderStatusIcon($icon, $label) { diff --git a/webroot/rsrc/css/fuel/fuel-grid.css b/webroot/rsrc/css/fuel/fuel-grid.css index 5014bc5cb4..16acb3eed7 100644 --- a/webroot/rsrc/css/fuel/fuel-grid.css +++ b/webroot/rsrc/css/fuel/fuel-grid.css @@ -2,28 +2,30 @@ * @provides fuel-grid-css */ -.device-desktop .fuel-grid { +.device-desktop .fuel-grid, +.device-tablet .fuel-grid-tablet > .fuel-grid { display: table; table-layout: fixed; } -.device-desktop .fuel-grid-body { +.device-desktop .fuel-grid-body, +.device-tablet .fuel-grid-tablet > .fuel-grid > .fuel-grid-body { display: table-row-group; } -.device-desktop .fuel-grid-row { +.device-desktop .fuel-grid-row, +.device-tablet .fuel-grid-tablet > .fuel-grid > .fuel-grid-body > + .fuel-grid-row { display: table-row; } -.device-desktop .fuel-grid-cell { +.device-desktop .fuel-grid-cell, +.device-tablet .fuel-grid-tablet > .fuel-grid > .fuel-grid-body > + .fuel-grid-row > .fuel-grid-cell { display: table-cell; vertical-align: top; } -.device-desktop .fuel-grid-cell-count-2 > .fuel-grid-cell { - width: 50%; -} - .fuel-grid-property-list > .fuel-grid { width: 100%; } diff --git a/webroot/rsrc/css/fuel/fuel-menu.css b/webroot/rsrc/css/fuel/fuel-menu.css new file mode 100644 index 0000000000..d03c43f691 --- /dev/null +++ b/webroot/rsrc/css/fuel/fuel-menu.css @@ -0,0 +1,52 @@ +/** + * @provides fuel-menu-css + */ + +.fuel-menu-item-icon { + width: 14px; + height: 14px; + position: absolute; + left: 8px; + top: 4px; + text-align: center; +} + +.fuel-menu-item-link { + padding: 4px 4px 4px 28px; + position: relative; + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: {$greytext}; + cursor: default; + border-radius: 3px; +} + +.fuel-menu-item.disabled > .fuel-menu-item-link { + color: {$lightgreytext}; +} + +.fuel-menu-item.has-link > .fuel-menu-item-link { + color: {$darkbluetext}; + cursor: pointer; +} + +.device-desktop .fuel-menu-item > .fuel-menu-item-link:hover { + text-decoration: none; +} + +.device-desktop .fuel-menu-item.has-link > .fuel-menu-item-link:hover { + color: {$sky}; + background: rgba({$alphablue}, .08); +} + +.fuel-menu-item-background-color-orange > .fuel-menu-item-link { + background: {$sh-orangebackground}; +} + +.device-desktop .fuel-menu-item.has-link.fuel-menu-item-background-color-orange + > .fuel-menu-item-link:hover { + background: {$lightorange}; + color: {$orange}; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css index f38731f3da..ea04518bdf 100644 --- a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css +++ b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css @@ -726,8 +726,20 @@ ul.phui-oi-list-view .phui-oi-selectable background: linear-gradient({$lightbluebackground}, #fff 66%, #fff); } -.phui-oi-action-list { +.phui-oi-menu { background: {$lightbluebackground}; - border-left: 1px solid {$thinblueborder}; + border-style: solid; + border-color: {$thinblueborder}; padding: 4px; } + +.device-desktop .phui-oi-menu, +.device-tablet .phui-oi-menu { + width: 200px; + border-width: 0 0 1px 1px; +} + +.device-phone .phui-oi-menu { + border-width: 0 0 1px; + margin-bottom: 12px; +} diff --git a/webroot/rsrc/js/core/behavior-device.js b/webroot/rsrc/js/core/behavior-device.js index d68a46ff4e..9e294b0663 100644 --- a/webroot/rsrc/js/core/behavior-device.js +++ b/webroot/rsrc/js/core/behavior-device.js @@ -43,7 +43,7 @@ JX.install('Device', { if (v.x <= self._tabletBreakpoint) { device = 'tablet'; } - if (v.x <= 480) { + if (v.x <= 512) { device = 'phone'; }