Skip to content

Commit

Permalink
Add Toggle Button with Story (#510)
Browse files Browse the repository at this point in the history
* Add Toggle Button with Story

* Improve view of ToggleButton stories

* Update FilterButton to new design

* Making basic the default design in Toggle Button

* Missing gap and indentation

* Update ToggleButton story to have design basic as the story value

---------

Co-authored-by: Leonard Burton <[email protected]>
  • Loading branch information
isacoder and atomworks authored Nov 27, 2024
1 parent 9cdd322 commit 61b2d3c
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 21 deletions.
125 changes: 125 additions & 0 deletions packages/storybook/src/stories/Filters/atoms/ToggleButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React, { useCallback, useState } from "react";
import { ToggleButton } from "scorer-ui-kit";
import { boolean, object, select, text } from "@storybook/addon-knobs";
import { action } from "@storybook/addon-actions";
import styled from "styled-components";

export default {
title: 'Filters/atoms',
component: ToggleButton,
decorators: []
};

const layoutOptions = [
{ text: 'Grid', value: 'grid', icon: 'LayoutGrid' },
{ text: 'List', value: 'list', icon: 'LayoutList' }
]

const CameraData = styled.div``;
const Camera = styled.li``;

const Container = styled.div``;
const DataGroup = styled.ol<{ layout: string }>`
margin-top: 20px;
display: grid;
${({ layout }) => layout === 'grid' &&
`
list-style-type: none;
grid-template-columns: repeat(3, 300px);
gap: 16px;
${Camera} {
padding: 100px 20px;
border: 1px solid var(--grey-9);
text-align: center;
}
`
};
`;

const StatusSpan = styled.span<{ isOnline?: boolean }>`
${({ isOnline }) => isOnline ?
`
color: var(--success);
`
:
`
color: var(--warning);
`}
`;

export const _ToggleButton = () => {
const [selectedLayout, setSelectedLayout] = useState(0)

const disabled = boolean('Disabled', false);
const design = select('Design type', { Default: 'default', Basic: 'basic' }, 'basic');
const categoryLabel = text('Category Label', 'Layout:');
const options = object('Options', layoutOptions);
const showToggleValue = action('Button Value: ');

const onToggle = useCallback((index: number, value: string | number) => {
setSelectedLayout(index);
showToggleValue(value);
}, [showToggleValue])

return (
<Container>
<ToggleButton
{...{
categoryLabel,
options,
onToggle,
disabled,
design,
selectedIndex: selectedLayout
}} />

<DataGroup layout={layoutOptions[selectedLayout].value}>
<Camera>
<CameraData>
Camera01 - <StatusSpan isOnline>Online</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera02 - <StatusSpan isOnline>Online</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera03 - <StatusSpan>OffLine</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera04 - <StatusSpan>OffLine</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera05 - <StatusSpan>OffLine</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera06 - <StatusSpan>OffLine</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera07 - <StatusSpan isOnline>Online</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera08 - <StatusSpan isOnline>Online</StatusSpan>
</CameraData>
</Camera>
<Camera>
<CameraData>
Camera09 - <StatusSpan>Online</StatusSpan>
</CameraData>
</Camera>
</DataGroup>
</Container>
)
}
4 changes: 3 additions & 1 deletion packages/ui-lib/src/Filters/FilterTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IFilterDropdown } from './molecules/FilterDropdown';
type IFilterItem = { text: string; value: string | number; }
type IFilterValue = IFilterItem | IFilterItem[] | null;
type IFilterType = 'search' | 'dropdown' | 'datepicker';
type IToggleOption = { text: string; value: string | number; icon: string }

// Type checking for IFilterItem
// https://stackoverflow.com/questions/14425568/interface-type-check-with-typescript
Expand Down Expand Up @@ -78,5 +79,6 @@ export type {
ISearchFilter,
IFilterDropdownExt,
IFilterDatePicker,
IFilterDropdownConfig
IFilterDropdownConfig,
IToggleOption,
};
51 changes: 32 additions & 19 deletions packages/ui-lib/src/Filters/atoms/FilterButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import Icon, { IconWrapper } from '../../Icons/Icon';
import { animation } from '../../theme/common';
import { FilterButtonDesign } from '..';

const FlipWrapper = styled.div<{ isSortAscending: boolean }>`
const LeftIconWrapper = styled.div<{ isSortAscending: boolean }>`
${({ isSortAscending }) => isSortAscending && css`
transform: scaleY(-1);
`};
padding: 0 6px;
`;

const fadeInAnimation = keyframes`
Expand All @@ -20,17 +21,29 @@ const fadeInAnimation = keyframes`
}
`;

const FlipArrowContainer = styled.div``;
const FlipArrowContainer = styled.div<{ design?: FilterButtonDesign }>`
${({ design }) => design === 'default' ?
`padding: 0px 12px 0px 8px;`
:
`padding: 0px 8px;`
};
`;

