Skip to content

Commit

Permalink
feat(frontend): new tags dropdown (#642)
Browse files Browse the repository at this point in the history
* chore(frontend): access Dropdown related items via indirection

* chore: support /label-values on 4041

* chore: migrate TagsBar to use @ui/Dropdown

* get rid of custom css for tags bar

* fix(frontend): scroll tagsbar

* feat(frontend): allow searching tags dropdown

* keep filter state for each tag
  • Loading branch information
eh-am committed Dec 22, 2021
1 parent 09e4e51 commit 6290e45
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 79 deletions.
3 changes: 3 additions & 0 deletions scripts/webpack/webpack.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ module.exports = merge(common, {
app.use(
builtins.proxy('/labels-diff', { target: 'http://localhost:4040' })
);
app.use(
builtins.proxy('/label-values', { target: 'http://localhost:4040' })
);

// New Endpoints are implemented under /api
app.use(builtins.proxy('/api', { target: 'http://localhost:4040' }));
Expand Down
22 changes: 20 additions & 2 deletions stories/Dropdown.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/* eslint-disable react/jsx-props-no-spreading */
import React, { useState } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Dropdown from '@ui/Dropdown';
import { MenuHeader, MenuItem, SubMenu } from '@szhsin/react-menu';
import Dropdown, { MenuItem, SubMenu } from '@ui/Dropdown';

const Template: ComponentStory<typeof Dropdown> = (args) => (
<DropdownSelect {...args} />
Expand Down Expand Up @@ -39,3 +38,22 @@ const DropdownSelect = (args) => {
</Dropdown>
);
};

export const DropdownWithLotsOfOptions = (args) => {
const times = 100;

// indirection just to shut up eslint
const getKey = (i: number) => i;

return (
<Dropdown {...args} label="Foobar">
<SubMenu label="foobar" overflow="auto" position="anchor">
{new Array(times).fill(0).map((a, i) => (
<MenuItem key={getKey(i)} value="foo">
foo
</MenuItem>
))}
</SubMenu>
</Dropdown>
);
};
63 changes: 43 additions & 20 deletions webapp/javascript/components/TagsBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Button from '@ui/Button';
import 'react-dom';
import { Menu, SubMenu, MenuItem, MenuButton } from '@szhsin/react-menu';
import Dropdown, { SubMenu, MenuItem, FocusableItem } from '@ui/Dropdown';

import {
fetchTags,
Expand All @@ -17,6 +17,7 @@ import styles from './TagsBar.module.css';

function TagsBar({ query, actions, tags, tagValuesLoading }) {
const [queryVal, setQuery] = useState(query);
const [filter, setFilter] = useState({});

useEffect(() => {
setQuery(query);
Expand Down Expand Up @@ -73,12 +74,8 @@ function TagsBar({ query, actions, tags, tagValuesLoading }) {
};

return (
<div className="tags-bar rc-menu-container--theme-dark">
<Menu
menuButton={<MenuButton>Select Tag</MenuButton>}
theming="dark"
keepMounted
>
<div className="tags-bar _rc-menu-container--theme-dark">
<Dropdown label="Select Tag">
{Object.keys(tags).length === 0 ? (
<MenuItem>No tags available</MenuItem>
) : (
Expand All @@ -88,6 +85,8 @@ function TagsBar({ query, actions, tags, tagValuesLoading }) {
<SubMenu
value={tag}
key={tag}
overflow="auto"
position="initial"
label={(e) => (
<span
className="tag-content"
Expand All @@ -102,25 +101,49 @@ function TagsBar({ query, actions, tags, tagValuesLoading }) {
)}
className="active"
>
{tags && tags[tag] && tags[tag].length > 1 && (
<FocusableItem>
{({ ref }) => (
<input
ref={ref}
type="text"
placeholder="Type a tag"
value={filter[tag] || ''}
onChange={(e) =>
setFilter({
...filter,
[tag]: e.target.value,
})
}
/>
)}
</FocusableItem>
)}

{tagValuesLoading === tag ? (
<MenuItem>Loading...</MenuItem>
) : (
tags[tag].map((tagValue) => (
<MenuItem
key={tagValue}
value={tagValue}
onClick={(e) => onTagsValueChange(tag, e.value)}
className={
queryVal.includes(`${tag}="${tagValue}"`) ? 'active' : ''
}
>
{tagValue}
</MenuItem>
))
tags[tag]
.filter((t) => {
const f = filter[tag] ? filter[tag].trim().toLowerCase() : '';
return t.toLowerCase().includes(f);
})
.map((tagValue) => (
<MenuItem
key={tagValue}
value={tagValue}
onClick={(e) => onTagsValueChange(tag, e.value)}
className={
queryVal.includes(`${tag}="${tagValue}"`) ? 'active' : ''
}
>
{tagValue}
</MenuItem>
))
)}
</SubMenu>
))}
</Menu>
</Dropdown>
<form
className="tags-query"
onSubmit={(e) => {
Expand Down
26 changes: 23 additions & 3 deletions webapp/javascript/ui/Dropdown.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,38 @@
.dropdownMenu {
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.33);
padding: 0.25rem 0;
background-color: $btn-color;
color: $white;
background-color: $btn-color !important;
color: $white !important;

& ul[class*='rc-menu'] {
background-color: $btn-color;
color: $white;
color: $white !important;
}

& li[class*='hover'],
div[class*='hover'] {
background-color: $btn-hover-color;
}

[class*='rc-menu--open']:empty {
display: none;
}

[class*='rc-menu__item active'] {
background-color: $btn-hover-color;
color: rgb(223, 139, 83);
}

[class*='rc-menu__item--focusable'] {
// important to ignore the hover effect
background-color: inherit !important;
padding-top: 1rem;
padding-bottom: 1rem;

input {
width: 100%;
}
}
}

.dropdownMenuButton {
Expand Down
15 changes: 14 additions & 1 deletion webapp/javascript/ui/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import React from 'react';
import { ClickEvent, Menu, MenuButton, MenuHeader } from '@szhsin/react-menu';
import {
ClickEvent,
Menu,
MenuHeader,
SubMenu as LibSubmenu,
MenuItem as LibMenuItem,
MenuButton as LibMenuButton,
FocusableItem as LibFocusableItem,
} from '@szhsin/react-menu';
import styles from './Dropdown.module.scss';

export interface DropdownProps {
Expand Down Expand Up @@ -52,3 +60,8 @@ export default function Dropdown({
</Menu>
);
}

export const SubMenu = LibSubmenu;
export const MenuItem = LibMenuItem;
export const MenuButton = LibMenuButton;
export const FocusableItem = LibFocusableItem;
53 changes: 0 additions & 53 deletions webapp/sass/components/tagsbar.scss
Original file line number Diff line number Diff line change
@@ -1,56 +1,11 @@
@use '../variables' as *;

@import '../../node_modules/@szhsin/react-menu/dist/index.css';
@import '../prism.scss';

.tags-bar {
display: flex;

padding: 5px 0 15px;
// padding: 5px 15px 15px;

.rc-menu-button {
outline: none;
display: inline-block;
position: relative;
border-radius: 4px;
background-color: $btn-color;
border: 1px solid $btn-border-color;
margin-right: 5px;
padding-right: 20px;
&::after {
content: '';
position: absolute;
top: 3px;
right: 5px;
}
}

.rc-menu {
// border: 1px solid #222222;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.33);
padding: 0.25rem 0;
}

.rc-menu,
.rc-menu__item {
background-color: $btn-color;
color: $white;
}

.rc-menu--open:empty {
display: none;
}

.rc-menu__item {
&:hover {
background-color: $btn-hover-color;
}
&.active {
background-color: $btn-hover-color;
color: rgb(223, 139, 83);
}
}

.tags-query {
flex-grow: 1;
Expand Down Expand Up @@ -120,14 +75,6 @@
}
}

.rc-menu__item {
$xpadding: 0.375rem;
$ypadding: 1.5rem;
$ypadding: 1rem;

padding: $xpadding $ypadding;
}

.tag-content {
width: 100%;
box-sizing: content-box;
Expand Down

0 comments on commit 6290e45

Please sign in to comment.