From d2864e6c36e0c1468269ef46bbb0006b2f6e6434 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 9 Dec 2024 08:42:29 -0800 Subject: [PATCH 1/9] styled the clear button --- src/app/App.tsx | 12 ++---- .../StateRoute/ComponentMap/ComponentMap.tsx | 4 +- src/app/containers/ActionContainer.tsx | 20 ++++------ src/app/containers/MainContainer.tsx | 2 +- src/app/styles/abstracts/_variablesLM.scss | 20 +++++----- .../styles/components/_actionComponent.scss | 9 +---- src/app/styles/components/_buttons.scss | 39 ++++++++++++------- src/app/styles/theme.ts | 31 --------------- 8 files changed, 50 insertions(+), 87 deletions(-) delete mode 100644 src/app/styles/theme.ts diff --git a/src/app/App.tsx b/src/app/App.tsx index df58c3232..199e209aa 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1,8 +1,6 @@ import React from 'react'; import { MemoryRouter as Router } from 'react-router-dom'; import MainContainer from './containers/MainContainer'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from './styles/theme'; /* 'currentTab' is the current active tab within Google Chrome. @@ -12,12 +10,10 @@ import theme from './styles/theme'; function App(): JSX.Element { return ( - - - {/* we wrap our application with the tag so that all components that are nested will have the react-router context */} - - - + + {/* we wrap our application with the tag so that all components that are nested will have the react-router context */} + + ); } diff --git a/src/app/components/StateRoute/ComponentMap/ComponentMap.tsx b/src/app/components/StateRoute/ComponentMap/ComponentMap.tsx index c4e813e15..6cf5476d9 100644 --- a/src/app/components/StateRoute/ComponentMap/ComponentMap.tsx +++ b/src/app/components/StateRoute/ComponentMap/ComponentMap.tsx @@ -215,8 +215,7 @@ export default function ComponentMap({ }; let filtered = processTreeData(currentSnapshot); - console.log('filtered', filtered); - collectNodes(filtered); + collectNodes(currentSnapshot); const keepContextAndProviderNodes = (node) => { if (!node) return null; @@ -248,7 +247,6 @@ export default function ComponentMap({ }; const contextProvidersOnly = keepContextAndProviderNodes(currentSnapshot); - console.log('context only', contextProvidersOnly); // @ts // find the node that has been selected and use it as the root diff --git a/src/app/containers/ActionContainer.tsx b/src/app/containers/ActionContainer.tsx index 70409e99e..7b37c8800 100644 --- a/src/app/containers/ActionContainer.tsx +++ b/src/app/containers/ActionContainer.tsx @@ -11,7 +11,6 @@ import ProvConContainer from './ProvConContainer'; import { ActionContainerProps, CurrentTab, MainState, Obj, RootState } from '../FrontendTypes'; import { Button, Switch } from '@mui/material'; - /* This file renders the 'ActionContainer'. The action container is the leftmost column in the application. It includes the button that shrinks and expands the action container, a dropdown to select the active site, a clear button, the current selected Route, and a list of selectable snapshots with timestamps. */ @@ -27,7 +26,6 @@ const resetSlider = () => { }; function ActionContainer(props: ActionContainerProps): JSX.Element { - const [dropdownSelection, setDropdownSelection] = useState('TimeJump'); const dispatch = useDispatch(); @@ -229,15 +227,14 @@ function ActionContainer(props: ActionContainerProps): JSX.Element { {/* add new component here for dropdown menu for useStae/ useReducer- ragad */} - +
- {dropdownSelection === 'Provider/Consumer' && } - {dropdownSelection === 'TimeJump' && + {dropdownSelection === 'Provider/Consumer' && } + {dropdownSelection === 'TimeJump' && Object.keys(routes).map((route, i) => ( - )) - } + ))} ) : null} diff --git a/src/app/containers/MainContainer.tsx b/src/app/containers/MainContainer.tsx index 9f91bd980..6d092a88f 100644 --- a/src/app/containers/MainContainer.tsx +++ b/src/app/containers/MainContainer.tsx @@ -33,7 +33,7 @@ function MainContainer(): JSX.Element { const { connectionStatus }: MainState = useSelector((state: RootState) => state.main); // JR 12.22.23: so far this log always returns true - // console.log('MainContainer connectionStatus at initialization: ', connectionStatus); + console.log('MainContainer connectionStatus at initialization: ', connectionStatus); const [actionView, setActionView] = useState(true); // We create a local state 'actionView' and set it to true diff --git a/src/app/styles/abstracts/_variablesLM.scss b/src/app/styles/abstracts/_variablesLM.scss index 75501f4af..7fb54051d 100644 --- a/src/app/styles/abstracts/_variablesLM.scss +++ b/src/app/styles/abstracts/_variablesLM.scss @@ -26,17 +26,17 @@ $contrasting-color: #161617; $contrasting-color-weak: #353536; /// HEATMAP COLORS -$heat-level-1: #F1B476; -$heat-level-2: #E4765B; -$heat-level-3: #C64442; -$heat-level-4: #8C2743; +$heat-level-1: #f1b476; +$heat-level-2: #e4765b; +$heat-level-3: #c64442; +$heat-level-4: #8c2743; ///////////////////////////////////////////////////////////////////// // ALL OF THE FOLLOWING COLORS SHOULD REFERENCE A COLOR FROM ABOVE // ///////////////////////////////////////////////////////////////////// /// @type Color - + //general text color theme $dark-text: $contrasting-color; $light-text: $background-color; @@ -70,14 +70,14 @@ $tab-arrow-indicator: lighten($contrasting-color, 30%); //SNAPSHOTS AND ROUTES LIST $action-tab-background: $background-color; $action-cont-border: $contrasting-color; -//$action-clear-button: $primary-color; //currently being handled by mui theme.ts file -//$action-clear-button-text: $background-color; //currently being handled by mui theme.ts file +// $action-clear-button: $primary-color; +// $action-clear-button-text: $background-color; $route-bar: $primary-color-strong; $route-bar-text: $light-text; $indiv-action-input-bg: $background-color-strong; $indiv-action-selected: darken($background-color, 15%); $indiv-action-selected-text: $light-text; -$indiv-action-filler-text: lighten($contrasting-color,60%); +$indiv-action-filler-text: lighten($contrasting-color, 60%); $indiv-action-custom-text: $dark-text; $indiv-action-border: $contrasting-color-weak; $indiv-action-time: $primary-color-weak; @@ -98,12 +98,12 @@ $header-button-inactive-text: $dark-text; $header-button-hover: lighten($header-button-inactive, 20%); //the buttons/tabs controlling what is displayed in STATECONTAINER (Map, Performance, History, Web Metrics, Tree) -$navbar-background: $background-color; //this color only shows up in Diff mode when buttons don't fill the whole bar //DIFF FEATURE IS CURRENTLY COMMENTED OUT +$navbar-background: $background-color; //this color only shows up in Diff mode when buttons don't fill the whole bar //DIFF FEATURE IS CURRENTLY COMMENTED OUT $navbar-selected: $primary-color-strong; $navbar-selected-text: $light-text; $navbar-unselected: $primary-color-weak; $navbar-unselected-text: $dark-text; -$navbar-hover: darken($navbar-unselected,15%); +$navbar-hover: darken($navbar-unselected, 15%); $state-background: $background-color-strong; $state-cont-border: $contrasting-color; diff --git a/src/app/styles/components/_actionComponent.scss b/src/app/styles/components/_actionComponent.scss index b28f8fcfc..6a3dabadf 100644 --- a/src/app/styles/components/_actionComponent.scss +++ b/src/app/styles/components/_actionComponent.scss @@ -15,20 +15,15 @@ @extend %disable-highlight; } -.clear-button { - background-color:#187924; - color:#187924; -} - .action-component-text { margin-bottom: 8px; - color: $indiv-action-custom-text + color: $indiv-action-custom-text; } .action-component.selected { //font-size: 16px; background-color: $indiv-action-selected; - color: $indiv-action-selected-text + color: $indiv-action-selected-text; } .action-component.exclude { diff --git a/src/app/styles/components/_buttons.scss b/src/app/styles/components/_buttons.scss index 5eb55191e..0c2bc961c 100644 --- a/src/app/styles/components/_buttons.scss +++ b/src/app/styles/components/_buttons.scss @@ -13,7 +13,9 @@ border-radius: 5px; cursor: pointer; line-height: 1.5em; - font: 400 16px 'Outfit', sans-serif; + font: + 400 16px 'Outfit', + sans-serif; width: 120px; background: $performance-save-series-button; height: 30px; @@ -37,7 +39,9 @@ border-radius: 3px; cursor: pointer; line-height: 1.5em; - font: 300 16px 'Outfit', sans-serif; + font: + 300 16px 'Outfit', + sans-serif; font-size: $button-text-size; width: 120px; height: 30px; @@ -59,17 +63,13 @@ border-radius: 3px; cursor: pointer; line-height: 1.5em; - font: 500 16px 'Roboto', sans-serif; + font: + 500 16px 'Roboto', + sans-serif; width: 120px; //background: #ff0000; } -.clear-button { - background: #3256f1; - background-color: #050787; - color: #3256f1; -} - .empty-button:hover { color: black; box-shadow: #ff0001; @@ -87,7 +87,9 @@ .action-component:hover .jump-button { opacity: 1; transform: rotateX(0deg); - transition: opacity 300ms, transform 0.15s linear; + transition: + opacity 300ms, + transform 0.15s linear; } .time-button { @@ -114,7 +116,9 @@ background-color: #232529; color: #ffffff; transform: rotateX(90deg); - transition: opacity 300ms, transform 0.15s linear; + transition: + opacity 300ms, + transform 0.15s linear; opacity: 0; display: flex; align-items: center; @@ -215,7 +219,9 @@ align-items: center; cursor: pointer; line-height: 1.5em; - font: 300 16px 'Outfit', sans-serif; + font: + 300 16px 'Outfit', + sans-serif; font-size: $button-text-size; background: #ff0001; @@ -234,8 +240,12 @@ background-image: -moz-linear-gradient(top, transparent, rgba(0, 0, 0, 0.4)); background-image: -o-linear-gradient(top, transparent, rgba(0, 0, 0, 0.4)); background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.4)); - -webkit-box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px 1px rgba(0, 0, 0, 0.2); - box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px 1px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: + inset 0 1px rgba(255, 255, 255, 0.1), + 0 1px 1px rgba(0, 0, 0, 0.2); + box-shadow: + inset 0 1px rgba(255, 255, 255, 0.1), + 0 1px 1px rgba(0, 0, 0, 0.2); } .dropdown-dark:before { @@ -275,7 +285,6 @@ } .dropdown-and-delete-series-container { - display: flex; align-items: center; justify-content: space-around; diff --git a/src/app/styles/theme.ts b/src/app/styles/theme.ts deleted file mode 100644 index d3e93e2bc..000000000 --- a/src/app/styles/theme.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { createTheme } from '@mui/material/styles'; -const theme = createTheme({ - // typography: { - // fontSize: 2, - // }, - palette: { - primary: { - main: '#3c6e71', - }, - secondary: { - main: '#3c6e71', - }, - }, - components: { - // Name of the component - - MuiButton: { - styleOverrides: { - // Name of the slot - root: { - // Some CSS - fontSize: '0.8rem', - letterSpacing: '0.1rem', - lineHeight: '0.8rem', - }, - }, - }, - }, -}); - -export default theme; From cd86f256b3800a5df2e4ed9a35c6d5d69e21a485 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 9 Dec 2024 12:48:51 -0800 Subject: [PATCH 2/9] styled clear button and route description header --- .../components/Actions/RouteDescription.tsx | 25 +++++++------------ src/app/containers/ActionContainer.tsx | 13 ++++------ src/app/styles/abstracts/_variablesLM.scss | 4 --- .../styles/components/_actionComponent.scss | 24 ++++++++++++------ src/app/styles/components/_buttons.scss | 16 ++++++++++++ src/app/styles/layout/_actionContainer.scss | 18 ++++++------- 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/app/components/Actions/RouteDescription.tsx b/src/app/components/Actions/RouteDescription.tsx index 92297e269..2a248fbc2 100644 --- a/src/app/components/Actions/RouteDescription.tsx +++ b/src/app/components/Actions/RouteDescription.tsx @@ -16,24 +16,17 @@ const RouteDescription = (props: RouteProps): JSX.Element => { const url: URL = new URL(actions[0].props.routePath); // Use new URL to use the url.pathname method. return ( -
-

Route: {url.pathname}

-
- -
- {/* actual snapshots per route */} - {actions} -
-
+
+
Route: {url.pathname}
+
+ +
+ {/* actual snapshots per route */} + {actions} +
+
); }; - export default RouteDescription; diff --git a/src/app/containers/ActionContainer.tsx b/src/app/containers/ActionContainer.tsx index d846b2abc..256859d79 100644 --- a/src/app/containers/ActionContainer.tsx +++ b/src/app/containers/ActionContainer.tsx @@ -14,7 +14,6 @@ import { Button, Switch } from '@mui/material'; This file renders the 'ActionContainer'. The action container is the leftmost column in the application. It includes the button that shrinks and expands the action container, a dropdown to select the active site, a clear button, the current selected Route, and a list of selectable snapshots with timestamps. */ - // resetSlider locates the rc-slider elements on the document and resets it's style attributes const resetSlider = () => { const slider = document.querySelector('.rc-slider-handle'); @@ -57,7 +56,6 @@ function ActionContainer(props: ActionContainerProps): JSX.Element { children?: []; } */ - const displayArray = (obj: Obj): void => { if ( @@ -234,9 +232,9 @@ function ActionContainer(props: ActionContainerProps): JSX.Element { dropdownSelection={dropdownSelection} setDropdownSelection={setDropdownSelection} /> -
+
- {dropdownSelection === 'Provider/Consumer' && } - {dropdownSelection === 'TimeJump' && + {dropdownSelection === 'Provider/Consumer' && } + {dropdownSelection === 'TimeJump' && Object.keys(routes).map((route, i) => ( - )) - } + ))}
) : null} diff --git a/src/app/styles/abstracts/_variablesLM.scss b/src/app/styles/abstracts/_variablesLM.scss index 7fb54051d..a18fc4f7c 100644 --- a/src/app/styles/abstracts/_variablesLM.scss +++ b/src/app/styles/abstracts/_variablesLM.scss @@ -70,10 +70,6 @@ $tab-arrow-indicator: lighten($contrasting-color, 30%); //SNAPSHOTS AND ROUTES LIST $action-tab-background: $background-color; $action-cont-border: $contrasting-color; -// $action-clear-button: $primary-color; -// $action-clear-button-text: $background-color; -$route-bar: $primary-color-strong; -$route-bar-text: $light-text; $indiv-action-input-bg: $background-color-strong; $indiv-action-selected: darken($background-color, 15%); $indiv-action-selected-text: $light-text; diff --git a/src/app/styles/components/_actionComponent.scss b/src/app/styles/components/_actionComponent.scss index 6a3dabadf..03156a8f1 100644 --- a/src/app/styles/components/_actionComponent.scss +++ b/src/app/styles/components/_actionComponent.scss @@ -26,13 +26,6 @@ color: $indiv-action-selected-text; } -.action-component.exclude { - color: #ff0000; - display: flex; - justify-content: center; - margin-top: 10px; -} - .action-component:focus { outline: none; } @@ -46,3 +39,20 @@ overflow: hidden; @extend %disable-highlight; } + +.route-container { + width: 100%; +} + +.route-header { + background-color: #1f2937; + color: #ffffff; + padding: 10px; + font-size: 14px; +} + +.route-content { + display: flex; + flex-direction: row; + margin-bottom: 50px; +} diff --git a/src/app/styles/components/_buttons.scss b/src/app/styles/components/_buttons.scss index 0c2bc961c..dd18323de 100644 --- a/src/app/styles/components/_buttons.scss +++ b/src/app/styles/components/_buttons.scss @@ -471,3 +471,19 @@ aside { margin-left: 5px; margin-right: -22px; } + +.clear-button-modern { + width: 100% !important; + background-color: #f3f4f6 !important; + color: #374151 !important; + font-size: 0.875rem !important; + font-weight: 500 !important; + text-transform: uppercase !important; + padding: 0.375rem 1rem !important; + border-radius: 0.375rem !important; + transition: background-color 200ms ease-in-out !important; +} + +.clear-button-modern:hover { + background-color: #e5e7eb !important; +} diff --git a/src/app/styles/layout/_actionContainer.scss b/src/app/styles/layout/_actionContainer.scss index 57a5655fe..c5b6ad0b8 100644 --- a/src/app/styles/layout/_actionContainer.scss +++ b/src/app/styles/layout/_actionContainer.scss @@ -1,7 +1,9 @@ .action-container { // overflow: auto; + background: white; + border-right: 1px solid #e5e7eb; + transition: width 0.3s ease; overflow-x: hidden; - background-color: $action-tab-background; } .actionname { @@ -34,14 +36,10 @@ width: 28px; } -.route { - background-color: $route-bar; - color: $route-bar-text; - padding-left: 10px; - padding-top: 5px; - padding-bottom: 5px; -} - .toggle-record { color: $toggle-record-text; -} \ No newline at end of file +} + +.clear-button-container { + padding: 16px; +} From 4c1c412ab56a0b16ce1c388ef127e614c345cd1d Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 9 Dec 2024 12:54:32 -0800 Subject: [PATCH 3/9] adjusted for fixed siwth of action container --- .../components/Actions/RouteDescription.tsx | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/app/components/Actions/RouteDescription.tsx b/src/app/components/Actions/RouteDescription.tsx index 95f82a771..1b1fc1ee5 100644 --- a/src/app/components/Actions/RouteDescription.tsx +++ b/src/app/components/Actions/RouteDescription.tsx @@ -16,24 +16,18 @@ const RouteDescription = (props: RouteProps): JSX.Element => { const url: URL = new URL(actions[0].props.routePath); // Use new URL to use the url.pathname method. return ( -
-

