profile
viewpoint
Max Yinger littlemilkstudio Formidable Labs Fort Collins, CO https://littlemilk.studio Frontend Developer

google/web-stories-wp 173

Web Stories WordPress plugin

littlemilkstudio/input-smoothing-demo 6

🐌 An Exploration in Input Smoothing.

Limlight86/Restaurant 0

Mock Fast food menu - ReactJS

littlemilkstudio/extra-normal 0

⏲ Declarative timelines for animating pure values.

littlemilkstudio/fond 0

[Old] React, WP, Docker, Webpack Starter Kit

littlemilkstudio/littlemilk-frontend 0

Front end for littlemilk.studio

Pull request review commentgoogle/web-stories-wp

Dashboard: My Stories View Karma Tests

 const ToggleButtonGroup = ({ buttons }) => {      const resizeContainerObserver = new ResizeObserver((entries) => {       entries.forEach((entry) => {-        if (entry.contentRect.width !== containerWidth) {-          setContainerWidth(entry.contentRect.width);-        }+        // window.requestAnimationFrame removes potential for ResizeObserver - loop limit exceeded error+        // see https://stackoverflow.com/a/50387233/13078978

Woah. super cool and good to know

dmmulroy

comment created time in a day

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha c930463b8886c931b476dd591c60b9b161e98bd6

remove trailing space on mask paths

view details

push time in 11 days

Pull request review commentgoogle/web-stories-wp

Shapes: Add new shapes to library

 export const MASKS = [     ratio: 1.15473441108545,   },   {-    type: MaskTypes.BLOB,-    name: __('Blob', 'web-stories'),-    path: CLIP_PATHS[MaskTypes.BLOB],+    type: MaskTypes.BLOB_1,+    name: __('Blob 1', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_1],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_2,+    name: __('Blob 2', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_2],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_3,+    name: __('Blob 3', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_3],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_4,+    name: __('Blob 4', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_4],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_5,+    name: __('Blob 5', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_5],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_6,+    name: __('Blob 6', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_6],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_7,+    name: __('Blob 7', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_7],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_8,+    name: __('Blob 8', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_8],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_9,+    name: __('Blob 9', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_9],+    iconPath: ICON_CLIP_PATHS[MaskTypes.BLOB_9],+    ratio: 653.02 / 836.92,+    iconRatio: 1,+  },+  {+    type: MaskTypes.GRID_2,+    name: __('Grid 2', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.GRID_2],+    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_2],+    ratio: 362 / 619,+    iconRatio: 1,+  },+  {+    type: MaskTypes.GRID_3,+    name: __('Grid 3', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.GRID_3],+    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_3],+    ratio: 360.8 / 619,+    iconRatio: 1,

No we're not showing skewed icons, but we have a separate icon ratio for icons we wanna draw relative to a 0-1 square. this allows us to visually balance the icons better while still having the paths in the editor be hugged by the transform box.

Again, I think this is a temporary work around until we can play with this more after beta. With complex shapes it makes sense that they need to altered to be visible & look nice as icons. We can come up with a more elegant way to do this down the line that alters this component more drastically after beta, but this is quick and fits within our existing system for now.

littlemilkstudio

comment created time in 11 days

Pull request review commentgoogle/web-stories-wp

Shapes: Add new shapes to library

 export const MASKS = [     ratio: 1.15473441108545,   },   {-    type: MaskTypes.BLOB,-    name: __('Blob', 'web-stories'),-    path: CLIP_PATHS[MaskTypes.BLOB],+    type: MaskTypes.BLOB_1,+    name: __('Blob 1', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_1],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_2,+    name: __('Blob 2', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_2],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_3,+    name: __('Blob 3', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_3],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_4,+    name: __('Blob 4', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_4],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_5,+    name: __('Blob 5', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_5],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_6,+    name: __('Blob 6', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_6],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_7,+    name: __('Blob 7', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_7],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_8,+    name: __('Blob 8', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_8],+    ratio: 1,+  },+  {+    type: MaskTypes.BLOB_9,+    name: __('Blob 9', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.BLOB_9],+    iconPath: ICON_CLIP_PATHS[MaskTypes.BLOB_9],+    ratio: 653.02 / 836.92,+    iconRatio: 1,+  },+  {+    type: MaskTypes.GRID_2,+    name: __('Grid 2', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.GRID_2],+    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_2],+    ratio: 362 / 619,+    iconRatio: 1,+  },+  {+    type: MaskTypes.GRID_3,+    name: __('Grid 3', 'web-stories'),+    path: CLIP_PATHS[MaskTypes.GRID_3],+    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_3],+    ratio: 360.8 / 619,

So the reason we have two separate ones here are because we have no notion of strokes in clip paths. because of this when we have an item that has a 1px stroke and is 620px tall, it's stroke in the shapes panel ends up being:

(1px / 620px) * 36px

This makes the stroke invisible to nearly invisible at this size, so to combat this, we have a separate icon path that has a thicker stroke baked in, so that it's visible at an icon size.

I see us eventually getting rid of this when if/when we start handling more of the svg spec in the editor instead of just clip-paths, but this is a necessary workaround to get this working and not adding new features before beta

littlemilkstudio

comment created time in 11 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha e8361aede2af46d0c5f4e84e6e38e9c3cd6f1efb

updated normalized paths to fit object

view details

push time in 11 days

push eventgoogle/web-stories-wp

Carlos Kelly

commit sha 9c24ffc3f3c642d9d457aa02fb697b5c8b45d2ac

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 7da4a6931689b420c828894468df69122b83c5df

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha 803f2ebf20a408ab9235e711fcef528024392c2e

Added search to font picker.

view details

Carlos Kelly

commit sha 2ab9170d71f0e08b48128433a2cd70bb308f960c

Fixed props and updated input type

view details

Carlos Kelly

commit sha 654ec4ee85aa7f62f44a412b7891bcaf605a1f46

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha ba476d3c577823d011e28c99368e220820cf6902

Remove unused useMemo

view details

Carlos Kelly

commit sha 566155fff734b4106d3ad24e4a505d0c193b6b18

Fix tests for new debounced callback

view details

Carlos Kelly

commit sha d110efa76b0d75b8d849a38e20718f6d3444205e

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 4c631ea51099c874e9d370c7a04ccf349d2ab196

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha a8b197c360144df4cfca287eaf968402b5740df5

Added search to font picker.

view details

Carlos Kelly

commit sha 8904c9eaab044ba75f3629fed0d265553b3878ec

Fixed props and updated input type

view details

Carlos Kelly

commit sha 0e318ad43016965eb6addd0e154cb2e363af3089

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha a5c0fa05f48b8e681e77ab61987c0db9962df152

Fixed font loading, Added Esc test.

view details

Carlos Kelly

commit sha 3d3d667a736571d3c7975d6e07e8ca4ed1c6f904

Focus search input on font picker open.

view details

Carlos Kelly

commit sha 50de7ea492667a6c198bd14fd1e8d79dd5fb6217

Open picker using ArrowDown when focused.

view details

Carlos Kelly

commit sha 7f486b99dd817b2fee1b9c023bb5faca43f131cf

Adding dialog role to prevent double-key events.

view details

Dima Voytenko

commit sha 6ff7f8b342ced1b797226e667756d7f0ed339f98

Test Percy

view details

Miina Sikk

commit sha 5d9cb3e173a35abe44892eb2053734694d59ddeb

Use correct icons for radios.

view details

Diego Varese

commit sha 03b9e193cfffa6147a4f50ff98ddbb34ba619d51

Add media3p pane This refactors a bit how which panes are shown is determined.

view details

Miina Sikk

commit sha d729d8d0e58b432184a4f6046a109ba1e89e4a88

Restore mousetrap to address it separately.

view details

push time in 11 days

push eventgoogle/web-stories-wp

Carlos Kelly

commit sha 9c24ffc3f3c642d9d457aa02fb697b5c8b45d2ac

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 7da4a6931689b420c828894468df69122b83c5df

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha 803f2ebf20a408ab9235e711fcef528024392c2e

Added search to font picker.

view details

Carlos Kelly

commit sha 2ab9170d71f0e08b48128433a2cd70bb308f960c

Fixed props and updated input type

view details

Carlos Kelly

commit sha 654ec4ee85aa7f62f44a412b7891bcaf605a1f46

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha ba476d3c577823d011e28c99368e220820cf6902

Remove unused useMemo

view details

Carlos Kelly

commit sha 566155fff734b4106d3ad24e4a505d0c193b6b18

Fix tests for new debounced callback

view details

Carlos Kelly

commit sha d110efa76b0d75b8d849a38e20718f6d3444205e

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 4c631ea51099c874e9d370c7a04ccf349d2ab196

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha a8b197c360144df4cfca287eaf968402b5740df5

Added search to font picker.

view details

Carlos Kelly

commit sha 8904c9eaab044ba75f3629fed0d265553b3878ec

Fixed props and updated input type

view details

Carlos Kelly

commit sha 0e318ad43016965eb6addd0e154cb2e363af3089

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha a5c0fa05f48b8e681e77ab61987c0db9962df152

Fixed font loading, Added Esc test.

view details

Carlos Kelly

commit sha 3d3d667a736571d3c7975d6e07e8ca4ed1c6f904

Focus search input on font picker open.

view details

Carlos Kelly

commit sha 50de7ea492667a6c198bd14fd1e8d79dd5fb6217

Open picker using ArrowDown when focused.

view details

Carlos Kelly

commit sha 7f486b99dd817b2fee1b9c023bb5faca43f131cf

Adding dialog role to prevent double-key events.

view details

Dima Voytenko

commit sha 6ff7f8b342ced1b797226e667756d7f0ed339f98

Test Percy

view details

Miina Sikk

commit sha 5d9cb3e173a35abe44892eb2053734694d59ddeb

Use correct icons for radios.

view details

Diego Varese

commit sha 03b9e193cfffa6147a4f50ff98ddbb34ba619d51

Add media3p pane This refactors a bit how which panes are shown is determined.

view details

Miina Sikk

commit sha d729d8d0e58b432184a4f6046a109ba1e89e4a88

Restore mousetrap to address it separately.

view details

push time in 11 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 69ebc4f122345080cfa9bfd70f518761fb9d27ab

wip

view details

Maxwell Yinger

commit sha 1f69d40384fe81ba9edae134ce83e1f9fe52e06d

wip

view details

Maxwell Yinger

commit sha f9a59ffb25c11ef75c63ad1d12a6f50a79a98b2d

added all given masks

view details

Maxwell Yinger

commit sha 497280addf8e4ba6d0a9891d050e9edb9657f230

fix merge conflict regressions

view details

push time in 11 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha c130774991e45c1c9555298010a56df8c07307f6

initial fitness update

view details

Maxwell Yinger

commit sha 369b75b5f94270be6c64256a03920d50532e5039

add proper bg pictures

view details

push time in 11 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 2438dc621b697244642d33f4fdfd007d6213a882

Revert "Dashboard: Applied design updates to Travel template" This reverts commit 93abdc2f05266a8c083a06dc5f073f5cb604222a.

view details

push time in 11 days

push eventgoogle/web-stories-wp

Carlos Kelly

commit sha 9c24ffc3f3c642d9d457aa02fb697b5c8b45d2ac

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 7da4a6931689b420c828894468df69122b83c5df

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha 803f2ebf20a408ab9235e711fcef528024392c2e

Added search to font picker.

view details

Carlos Kelly

commit sha 2ab9170d71f0e08b48128433a2cd70bb308f960c

Fixed props and updated input type

view details

Carlos Kelly

commit sha 654ec4ee85aa7f62f44a412b7891bcaf605a1f46

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha ba476d3c577823d011e28c99368e220820cf6902

Remove unused useMemo

view details

Carlos Kelly

commit sha 566155fff734b4106d3ad24e4a505d0c193b6b18

Fix tests for new debounced callback

view details

Carlos Kelly

commit sha d110efa76b0d75b8d849a38e20718f6d3444205e

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 4c631ea51099c874e9d370c7a04ccf349d2ab196

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha a8b197c360144df4cfca287eaf968402b5740df5

Added search to font picker.

view details

Carlos Kelly

commit sha 8904c9eaab044ba75f3629fed0d265553b3878ec

Fixed props and updated input type

view details

Carlos Kelly

commit sha 0e318ad43016965eb6addd0e154cb2e363af3089

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha a5c0fa05f48b8e681e77ab61987c0db9962df152

Fixed font loading, Added Esc test.

view details

Carlos Kelly

commit sha 3d3d667a736571d3c7975d6e07e8ca4ed1c6f904

Focus search input on font picker open.

view details

Carlos Kelly

commit sha 50de7ea492667a6c198bd14fd1e8d79dd5fb6217

Open picker using ArrowDown when focused.

view details

Carlos Kelly

commit sha 7f486b99dd817b2fee1b9c023bb5faca43f131cf

Adding dialog role to prevent double-key events.

view details

Dima Voytenko

commit sha 6ff7f8b342ced1b797226e667756d7f0ed339f98

Test Percy

view details

Miina Sikk

commit sha 095b146b1c19f678b68cd715010e824c9ed17943

Display whiteout on text and only when it's not Fill.

view details

Miina Sikk

commit sha bb1a1dad6f1460b2f777294b6ebd880552df5cb9

Revert fill logic.

view details

Pascal Birchler

commit sha 16d6de99e50b0dd2b466f66e899a90dce6e03207

Add uninstall.php file

view details

push time in 11 days

push eventgoogle/web-stories-wp

Mariano Martinez III

commit sha a234006a5e8c40cf920b9bcb3bf49890e0f1e07f

Dashboard: Applied design updates to Travel template

view details

Maxwell Yinger

commit sha f804a5dc4c73ec4eaef5e29f5a5b6f5dfb1cdc6f

wip

view details

Maxwell Yinger

commit sha 8853f25ba80e6ac0b6d285e759df8b435a9cd4ab

wip

view details

Maxwell Yinger

commit sha 07bf6bc745f5fc0b22dee31d67e34a43cb2aa103

added all given masks

view details

Maxwell Yinger

commit sha 370008d826e1f6e8118d49f243942f6bcc06c604

fix merge conflict regressions

view details

push time in 11 days

push eventgoogle/web-stories-wp

Carlos Kelly

commit sha 9c24ffc3f3c642d9d457aa02fb697b5c8b45d2ac

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 7da4a6931689b420c828894468df69122b83c5df

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha 803f2ebf20a408ab9235e711fcef528024392c2e

Added search to font picker.

view details

Carlos Kelly

commit sha 2ab9170d71f0e08b48128433a2cd70bb308f960c

Fixed props and updated input type

view details

Carlos Kelly

commit sha 654ec4ee85aa7f62f44a412b7891bcaf605a1f46

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha ba476d3c577823d011e28c99368e220820cf6902

Remove unused useMemo

view details

Carlos Kelly

commit sha 566155fff734b4106d3ad24e4a505d0c193b6b18

Fix tests for new debounced callback

view details

Carlos Kelly

commit sha d110efa76b0d75b8d849a38e20718f6d3444205e

Add Keyboard Events to New Font Picker Remove unused import.

view details

Carlos Kelly

commit sha 4c631ea51099c874e9d370c7a04ccf349d2ab196

Remove tabbing for navigating fonts.

view details

Carlos Kelly

commit sha a8b197c360144df4cfca287eaf968402b5740df5

Added search to font picker.

view details

Carlos Kelly

commit sha 8904c9eaab044ba75f3629fed0d265553b3878ec

Fixed props and updated input type

view details

Carlos Kelly

commit sha 0e318ad43016965eb6addd0e154cb2e363af3089

Add aria props and debounce callback.

view details

Carlos Kelly

commit sha a5c0fa05f48b8e681e77ab61987c0db9962df152

Fixed font loading, Added Esc test.

view details

Carlos Kelly

commit sha 3d3d667a736571d3c7975d6e07e8ca4ed1c6f904

Focus search input on font picker open.

view details

Carlos Kelly

commit sha 50de7ea492667a6c198bd14fd1e8d79dd5fb6217

Open picker using ArrowDown when focused.

view details

Carlos Kelly

commit sha 7f486b99dd817b2fee1b9c023bb5faca43f131cf

Adding dialog role to prevent double-key events.

view details

Pascal Birchler

commit sha 16d6de99e50b0dd2b466f66e899a90dce6e03207

Add uninstall.php file

view details

Pascal Birchler

commit sha a29db0bc724226195a64aae11669b175335904c6

Merge branch 'master' into add/uninstall-poc

view details

Pascal Birchler

commit sha 736dd95a8adccb247be278d3572ea7876cd7dedd

Update based on feedback

view details

Pascal Birchler

commit sha 9904c8a277dd8cc841f6ea78cfca8f394d7e1cbe

Lint fix

view details

push time in 11 days

issue commentgoogle/web-stories-wp

Templates - Add SVGs to shape panel

https://github.com/google/web-stories-wp/pull/2760

littlemilkstudio

comment created time in 12 days

PR opened google/web-stories-wp

Feature | Add shapes to shape panel [1895]

Summary

https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/1895 Goes through and normalizes and formats svgs in templates to be normalized clip paths.

Relevant Technical Choices

Had to add an altered icon path so large shapes with small small stroke widths were visible

To-do

Go through templates and replace any placeholder pngs with these shapes.

User-facing changes

Adds new shapes to shapes panel: Screen Shot 2020-06-25 at 3 30 18 PM

Testing Instructions

Create a new template or alter and existing one and add all new shapes to the template and make sure they work and are visible.


<!-- Please reference the issue(s) this PR addresses. -->

Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/1895

+1050 -1448

0 comment

5 changed files

pr created time in 12 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 98189b56079d552b93b6e6ae0a78623fffbea655

added all given masks

view details

push time in 12 days

create barnchgoogle/web-stories-wp

branch : 1895-add-shapes-shapepanel

created branch time in 12 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Make sure story menus are always within confines of browser

 function PopoverCard({ children, isOpen }) {   return (     <ButtonInner       ref={menuTogglePositionRef}-      isOpen={isOpen && isReady}+      isOpen={isOpen}

doesn't seem like this is used anymore in ButtonInner should it be removed?

BrittanyIRL

comment created time in 12 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import { createContext, useMemo, useCallback, useState } from 'react';+import PropTypes from 'prop-types';++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [toasts, setToasts] = useState({});+  const activeToasts = useMemo(+    () => Object.values(toasts).filter((toast) => toast.isActive),+    [toasts]+  );++  const removeToast = useCallback(+    (id) =>+      id &&+      setToasts((existingToasts) => ({+        ...existingToasts,+        [id]: { ...existingToasts[id], isActive: false },

@BrittanyIRL if you wanted to do this, you could expose a delete method from the provider and call it with

onTransitionEnd={() => !isActive && deleteToast(id)}

on the individual toasts. or onAnimationEnd if it's using animation instead of transition

BrittanyIRL

comment created time in 14 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [toasts, setToasts] = useState({});++  const activeToasts = useMemo(+    () => Object.values(toasts).filter((toast) => toast.isActive),+    [toasts]+  );++  const resetToasts = useCallback(() => {+    setToasts({});+  }, [setToasts]);++  const removeToast = useCallback(+    (id) =>+      id &&+      setToasts((existingToasts) => ({+        ...existingToasts,+        [id]: { ...existingToasts[id], isActive: false },+      })),+    []+  );++  const addToast = useCallback(+    ({ message, severity, id }) =>+      setToasts((existingToasts) => ({+        ...existingToasts,+        [id]: { message, severity, id, isActive: true },+      })),+    []+  );++  useEffect(() => resetToasts, [resetToasts]);

I thought the point of this was just to reset the toasts on unmount for the provider, which makes sense for only running on initial render.

But now thinking about it, I'm wondering wondering why we need to reset the toasts when this unmounts.

BrittanyIRL

comment created time in 14 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 63b9c8c15a28a18d92bb99bdf2a1b6ebcb68517e

add proper bg pictures

view details

push time in 15 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [toasts, setToasts] = useState({});++  const activeToasts = useMemo(+    () => Object.values(toasts).filter((toast) => toast.isActive),+    [toasts]+  );++  const resetToasts = useCallback(() => {+    setToasts({});+  }, [setToasts]);++  const removeToast = useCallback(+    (id) => {+      const toastIdToUpdate = id || activeToasts[0].id;+      toastIdToUpdate &&+        setToasts({+          ...toasts,+          [toastIdToUpdate]: { ...toasts[toastIdToUpdate], isActive: false },+        });+    },+    [activeToasts, toasts]
        setToasts(toasts => ({
          ...toasts,
          [toastIdToUpdate]: { ...toasts[toastIdToUpdate], isActive: false },
        }));
    },
    [activeToasts]
BrittanyIRL

comment created time in 15 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import { renderHook, act } from '@testing-library/react-hooks';++/**+ * Internal dependencies+ */+import ToastProvider from '../provider';+import useToastContext from '../useToastContext';+import { ALERT_SEVERITY } from '../../../constants';++const TOAST_1 = {+  message: 'one',+  severity: ALERT_SEVERITY.ERROR,+  id: 1,+  isActive: true,+};++const TOAST_2 = {+  message: 'two',+  id: 2,+  severity: ALERT_SEVERITY.ERROR,+  isActive: true,+};++const TOAST_3 = {+  message: 'three',+  id: 3,+  severity: ALERT_SEVERITY.WARNING,+  isActive: true,+};++describe('useToastContext', () => {+  it('should throw an error if used outside of Toast.Provider', () => {+    expect(() => {+      const {+        // eslint-disable-next-line no-unused-vars+        result: { current },+      } = renderHook(() => useToastContext());+    }).toThrow(+      Error('useToasterContext() must be used within a <Toast.Provider />')+    );+  });++  it('should not throw an error if used inside ToastProvider', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });+    expect(result.current.error).toBeUndefined();+  });++  it('should have default state initially set up', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });++    expect(result.current.state.activeToasts).toStrictEqual([]);+  });++  it('should add a new activeToast when addToast is called and new toast has unique id', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });++    act(() => {+      result.current.actions.addToast(TOAST_1);+    });++    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);+  });++  it('should not add a duplicate activeToast when addToast is called with existing toast id', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });+    act(() => {+      result.current.actions.addToast(TOAST_1);+    });++    act(() => {+      result.current.actions.addToast(TOAST_1);+    });++    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);+  });++  it('should remove an activeToast but maintain allToasts when removeToast is called', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });++    act(() => {+      result.current.actions.addToast(TOAST_1);+    });+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);++    act(() => {+      result.current.actions.addToast(TOAST_2);+    });+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1, TOAST_2]);++    act(() => {+      result.current.actions.removeToast(TOAST_2.id);+    });++    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);++    act(() => {+      result.current.actions.removeToast(TOAST_1.id);+    });+    expect(result.current.state.activeToasts).toStrictEqual([]);+  });

this is kind of a nit, but how are we testing the but maintain allToasts when removeToast is called portion of this test? seems like maybe it could be removed from the description of the test 🤷

BrittanyIRL

comment created time in 15 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

  * See the License for the specific language governing permissions and  * limitations under the License.  */++/**+ * WordPress dependencies+ */+import { __ } from '@wordpress/i18n';++/**+ * External dependencies+ */+import PropTypes from 'prop-types';+import { useRef, useEffect } from 'react';+ /**  * Internal dependencies  */-import Container from './container';-import { Wrapper } from './components';+import { Close } from '../../icons';+import { AlertSeveritiesPropType } from '../../types';+import { AUTO_REMOVE_ALERT_TIME_INTERVAL } from '../../constants';+import { AlertContainer, AlertText, DismissButton } from './components';++const Alert = ({+  isPreventAutoDismiss,+  isAllowDismiss,+  message,+  severity,+  handleDismissClick,+}) => {+  const autoDismissRef = useRef();+  autoDismissRef.current = isPreventAutoDismiss ? () => {} : handleDismissClick;++  useEffect(() => {+    if (!autoDismissRef.current) {+      return () => {};+    }+    const dismissTimeout = setTimeout(+      () => autoDismissRef.current(),+      AUTO_REMOVE_ALERT_TIME_INTERVAL+    );++    return () => clearTimeout(dismissTimeout);+  }, []);

Gorgeous 🤩

BrittanyIRL

comment created time in 15 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha ca195585e7ffd83ed1acd6a5742f66c3b4ccb439

remove trailing space from path def

view details

push time in 15 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 13dd226c66b0e8849201adb4fb6ba241f7be7043

added beauty grid to shapes panel

view details

Maxwell Yinger

commit sha 8178f3fd76821d98710501cefec5163640e3161b

update beauty template to use grid svgs

view details

push time in 15 days

PR opened google/web-stories-wp

Feature | Update Fitness Template Aspect Ratio to 9:16 [2473]

Summary

Updates Fitness template to new aspect ratio and fixes other critiques put in latest template design pass for fitness.

Designs & Critiques: https://www.figma.com/file/RTzSw47oi6pEZXEfP2JoBo/Templates?node-id=766%3A61

Relevant Technical Choices

NA

To-do

Still need a couple background images that have the color/blend-mode baked in. made notes of this in figma

User-facing changes

Fitness template update

Testing Instructions

Go to explore templates and view the Fitness template. Each page should now match these designs: https://www.figma.com/file/RTzSw47oi6pEZXEfP2JoBo/Templates?node-id=766%3A61


<!-- Please reference the issue(s) this PR addresses. -->

Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2473

Screenshots

Screen Shot 2020-06-19 at 3 16 48 PM Screen Shot 2020-06-19 at 3 16 01 PM Screen Shot 2020-06-19 at 3 16 40 PM Screen Shot 2020-06-19 at 3 16 07 PM Screen Shot 2020-06-19 at 3 16 13 PM Screen Shot 2020-06-19 at 3 16 21 PM Screen Shot 2020-06-19 at 3 16 28 PM Screen Shot 2020-06-19 at 3 16 34 PM

+1363 -2850

0 comment

8 changed files

pr created time in 18 days

create barnchgoogle/web-stories-wp

branch : 2473-template-fitness-aspect

created branch time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);

awesome. yea I think that'll help reduce duplicate state

BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));+      activeToastsCopy.splice(index, 1);+      setActiveToasts(activeToastsCopy);+    },+    [activeToasts]+  );++  const addToast = useCallback(+    ({ message, severity, id }) => {+      const newToast =+        allToasts.length === 0+          ? true+          : allToasts.reduce((_, toast) => {+              return toast?.id !== id;+            }, []);++      if (newToast) {+        setActiveToasts([+          ...new Set([...activeToasts, { message, severity, id }]),+        ]);+        setAllToasts([...new Set([...allToasts, { message, severity, id }])]);+      }+    },+    [allToasts, activeToasts]+  );++  useEffect(() => {+    let deleteToastInterval;+    if (activeToasts.length > 0) {+      deleteToastInterval = setInterval(+        removeToast,+        AUTO_REMOVE_TOAST_TIME_INTERVAL+      );+    }++    return () => deleteToastInterval && clearInterval(deleteToastInterval);+  }, [activeToasts.length, removeToast]);++  useEffect(() => {+    return () => {+      resetToasts();+    };+  }, [resetToasts]);

If you wanna tighten it up at all:

useEffect(() => resetToasts, [resetToasts]);
BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));+      activeToastsCopy.splice(index, 1);+      setActiveToasts(activeToastsCopy);+    },+    [activeToasts]+  );++  const addToast = useCallback(+    ({ message, severity, id }) => {+      const newToast =+        allToasts.length === 0+          ? true+          : allToasts.reduce((_, toast) => {+              return toast?.id !== id;+            }, []);++      if (newToast) {+        setActiveToasts([

I think storing these as objects should clean this up quite a bit:

const addToast = useCallback(
  toast => {
    setAllToasts(allToasts => ({
      ...allToasts,
      [toast.id]: toast
    }));
   setActiveToasts(activeToasts => ({
      ...activeToasts,
      [toast.id]: toast
    }));
  },
  []
);
BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);

Hmm what's the need for both activeToasts & allToasts state instead of just one toasts state?

BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);

Seems like you want both of these things to have only one item per toast id?

If so, might make sense to store these as objects shaped like:

interface AllToastsState {
  [toast_id]: toast
}

Then just make allToasts & activeToasts a derived array down stream so their easily iterable:

const value. = useMemo(() => ({
   state: { 
     allToasts: Object.values(allToasts),
     activeToasts: Object.values(activeToasts),
   },
   actions: { ... }
}), [activeToasts, allToasts, ...])
BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import { renderHook, act } from '@testing-library/react-hooks';++/**+ * Internal dependencies+ */+import ToastProvider from '../provider';+import useToastContext from '../useToastContext';+import { ALERT_SEVERITY } from '../../../constants';++const TOAST_1 = {+  message: 'one',+  severity: ALERT_SEVERITY.ERROR,+  id: 1,+};++const TOAST_2 = {+  message: 'two',+  id: 2,+  severity: ALERT_SEVERITY.ERROR,+};++const TOAST_3 = {+  message: 'three',+  id: 3,+  severity: ALERT_SEVERITY.WARNING,+};++describe('useToastContext', () => {+  it('should throw an error if used outside of Toast.Provider', () => {+    expect(() => {+      const {+        // eslint-disable-next-line no-unused-vars+        result: { current },+      } = renderHook(() => useToastContext());+    }).toThrow(+      Error('useToasterContext() must be used within a <Toast.Provider />')+    );+  });++  it('should not throw an error if used inside ToastProvider', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });+    expect(result.current.error).toBeUndefined();+  });++  it('should have default state initially set up', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });++    expect(result.current.state.activeToasts).toStrictEqual([]);+  });++  it('should add a new activeToast when addToast is called and new toast has unique id', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });++    act(() => {+      result.current.actions.addToast(TOAST_1);+    });++    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);+  });++  it('should not add a duplicate activeToast when addToast is called with existing toast id', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });+    act(() => {+      result.current.actions.addToast(TOAST_1);+    });++    act(() => {+      result.current.actions.addToast(TOAST_1);+    });++    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);+  });++  it('should remove an activeToast but maintain allToasts when removeToast is called', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });++    act(() => {+      result.current.actions.addToast(TOAST_1);+    });+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1]);++    act(() => {+      result.current.actions.addToast(TOAST_2);+    });+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1, TOAST_2]);+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1, TOAST_2]);++    act(() => {+      result.current.actions.removeToast(1);+    });++    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1, TOAST_2]);++    act(() => {+      result.current.actions.removeToast(0);+    });+    expect(result.current.state.activeToasts).toStrictEqual([]);+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1, TOAST_2]);+  });++  it('should reset allToasts when resetToasts is called', () => {+    const { result } = renderHook(() => useToastContext(), {+      wrapper: ToastProvider,+    });+    act(() => {+      result.current.actions.addToast(TOAST_1);+    });+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1]);+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);++    act(() => {+      result.current.actions.addToast(TOAST_3);+    });+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1, TOAST_3]);+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1, TOAST_3]);++    act(() => {+      result.current.actions.removeToast(1);+    });+    expect(result.current.state.allToasts).toStrictEqual([TOAST_1, TOAST_3]);+    expect(result.current.state.activeToasts).toStrictEqual([TOAST_1]);++    act(() => {+      result.current.actions.resetToasts();+    });++    expect(result.current.state.allToasts).toStrictEqual([]);+    expect(result.current.state.activeToasts).toStrictEqual([]);+  });++  // eslint-disable-next-line jest/no-commented-out-tests+  //   it(+  //     'should automatically remove activeToasts at an increment of 10000ms',+  //     async () => {+  //       const { result, waitForNextUpdate } = renderHook(+  //         () => useToastContext(),+  //         {+  //           wrapper: ToastProvider,+  //         }+  //       );++  //       act(() => {+  //         result.current.actions.addToast(TOAST_1);+  //       });+  //       act(() => {+  //         result.current.actions.addToast(TOAST_2);+  //       });+  //       act(() => {+  //         result.current.actions.addToast(TOAST_3);+  //       });++  //       expect(result.current.state.activeToasts).toStrictEqual([+  //         TOAST_1,+  //         TOAST_2,+  //         TOAST_3,+  //       ]);++  //       await waitForNextUpdate(AUTO_REMOVE_TOAST_TIME_INTERVAL + 1, true);++  //       expect(result.current.state.activeToasts).toStrictEqual([+  //         TOAST_2,+  //         TOAST_3,+  //       ]);++  //       await waitForNextUpdate(AUTO_REMOVE_TOAST_TIME_INTERVAL + 1, true);++  //       expect(result.current.state.activeToasts).toStrictEqual([TOAST_3]);++  //       await waitForNextUpdate(AUTO_REMOVE_TOAST_TIME_INTERVAL + 1, true);++  //       expect(result.current.state.activeToasts).toStrictEqual([]);+  //       expect(result.current.state.allToasts).toStrictEqual([+  //         TOAST_1,+  //         TOAST_2,+  //         TOAST_3,+  //       ]);+  //     }+  //   );

is this a WIP? could you just do it.skip(...) instead of commenting it out? or does it have linter warnings and this was easiest?

BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));+      activeToastsCopy.splice(index, 1);+      setActiveToasts(activeToastsCopy);+    },+    [activeToasts]+  );++  const addToast = useCallback(+    ({ message, severity, id }) => {+      const newToast =+        allToasts.length === 0+          ? true+          : allToasts.reduce((_, toast) => {+              return toast?.id !== id;+            }, []);++      if (newToast) {+        setActiveToasts([+          ...new Set([...activeToasts, { message, severity, id }]),

I don't think the Set is doing anything here since it uses referential equality for it's items and this is passing it a new object.

BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));+      activeToastsCopy.splice(index, 1);+      setActiveToasts(activeToastsCopy);+    },+    [activeToasts]+  );++  const addToast = useCallback(+    ({ message, severity, id }) => {+      const newToast =+        allToasts.length === 0+          ? true+          : allToasts.reduce((_, toast) => {+              return toast?.id !== id;+            }, []);++      if (newToast) {+        setActiveToasts([+          ...new Set([...activeToasts, { message, severity, id }]),+        ]);+        setAllToasts([...new Set([...allToasts, { message, severity, id }])]);+      }+    },+    [allToasts, activeToasts]+  );++  useEffect(() => {+    let deleteToastInterval;+    if (activeToasts.length > 0) {+      deleteToastInterval = setInterval(+        removeToast,+        AUTO_REMOVE_TOAST_TIME_INTERVAL+      );+    }++    return () => deleteToastInterval && clearInterval(deleteToastInterval);+  }, [activeToasts.length, removeToast]);

I'm curious what the expected behavior of toast auto dismiss is.

If I add a toast at 0s, then 2s later add another. At what times should the toasts auto-dismiss?

BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));+      activeToastsCopy.splice(index, 1);+      setActiveToasts(activeToastsCopy);+    },+    [activeToasts]
  const removeToast = useCallback(
    (index = 0) => setActiveToasts(activeToasts => [
        ...activeToasts.slice(0, index),
        ...activeToasts.slice(index + 1)
     ]),
    []
  );
BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));+      activeToastsCopy.splice(index, 1);+      setActiveToasts(activeToastsCopy);+    },+    [activeToasts]+  );++  const addToast = useCallback(+    ({ message, severity, id }) => {+      const newToast =+        allToasts.length === 0+          ? true+          : allToasts.reduce((_, toast) => {+              return toast?.id !== id;+            }, []);++      if (newToast) {+        setActiveToasts([+          ...new Set([...activeToasts, { message, severity, id }]),+        ]);+        setAllToasts([...new Set([...allToasts, { message, severity, id }])]);

This should allow you to remove deps & remove any possible race conditions:

        setActiveToasts(activeToasts => [
          ...new Set([...activeToasts, { message, severity, id }]),
        ]);
        setAllToasts(allToasts => [...new Set([...allToasts, { message, severity, id }])]);
BrittanyIRL

comment created time in 18 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Toaster UI

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */+/**+ * External dependencies+ */+import {+  createContext,+  useMemo,+  useCallback,+  useState,+  useEffect,+} from 'react';+import PropTypes from 'prop-types';++/**+ * ToastProvider tracks messages to display based on id so that if the same message occurs in a different instance it will still display+ * When a toast is dismissed early or at interval it is removed from the activeToasts but stays part of allToasts+ * When useEffect clean up is called (view change) allToasts and activeToasts will reset+ */+export const AUTO_REMOVE_TOAST_TIME_INTERVAL = 10000;++export const ToasterContext = createContext(null);++const ToastProvider = ({ children }) => {+  const [activeToasts, setActiveToasts] = useState([]);+  const [allToasts, setAllToasts] = useState([]);++  const resetToasts = useCallback(() => {+    setAllToasts([]);+    setActiveToasts([]);+  }, [setAllToasts, setActiveToasts]);++  const removeToast = useCallback(+    (index = 0) => {+      const activeToastsCopy = JSON.parse(JSON.stringify(activeToasts));

what's the JSON stringify & parse needed for? If it's just to copy the array can just use the Array.slice() method instead of splice on it directly and it will return a shallow copy

BrittanyIRL

comment created time in 18 days

PR opened google/web-stories-wp

Feature | Update Beauty Template Aspect Ratio to 9:16 [2476]

Summary

Updates Beauty template to new aspect ratio and fixes other critiques put in latest template design pass for fashion.

Designs & Critiques: https://www.figma.com/file/RTzSw47oi6pEZXEfP2JoBo/Templates?node-id=772%3A540

Relevant Technical Choices

NA

To-do

  • Still waiting for grid SVG assets to replace grid pngs on here so they can support custom colors

User-facing changes

  • Beauty template styles

Testing Instructions

Go to explore templates and view the beauty template. Each page should now match these designs: https://www.figma.com/file/RTzSw47oi6pEZXEfP2JoBo/Templates?node-id=772%3A540


<!-- Please reference the issue(s) this PR addresses. -->

Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2476

Screenshots

Screen Shot 2020-06-18 at 3 08 58 PM Screen Shot 2020-06-18 at 3 08 52 PM Screen Shot 2020-06-18 at 3 08 42 PM Screen Shot 2020-06-18 at 3 08 34 PM Screen Shot 2020-06-18 at 3 08 28 PM Screen Shot 2020-06-18 at 3 08 21 PM Screen Shot 2020-06-18 at 3 08 15 PM Screen Shot 2020-06-18 at 3 08 08 PM Screen Shot 2020-06-18 at 3 08 00 PM

+1220 -1792

0 comment

5 changed files

pr created time in 19 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha e87ee4b2b3e0ce3e9ec042216af2b2ebd97bf156

beauty template updated

view details

push time in 19 days

create barnchgoogle/web-stories-wp

branch : 2476-template-beauty-aspect

created branch time in 19 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {+  return alertBackgrounds[severity];+};++export const Wrapper = styled.div`+  position: fixed;+  bottom: 40px;+  right: 0;+  display: flex;+  flex-direction: column;+  align-items: flex-start;+  max-width: 300px;+  min-width: 40vw;+`;++export const AlertContainer = styled.div`+  display: flex;+  align-items: center;+  justify-content: space-between;+  width: 100%;+  padding: 10px 20px;+  margin-top: 20px;+  color: ${({ theme }) => theme.colors.white};+  background-color: ${({ theme, severity }) =>+    theme.colors[getColor(severity)]};+  border-radius: 5px;+  z-index: ${Z_INDEX.ALERT};+  animation: 0.5s ${slideIn} ease-in;+`;++export const AlertText = styled.p`+  ${TypographyPresets.Medium};+  width: calc(100% - 25px);+  display: inline;+`;++export const DismissButton = styled.button`+  align-self: center;+  margin: 0 0 0 auto;+  width: 25px;+  height: 25px;+  background-color: transparent;+  color: ${({ theme }) => theme.colors.white};+  border: ${({ theme }) => theme.borders.transparent};+  cursor: pointer;

Ah yea guess we stripped this default with our base styling. good to know. thanks!

BrittanyIRL

comment created time in 19 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {+  return alertBackgrounds[severity];+};++export const Wrapper = styled.div`+  position: fixed;+  bottom: 40px;+  right: 0;+  display: flex;+  flex-direction: column;+  align-items: flex-start;+  max-width: 300px;+  min-width: 40vw;+`;++export const AlertContainer = styled.div`+  display: flex;+  align-items: center;+  justify-content: space-between;+  width: 100%;+  padding: 10px 20px;+  margin-top: 20px;+  color: ${({ theme }) => theme.colors.white};+  background-color: ${({ theme, severity }) =>+    theme.colors[getColor(severity)]};

Feels like severity is only enforced to be a key of ALERT_SEVERITIES by the prop types on the Alert component level. A switch statement here returning a theme.colors may be a little more stable.

That being said, I'm fine with this solution

BrittanyIRL

comment created time in 20 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {+  return alertBackgrounds[severity];+};++export const Wrapper = styled.div`+  position: fixed;+  bottom: 40px;+  right: 0;+  display: flex;+  flex-direction: column;+  align-items: flex-start;+  max-width: 300px;+  min-width: 40vw;+`;++export const AlertContainer = styled.div`+  display: flex;+  align-items: center;+  justify-content: space-between;+  width: 100%;+  padding: 10px 20px;+  margin-top: 20px;+  color: ${({ theme }) => theme.colors.white};+  background-color: ${({ theme, severity }) =>+    theme.colors[getColor(severity)]};+  border-radius: 5px;+  z-index: ${Z_INDEX.ALERT};+  animation: 0.5s ${slideIn} ease-in;+`;++export const AlertText = styled.p`+  ${TypographyPresets.Medium};+  width: calc(100% - 25px);+  display: inline;

isn't this part of the default styling for the paragraph element? was it behaving differently without it?

BrittanyIRL

comment created time in 20 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {+  return alertBackgrounds[severity];+};++export const Wrapper = styled.div`+  position: fixed;+  bottom: 40px;+  right: 0;+  display: flex;+  flex-direction: column;+  align-items: flex-start;+  max-width: 300px;+  min-width: 40vw;

width could be used here instead of min-width. understand if it's a preference thing tho

BrittanyIRL

comment created time in 20 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {

This might be a little more clear if it's a default provided at the Alert component prop level so it's apparent at the component declaration instead of looking at implementation details. That being said, not a biggie

BrittanyIRL

comment created time in 20 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {+  return alertBackgrounds[severity];+};++export const Wrapper = styled.div`+  position: fixed;+  bottom: 40px;+  right: 0;+  display: flex;+  flex-direction: column;+  align-items: flex-start;+  max-width: 300px;+  min-width: 40vw;+`;++export const AlertContainer = styled.div`+  display: flex;+  align-items: center;+  justify-content: space-between;+  width: 100%;+  padding: 10px 20px;+  margin-top: 20px;+  color: ${({ theme }) => theme.colors.white};+  background-color: ${({ theme, severity }) =>+    theme.colors[getColor(severity)]};+  border-radius: 5px;+  z-index: ${Z_INDEX.ALERT};+  animation: 0.5s ${slideIn} ease-in;+`;++export const AlertText = styled.p`+  ${TypographyPresets.Medium};+  width: calc(100% - 25px);+  display: inline;+`;++export const DismissButton = styled.button`+  align-self: center;+  margin: 0 0 0 auto;+  width: 25px;+  height: 25px;+  background-color: transparent;+  color: ${({ theme }) => theme.colors.white};+  border: ${({ theme }) => theme.borders.transparent};+  cursor: pointer;

isn't this part of the default styling for the button? was it behaving differently without it?

BrittanyIRL

comment created time in 20 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Alert UI Component

+/*+ * Copyright 2020 Google LLC+ *+ * Licensed under the Apache License, Version 2.0 (the "License");+ * you may not use this file except in compliance with the License.+ * You may obtain a copy of the License at+ *+ *     https://www.apache.org/licenses/LICENSE-2.0+ *+ * Unless required by applicable law or agreed to in writing, software+ * distributed under the License is distributed on an "AS IS" BASIS,+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ * See the License for the specific language governing permissions and+ * limitations under the License.+ */++/**+ * External dependencies+ */+import styled, { keyframes } from 'styled-components';++/**+ * Internal dependencies+ */+import {+  ALERT_SEVERITIES,+  KEYBOARD_USER_SELECTOR,+  Z_INDEX,+} from '../../constants';+import { TypographyPresets } from '../typography';++const slideIn = keyframes`+	from {+		transform: translateX(100%);+	}+	to {+		transform: translateX(0);+	}+`;++const alertBackgrounds = {+  [ALERT_SEVERITIES.ERROR]: 'danger',+  [ALERT_SEVERITIES.WARNING]: 'warning',+  [ALERT_SEVERITIES.INFO]: 'bluePrimary',+  [ALERT_SEVERITIES.SUCCESS]: 'success',+  [ALERT_SEVERITIES.DEFAULT]: 'bluePrimary',+};++const getColor = (severity = ALERT_SEVERITIES.DEFAULT) => {+  return alertBackgrounds[severity];+};++export const Wrapper = styled.div`+  position: fixed;+  bottom: 40px;+  right: 0;+  display: flex;+  flex-direction: column;+  align-items: flex-start;+  max-width: 300px;+  min-width: 40vw;+`;++export const AlertContainer = styled.div`+  display: flex;+  align-items: center;+  justify-content: space-between;+  width: 100%;+  padding: 10px 20px;+  margin-top: 20px;+  color: ${({ theme }) => theme.colors.white};+  background-color: ${({ theme, severity }) =>+    theme.colors[getColor(severity)]};+  border-radius: 5px;+  z-index: ${Z_INDEX.ALERT};+  animation: 0.5s ${slideIn} ease-in;

an ease-out value might make the end of the animation look a little less abrupt here

BrittanyIRL

comment created time in 20 days

Pull request review commentgoogle/web-stories-wp

Dashboard: Applied design updates to Travel template

       ],       "type": "page",       "id": "d47afc22-71b7-4303-9917-96f9a31ad38a",-      "backgroundOverlay": "none",-      "animations": [-        {-          "id": "d5e53845-e936-49a7-972f-7dcbac6a29df",-          "type": "blinkOn",-          "duration": 1250,-          "delay": 0,-          "direction": "normal",-          "easing": "",-          "fill": "forwards",-          "iterations": "",-          "blinkCount": 5,-          "targets": [-            "a0f67513-d98a-43f4-bb0b-ad3383051452",-            "04ec92dc-313f-428d-87d0-00bd975290b5",-            "59955c3a-57a0-4c4a-857d-bd6234e1382c"-          ]-        },

was this causing errors even with enableAnimation feature disabled?

mariano-formidable

comment created time in 20 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha a2319f23e193d1e510acbbb02df0257ebc81ed80

remove trailing space on burst mask path

view details

push time in 20 days

issue commentgoogle/web-stories-wp

Templates: Update Fashion template to 9:16

https://github.com/google/web-stories-wp/pull/2577

mariano-formidable

comment created time in 20 days

PR opened google/web-stories-wp

Feature | Update Fashion Template Aspect Ratio to 9:16 [2471]

Summary

Updates Fashion template to new aspect ratio and fixes other critiques put in latest template design pass for fashion.

Designs & Critiques: https://www.figma.com/file/RTzSw47oi6pEZXEfP2JoBo/Templates?node-id=766%3A61

Relevant Technical Choices

N/A

To-do

N/A

User-facing changes

Fashion template design update.

Testing Instructions

Go to explore templates and view the fashion template. Each page should now match these designs: https://www.figma.com/file/RTzSw47oi6pEZXEfP2JoBo/Templates?node-id=766%3A61


<!-- Please reference the issue(s) this PR addresses. -->

Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2471

Screenshots

Screen Shot 2020-06-17 at 1 55 08 PM

+496 -1020

0 comment

5 changed files

pr created time in 20 days

create barnchgoogle/web-stories-wp

branch : 2471-template-fashion-aspect

created branch time in 20 days

pull request commentgoogle/web-stories-wp

Remove slash after imageBaseUrl

@littlemilkstudio can you check again now?

Yup. pulling latest

swissspidy

comment created time in 21 days

pull request commentgoogle/web-stories-wp

Remove slash after imageBaseUrl

@swissspidy this breaks all the template images on my local. I'm guessing that there's some discrepancy between trailing slashes on local vs prod for the base url.

Maybe we should just make a util that adds a trailing slash if there isn't one for imageBaseUrl.

What are your thoughts?

Screen Shot 2020-06-16 at 2 17 59 PM

swissspidy

comment created time in 21 days

PR closed google/web-stories-wp

Reviewers
Address MultiSelection Keyboard Selection Bug Pod: Workspace Type: Bug cla: yes

Summary

This just fixes a bug where mutli-selection on first load wasn't allowing for keyboard shortcuts on selected elements.

This is just because doing the drag gesture with a mouse doesn't actually cause the browser to change focus.

Focus on the canvas or one of its children is necessary to pick up keyboard events on it.

The bug was caused because we were only setting the canvas as the default focus element in focusout which doesn't fire if you multiselect right after initial page load. The only real update here was checking if we needed to update the default focus on the initial render.

Relevant Technical Choices

Changed setTimout duration to be 0 instead of 300 because it will still be queued after any potential focusin events queued up in the IO queue, but be a little more snappy. 🌭 🐊

Also added in depth comments because the approach wasn't very straight forward to me at first. I'd be happy to remove some if they're feeling a little dense

To-do

If we wanted to, we could make a useDefaultFocus(ref) hook that encapsulates this functionality since it feels like it has a separate purpose then the useCanvasKeys(ref) hook. But also feel like the hooks are already pretty spread out and nested here, so understand not wanting to do this.

User-facing changes

Fixes being able to use keyboard commands on mutliselected canvas elements on initial load.

Testing Instructions

  • On a fresh load of the story editor multiselect several elements before clicking anywhere else on the page. try to use keyboard shortcuts (arrows, delete) on them and they should work.

Also just play around with editor a but and make sure there were no regressions on inputs.


<!-- Please reference the issue(s) this PR addresses. -->

Addresses #1070

+25 -9

4 comments

1 changed file

littlemilkstudio

pr closed time in 21 days

pull request commentgoogle/web-stories-wp

Address MultiSelection Keyboard Selection Bug

I'm gonna close this since I think @dvoytenko 's update to how we we're capturing focus on the canvas fixed this

littlemilkstudio

comment created time in 21 days

PR opened google/web-stories-wp

Feature | Base Template Animations - Fashion [2213]

Summary

Adds the base animations for the fashion template and documents current missing animation parts I ran into in this doc: https://docs.google.com/spreadsheets/d/1iJ8Adqs4zGWteMoxVCZ2MM4LAza0LQmtPUX6I9qdshY/edit#gid=21496487

Relevant Technical Choices

All work should just be story data appended to the raw template. Only thing that should have really been changed was origin point to be in the center of an element so scaled elements are anchored in the center.

To-do

N/A

User-facing changes

Should be none. All animations behind feature flag

Testing Instructions

User Facing Only thing to test here is that the animations are still behind a feature flag, so just open up the templates and hover over the fashion story. There should be no Animations.

Behind Feature Flag go to includes/Dashboard.php and set enableAnimations: true . Then navigate to external templates in the dashboard. Hover over the thumbnail & should see animations on every page.


Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2213

Screenshots

(outputted at 15 fps just so file size isn't too large. To view in high fidelity, open run this branch on your local) fashion_base_anims

+1945 -745

0 comment

2 changed files

pr created time in 22 days

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha c7c0b9af2cf98cec53c42c0f9088bfc673731d49

base anims for fashion template

view details

push time in 22 days

create barnchgoogle/web-stories-wp

branch : 2213-fashion-template-anims-3-4

created branch time in 25 days

Pull request review commentgoogle/web-stories-wp

Address MultiSelection Keyboard Selection Bug

 function useCanvasKeys(ref) {     }   ); -  // Return focus back to the canvas when another section loses the focus.+  /**

Oh just personal preference. Happy to revert back to // knowing we're only using block comments as jsdocs

littlemilkstudio

comment created time in 25 days

Pull request review commentgoogle/web-stories-wp

Workspace: New Safe Zone Design & Toggle

 const PlainStyled = styled(Plain)` `;  const MenuIconsWrapper = styled.div`+  & > * {+    margin-bottom: 12px;+  }

Totally cool with a quick fix here and don't need to change, but would like to actively try to keep specificity down when coming up with future solutions.

Wanna avoid tracking down which parent up the component tree is applying some styles as much as possible when visual regressions eventually come.

dmmulroy

comment created time in 25 days

Pull request review commentgoogle/web-stories-wp

Workspace: New Safe Zone Design & Toggle

+<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">+<path d="M9 7C9 6.44772 9.44772 6 10 6H19C19.5523 6 20 6.44772 20 7V21C20 21.5523 19.5523 22 19 22H10C9.44771 22 9 21.5523 9 21V7Z" stroke="currentColor" stroke-width="2"/>+<rect x="11" y="9" width="3" height="1" fill="currentColor"/>+<rect x="15" y="9" width="3" height="1" fill="currentColor"/>+</svg>

lgtm. just a heads up it's nice to strip height & width off of svg definitions and just make them take up the full size of their parent that way they're more portable to be used in other places.

Won't mess with the elements inside because viewBox establishes the coordinate system all the shapes and paths reference internally.

Probably not needed here, but just good practice in the future

dmmulroy

comment created time in 25 days

Pull request review commentgoogle/web-stories-wp

Workspace: New Safe Zone Design & Toggle

 const PageAreaSafeZone = styled.div`   overflow: visible;   position: relative;   margin: auto 0;-`; -const PageAreaDangerZone = styled.div`-  pointer-events: none;+  ${({ showSafeZone }) =>+    showSafeZone &&+    `&::before {+  content: '';+  width: 20px;+  height: var(--page-height-px);

if you want better syntax highlighting and formatting from your editor you can import css from styled components and do:

  ${({ showSafeZone }) =>
    showSafeZone && css`
      &::before {
        content: '';
        width: 20px;
        height: var(--page-height-px);

Have asked Phil about this before and he said css is just an internal utility and there should be no perf cost of using it so it's totally cool to use.

dmmulroy

comment created time in 25 days

Pull request review commentgoogle/web-stories-wp

Workspace: New Safe Zone Design & Toggle

 function Carousel() {     }) => ({ pages, currentPageId, setCurrentPage, arrangePage })   );   const { isRTL } = useConfig();+  const { showSafeZone, setShowSafeZone } = useCanvas(+    ({ state: { showSafeZone }, actions: { setShowSafeZone } }) => ({+      showSafeZone,+      setShowSafeZone,+    })+  );

I wonder if we can set up our useContextSelector pattern to just accept some sort of shorthand for this frequently occurring case where we're just pulling selected properties off of the context.

  const { showSafeZone, setShowSafeZone } = useCanvas([['showSafeZone'], ['setShowSafeZone']]);
// or something more like dlv
  const { showSafeZone, setShowSafeZone } = useCanvas('state.showSafeZone', 'actions.setShowSafeZone');

Or maybe we just make it a pattern to statically define these outside the component definition:

const selector = ({ state: { showSafeZone }, actions: { setShowSafeZone } }) => ({
    showSafeZone,
    setShowSafeZone,
});
...
function Carousel() {
  ...
  const { showSafeZone, setShowSafeZone } = useCanvas(selector);
  ...
}
dmmulroy

comment created time in 25 days

Pull request review commentgoogle/web-stories-wp

1070 | MultiSelection Keyboard Selection Bug

 function useCanvasKeys(ref) {     }   ); -  // Return focus back to the canvas when another section loses the focus.+  /**+   * Sets default focus node from body to the ref element.+   */   useEffect(() => {     const container = ref.current;     if (!container) {       return undefined;     }-+    /**+     * If node loses focus, wait to see if another node gains it.+     * if not focus default element.+     */     const doc = container.ownerDocument;-     const handler = () => {-      // Make sure that no other component is trying to get the focus-      // at this time. We have to check all "focusout" events here because-      // after DOM removal, the "focusout" events are all over the place.+      /**+       * setTimeout places callback in the back of the IO queue after+       * any postential focusin events are queued.+       */       setTimeout(() => {         if (doc.activeElement === doc.body) {           container.focus();         }-      }, 300);+      }, 0);

This should accomplish the same thing putting this behind any focusin events in the IO queue. Happy to change it back tho as it doesn't really change much for the user

littlemilkstudio

comment created time in a month

Pull request review commentgoogle/web-stories-wp

1070 | MultiSelection Keyboard Selection Bug

 import { getPastedCoordinates } from '../../utils/copyPaste'; const MOVE_COARSE_STEP = 10;  /**- * @param {{current: Node}} ref+ * @param {MutableRefObject<HTMLElement | null>} ref

little tighter type here. nice to see doc strings accepts TS types

littlemilkstudio

comment created time in a month

Pull request review commentgoogle/web-stories-wp

1070 | MultiSelection Keyboard Selection Bug

 function useCanvasKeys(ref) {     }   ); -  // Return focus back to the canvas when another section loses the focus.+  /**+   * Sets default focus node from body to the ref element.+   */   useEffect(() => {     const container = ref.current;     if (!container) {       return undefined;     }-+    /**+     * If node loses focus, wait to see if another node gains it.+     * if not focus default element.+     */     const doc = container.ownerDocument;-     const handler = () => {-      // Make sure that no other component is trying to get the focus-      // at this time. We have to check all "focusout" events here because-      // after DOM removal, the "focusout" events are all over the place.+      /**+       * setTimeout places callback in the back of the IO queue after+       * any postential focusin events are queued.+       */       setTimeout(() => {         if (doc.activeElement === doc.body) {           container.focus();         }-      }, 300);+      }, 0);     };+    /**+     * This is necessary on first load as no events will fire and+     * we need to check to see if we need to swap out the default+     * focus element.+     */+    handler();

This is the only real change.

littlemilkstudio

comment created time in a month

PR opened google/web-stories-wp

1070 | MultiSelection Keyboard Selection Bug

Summary

This just fixes a bug where mutli-selection on first load wasn't allowing for keyboard shortcuts on selected elements.

This is just because doing the drag gesture with a mouse doesn't actually cause the browser to change focus.

Focus on the canvas or one of its children is necessary to pick up keyboard events on it.

The bug was caused because we were only setting the canvas as the default focus element in focusout which doesn't fire if you multiselect right after initial page load. The only real update here was checking if we needed to update the default focus on the initial render.

Relevant Technical Choices

Changed setTimout duration to be 0 instead of 300 because it will still be queued after any potential focusin events queued up in the IO queue, but be a little more snappy. 🌭 🐊

Also added in depth comments because the approach wasn't very straight forward to me at first. I'd be happy to remove some if they're feeling a little dense

To-do

If we wanted to, we could make a useDefaultFocus(ref) hook that encapsulates this functionality since it feels like it has a separate purpose then the useCanvasKeys(ref) hook. But also feel like the hooks are already pretty spread out and nested here, so understand not wanting to do this.

User-facing changes

Fixes being able to use keyboard commands on mutliselected canvas elements on initial load.

Testing Instructions

  • On a fresh load of the story editor multiselect several elements before clicking anywhere else on the page. try to use keyboard shortcuts (arrows, delete) on them and they should work.

Also just play around with editor a but and make sure there were no regressions on inputs.


<!-- Please reference the issue(s) this PR addresses. -->

Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/1070

+25 -9

0 comment

1 changed file

pr created time in a month

create barnchgoogle/web-stories-wp

branch : 1070-multiselection-bug

created branch time in a month

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 758f6818f71d6a340daadc13b54a9f19370d6e1d

initial transforms for fashion page 1

view details

Maxwell Yinger

commit sha b63ae479434e508fd8c981c1a07d02901129dd15

Fashion page 1 & 2 WIP

view details

Maxwell Yinger

commit sha 45fa2e731e13b7625e25b6fe9a9c4a8b233b3c90

alter rotation input

view details

Maxwell Yinger

commit sha 79cb451ffc0f3c3f956b12430386816d98a8d1d3

initial anims page 1 & 2

view details

Max Yinger

commit sha 11865d31f08300fd6523d6bc21e3e2d30d93f052

Merge pull request #2327 from google/2213-template-fashion-animation 2213 [PARTIAL] | Template Fashion Animation

view details

push time in a month

delete branch google/web-stories-wp

delete branch : 2213-template-fashion-animation

delete time in a month

PR merged google/web-stories-wp

2213 [PARTIAL] | Template Fashion Animation cla: yes

Summary

This PR adds the initial animations to the first two pages of the fashion template, as well as necessary tweaks and updates to achieve them.

Relevant Technical Choices

Updated animation parts to be more unit agnostic, but have a default unit that gets applied.

Also changed display elements to be contain: layout; vs contain: layout paint which although not as performant removes mask like behavior from element transforming outside of its original bounds. This should also fix the issue where we were getting culling on typefaces when the line height was below 1. Open to other suggestions here too, but figure with this alteration the small loss in perf is worth the benefit in behavior

To-do

Pretty much the only animation that's keeping this implementation from being 95% of the mockup is the staggered split line animations. There are several ways we can accomplish this each with their own tradeoffs. Gonna get feedback on what we're prioritizing for v1 and then choose option that gets us there quickest.

Figure for now tho, the current implementation is a good first step.

User-facing changes

There should be none here.

Testing Instructions

first run on your local server and make sure no animations play (since the PR should keep the enableAnimation flag disabled)

Then, set the enableAnimation flag in includes/Dashboard.php to true and hover over the fashion template with a mouse or click into the details view to see the animations on the first two pages.


Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2213

Screenshots

fashion_template-1-2

Initial Mockups

https://drive.google.com/drive/folders/1E0nLATcplhGNzgteOymx3s2SyA-cc7_M

+439 -169

2 comments

17 changed files

littlemilkstudio

pr closed time in a month

Pull request review commentgoogle/web-stories-wp

Dashboard: Integrating amp-animations into a generated amp-story

 import moveProps from './move/animationProps'; import spinProps from './spin/animationProps'; import zoomProps from './zoom/animationProps'; +function EmptyAMPTarget({ children, ...rest }) {+  return <div {...rest}>{children}</div>;+}

Nice. Just to clarify, this is an empty AMPTarget because the AMPWrapper will be used for positioning regardless of if an animation has been applied?

mariano-formidable

comment created time in a month

Pull request review commentgoogle/web-stories-wp

Dashboard: Integrating amp-animations into a generated amp-story

 function ComposableWrapper({ animationParts, children, style }) { ComposableWrapper.propTypes = {   animationParts: PropTypes.arrayOf(PropTypes.object),   children: PropTypes.node.isRequired,-  style: PropTypes.object, };  function AMPWrapper({ target, children, style }) {   const {     actions: { getAnimationParts },   } = useStoryAnimationContext(); -  return (-    <ComposableWrapper style={style} animationParts={getAnimationParts(target)}>-      {children}-    </ComposableWrapper>+  const animationParts = getAnimationParts(target);++  return animationParts.length > 0 ? (+    <div style={style}>+      <ComposableWrapper animationParts={getAnimationParts(target)}>+        {children}+      </ComposableWrapper>+    </div>+  ) : (+    <div style={style}>{children}</div>

if this feels more safe to you, totally get it. But if you do want to make this a little more lean, think you can achieve the same thing with just:

return (
    <div style={style}>
      <ComposableWrapper animationParts={getAnimationParts(target) || []}>
        {children}
      </ComposableWrapper>
    </div>
  )

Since the reducer in ComposableWrapper should have an initial value of just passing children through

mariano-formidable

comment created time in a month

Pull request review commentgoogle/web-stories-wp

Dashboard: Integrating amp-animations into a generated amp-story

 function ComposableWrapper({ animationParts, children, style }) {           const Composed = function (props) {             return (               <Composable>-                <AMPTarget style={style}>{props.children}</AMPTarget>+                <AMPTarget style={fullSizeAbsoluteStyles}>+                  {props.children}+                </AMPTarget>

Nice. I like that this mirrors the WAAPI approach a little more now

mariano-formidable

comment created time in a month

Pull request review commentgoogle/web-stories-wp

2213 [PARTIAL] | Template Fashion Animation

 const Wrapper = styled.div`   ${elementWithPosition}   ${elementWithSize}   ${elementWithRotation}-  contain: layout paint;+  contain: layout;

@dvoytenko @swissspidy Is this alright?

Trying to allow elements to animate across the page and maintain visibility. Currently containing painting to the elements bounding box is preventing that by causing a mask like behavior to the bounding box.

This also fixes the issue in the editor and the dashboard for stories where typefaces that have a line height less than 1 aren't culled off by the bounding box.

Other option is making the animation wrapper the top level wrapper instead of the positioning wrapper which currently is. (this solution would allow us to animate without needing to do this, but wouldn't fix the line-height less than 1 issue I mentioned above)

littlemilkstudio

comment created time in a month

PR opened google/web-stories-wp

2213 [PARTIAL] | Template Fashion Animation

Summary

This PR adds the initial animations to the first two pages of the fashion template, as well as necessary tweaks and updates to achieve them.

Relevant Technical Choices

Updated animation parts to be more unit agnostic, but have a default unit that gets applied.

Also changed display elements to be contain: layout; vs contain: layout paint which although not as performant removes mask like behavior from element transforming outside of its original bounds. This should also fix the issue where we were getting culling on typefaces when the line height was below 1. Open to other suggestions here too, but figure with this alteration the small loss in perf is worth the benefit in behavior

To-do

Pretty much the only animation that's keeping this implementation from being 95% of the mockup is the staggered split line animations. There are several ways we can accomplish this each with their own tradeoffs. Gonna get feedback on what we're prioritizing for v1 and then choose option that gets us there quickest.

Figure for now tho, the current implementation is a good first step.

User-facing changes

There should be none here.

Testing Instructions

first run on your local server and make sure no animations play (since the PR should keep the enableAnimation flag disabled)

Then, set the enableAnimation flag in includes/Dashboard.php to true and hover over the fashion template with a mouse or click into the details view to see the animations on the first two pages.


Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2213

+439 -169

0 comment

17 changed files

pr created time in a month

push eventgoogle/web-stories-wp

Clinton Volzke

commit sha 88c43e4352d6d5370276c6ae1d7ad695886e6abe

Add selectors to useContext calls

view details

Clinton Volzke

commit sha 1104cf408a1dc6c5ff0f2745c49ab1069122fa2f

Fix selector in editLayer.js

view details

Clinton Volzke

commit sha a9943703044650a39601223164b8b513d00098f3

Merge branch 'master' into fix/1466-add-context-selectors

view details

Clinton Volzke

commit sha a1f4d1d253f1a665b674dfe7bc1453eccaac2301

Merge branch 'master' into fix/1466-add-context-selectors

view details

Clinton Volzke

commit sha faa56ec85010a78f9e5e7deefb6b1fac2e92b7da

Add new instances of useMedia and useStory.

view details

Clinton Volzke

commit sha 10961d4d20e24528ab8c05be37729f8e1f4c3c7a

Fix lint error

view details

Miina Sikk

commit sha 02d0521f90b5b296cc53389a2a32f1b7d24d9005

Prevent dragging when cntrl is pressed.

view details

Miina Sikk

commit sha 984f6e2407ee25e1151bcbf8cd389d44e2d40fd8

Add check for right-click button.

view details

Miina Sikk

commit sha 3da85732355b8866d9cf2a7a28d80c438989399d

Update Moveable.

view details

Clinton Volzke

commit sha 41a0451a2a7df605e960f33b102c08fb020bd759

Merge branch 'master' into fix/1466-add-context-selectors

view details

Miina Sikk

commit sha 7a882ec65ceb81f482245b15ea0923e30fb47b7c

Merge remote-tracking branch 'origin/master' into fix/2087-fix-right-click

view details

Miina Sikk

commit sha 728788ca3e4921e47e30d184dc6b93c6690977a5

Upgrade moveable again

view details

Pascal Birchler

commit sha c1f0198e3433bbf658ccfb3a7489c6732a17a104

Fix ‘Add New’ string

view details

Pascal Birchler

commit sha 7b127e61c8f0432ccfcc9852081a1251976a5cd4

Fix translatable strings for templates

view details

Wassim Gharbi

commit sha 348ffd9fcc340a1309221546f43b6fe9017ec3b5

Fix popup stacking with modals (#2045) * Fix popup z-index * Reverter overflow

view details

Pascal Birchler

commit sha 434e48a4d54facf18c2f207184be0daad85b827a

Update phpstan config

view details

Pascal Birchler

commit sha 1ce8582ba066f3a16d2665405424caf4f8bf4874

Composer update

view details

Brittany Feenstra

commit sha 5618ea7c1ab8ec3c1ee91e26e7527afcf413b315

use _n not __ for translation of dropdown with numbers

view details

Brittany Feenstra

commit sha db30d7e1dd6cdd5d7f984208548e451e3e1ad121

move uppercase to css for detail nav button

view details

Brittany Feenstra

commit sha 09dd19fa0f1a1cb4f1156d275345cf9898511104

Merge pull request #2311 from google/task/2293-i18n-numbers Dashboard: Bug fixes for color panel translation and detail template capitalization

view details

push time in a month

create barnchgoogle/web-stories-wp

branch : 2213-template-fashion-animation

created branch time in a month

create barnchlittlemilkstudio/extra-normal

branch : feature/animator-update

created branch time in a month

push eventlittlemilkstudio/extra-normal

Maxwell Yinger

commit sha 0cd6ebcf0d80b79d919291a6e81306f2baaa9a35

figuring out base controller

view details

Maxwell Yinger

commit sha 78c5836ed9da0c34b2ef028d8ced651f2632dfe0

controller tests completed

view details

Max Yinger

commit sha 92461f16154dc73bc812f0081223eee94bec74e4

Merge pull request #17 from littlemilkstudio/feature/controller Feature | Controller

view details

push time in a month

delete branch littlemilkstudio/extra-normal

delete branch : feature/controller

delete time in a month

PR merged littlemilkstudio/extra-normal

Feature | Controller

Adds controller(v => v) which returns a source with some methods:

instance source method

const source = controller<A, B>(v => v);
const sink = stream<B, C>(v => v);

// `()` Instance source method
const stopFromSource = source(sink);

// `.next(v)` method passes value down to controlled sink.
source.next(v);
+131 -10

0 comment

8 changed files

littlemilkstudio

pr closed time in a month

push eventlittlemilkstudio/extra-normal

Maxwell Yinger

commit sha 78c5836ed9da0c34b2ef028d8ced651f2632dfe0

controller tests completed

view details

push time in a month

delete branch google/web-stories-wp

delete branch : task/easing-selection

delete time in a month

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha b71b2e04875693a0f0034a5aaafe37b7b9a636b7

easing presets

view details

Max Yinger

commit sha f7d28ecdfb48ef9038331e8e3410276e0add3f4a

Merge pull request #2284 from google/task/easing-selection Feature | Easing Presets

view details

push time in a month

PR merged google/web-stories-wp

Reviewers
Feature | Easing Presets cla: yes

Summary

Adds base easing presets field to /story-anim-tools which contains frequently used bezier values found here: https://easings.net/

Way this works is custom Easing field always overrides it, but if nothing found in custom field, it will use the selected preset.

Relevant Technical Choices

Quick n' Dirty

To-do

NA

User-facing changes

NA

Testing Instructions

Turn enableAnimation feature on.

Then go to /story-anim-tool. Try out a custom easing & try out a preset. Make sure nothing errors out and it follows spec above.


<!-- Please reference the issue(s) this PR addresses. -->

Fixes # 2283 - https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2283

Screenshots

Screen Shot 2020-06-05 at 12 39 52 PM Screen Shot 2020-06-05 at 12 39 40 PM

+29 -2

2 comments

4 changed files

littlemilkstudio

pr closed time in a month

issue commentgoogle/web-stories-wp

Add Easing Presets Selector to Story Anim Tool

https://github.com/google/web-stories-wp/pull/2284

littlemilkstudio

comment created time in a month

PR opened google/web-stories-wp

Feature | Easing Presets

Summary

Adds base easing presets field to /story-anim-tools which contains frequently used bezier values found here: https://easings.net/

Way this works is custom Easing field always overrides it, but if nothing found in custom field, it will use the selected preset.

Relevant Technical Choices

Quick n' Dirty

To-do

NA

User-facing changes

NA

Testing Instructions

Turn enableAnimation feature on.

Go to /story-anim-tool. Try out a custom easing & try out a preset. Make sure nothing errors out and it follows spec above.

<!-- Please reference the issue(s) this PR addresses. -->

Fixes # https://app.zenhub.com/workspaces/web-stories-5e94d3aced449034e1e9b226/issues/google/web-stories-wp/2283

+29 -2

0 comment

4 changed files

pr created time in a month

issue openedgoogle/web-stories-wp

Add Easing Presets Selector to Story Anim Tool

Add selector for frequently used bezier curves to story anim tool found here: https://easings.net/

But still allow for custom input for easing

created time in a month

create barnchgoogle/web-stories-wp

branch : task/easing-selection

created branch time in a month

Pull request review commentgoogle/web-stories-wp

Quick bug fix to story anim tool

 function Timeline({        onAddOrUpdateAnimation(         Object.keys(animation)-          .filter((name) => typeof animation[name] !== 'undefined')+          .filter(+            (name) =>+              typeof animation[name] !== 'undefined' && animation[name] !== ''+          )           .reduce(

oh yea, I did a quick and dirty fix for this in the scrubbing feature, but I like this better.

Also may be nice to make easing a dropdown with an option for custom input cus I find myself referencing these a lot: https://easings.net/#easeOutSine

mariano-formidable

comment created time in a month

delete branch google/web-stories-wp

delete branch : feature/pasue-n-play-anim-tool

delete time in a month

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 0025e4c9a2ecb4b72101739c94a19451a8f6eef2

add scrub & pause functionality to previewPage

view details

Maxwell Yinger

commit sha cfb9186c979f62ffb2a70c92936268e6281f6795

working scrubber

view details

Maxwell Yinger

commit sha 0c32551403c0a14e7979941d5f5aa10a97e89f56

cleanup wip

view details

Maxwell Yinger

commit sha 24c1f20cb3c97b6d41caf95d37b072baad8117c1

fix unit tests

view details

Maxwell Yinger

commit sha 833d07116b71ddc7c74a308ed690c2c764fce144

hopefully this fixes CI failing this test

view details

Maxwell Yinger

commit sha 6cc9c9f10062f53633bf76ec6fe040fc0ce768b4

revert animation flag

view details

Maxwell Yinger

commit sha cd9784f8521992ae7349211b938b1d6d97f62a34

cleanup from comments

view details

Max Yinger

commit sha b9ddf651e35506de866deeb92d67ebfdc1b0336d

Merge pull request #2260 from google/feature/pasue-n-play-anim-tool Feature | Adds animation controls in /story-anim-tool

view details

push time in a month

PR merged google/web-stories-wp

Reviewers
Feature | Adds animation controls in /story-anim-tool cla: yes

Summary

This should just help us assess how animations are looking while we're building them

Relevant Technical Choices

Just tried to get this working as quick as possible cus it's a temporary internal tool. So may be a little messy.

To-do

NA

User-facing changes

none

Testing Instructions

Update enableAnimation feature flag to be true, then:

Go to /story-anim-tool and add animations to your story and use the animation method buttons: play, pause, reset & scrub


Fixes # Helps all template animation tickets

Screenshots

scrub_functionality

+207 -33

2 comments

13 changed files

littlemilkstudio

pr closed time in a month

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha cd9784f8521992ae7349211b938b1d6d97f62a34

cleanup from comments

view details

push time in a month

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 6cc9c9f10062f53633bf76ec6fe040fc0ce768b4

revert animation flag

view details

push time in a month

push eventgoogle/web-stories-wp

Maxwell Yinger

commit sha 833d07116b71ddc7c74a308ed690c2c764fce144

hopefully this fixes CI failing this test

view details

push time in a month

more