diff --git a/src/webextension/images/intro-step-1.png b/src/webextension/images/intro-step-1.png new file mode 100644 index 00000000..7654052b Binary files /dev/null and b/src/webextension/images/intro-step-1.png differ diff --git a/src/webextension/images/intro-step-2.png b/src/webextension/images/intro-step-2.png new file mode 100644 index 00000000..d2f84829 Binary files /dev/null and b/src/webextension/images/intro-step-2.png differ diff --git a/src/webextension/images/intro-step-3.png b/src/webextension/images/intro-step-3.png new file mode 100644 index 00000000..48d45e18 Binary files /dev/null and b/src/webextension/images/intro-step-3.png differ diff --git a/src/webextension/list/manage/components/intro-page.css b/src/webextension/list/manage/components/intro-page.css new file mode 100644 index 00000000..1d7eb66a --- /dev/null +++ b/src/webextension/list/manage/components/intro-page.css @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +.intro-images { + display: grid; + grid-auto-flow: column; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: auto auto auto; + grid-column-gap: 4em; + margin: 4em auto; + padding: 0 4em; + max-width: 800px; +} + +.intro-image { + display: contents; + text-align: center; +} + +.intro-image > h1, +.intro-image > p { + overflow: hidden; +} + +.intro-image > img { + width: 100%; + border: 1px solid rgba(12, 12, 13, 0.3); + border-radius: 5px; + box-shadow: 0 0 10px rgba(12, 12, 13, 0.3); +} + +.intro-image > h1 { + font-size: 17px; + margin-bottom: 0; +} + +.intro-image > p { + font-size: 15px; +} diff --git a/src/webextension/list/manage/components/intro-page.js b/src/webextension/list/manage/components/intro-page.js new file mode 100644 index 00000000..0d45f04e --- /dev/null +++ b/src/webextension/list/manage/components/intro-page.js @@ -0,0 +1,55 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { Localized } from "fluent-react"; +import PropTypes from "prop-types"; +import React from "react"; + +import AccountDetails from "../containers/account-details"; + +import styles from "./intro-page.css"; + +function IntroImage({src, title, children}) { + return ( +
+ +

{title}

+

{children}

+
+ ); +} + +IntroImage.propTypes = { + src: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + children: PropTypes.node, +}; + +export default function IntroPage() { + return ( +
+
+ + + sAVe uSERNAMe aNd pASSWORd... + + + + + cLICk tHe lOCKBOx iCOn... + + + + + cOPy an eNTRY's iNFo... + + +
+ +
+ ); +} diff --git a/src/webextension/list/manage/containers/current-selection.js b/src/webextension/list/manage/containers/current-selection.js index eed34df2..3c765e9a 100644 --- a/src/webextension/list/manage/containers/current-selection.js +++ b/src/webextension/list/manage/containers/current-selection.js @@ -14,6 +14,7 @@ import { import EditItemDetails from "../components/edit-item-details"; import ItemDetails from "../components/item-details"; import Homepage from "../components/homepage"; +import IntroPage from "../components/intro-page"; const ConnectedEditItemDetails = connect( (state, ownProps) => ({ @@ -51,7 +52,7 @@ const ConnectedItemDetails = connect( }) )(ItemDetails); -function CurrentSelection({editing, item, hideHome}) { +function CurrentSelection({editing, item, hideHome, numItems}) { let inner; if (editing) { inner = ; @@ -60,8 +61,10 @@ function CurrentSelection({editing, item, hideHome}) { } else if (hideHome) { // Don't show anything since we're still loading the item details. inner = null; - } else { + } else if (numItems !== 0) { inner = ; + } else { + inner = ; } return
{inner}
; } @@ -70,6 +73,7 @@ CurrentSelection.propTypes = { editing: PropTypes.bool.isRequired, item: PropTypes.object, hideHome: PropTypes.bool.isRequired, + numItems: PropTypes.number.isRequired, }; export default connect( @@ -77,5 +81,6 @@ export default connect( editing: state.editor.editing, hideHome: state.editor.hideHome, item: state.cache.currentItem, + numItems: state.cache.items.length, }) )(CurrentSelection); diff --git a/src/webextension/locales/en-US/list.ftl b/src/webextension/locales/en-US/list.ftl index c975ab28..1985d40a 100644 --- a/src/webextension/locales/en-US/list.ftl +++ b/src/webextension/locales/en-US/list.ftl @@ -45,6 +45,21 @@ all-items-empty = all-items-filtered = No results +intro-page-step-1 = + Save username and password info to create a { product-title } entry. + + .title = Add Login Info to { product-title } + +intro-page-step-2 = + Click the { product-title } icon to see all the entries you've saved. + + .title = Go Straight to Your Logins + +intro-page-step-3 = + Copy an entry's info to sign in right from Firefox. + + .title = Sign in From { product-title } + homepage-title = { product-tagline } homepage-linkaccount-title = Add Serious Security & Convenience diff --git a/test/integration/pages/home.py b/test/integration/pages/home.py index 4d3c93cd..49e3858f 100644 --- a/test/integration/pages/home.py +++ b/test/integration/pages/home.py @@ -11,11 +11,10 @@ class Home(Base): """Contain the locators and actions relating to the home page.""" + _modal_portal_locator = (By.CLASS_NAME, 'ReactModalPortal') _entries_locator = (By.CSS_SELECTOR, 'ul li div.{}'.format( munged_class_name('item-summary'))) - _homepage_section_locator = (By.CSS_SELECTOR, '.{} h1'.format( - munged_class_name('homepage'))) _delete_entry_locator = (By.CSS_SELECTOR, 'article div menu ' 'button.{}'.format(munged_class_name('normal'))) @@ -42,7 +41,7 @@ def door_hanger(self): def wait_for_page_to_load(self): """Wait for page to load.""" self.wait.until( - lambda s: s.find_element(*self._homepage_section_locator)) + lambda s: s.find_element(*self._modal_portal_locator)) return self @property