Route: {url.pathname}

-
-
- -
-
- {/* actual snapshots per route */} - {actions} -
-
+
+
Route: {url.pathname}
+
+
+ +
+
+ {/* actual snapshots per route */} + {actions} +
+
); }; From e79c3c1adb6b33ed74fe91410a95829c775285d9 Mon Sep 17 00:00:00 2001 From: Garrett Date: Mon, 9 Dec 2024 13:26:31 -0800 Subject: [PATCH 4/9] fixed snapshot naming and current status of snapshots --- src/app/components/Actions/Action.tsx | 90 +++++++++----------------- src/app/containers/ActionContainer.tsx | 2 +- 2 files changed, 31 insertions(+), 61 deletions(-) diff --git a/src/app/components/Actions/Action.tsx b/src/app/components/Actions/Action.tsx index 31dd368ae..ed47b7755 100644 --- a/src/app/components/Actions/Action.tsx +++ b/src/app/components/Actions/Action.tsx @@ -1,95 +1,59 @@ -/* eslint-disable react/require-default-props */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable react/no-unused-prop-types */ - import React from 'react'; import ReactHover, { Trigger, Hover } from 'react-hover'; import { changeView, changeSlider } from '../../slices/mainSlice'; import { ActionProps, OptionsCursorTrueWithMargin } from '../../FrontendTypes'; import { useDispatch } from 'react-redux'; -/* - This renders the individual snapshot components on the left side column -*/ - -/** - * @function Action - * @param selected : The selected action in the array of state changes - * @param displayName : Label showing sequence number of state change, reflects changes in Chart.tsx - * @param componentName : Displays the name of compenent's state being changed - * @param last : The last index in the array - * @param sliderIndex: Index of the slider in the array of state changes - * (clicking the block changes the slider, related to MainSlider.tsx slider) - * @param componentData: Displays react fiber data - * @param viewIndex: Index of the tab in the array when timejump is made - * @method dispatch Executes actions that changes state in reactime - * @method handleOnkeyDown Executes key commands - * - */ - const Action = (props: ActionProps): JSX.Element => { - //here we are adding useSelector and useDispatch for RTK state conversion const dispatch = useDispatch(); - // We destructure the 'props' that were passed into this component const { - selected, // boolean on whether the current index is the same as the viewIndex in 'ActionContainer' - last, // boolean on (whether the view index is less than 0) AND if (the index is the same as the last snapshot's index value in hierarchyArr) in 'ActionContainer' - index, // from snapshot.index in "ActionContainer's" 'hierarchyArr' - sliderIndex, // from tabs[currentTab] object in 'ActionContainer' - displayName, // from snapshot.displayName in "ActionContainer's" 'hierarchyArr' - componentData, // from snapshot.componentData in "ActionContainer's" 'hierarchyArr' - viewIndex, // from tabs[currentTab] object in 'ActionContainer' + selected, + last, + index, + sliderIndex, + displayName, + componentData, + viewIndex, isCurrIndex, - handleOnkeyDown, // function that allows arrows keys to jump between snapshots defined in 'ActionContainer.tsx' + handleOnkeyDown, } = props; - /** - * @function cleanTime: Displays render times for state changes - * @returns render display time in seconds in milliseconds - */ - const cleanTime = (): string => { if (!componentData || !componentData.actualDuration) { - // if there is no 'componentData' or 'componentData.actualDuration' return 'NO TIME'; } - let seconds: number | string; // seconds is undefined but can take a number or a string - let milliseconds: any = componentData.actualDuration; // milliseconds is of any type and taken from the 'componentData.actualDuration' + let seconds: number | string; + let milliseconds: any = componentData.actualDuration; if (Math.floor(componentData.actualDuration) > 60) { - // if the milliseconds is greater than 60 - seconds = Math.floor(componentData.actualDuration / 60); // we divide our milliseconds by 60 to determine our seconds - seconds = JSON.stringify(seconds); // and we convert our seconds into a string + seconds = Math.floor(componentData.actualDuration / 60); + seconds = JSON.stringify(seconds); if (seconds.length < 2) { - // if the seconds string is only a single digit - seconds = '0'.concat(seconds); // we can add a 0 in front of it so that if 'seconds = "1"' it will come out as 'seconds = "01"' + seconds = '0'.concat(seconds); } - milliseconds = Math.floor(componentData.actualDuration % 60); // Our true milliseconds then becomes the remainder of dividing our initial milliseconds by 60 + milliseconds = Math.floor(componentData.actualDuration % 60); } else { - seconds = '00'; // if we haven't even reached one second yet, our seconds are 00 + seconds = '00'; } - milliseconds = Number.parseFloat(milliseconds as string).toFixed(2); // we convert our milliseconds string into a floating point number that has up to two decimal places. - const arrayMilliseconds: [string, number] = milliseconds.split('.'); // we split our milliseconds using the decimal and come out with an array of two numbers + milliseconds = Number.parseFloat(milliseconds as string).toFixed(2); + const arrayMilliseconds: [string, number] = milliseconds.split('.'); if (arrayMilliseconds[0].length < 2) { - // if our millisecond string only has one digit - arrayMilliseconds[0] = '0'.concat(arrayMilliseconds[0]); // we add a 0 in front of it so that in the a sample number of '1' becomes '01' + arrayMilliseconds[0] = '0'.concat(arrayMilliseconds[0]); } if (index === 0) { - // if this is the initial snapshot - return `${seconds}:${arrayMilliseconds[0]}.${arrayMilliseconds[1]}`; // we give it a timestamp + return `${seconds}:${arrayMilliseconds[0]}.${arrayMilliseconds[1]}`; } - return `+${seconds}:${arrayMilliseconds[0]}.${arrayMilliseconds[1]}`; // if these are succeeding snapshots, we add a '+' to the timestamp + return `+${seconds}:${arrayMilliseconds[0]}.${arrayMilliseconds[1]}`; }; - const displayTime: string = cleanTime(); // we run cleanTime on the creation of this component so that we can get the timestamp + const displayTime: string = cleanTime(); - // creates an options object that 'ReactHover' component will use to modify it's behaviour const optionsCursorTrueWithMargin: OptionsCursorTrueWithMargin = { followCursor: true, shiftX: 20, @@ -123,9 +87,15 @@ const Action = (props: ActionProps): JSX.Element => { placeholder={`Snapshot: ${displayName}`} />
- + {isCurrIndex ? ( + + ) : ( + + )} {isCurrIndex ? (
{isCurrIndex ? ( - ) : (