const StyledButton = styled.button<{ isOpen?: boolean, hasFlipArrow?: boolean, design?: FilterButtonDesign }>`
${resetButtonStyles};
border-radius: 3px;
height: var(--common-height);
display: inline-flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
padding: 4px 10px 4px 4px;
${({design}) => design === 'basic'?
${({ design }) => design === 'basic' ?
`
background-color: transparent;
border: 1px solid transparent;
padding: 4px;
`
:
`
Expand All @@ -40,6 +53,8 @@ const StyledButton = styled.button<{ isOpen?: boolean, hasFlipArrow?: boolean, d
`
};
${({ hasFlipArrow }) => hasFlipArrow && `padding: 4px 0px 4px 4px;`};
text-align: left;
font-size: 12px;
font-weight: 500;
Expand All @@ -56,7 +71,6 @@ const StyledButton = styled.button<{ isOpen?: boolean, hasFlipArrow?: boolean, d
animation: ${fadeInAnimation} ${animation.speed.slower} ${animation.easing.primary.out};
${IconWrapper} {
padding: 0 9px;
display: flex;
align-items: center;
[stroke]{
Expand All @@ -66,26 +80,26 @@ const StyledButton = styled.button<{ isOpen?: boolean, hasFlipArrow?: boolean, d
&:hover:enabled, &:active:enabled {
color: var(--grey-12);
${({design}) => design === 'basic'? '' : css`
box-shadow: 0px 4px 9px 0px var(--primary-a2);
border-color: var(--primary-7);
`};
${IconWrapper} {
[stroke]{
stroke: var(--primary-9);
}
}
${({isOpen}) => !isOpen && css`
${FlipArrowContainer} ${IconWrapper} {
[stroke]{
stroke: var(--grey-12);
}
};
`};
}
&:disabled {
Expand All @@ -106,7 +120,7 @@ const StyledButton = styled.button<{ isOpen?: boolean, hasFlipArrow?: boolean, d
}
}
}
${FlipArrowContainer} ${IconWrapper} {
[stroke]{
stroke: var(--white-1);
Expand All @@ -119,13 +133,12 @@ const StyledButton = styled.button<{ isOpen?: boolean, hasFlipArrow?: boolean, d


const InnerContainer = styled.div`
display: flex;
align-items: center;
display: flex;
align-items: center;
gap: 4px;
`;

const ButtonText = styled.div<{ hasFlipArrow: boolean }>`
padding-right: ${({ hasFlipArrow }) => hasFlipArrow ? '3px' : '20px'};
`;
const ButtonText = styled.div<{ hasFlipArrow: boolean }>``;

interface OwnProps {
icon: string
Expand All @@ -150,18 +163,18 @@ const FilterButton: React.FC<IFilterButton> = ({
return (
<StyledButton type='button' {...props} {...{ isOpen, hasFlipArrow, design }}>
<InnerContainer>
<FlipWrapper {...{ isSortAscending }}>
<LeftIconWrapper {...{ isSortAscending }}>
<Icon
icon={icon}
size={12}
weight='light'
color='filter-button-icon-color'
/>
</FlipWrapper>
</LeftIconWrapper>
<ButtonText {...{ hasFlipArrow }}>{children}</ButtonText>
{hasFlipArrow && <FlipArrowContainer><Icon icon={isOpen ? 'Up' : 'Down'} size={6} color='grey-11' /></FlipArrowContainer>}

{hasFlipArrow && <FlipArrowContainer {...{ design }}><Icon icon={isOpen ? 'Up' : 'Down'} size={6} color='grey-11' /></FlipArrowContainer>}

</InnerContainer>
</StyledButton>
);
Expand Down
31 changes: 31 additions & 0 deletions packages/ui-lib/src/Filters/atoms/ToggleButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { useCallback } from 'react';
import { IToggleOption } from '../FilterTypes';
import FilterButton from './FilterButton';
import { FilterButtonDesign } from '..';

type IToggleButton = {
options: IToggleOption[]
categoryLabel: String
selectedIndex: number
design?: FilterButtonDesign
onToggle: (index: number, value: string | number) => void
}

const ToggleButton: React.FC<IToggleButton> = ({ options, categoryLabel, selectedIndex, design = 'basic', onToggle, ...props }) => {

const onToggleCallback = useCallback((currentIndex: number) => {
const selected = currentIndex === 1 ? 0 : 1;
onToggle(selected, options[selected].value);

}, [onToggle, options]);

if (selectedIndex !== 0 && selectedIndex !== 1) return null;

return (
<FilterButton icon={options[selectedIndex].icon} onClick={() => onToggleCallback(selectedIndex)} {...{design}} {...props}>
{`${categoryLabel} : ${options[selectedIndex].text}`}
</FilterButton>
);
};

export default ToggleButton;
5 changes: 5 additions & 0 deletions packages/ui-lib/src/Filters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import FilterLayout from './molecules/FilterLayout';
import FilterInputs, { IFilterInputs } from './molecules/FilterInputs';
import FiltersResults, { IFilterLabel } from './molecules/FiltersResults';
import FilterBar from './organisms/FilterBar';
import ToggleButton from './atoms/ToggleButton';

import {
IFilterType,
IFilterItem,
Expand All @@ -17,6 +19,7 @@ import {
IFilterDropdownConfig,
IFilterDatePicker,
isFilterItem,
IToggleOption,
} from './FilterTypes';

export {
Expand All @@ -31,6 +34,7 @@ export {
FilterBar,
isFilterItem,
isDateInterval,
ToggleButton
};

type FilterButtonDesign = 'default' | 'basic'
Expand All @@ -48,5 +52,6 @@ export type {
DateInterval,
IFilterDatePicker,
FilterButtonDesign,
IToggleOption,
DateRange
};
6 changes: 5 additions & 1 deletion packages/ui-lib/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ import {
IFilterValue,
IFilterResult,
isFilterItem,
FilterButtonDesign
FilterButtonDesign,
ToggleButton,
IToggleOption
} from './Filters';

import Icon, { IconSVGs } from './Icons/Icon';
Expand Down Expand Up @@ -279,6 +281,7 @@ export {
FilterInputs,
FiltersResults,
FilterBar,
ToggleButton,
isFilterItem,
isDateInterval,

Expand Down Expand Up @@ -419,5 +422,6 @@ export type {
AlertType,
ITooltipType,
FilterButtonDesign,
IToggleOption,
DateRange
};

0 comments on commit 61b2d3c

Please sign in to comment.