Skip to content

Commit

Permalink
fix: Rework all styling to better match UX spec
Browse files Browse the repository at this point in the history
* Styling tweaks across all panels to better match UX spec
* Adapt styles to narrower popup under hamburger menu panel
* Rollover & active colors for fotter buttons
* Calendar styling reworked, "now" link removed
* Switch to inline time picker instead of separate view
* Time display formatting tweaks
* Sub-panels no longer full-width and dimming effect added underneath
* Add Fira Sans web font
* Additional storybook story to reflect non-snoozable tab version of
  management panel

Fixes bwinton#68.
Fixes bwinton#101.
Fixes bwinton#107.
Fixes bwinton#113.
Fixes bwinton#118.
  • Loading branch information
lmorchard committed Feb 1, 2017
1 parent 776bf34 commit db493c4
Show file tree
Hide file tree
Showing 10 changed files with 661 additions and 145 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"run": "web-ext run -s dist --firefox=nightly",
"clean": "rm -rf dist && shx mkdir -p dist/popup",
"watch": "npm-run-all --parallel watch:*",
"copy:assets": "shx cp -r src/manifest.json src/icons dist/ && svgo src/icons -o dist/icons && shx cp -r src/popup/*.html dist/popup/",
"copy:assets": "shx cp -r src/manifest.json src/icons dist/ && svgo src/icons -o dist/icons && shx cp -r src/popup/*.html src/popup/FiraSans-Regular.* dist/popup/",
"bundle:js": "npm run lint:js && rollup -c --environment entry:background && rollup -c --environment entry:popup/snooze-content",
"bundle:css": "npm run lint:sass && shx mkdir -p dist/popup && node-sass src/popup/snooze.scss > dist/popup/snooze.css",
"package": "npm run build && web-ext build -s dist -a .",
Expand Down
17 changes: 12 additions & 5 deletions src/lib/components/DatePickerPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import moment from 'moment';
import classnames from 'classnames';

import Calendar from 'rc-calendar';
import TimePickerPanel from 'rc-time-picker/lib/Panel';
import TimePicker from 'rc-time-picker';

