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
66 changes: 66 additions & 0 deletions src/lib/components/base-table/base-table.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import { BaseTable, BaseTableProps } from './base-table';
import { Meta, StoryFn } from '@storybook/react';
import TableDataHeader from '../table-data-header/table-data-header';
import TableRow from '../table-row/table-row';
import TableData from '../table-data/table-data';
import BodyText from '../body-text/body-text';
import { PrecisionCase } from '../../utils/currency';
import Cspr from '../cspr/cspr';
import PageTile from '../page-tile/page-tile';

const mockedData = [
{ rank: 1, motes: '50000000000000', owner: 'konrad.cspr' },
{ rank: 2, motes: '482900000000000', owner: 'victoria.cspr' },
{ rank: 3, motes: '1000000', owner: 'ab.cspr' },
];

export default {
component: BaseTable,
title: 'Components/Table/Base Table',
args: {
renderDataHeaders: () => (
<TableRow>
<TableDataHeader>Rank</TableDataHeader>
<TableDataHeader align={'right'}>Balance</TableDataHeader>{' '}
<TableDataHeader>Owner</TableDataHeader>
</TableRow>
),
renderData: () => (
<>
{mockedData.map((data) => (
<TableRow>
<TableData>
<BodyText size={3}>{data.rank}</BodyText>
</TableData>
<TableData align={'right'}>
<BodyText size={3}>
<Cspr
motes={data.motes}
precisionCase={PrecisionCase.deployCost}
/>
</BodyText>
</TableData>
<TableData>
<BodyText size={3}>{data.owner}</BodyText>
</TableData>
</TableRow>
))}
</>
),
},
} as Meta<typeof BaseTable>;

const Template: StoryFn<typeof BaseTable> = (args: BaseTableProps) => {
return (
<PageTile>
<BaseTable
renderDataHeaders={args.renderDataHeaders}
renderData={args.renderData}
renderFooter={args.renderFooter}
/>
</PageTile>
);
};

export const Primary = Template.bind({});
70 changes: 70 additions & 0 deletions src/lib/components/base-table/base-table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { ReactNode } from 'react';
import styled from 'styled-components';
import TableHead from '../table-head/table-head';
import TableBody from '../table-body/table-body';
import BodyText from '../body-text/body-text';

export interface BaseTableProps {
renderHeader?: () => ReactNode;
renderDataHeaders?: () => ReactNode;
renderData?: () => ReactNode;
renderFooter?: () => ReactNode;
noData?: boolean;
noDataMessage?: string;
paddingBottom?: number;
}

export const TableContainer = styled.div<{ paddingBottom?: number }>(
({ theme, paddingBottom }) => ({
overflowX: 'auto',
...(paddingBottom && { paddingBottom }),
}),
);

const StyledTable = styled.table(({ theme }) => ({
width: '100%',
position: 'relative',
borderCollapse: 'collapse',
}));

