Skip to content

Commit

Permalink
fix(uikit): Accept float values for Slider (#4)
Browse files Browse the repository at this point in the history
- Refactored progress to remove excess class names
  • Loading branch information
hachiojidev authored Mar 17, 2021
1 parent 8cbc1b8 commit 018d7e5
Show file tree
Hide file tree
Showing 6 changed files with 2,548 additions and 120 deletions.
33 changes: 16 additions & 17 deletions packages/pancake-uikit/src/components/Slider/Slider.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
import React, { ChangeEvent } from "react";
import { SliderContainer, BunnySlider, BarBackground, BarProgress, StyledInput, SliderLabel } from "./styles";
import { Box } from "../Box";
import { BunnySlider, BarBackground, BarProgress, StyledInput, SliderLabel } from "./styles";
import BunnyButt from "./svg/BunnyButt";
import SliderProps from "./types";

// We need to adjust the offset as the percentage increases, as 100% really is 100% - label width. The number 10 is arbitrary, but seems to work...
const MOVING_SLIDER_LABEL_OFFSET_FACTOR = 10;
// We need to adjust the offset as the percentage increases, as 100% really is 100% - label width.
// The number 10 is arbitrary, but seems to work...
const LABEL_OFFSET = 10;

const Slider: React.FC<SliderProps> = ({ min, max, value, onValueChanged, valueLabel, ...props }) => {
const Slider: React.FC<SliderProps> = ({ min, max, value, step = "any", onValueChanged, valueLabel, ...props }) => {
const handleChange = ({ target }: ChangeEvent<HTMLInputElement>) => {
onValueChanged(parseInt(target.value, 10));
onValueChanged(parseFloat(target.value));
};

const progressPercentage = (value / max) * 100;
const isCurrentValueMaxValue = value === max;
const isMax = value === max;

const labelOffset = progressPercentage - progressPercentage / MOVING_SLIDER_LABEL_OFFSET_FACTOR;
const labelOffset = progressPercentage - progressPercentage / LABEL_OFFSET;

return (
<SliderContainer {...props}>
<Box position="relative" height="48px" {...props}>
<BunnyButt style={{ position: "absolute" }} />
<BunnySlider>
<BarBackground />
<BarProgress isCurrentValueMaxValue={isCurrentValueMaxValue} progress={progressPercentage} />
<StyledInput
type="range"
min={min}
max={max}
value={value}
onChange={handleChange}
isCurrentValueMaxValue={isCurrentValueMaxValue}
<BarProgress
isMax={isMax}
progress={progressPercentage}
style={{ width: isMax ? "calc(100% - 16px)" : `${progressPercentage}%` }}
/>
<StyledInput type="range" min={min} max={max} value={value} step={step} onChange={handleChange} isMax={isMax} />
</BunnySlider>
{valueLabel && <SliderLabel progress={labelOffset}>{valueLabel}</SliderLabel>}
</SliderContainer>
</Box>
);
};

Expand Down
42 changes: 41 additions & 1 deletion packages/pancake-uikit/src/components/Slider/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { useState } from "react";
import styled from "styled-components";
import Slider from "./Slider";
import Flex from "../Box/Flex";
import Box from "../Box/Box";
import Text from "../Text/Text";
import Button from "../Button/Button";
import Slider from "./Slider";

export default {
title: "Components/Slider",
Expand Down Expand Up @@ -48,3 +51,40 @@ export const Variants: React.FC = () => {
</Col>
);
};

const percentShortcuts = [10, 25, 50, 75];
const initialBalance = 1.795394;
const maxBalance = initialBalance - 0.01;

export const Balance: React.FC = () => {
const [balance, setBalance] = useState(maxBalance);

const handleChange = (newValue: number) => {
setBalance(newValue);
};

const setMax = () => {
setBalance(maxBalance);
};

return (
<Box width="420px">
<Slider min={0} max={maxBalance} value={balance} onValueChanged={handleChange} />
<Flex justifyContent="space-between" py="16px">
{percentShortcuts.map((percent) => {
const handleClick = () => {
setBalance((percent / 100) * maxBalance);
};

return <Button scale="sm" variant="secondary" onClick={handleClick}>{`${percent}%`}</Button>;
})}
<Button scale="sm" variant="secondary" onClick={setMax}>
Max
</Button>
</Flex>
<Text>{`Current Balance: ${balance}`}</Text>
<Text fontSize="12px" color="textSubtle">{`Initial Balance: ${initialBalance}`}</Text>
<Text fontSize="12px" color="textSubtle">{`Max Balance: ${maxBalance}`}</Text>
</Box>
);
};
78 changes: 30 additions & 48 deletions packages/pancake-uikit/src/components/Slider/styles.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { InputHTMLAttributes } from "react";
import styled from "styled-components";
import { Box } from "../Box";
import Text from "../Text/Text";
import bunnyHeadMain from "./svg/bunnyhead-main.svg";
import bunnyHeadMax from "./svg/bunnyhead-max.svg";

export const SliderContainer = styled(Box)`
position: relative;
height: 48px;
`;

interface SliderLabelProps {
progress: number;
}
export const SliderLabel = styled.label<SliderLabelProps>`
position: absolute;

interface StyledInputProps extends InputHTMLAttributes<HTMLInputElement> {
isMax: boolean;
}

export const SliderLabel = styled(Text)<SliderLabelProps>`
bottom: 0;
margin-left: 16px; // offset the bunny butt width
font-size: 12px;
left: calc(${({ progress }) => progress}%);
position: absolute;
margin-left: 16px; // offset the bunny butt width
`;

export const BunnyButt = styled.img`
Expand All @@ -29,56 +30,38 @@ export const BunnySlider = styled.div`
width: 100%;
`;

interface StyledInputProps extends InputHTMLAttributes<HTMLInputElement> {
isCurrentValueMaxValue: boolean;
}
const getBaseThumbStyles = ({ isMax }: StyledInputProps) => `
-webkit-appearance: none;
background-image: url(${isMax ? bunnyHeadMax : bunnyHeadMain});
width: 24px;
height: 32px;
cursor: pointer;
transform: translate(-2px, -2px);
transition: 0.1s all;
:hover {
transform: scale(1.1) translate(-3px, -3px);
}
`;

export const StyledInput = styled.input<StyledInputProps>`
cursor: pointer;
height: 32px;
position: relative;
cursor: pointer;
::-webkit-slider-thumb {
-webkit-appearance: none;
background-image: url(${({ isCurrentValueMaxValue }) => (isCurrentValueMaxValue ? bunnyHeadMax : bunnyHeadMain)});
width: 24px;
height: 32px;
cursor: pointer;
transform: translate(-2px, -2px);
transition: 0.1s all;
:hover {
transform: scale(1.1) translate(-3px, -3px);
}
${getBaseThumbStyles}
}
::-moz-range-thumb {
-webkit-appearance: none;
background-image: url(${({ isCurrentValueMaxValue }) => (isCurrentValueMaxValue ? bunnyHeadMax : bunnyHeadMain)});
width: 24px;
height: 32px;
cursor: pointer;
transition: 0.1s all;
transform: translate(-2px, -2px);
// custom moz reset
${getBaseThumbStyles}
background-color: transparent;
border: 0;
:hover {
transform: scale(1.1) translate(-3px, -3px);
}
}
::-ms-thumb {
-webkit-appearance: none;
background-image: url(${({ isCurrentValueMaxValue }) => (isCurrentValueMaxValue ? bunnyHeadMax : bunnyHeadMain)});
width: 24px;
height: 32px;
cursor: pointer;
transform: translate(-2px, -2px);
transition: 0.1s all;
:hover {
transform: scale(1.1) translate(-3px, -3px);
}
::-ms-thumb {
${getBaseThumbStyles}
}
`;

Expand All @@ -90,9 +73,8 @@ export const BarBackground = styled.div`
background-color: ${({ theme }) => theme.colors.inputSecondary};
`;

export const BarProgress = styled.div<{ progress: number; isCurrentValueMaxValue: boolean }>`
export const BarProgress = styled.div<{ progress: number; isMax: boolean }>`
position: absolute;
width: ${({ progress, isCurrentValueMaxValue }) => (isCurrentValueMaxValue ? "calc(100% - 16px)" : `${progress}%`)};
height: 10px;
top: 18px;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/pancake-uikit/src/components/Slider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export default interface SliderProps extends BoxProps {
min: number;
max: number;
value: number;
step?: number | "any";
onValueChanged: (newValue: number) => void;
valueLabel?: string;
}
Loading

0 comments on commit 018d7e5

Please sign in to comment.