// Arbitrary 0.5s interval for live validation of time selection
const VALIDATION_INTERVAL = 500;
Expand Down Expand Up @@ -35,21 +35,28 @@ export default class DatePickerPanel extends React.Component {
render() {
const { id, header, active, onClose } = this.props;
const { currentValue, confirmDisabled } = this.state;
const disabledTimeFns = this.disabledTime();

return (
<div id={id} className={classnames('panel', { active })}>
<div className="header">{header}</div>
<Calendar showOk={false}
showDateInput={false}
showToday={false}
value={currentValue}
timePicker={(
<TimePickerPanel value={currentValue}
showHour={true} showMinute={true} showSecond={false} />
)}
disabledDate={this.disabledDate.bind(this)}
disabledTime={this.disabledTime.bind(this)}
onChange={value => this.handleChange(value)}
onSelect={value => this.handleChange(value)} />
<div className="time-wrapper">
<TimePicker showSecond={false}
hideDisabledOptions={true}
allowEmpty={false}
value={currentValue}
format="h:mm a"
onChange={value => this.handleChange(value)}
{...disabledTimeFns} />
</div>
<div className="footer">
<div className="back"
onClick={onClose}><span>« Back</span></div>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/MainPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class MainPanel extends React.Component {

return (
<div>
<div id={id} className={classnames('panel', { active })}>
<div id={id} className={classnames('static', 'panel', { active, obscured: datepickerActive })}>
<ul className="times">
{ times.map(item => this.renderTime(item)) }
</ul>
Expand Down
17 changes: 13 additions & 4 deletions src/lib/components/ManagePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,20 @@ export default class ManagePanel extends React.Component {

return (
<div>
<div id={id} className={classnames('panel', { active, 'static': !tabIsSnoozable })}>
<div id={id} className={classnames('panel', { active, obscured: datepickerActive, static: !tabIsSnoozable })}>
<div className="header">Manage Snoozed Tabs</div>
<ul className={classnames('entries', { 'big': !tabIsSnoozable })}>
{ sortedEntries.map((item, idx) => this.renderEntry(idx, item)) }
</ul>
{ (sortedEntries.length > 0) ? (
<ul className={classnames('entries', { 'big': !tabIsSnoozable })}>
{ sortedEntries.map((item, idx) => this.renderEntry(idx, item)) }
</ul>
) : (
<div className="empty-entries">
<div className="icon">
<img src="../icons/bell_icon.svg" width="64" height="64" />
</div>
<div className="message">No upcoming snoozes</div>
</div>
)}
<div className={classnames('footer', { 'hide': !tabIsSnoozable })}>
<div className="back" onClick={ () => switchPanel('main') }><span>« Back</span></div>
</div>
Expand Down
8 changes: 5 additions & 3 deletions src/lib/components/SnoozePopup.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React from 'react';

import classnames from 'classnames';

import MainPanel from './MainPanel';
import ManagePanel from './ManagePanel';

export default class SnoozePopup extends React.Component {
render() {
const { activePanel } = this.props;
const { activePanel, tabIsSnoozable, narrowPopup } = this.props;
return (
<div>
<MainPanel {...this.props} id="main" active={'main' === activePanel} />
<div className={classnames('panel-wrapper', { 'popup-narrow': narrowPopup })}>
{tabIsSnoozable && <MainPanel {...this.props} id="main" active={'main' === activePanel} />}
<ManagePanel {...this.props} id="manage" active={'manage' === activePanel} />
</div>
);
Expand Down
12 changes: 6 additions & 6 deletions src/lib/times.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,27 @@ export function timeForId(time, id) {
switch (id) {
case 'debug':
rv = rv.add(5, 'seconds');
text = rv.format('[@]ha');
text = rv.format('[@] ha');
break;
case 'later':
rv = rv.add(3, 'hours');
text = rv.format('[@]ha');
text = rv.format('[@] ha');
break;
case 'tomorrow':
rv = rv.add(1, 'day').hour(9);
text = rv.format('ddd [@]ha');
text = rv.format('ddd [@] ha');
break;
case 'weekend':
rv = rv.day(6).hour(9);
text = rv.format('ddd [@]ha');
text = rv.format('ddd [@] ha');
break;
case 'week':
rv = rv.add(1, 'week').hour(9);
text = rv.format('ddd MMM D \ [@]ha');
text = rv.format('ddd MMM D \ [@] ha');
break;
case 'month':
rv = rv.add(1, 'month').hour(9);
text = rv.format('ddd MMM D \ [@]ha');
text = rv.format('ddd MMM D \ [@] ha');
break;
case NEXT_OPEN:
rv = NEXT_OPEN;
Expand Down
Binary file added src/popup/FiraSans-Regular.woff
Binary file not shown.
31 changes: 27 additions & 4 deletions src/popup/snooze-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ import React from 'react';
import ReactDOM from 'react-dom';
import SnoozePopup from '../lib/components/SnoozePopup';

// HACK: Arbitrary value found by measuring menu panel popup width
const NARROW_PANEL_MIN_WIDTH = 225;

const DEBUG = (process.env.NODE_ENV === 'development');

let state = {
activePanel: 'main',
tabIsSnoozable: true,
entries: [
{ title: 'foo', url: 'http://qz.com', date: Date.now() }
]
narrowPopup: false,
entries: []
};

function setState(data) {
Expand Down Expand Up @@ -139,13 +141,34 @@ function fetchEntries() {
});
}

// Resize handler that lets us switch styles & rendering when the popup is
// summoned from the toolbar versus from the menu panel. Toolbar size is based
// on content size, menu panel body size is forcibly fixed.
function setupResizeHandler() {
const handler = () => {
const clientWidth = document.body.clientWidth;
if (clientWidth === 0) { return; }

const newNarrowPopup = (clientWidth < NARROW_PANEL_MIN_WIDTH);
log('resize', clientWidth, state.narrowPopup, newNarrowPopup);

if (newNarrowPopup !== state.narrowPopup) {
setState({ narrowPopup: newNarrowPopup });
}
};
handler();
window.addEventListener('resize', handler);
}

function init() {
log('init');
setupResizeHandler();
render();
browser.storage.onChanged.addListener((changes, area) => {
// TODO: granularly apply the changes, rather than triggering a refresh?
if (area === 'local') { fetchEntries(); }
});
fetchEntries();
render();
browser.runtime.sendMessage({ op: 'panelOpened' });
}

Expand Down
Loading

0 comments on commit db493c4

Please sign in to comment.