Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(navbar): Add themepicker component with lazy loaded themes #136

Merged
merged 1 commit into from
Jun 15, 2017

Conversation

riavalon
Copy link
Contributor

@riavalon riavalon commented Mar 23, 2017

Picking up the theme picker feature from where it was left off.

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pulled this down and tried it out- this is a good start!

Let's keep this PR scoped as-is but omit the theme-picker from the navbar until we get these follow-ups done:

  • Show the currently selected theme in the picker (similar to fonts.google.com)
  • Use inline SVGs instead of img / background-image so that we can manipulate their colors (could use md-icon for this).
  • Fix text and background color on all pages when switching to a dark theme
  • Remember selected theme in local storage (including updating on change)
  • Load different highlight.js files based on whether we're in a light or dark theme

* @param key The key for the slot whose element we want.
* @param create Whether to create the element if it doesn't exist.
* @returns {HTMLLinkElement} The `<link.` element.
* @private
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omit @private and type information from JsDoc since that's captured in the TypeScript code.

document.head.appendChild(linkEl);
}
return linkEl as HTMLLinkElement;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than having one function perform two behaviors with an option, I generally prefer breaking it up into separate functions. Also, most of these can be module-level functions since they are pure functions, e.g.

class StyleManager {
  setStyle(key: string, href: string) {
    getLinkElementForKey(key).setAttribute('href', href);
  }

  removeStyle(key: string) {
    const existingLinkElement = getExistingLinkElementByKey(key);
    if (existingLinkElement) {
      document.head.removeChild(existingLinkElement);
    }
  }
}

function getLinkElementForKey(key: string) {
  return getExistingLinkElementByKey(key) || createLinkElementWithKey(key);
}

function getExistingLinkElementByKey(key: string) {
  return document.head.querySelector(`link[rel="stylesheet"].${getClassNameForKey(key)}`);
}

function createLinkElementWithKey(key: string) {
  const linkEl = document.createElement('link');
  linkEl.setAttribute('rel', 'stylesheet');
  linkEl.classList.add(getClassNameForKey(key));
  document.head.appendChild(linkEl);

  return linkEl;
}

function getClassNameForKey(key: string) {
  return `style-manager-${key}`;
}

$theme-chooser-accent-stripe-size: 6px;


.theme-chooser-menu {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefix css classes with docs-

import {Component, ViewEncapsulation, ChangeDetectionStrategy} from '@angular/core';
import {StyleManager} from '../style-manager/style-manager';

@Component({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make the theme chooser aria-hidden="true" and ensure that the button is not in the tab order since a screen-reader user won't get any benefit from changing the app colors.

{
primary: '#673AB7',
accent: '#FFC107',
href: 'assets/deeppurple-amber.css'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should omit assets/ on each entry and add it in the function call.

{"input": "assets/pink-bluegrey.css", "lazy": true},
{"input": "assets/deeppurple-amber.css", "lazy": true},
{"input": "assets/indigo-pink.css", "lazy": true},
{"input": "assets/purple-green.css", "lazy": true}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these be referenced directly from node_modules rather than copying them to assets?


.theme-chooser-accent {
position: absolute;
bottom: $theme-chooser-accent-stripe-size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you feel about the accent stripe? I'm not particularly fond of it.

@riavalon riavalon force-pushed the theme-picker branch 3 times, most recently from 46e1553 to 74eb084 Compare April 13, 2017 17:24
@riavalon riavalon force-pushed the theme-picker branch 4 times, most recently from d586c1e to f9b7669 Compare April 24, 2017 15:05
@riavalon riavalon force-pushed the theme-picker branch 4 times, most recently from 9dcc56b to 1cfa71f Compare April 26, 2017 15:59
@riavalon riavalon force-pushed the theme-picker branch 3 times, most recently from ee4b628 to db8f833 Compare May 26, 2017 18:22
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled down the PR and tried it out- looks great!

Footer,
],
schemas: [
CUSTOM_ELEMENTS_SCHEMA,
Copy link
Member

@jelbourn jelbourn May 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CUSTOM_ELEMENTS_SCHEMA ideally shouldn't be here; why was this needed?

@@ -44,10 +54,12 @@ import {ComponentPageHeader} from './pages/component-page-header/component-page-
MaterialModule,
MdNativeDateModule,
routing,
InlineSVGModule,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InlineSvgModule (camelCase even for acronyms)

@@ -1,6 +1,8 @@
import {Component, ViewEncapsulation} from '@angular/core';
import {Router, NavigationStart} from '@angular/router';

// import {ThemeStorage} from './shared/theme-chooser/theme-storage/theme-storage';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented line


// public _setIsDarkTheme(theme) {
// this.isDarkTheme = theme ? theme.isDark : this.isDarkTheme;
// }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented code

background-size: contain;
background-repeat: no-repeat;
background-position: center;
:host /deep/ .docs-component-category-list-card-image svg {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid /deep/ completely, instead preferring to add a global style (or, barring that, turning off view encapsulation for the component)

const Color = require('color');


export interface IThemeColors {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We prefer not to prefix interfaces with I (here and elsewhere)


import {IDocsSiteTheme} from '../theme-chooser/theme-storage/theme-storage';

const Color = require('color');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this require doing here?


public ngAfterViewInit() {
if (this.currTheme) {
setTimeout(this.swapTheme.bind(this, this.currTheme));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer arrow functions to using bind

<div class="docs-theme-chooser-swatch">
<md-icon class="docs-theme-chosen-icon" *ngIf="currentTheme === theme">check_circle</md-icon>
<div class="docs-theme-chooser-primary" [style.background]="theme.primary"></div>
<!--<div class="docs-theme-chooser-accent" [style.background]="theme.accent"></div>-->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented code

<md-icon>format_color_fill</md-icon>
</button>

<md-menu class="docs-theme-chooser-menu" #themeMenu="mdMenu" x-position="before">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a TODO here like

<!-- TODO: replace use of `md-menu` here with a custom overlay -->

@riavalon riavalon force-pushed the theme-picker branch 3 times, most recently from 798538e to 1649a41 Compare June 6, 2017 19:39
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn merged commit f5478ed into angular:master Jun 15, 2017
@Splaktar Splaktar mentioned this pull request Jul 10, 2017
@masonlr
Copy link

masonlr commented Mar 1, 2019

@jelbourn I'm looking at theme-picker.ts and can't see how the default theme (isDefault: true property in themes) is honoured when you first load the page.

installTheme() is called from the constructor with a theme argument if there is a theme in local storage or a theme is supplied by query parameters (otherwise it's called with a null argument). If it's the first time you're visiting the page, neither of these may be present.

Am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants