Skip to content

Commit

Permalink
[NTP][Panorama] Show which category is currently selected
Browse files Browse the repository at this point in the history
Adds customize-chrome-check-mark-wrapper around each category to add a border and check mark to the category/type of the currently selected theme.

There is no selection state for the chrome web store tile so that is the only tile on the page that was left out of this change.

Also, added FocusOutlineManager so that the focus outline only shows with keyboard navigation.

screenshots:
large icon: screenshot/C3hsFmnSWZusWj3
small icon: screenshot/4qfishgTQpLm6TB

Bug: 1403334, 1402972
Change-Id: I928709d7d7c1de039264db6bc8081a5d9613886c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4196336
Reviewed-by: Tibor Goldschwendt <tiborg@chromium.org>
Reviewed-by: Paul Adedeji <pauladedeji@google.com>
Commit-Queue: Riley Tatum <rtatum@google.com>
Cr-Commit-Position: refs/heads/main@{#1098216}
  • Loading branch information
Riley Tatum authored and Chromium LUCI CQ committed Jan 28, 2023
1 parent 2b0976c commit 04d84bb
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 28 deletions.
Expand Up @@ -33,10 +33,6 @@
place-self: stretch;
}

.tile:focus {
box-shadow: 0 0 0 2px var(--cr-focus-outline-color);
}

.image-container {
background-color: var(--google-grey-100);
overflow: hidden;
Expand Down Expand Up @@ -147,6 +143,27 @@
transform: translate(-50%, -50%);
width: 32px;
}

.tile:nth-child(-n+4) customize-chrome-check-mark-wrapper {
--customize-chrome-check-mark-wrapper-end: -6px;
--customize-chrome-check-mark-wrapper-size: 24px;
--customize-chrome-check-mark-wrapper-top: -9px;
}

.tile customize-chrome-check-mark-wrapper {
--customize-chrome-check-mark-wrapper-end: -4px;
--customize-chrome-check-mark-wrapper-size: 20px;
--customize-chrome-check-mark-wrapper-top: -6px;
}

customize-chrome-check-mark-wrapper[checked] .image-container {
padding-top: calc(100% - 4px);
width: calc(100% - 4px);
}

:host-context(.focus-outline-visible) .tile:focus {
box-shadow: 0 0 0 2px var(--cr-focus-outline-color);
}
</style>
<div id="headerContainer">
<cr-icon-button on-click="onBackClick_" id="backButton"
Expand All @@ -156,36 +173,52 @@ <h1>$i18n{categoriesHeader}</h1>
</div>
<cr-grid columns="6">
<div class="tile" tabindex="0" id="classicChromeTile"
role="button" on-click="onClassicChromeClick_">
<div class="image-container">
<img id="miniNewTabPage" src="icons/corner_new_tab_page.svg"></img>
</div>
role="button" on-click="onClassicChromeClick_"
aria-checked$="[[isClassicChromeSelected_]]">
<customize-chrome-check-mark-wrapper
checked="[[isClassicChromeSelected_]]">
<div class="image-container">
<img id="miniNewTabPage" src="icons/corner_new_tab_page.svg"></img>
</div>
</customize-chrome-check-mark-wrapper>
<div class="label">$i18n{classicChrome}</div>
</div>
<div class="tile" tabindex="0" id="uploadImageTile"
role="button" on-click="onUploadImageClick_">
<div class="image-container">
<div id="uploadIcon" class="cr-icon"></div>
</div>
role="button" on-click="onUploadImageClick_"
aria-checked$="[[isLocalImageSelected_]]">
<customize-chrome-check-mark-wrapper
checked="[[isLocalImageSelected_]]">
<div class="image-container">
<div id="uploadIcon" class="cr-icon"></div>
</div>
</customize-chrome-check-mark-wrapper>
<div class="label">$i18n{uploadImage}</div>
</div>
<div class="tile" tabindex="0" id="chromeColorsTile"
role="button" on-click="onChromeColorsClick_">
<div class="image-container">
<div class="chrome-color"></div>
<div class="chrome-color"></div>
</div>
role="button" on-click="onChromeColorsClick_"
aria-checked$="[[isChromeColorsSelected_]]">
<customize-chrome-check-mark-wrapper
checked="[[isChromeColorsSelected_]]">
<div class="image-container">
<div class="chrome-color"></div>
<div class="chrome-color"></div>
</div>
</customize-chrome-check-mark-wrapper>
<div class="label">$i18n{chromeColors}</div>
</div>
<template is="dom-repeat" id="collectionsRepeat" items="[[collections_]]">
<div class="tile collection" tabindex="0" role="button"
on-click="onCollectionClick_">
<div class="image-container">
<img is="cr-auto-img"
auto-src="[[item.previewImageUrl.url]]"
draggable="false">
</img>
</div>
on-click="onCollectionClick_"
aria-checked$="[[isCollectionSelected_(item.id, selectedCategory_)]]">
<customize-chrome-check-mark-wrapper
checked="[[isCollectionSelected_(item.id, selectedCategory_)]]">
<div class="image-container">
<img is="cr-auto-img"
auto-src="[[item.previewImageUrl.url]]"
draggable="false">
</img>
</div>
</customize-chrome-check-mark-wrapper>
<div class="label">[[item.label]]</div>
</div>
</template>
Expand Down
95 changes: 93 additions & 2 deletions chrome/browser/resources/side_panel/customize_chrome/categories.ts
Expand Up @@ -6,13 +6,28 @@ import 'chrome://resources/cr_elements/cr_hidden_style.css.js';
import 'chrome://resources/cr_elements/cr_grid/cr_grid.js';
import 'chrome://resources/cr_elements/cr_icons.css.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
import './check_mark_wrapper.js';

import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js';
import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {getTemplate} from './categories.html.js';
import {BackgroundCollection, CustomizeChromePageHandlerInterface} from './customize_chrome.mojom-webui.js';
import {BackgroundCollection, CustomizeChromePageHandlerInterface, Theme} from './customize_chrome.mojom-webui.js';
import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js';

export enum CategoryType {
NONE,
CLASSIC,
LOCAL,
COLOR,
COLLECTION,
}

export interface SelectedCategory {
type: CategoryType;
collectionId?: string;
}

export interface CategoriesElement {
$: {
backButton: HTMLElement,
Expand All @@ -35,10 +50,30 @@ export class CategoriesElement extends PolymerElement {
static get properties() {
return {
collections_: Array,
theme_: Object,
selectedCategory_: {
type: Object,
computed: 'computeSelectedCategory_(theme_, collections_)',
},
isClassicChromeSelected_: {
type: Boolean,
computed: 'computeIsClassicChromeSelected_(selectedCategory_)',
},
isLocalImageSelected_: {
type: Boolean,
computed: 'computeIsLocalImageSelected_(selectedCategory_)',
},
isChromeColorsSelected_: {
type: Boolean,
computed: 'computeIsChromeColorsSelected_(selectedCategory_)',
},
};
}

private collections_: BackgroundCollection[];
private selectedCategory_: SelectedCategory;
private theme_: Theme;
private setThemeListenerId_: number|null = null;

private pageHandler_: CustomizeChromePageHandlerInterface;

Expand All @@ -50,9 +85,65 @@ export class CategoriesElement extends PolymerElement {
});
}

override connectedCallback() {
super.connectedCallback();
this.setThemeListenerId_ =
CustomizeChromeApiProxy.getInstance()
.callbackRouter.setTheme.addListener((theme: Theme) => {
this.theme_ = theme;
});
this.pageHandler_.updateTheme();
FocusOutlineManager.forDocument(document);
}

override disconnectedCallback() {
super.disconnectedCallback();
CustomizeChromeApiProxy.getInstance().callbackRouter.removeListener(
this.setThemeListenerId_!);
}

private computeSelectedCategory_() {
if (!this.theme_) {
return {type: CategoryType.NONE};
}
if (!this.theme_.backgroundImage) {
if (!this.theme_.foregroundColor) {
return {type: CategoryType.CLASSIC};
}
return {type: CategoryType.COLOR};
}
if (this.theme_.backgroundImage.isUploadedImage) {
return {type: CategoryType.LOCAL};
}
if (this.theme_.backgroundImage.collectionId) {
return {
type: CategoryType.COLLECTION,
collectionId: this.theme_.backgroundImage.collectionId,
};
}
return {type: CategoryType.NONE};
}

private computeIsClassicChromeSelected_() {
return this.selectedCategory_.type === CategoryType.CLASSIC;
}

private computeIsLocalImageSelected_() {
return this.selectedCategory_.type === CategoryType.LOCAL;
}

private computeIsChromeColorsSelected_() {
return this.selectedCategory_.type === CategoryType.COLOR;
}

private isCollectionSelected_(id: string) {
return this.selectedCategory_.type === CategoryType.COLLECTION &&
this.selectedCategory_.collectionId === id;
}

private onClassicChromeClick_() {
this.pageHandler_.removeBackgroundImage();
this.pageHandler_.setDefaultColor();
this.pageHandler_.removeBackgroundImage();
}

private async onUploadImageClick_() {
Expand Down
Expand Up @@ -6,13 +6,14 @@ import 'chrome://webui-test/mojo_webui_test_support.js';
import 'chrome://customize-chrome-side-panel.top-chrome/categories.js';

import {CategoriesElement} from 'chrome://customize-chrome-side-panel.top-chrome/categories.js';
import {BackgroundCollection, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js';
import {BackgroundCollection, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js';
import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js';
import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
import {eventToPromise} from 'chrome://webui-test/test_util.js';

import {installMock} from './test_support.js';
import {createBackgroundImage, createTheme, installMock} from './test_support.js';

function createTestCollections(length: number): BackgroundCollection[] {
const testCollections: BackgroundCollection[] = [];
Expand All @@ -29,6 +30,7 @@ function createTestCollections(length: number): BackgroundCollection[] {
suite('CategoriesTest', () => {
let categoriesElement: CategoriesElement;
let handler: TestBrowserProxy<CustomizeChromePageHandlerRemote>;
let callbackRouterRemote: CustomizeChromePageRemote;

async function setInitialSettings(numCollections: number) {
handler.setResultFor('getBackgroundCollections', Promise.resolve({
Expand All @@ -46,6 +48,8 @@ suite('CategoriesTest', () => {
(mock: CustomizeChromePageHandlerRemote) =>
CustomizeChromeApiProxy.setInstance(
mock, new CustomizeChromePageCallbackRouter()));
callbackRouterRemote = CustomizeChromeApiProxy.getInstance()
.callbackRouter.$.bindNewPipeAndPassRemote();
});

test('hide collection elements when collections empty', async () => {
Expand Down Expand Up @@ -123,4 +127,61 @@ suite('CategoriesTest', () => {
const event = await eventPromise;
assertTrue(!!event);
});

test('checks selected category', async () => {
await setInitialSettings(2);

// Set an empty theme with no color and no background.
const theme = createTheme();
callbackRouterRemote.setTheme(theme);
await callbackRouterRemote.$.flushForTesting();
await waitAfterNextRender(categoriesElement);

// Check that classic chrome is selected.
let checkedCategories =
categoriesElement.shadowRoot!.querySelectorAll('[checked]');
assertEquals(1, checkedCategories.length);
assertEquals(checkedCategories[0]!.parentElement!.id, 'classicChromeTile');

// Set a theme with a color.
theme.foregroundColor = {value: 0xffff0000};
callbackRouterRemote.setTheme(theme);
await callbackRouterRemote.$.flushForTesting();
await waitAfterNextRender(categoriesElement);

// Check that chrome colors is selected.
checkedCategories =
categoriesElement.shadowRoot!.querySelectorAll('[checked]');
assertEquals(1, checkedCategories.length);
assertEquals(checkedCategories[0]!.parentElement!.id, 'chromeColorsTile');

// Set a theme with local background.
const backgroundImage = createBackgroundImage('https://test.jpg');
backgroundImage.isUploadedImage = true;
theme.backgroundImage = backgroundImage;
callbackRouterRemote.setTheme(theme);
await callbackRouterRemote.$.flushForTesting();
await waitAfterNextRender(categoriesElement);

// Check that upload image is selected.
checkedCategories =
categoriesElement.shadowRoot!.querySelectorAll('[checked]');
assertEquals(1, checkedCategories.length);
assertEquals(checkedCategories[0]!.parentElement!.id, 'uploadImageTile');

// Set a theme with collection background.
backgroundImage.isUploadedImage = false;
backgroundImage.collectionId = '2';
theme.backgroundImage = backgroundImage;
callbackRouterRemote.setTheme(theme);
await callbackRouterRemote.$.flushForTesting();
await waitAfterNextRender(categoriesElement);

// Check that collection is selected.
checkedCategories =
categoriesElement.shadowRoot!.querySelectorAll('[checked]');
assertEquals(1, checkedCategories.length);
assertEquals(
checkedCategories[0]!.parentElement!.className, 'tile collection');
});
});

0 comments on commit 04d84bb

Please sign in to comment.