Skip to content

Commit

Permalink
chore(web): Slider Field (#652)
Browse files Browse the repository at this point in the history
  • Loading branch information
jashanbhullar authored Sep 6, 2023
1 parent 6abb7b0 commit f7fe7f6
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 40 deletions.
56 changes: 47 additions & 9 deletions web/src/beta/components/Slider/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,51 @@
import { action } from "@storybook/addon-actions";
import { Meta } from "@storybook/react";
import { useArgs } from "@storybook/preview-api";
import { Meta, StoryObj } from "@storybook/react";
import { useCallback } from "react";

import Slider from ".";
import { styled } from "@reearth/services/theme";

export default {
import Slider, { Props } from ".";

const meta: Meta<typeof Slider> = {
component: Slider,
} as Meta;
};

type Story = StoryObj<typeof Slider>;

export default meta;

export const Default: Story = (args: Props) => {
const [_, updateArgs] = useArgs();

const handleChange = useCallback((value: number) => updateArgs({ value: value }), [updateArgs]);

return (
<Wrapper>
<div>
<Slider {...args} onChange={handleChange} />
</div>
<div>
<Slider {...args} max={2 * args.max} onChange={handleChange} />
</div>
<div>
<Slider {...args} disabled={true} onChange={handleChange} />
</div>
</Wrapper>
);
};

Default.args = {
value: 50,
min: 0,
max: 100,
step: 1,
disabled: false,
};

export const Default = () => <Slider value={120} min={0} max={100} onChange={action("onchange")} />;
export const Frame = () => (
<Slider value={120} min={0} max={100} onChange={action("onchange")} frame />
);
const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 10%;
margin: 2rem;
height: 300px;
`;
73 changes: 43 additions & 30 deletions web/src/beta/components/Slider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,64 @@
import RCSlider from "rc-slider";
import React, { ComponentProps } from "react";

import { styled, css } from "@reearth/services/theme";
import { styled } from "@reearth/services/theme";

import "rc-slider/assets/index.css";

type Props = {
const SliderWithTooltip = RCSlider.createSliderWithTooltip(RCSlider);

export type Props = {
min: number;
max: number;
frame?: boolean;
} & Omit<ComponentProps<typeof RCSlider>, "defaultValue">;
} & Omit<ComponentProps<typeof SliderWithTooltip>, "defaultValue">;

const Slider: React.FC<Props> = ({ frame = false, ...props }) => (
<Wrapper frame={frame}>
<StyledSlider {...props} />
</Wrapper>
const Slider: React.FC<Props> = ({ ...props }) => (
<SliderStyled disabled={props.disabled as boolean}>
<SliderWithTooltip {...props} />
</SliderStyled>
);

const Wrapper = styled.div<{ frame: boolean }>`
display: flex;
align-items: center;
border: ${({ frame, theme }) => (frame ? `solid 1px ${theme.outline.main}` : "none")};
border-radius: 3px;
background: ${({ frame, theme }) => (frame ? theme.bg[1] : "transparent")};
width: 100%;
flex: 1;
box-sizing: border-box;
${({ frame }) =>
frame &&
css`
padding: 6px 12px;
margin-right: 5px;
`};
`;
const SliderStyled = styled.div<{ disabled: boolean }>`
.rc-slider-disabled {
background-color: transparent;
opacity: ${({ disabled }) => (disabled ? 0.6 : 1)};
cursor: ${({ disabled }) => (disabled ? "not-allowed" : "inherit")};
}
.rc-slider-rail {
height: 8px;
}
const StyledSlider = styled(RCSlider)`
.rc-slider-handle {
background-color: ${({ theme }) => theme.bg[2]};
border: ${({ theme }) => theme.bg[2]};
background-color: ${({ theme }) => theme.item.default};
border: ${({ theme }) => theme.primary.weak};
height: 12px;
width: 12px;
margin-top: -2px;
}
.rc-slider-track {
background-color: ${({ theme }) => theme.bg[2]};
background-color: ${({ theme }) => theme.primary.weak};
height: 8px;
}
.rc-slider-rail {
background-color: ${({ theme }) => theme.outline.weaker};
box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25) inset;
}
.rc-slider-handle:focus {
box-shadow: none;
.rc-slider-tooltip-arrow {
background-color: transparent;
border-top-color: ${({ theme }) => theme.bg[2]};
bottom: 2px;
margin-left: -8px;
border-width: 9px 8px 0;
}
.rc-slider-tooltip-inner {
background-color: ${({ theme }) => theme.bg[2]};
color: ${({ theme }) => theme.content.main};
box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25);
}
`;

Expand Down
17 changes: 16 additions & 1 deletion web/src/beta/components/fields/PropertyFields/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import TextInput from "@reearth/beta/components/fields/TextInput";
import { type Item } from "@reearth/services/api/propertyApi/utils";

import ColorField from "../ColorField";
import SliderField from "../SliderField";
import SpacingInput, { SpacingValues } from "../SpacingInput";
import ToggleField from "../ToggleField";

Expand Down Expand Up @@ -53,14 +54,28 @@ const PropertyFields: React.FC<Props> = ({ propertyId, item }) => {
max={sf.max}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
) : sf.type == "bool" ? (
) : sf.type === "bool" ? (
<ToggleField
key={sf.id}
name={sf.name}
checked={value as boolean}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
) : sf.type === "number" ? (
sf.ui === "slider" ? (
<SliderField
key={sf.id}
name={sf.name}
value={value as number}
min={sf.min as number}
max={sf.max as number}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
) : (
<p key={sf.id}>{sf.name} number field</p>
)
) : (
<p key={sf.id}>{sf.name} field</p>
);
Expand Down
67 changes: 67 additions & 0 deletions web/src/beta/components/fields/SliderField/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useArgs } from "@storybook/preview-api";
import { Meta, StoryObj } from "@storybook/react";
import { useCallback } from "react";

import { styled } from "@reearth/services/theme";

import SliderField, { Props } from ".";

const meta: Meta<typeof SliderField> = {
component: SliderField,
};

export default meta;

type Story = StoryObj<typeof SliderField>;

export const Default: Story = (args: Props) => {
const [_, updateArgs] = useArgs();

const handleChange = useCallback((value: number) => updateArgs({ value: value }), [updateArgs]);

return (
<Wrapper>
<div>
<SliderField {...args} onChange={handleChange} />
</div>
<div>
<SliderField
{...args}
name="Inverse of above"
value={args.max - (args?.value || 0)}
description={undefined}
onChange={handleChange}
/>
</div>
<div>
<SliderField
{...args}
name="Disabled"
description="Disabled field"
disabled={true}
onChange={handleChange}
/>
</div>
</Wrapper>
);
};

const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 10%;
margin-left: 2rem;
margin-top: 2rem;
height: 300px;
`;

Default.args = {
name: "Slider Field",
description: "Slider field Sample description",
value: 50,
min: 0,
max: 100,
step: 1,
disabled: false,
onChange: () => console.log("clicked"),
};
17 changes: 17 additions & 0 deletions web/src/beta/components/fields/SliderField/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Property from "@reearth/beta/components/fields";
import Slider, { Props as SliderProps } from "@reearth/beta/components/Slider";

export type Props = {
name?: string;
description?: string;
} & SliderProps;

const SliderField: React.FC<Props> = ({ name, description, ...args }: Props) => {
return (
<Property name={name} description={description}>
<Slider {...args} />
</Property>
);
};

export default SliderField;

0 comments on commit f7fe7f6

Please sign in to comment.