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
14 changes: 13 additions & 1 deletion stories/Box.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable react/jsx-props-no-spreading */
import React from 'react';
import Box from '@ui/Box';
import Box, { CollapseBox } from '@ui/Box';
import Button from '@ui/Button';
import { ComponentMeta } from '@storybook/react';
import '../webapp/sass/profile.scss';
Expand All @@ -24,3 +24,15 @@ export const BoxWithButtonNoPadding = () => (
<h1>Hello, world</h1>
</Box>
);

export const CollapseBoxWithContent = () => (
<CollapseBox title="Title">
<h1>Hello, world</h1>
</CollapseBox>
);

export const CollapseBoxWhenTitleIsEmptyString = () => (
<CollapseBox title="">
<h1>Hello, world</h1>
</CollapseBox>
);
4 changes: 2 additions & 2 deletions webapp/javascript/pages/TagExplorerView.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@

.tableDescription {
display: flex;
justify-content: space-between;
margin: 0 10px 10px;
justify-content: flex-end;
margin: 0 0 10px 10px;
}

.title {
Expand Down
11 changes: 7 additions & 4 deletions webapp/javascript/pages/TagExplorerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { ClickEvent } from '@szhsin/react-menu';
import Color from 'color';

import type { Profile } from '@pyroscope/models/src';
import Box from '@webapp/ui/Box';
import Box, { CollapseBox } from '@webapp/ui/Box';
import Toolbar from '@webapp/components/Toolbar';
import ExportData from '@webapp/components/ExportData';
import TimelineChartWrapper, {
Expand Down Expand Up @@ -238,7 +238,11 @@ function TagExplorerView() {
)}
</div>
</Box>
<Box>
<CollapseBox
title={`${appName
.map((a) => `${a} Descriptive Statistics`)
.unwrapOr('Descriptive Statistics')}`}
>
<Table
appName={appName.unwrapOr('')}
whereDropdownItems={whereDropdownItems}
Expand All @@ -248,7 +252,7 @@ function TagExplorerView() {
handleGroupByTagValueChange={handleGroupByTagValueChange}
isLoading={type === 'loading'}
/>
</Box>
</CollapseBox>
<Box>
<div className={styles.flamegraphWrapper}>
{type === 'loading' ? (
Expand Down Expand Up @@ -377,7 +381,6 @@ function Table({
return (
<>
<div className={styles.tableDescription} data-testid="explore-table">
<span className={styles.title}>{appName} Descriptive Statistics</span>
<div className={styles.buttons}>
<NavLink
to={{
Expand Down
45 changes: 45 additions & 0 deletions webapp/javascript/ui/Box.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,48 @@
margin-bottom: 10px;
padding: 10px;
}

.collapseBox {
@extend .box;
margin-bottom: 10px;

.box {
background-color: transparent;
border: none;
border-radius: 0;
padding-bottom: 0;
overflow: hidden;
height: auto;

&.collapsedContent {
height: 0;
margin: 0;
padding: 0;
}
}
}

.collapseTitle {
font-weight: 500;
font-size: 18px;
cursor: pointer;
padding: 5px 10px;
display: flex;
justify-content: space-between;
align-items: center;
height: 40px;

&:hover {
background-color: var(--ps-ui-border);
}
}

.collapseIcon {
display: flex;
transition: transform 0.1s;

&.collapsed {
transform: rotate(90deg);
display: flex;
}
}
42 changes: 41 additions & 1 deletion webapp/javascript/ui/Box.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React from 'react';
import React, { useState } from 'react';
import classNames from 'classnames/bind';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons/faChevronDown';
import styles from './Box.module.scss';

const cx = classNames.bind(styles);
/**
* Box renders its children with a box around it
*/
Expand All @@ -24,3 +28,39 @@ export default function Box(props: BoxProps) {
</div>
);
}

export interface CollapseBoxProps {
/** must be non empty */
title: string;
children: React.ReactNode;
}

export function CollapseBox({ title, children }: CollapseBoxProps) {
const [collapsed, toggleCollapse] = useState(false);

return (
<div className={styles.collapseBox}>
<div
onClick={() => toggleCollapse((c) => !c)}
className={styles.collapseTitle}
aria-hidden
>
<div>{title}</div>
<FontAwesomeIcon
className={cx({
[styles.collapseIcon]: true,
[styles.collapsed]: collapsed,
})}
icon={faChevronDown}
/>
</div>
<Box
className={cx({
[styles.collapsedContent]: collapsed,
})}
>
{children}
</Box>
</div>
);
}