Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/app/ProfileFilterNavigator.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
inset-inline-start: 4px;
}

span.profileFilterNavigator--tab-selector::before {
.profileFilterNavigator--tab-selector:not(.button)::before {
/* Disabled tab selector indicates this with a grayed out arrow. */
color: var(--grey-30);
}
Expand All @@ -38,7 +38,7 @@ span.profileFilterNavigator--tab-selector::before {
color: currentcolor;
}

span.profileFilterNavigator--tab-selector::before {
.profilefilternavigator--tab-selector:not(.button)::before {
color: GrayText;
}
}
20 changes: 14 additions & 6 deletions src/components/app/ProfileFilterNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class ProfileFilterNavigatorBarImpl extends React.PureComponent<Props> {
}
);

_onFirstItemClick = (event: React.MouseEvent<HTMLElement>) => {
this._showTabSelectorMenu(event);
};

_showTabSelectorMenu = (event: React.MouseEvent<HTMLElement>) => {
if (this.props.items.length > 0 || this.props.uncommittedItem) {
// Do nothing if there are committed ranges. We only allow users to change
Expand Down Expand Up @@ -82,6 +86,7 @@ class ProfileFilterNavigatorBarImpl extends React.PureComponent<Props> {
} = this.props;

let firstItem;
let isFirstItemClickable = false;
if (pageDataByTabID && pageDataByTabID.size > 0) {
const pageData =
tabFilter !== null ? pageDataByTabID.get(tabFilter) : null;
Expand Down Expand Up @@ -114,18 +119,18 @@ class ProfileFilterNavigatorBarImpl extends React.PureComponent<Props> {
);

if (items.length === 0 && !uncommittedItem) {
// It should be a clickable button if there are no committed ranges.
// It should be clickable if there are no committed ranges.
isFirstItemClickable = true;
firstItem = (
<button
type="button"
onClick={this._showTabSelectorMenu}
<span
className={classNames(
'filterNavigatorBarItemContent',
'profileFilterNavigator--tab-selector'
'profileFilterNavigator--tab-selector',
'button'
)}
>
{itemContents}
</button>
</span>
);
} else {
// There are committed ranges, don't make it button because this will
Expand Down Expand Up @@ -169,6 +174,9 @@ class ProfileFilterNavigatorBarImpl extends React.PureComponent<Props> {
selectedItem={selectedItem}
uncommittedItem={uncommittedItem}
onPop={onPop}
onFirstItemClick={
isFirstItemClickable ? this._onFirstItemClick : undefined
}
/>
{pageDataByTabID && pageDataByTabID.size > 0 ? (
<TabSelectorMenu />
Expand Down
6 changes: 4 additions & 2 deletions src/components/shared/FilterNavigatorBar.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@
}

.filterNavigatorBarItem:not(.filterNavigatorBarLeafItem):hover,
.filterNavigatorBarItem:has(button.profileFilterNavigator--tab-selector):hover {
.filterNavigatorBarItem:has(
.profileFilterNavigator--tab-selector.button
):hover {
background-color: var(--internal-hover-background-color);
color: var(--internal-hover-color);
}
Expand Down Expand Up @@ -168,7 +170,7 @@

/* When the tab selector is active, we want the item to look like a button */
.filterNavigatorBarSelectedItem:has(
button.profileFilterNavigator--tab-selector
.profileFilterNavigator--tab-selector.button
) {
background-color: ButtonFace;
color: ButtonText;
Expand Down
65 changes: 48 additions & 17 deletions src/components/shared/FilterNavigatorBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import classNames from 'classnames';
import './FilterNavigatorBar.css';

type FilterNavigatorBarListItemProps = {
readonly onClick?: null | ((index: number) => unknown);
readonly onClick?:
| null
| ((index: number, event: React.MouseEvent<HTMLElement>) => unknown);
readonly index: number;
readonly isFirstItem: boolean;
readonly isLastItem: boolean;
Expand All @@ -18,10 +20,10 @@ type FilterNavigatorBarListItemProps = {
};

class FilterNavigatorBarListItem extends React.PureComponent<FilterNavigatorBarListItemProps> {
_onClick = () => {
_onClick = (event: React.MouseEvent<HTMLElement>) => {
const { index, onClick } = this.props;
if (onClick) {
onClick(index);
onClick(index, event);
}
};

Expand Down Expand Up @@ -61,29 +63,58 @@ type Props = {
readonly className: string;
readonly items: ReadonlyArray<React.ReactNode>;
readonly onPop: (param: number) => void;
readonly onFirstItemClick?: (event: React.MouseEvent<HTMLElement>) => void;
readonly selectedItem: number;
readonly uncommittedItem?: string;
};

export class FilterNavigatorBar extends React.PureComponent<Props> {
_onPop = (index: number, _event: React.MouseEvent<HTMLElement>) => {
const { onPop } = this.props;
onPop(index);
};

_onFirstItemClick = (_: number, event: React.MouseEvent<HTMLElement>) => {
const { onFirstItemClick } = this.props;
if (onFirstItemClick) {
onFirstItemClick(event);
}
};

override render() {
const { className, items, selectedItem, uncommittedItem, onPop } =
this.props;
const {
className,
items,
selectedItem,
uncommittedItem,
onFirstItemClick,
} = this.props;

return (
<ol className={classNames('filterNavigatorBar', className)}>
{items.map((item, i) => (
<FilterNavigatorBarListItem
key={i}
index={i}
onClick={i === items.length - 1 && !uncommittedItem ? null : onPop}
isFirstItem={i === 0}
isLastItem={i === items.length - 1}
isSelectedItem={i === selectedItem}
>
{item}
</FilterNavigatorBarListItem>
))}
{items.map((item, i) => {
let onClick = null;
if (i === 0 && !uncommittedItem && onFirstItemClick) {
onClick = this._onFirstItemClick;
} else if (i === items.length - 1 && !uncommittedItem) {
onClick = null;
} else {
onClick = this._onPop;
}

return (
<FilterNavigatorBarListItem
key={i}
index={i}
onClick={onClick}
isFirstItem={i === 0}
isLastItem={i === items.length - 1}
isSelectedItem={i === selectedItem}
>
{item}
</FilterNavigatorBarListItem>
);
})}
{uncommittedItem ? (
<FilterNavigatorBarListItem
index={items.length}
Expand Down
17 changes: 17 additions & 0 deletions src/test/components/FilterNavigatorBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,21 @@ describe('app/ProfileFilterNavigator', () => {
const { getByText } = setup();
expect(getByText(/Full Range/)).toBeInTheDocument();
});

it('opens a menu when the first item is clicked', () => {
const { getByText } = setup();

const item = getByText(/Full Range/).closest('.filterNavigatorBarItem');

const listener = jest.fn();
window.addEventListener('REACT_CONTEXTMENU_SHOW', listener);
fireEvent.click(item!);
window.removeEventListener('REACT_CONTEXTMENU_SHOW', listener);

expect(listener).toHaveBeenCalledWith(
expect.objectContaining({
type: 'REACT_CONTEXTMENU_SHOW',
})
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ exports[`app/ProfileFilterNavigator renders ProfileFilterNavigator properly 1`]
<li
class="filterNavigatorBarItem filterNavigatorBarRootItem filterNavigatorBarSelectedItem filterNavigatorBarLeafItem"
>
<span
<button
class="filterNavigatorBarItemContent"
type="button"
>
<button
class="filterNavigatorBarItemContent profileFilterNavigator--tab-selector"
type="button"
<span
class="filterNavigatorBarItemContent profileFilterNavigator--tab-selector button"
>
Full Range (⁨51ms⁩)
</button>
</span>
</span>
</button>
</li>
</ol>
`;
Expand Down