const NoDataContainer = styled.div(({ theme }) => ({
position: 'absolute',
top: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));

export function BaseTable(props: BaseTableProps) {
const {
renderHeader,
renderDataHeaders,
renderData,
renderFooter,
noData,
noDataMessage,
paddingBottom,
} = props;

return (
<>
{renderHeader && renderHeader()}
<TableContainer paddingBottom={paddingBottom}>
<StyledTable>
{renderDataHeaders && <TableHead>{renderDataHeaders()}</TableHead>}
{renderData && <TableBody>{renderData()}</TableBody>}
</StyledTable>
</TableContainer>
{renderFooter && renderFooter()}
{noDataMessage && noData && (
<NoDataContainer>
<BodyText size={1}>{noDataMessage}</BodyText>
</NoDataContainer>
)}
</>
);
}

export default BaseTable;
45 changes: 45 additions & 0 deletions src/lib/components/pagination/pagination-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import styled from 'styled-components';
import Button, { ButtonProps } from '../button/button';
import CaptionText from '../caption-text/caption-text';

interface PaginationButtonProps extends ButtonProps {
children?: React.ReactNode;
}

const StyledButton = styled(Button)(({ theme }) =>
theme.withMedia({
width: 'auto',
fontWeight: theme.typography.fontWeight.medium,
minHeight: 24,
padding: ['2px 10px'],
}),
);

const StyledArrowsButton = styled(StyledButton)(({ theme }) =>
theme.withMedia({
padding: ['2px 4px'],
}),
);

export const PaginationButton = ({
children,
...restProps
}: PaginationButtonProps) => {
return (
<StyledButton color={'utility'} lineHeight={'xs'} {...restProps}>
<CaptionText size={2}>{children}</CaptionText>
</StyledButton>
);
};

export const PaginationArrowButton = ({
children,
...restProps
}: PaginationButtonProps) => {
return (
<StyledArrowsButton lineHeight={'xs'} {...restProps}>
{children}
</StyledArrowsButton>
);
};
25 changes: 25 additions & 0 deletions src/lib/components/pagination/pagination-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from 'styled-components';

export const PaginationContainer = styled.div(({ theme }) =>
theme.withMedia({
border: 'none',
cursor: 'pointer',
color: theme.styleguideColors.contentRed,
background: theme.styleguideColors.fillSecondary,
borderRadius: theme.borderRadius.base,
fontWeight: theme.typography.fontWeight.medium,
minHeight: 24,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: ['2px 8px'],
':hover': {
background: theme.styleguideColors.fillSecondaryRedHover,
color: theme.styleguideColors.fillPrimaryRedHover,
},
':active': {
background: theme.styleguideColors.fillSecondaryRedClick,
color: theme.styleguideColors.fillPrimaryRedClick,
},
}),
);
113 changes: 113 additions & 0 deletions src/lib/components/pagination/pagination-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { PaginationContainer } from './pagination-container';
import { useClickAway } from '../../hooks/use-click-away';
import CaptionText from '../caption-text/caption-text';
import SvgIcon from '../svg-icon/svg-icon';
import ArrowDownIcon from '../../assets/icons/ic-arrow-down.svg';

export const PaginationDropdownContainer = styled.div(({ theme }) =>
theme.withMedia({
position: 'relative',
minWidth: [58],
}),
);

export const PaginationDropdownMenu = styled.ul(({ theme }) =>
theme.withMedia({
width: '100%',
position: 'absolute',
display: 'block',
background: theme.styleguideColors.fillSecondary,
boxShadow: theme.boxShadow.block,
padding: 0,
margin: '4px 0',
borderRadius: theme.borderRadius.base,
zIndex: theme.zIndex.dropdown,
'& > div': {
borderRadius: 0,
},
'& > :first-child': {
borderRadius: theme.borderRadius.base,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
},
'& > :last-child': {
borderRadius: theme.borderRadius.base,
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
},
}),
);

const PaginationDropdownMenuItem = styled.li(({ theme }) => ({
alignItems: 'center',
display: 'flex',
position: 'relative',
'& > input': {
display: 'none',
},
}));

interface PaginationDropdownProps {
value: number;
items: number[];
onChange: (perPage: number) => void;
}

export const PaginationDropdown = ({
value,
items,
onChange,
}: PaginationDropdownProps) => {
const [opened, setOpened] = useState(false);

const { ref } = useClickAway({
callback: () => {
setOpened(false);
},
});

return (
<PaginationDropdownContainer
ref={ref}
onClick={() => {
setOpened(!opened);
}}
>
<PaginationContainer>
<CaptionText size={1}>{value}</CaptionText>
<SvgIcon
src={ArrowDownIcon}
marginLeft
rotate={opened}
role={'img'}
alt={'Arrow down icon'}
/>
</PaginationContainer>
{opened && (
<PaginationDropdownMenu>
{items.map((item) => (
<PaginationContainer
key={item}
onClick={() => {
onChange(item);
}}
>
<PaginationDropdownMenuItem>
<input
type="radio"
name="rows"
id={`${item}-row`}
defaultChecked={item === value}
value={item}
/>
<CaptionText size={2}>{item}</CaptionText>
</PaginationDropdownMenuItem>
</PaginationContainer>
))}
</PaginationDropdownMenu>
)}
</PaginationDropdownContainer>
);
};
33 changes: 33 additions & 0 deletions src/lib/components/pagination/pagination-info-text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import styled from 'styled-components';
import CaptionText from '../caption-text/caption-text';
import FlexBox from '../flex-box/flex-box';

interface PaginationInfoTextProps {
children?: React.ReactNode;
}

export const StyledContainer = styled(FlexBox)(({ theme }) =>
theme.withMedia({
textAlign: 'center',
borderRadius: theme.borderRadius.base,
backgroundColor: theme.styleguideColors.fillSecondary,
color: theme.styleguideColors.contentPrimary,
height: 20,
padding: ['4px 8px', '4px 16px'],
width: '100%',
}),
);

export const PaginationInfoText = ({
children,
...props
}: PaginationInfoTextProps) => {
return (
<StyledContainer {...props} align={'center'} justify={'center'}>
<CaptionText size={2} variation={'black'} noWrap>
{children}
</CaptionText>
</StyledContainer>
);
};
Loading