Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): Toggle Field #651

Merged
merged 12 commits into from
Aug 31, 2023
55 changes: 55 additions & 0 deletions web/src/beta/components/Toggle/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useArgs } from "@storybook/preview-api";
import { Meta, StoryObj } from "@storybook/react";
import React, { useCallback } from "react";

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

import Toggle from ".";

type Props = React.ComponentProps<typeof Toggle>;

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

export default meta;

type Story = StoryObj<typeof Toggle>;

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

const handleChange = useCallback(
(checked: boolean) => updateArgs({ checked: !checked }),
[updateArgs],
);

return (
<Wrapper>
<div>
<Toggle {...args} onChange={handleChange} />
</div>
<div>
<Toggle {...args} checked={!args.checked} onChange={handleChange} />
</div>
<div>
<Toggle {...args} checked={!args.checked} 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 = {
checked: true,
disabled: false,
onChange: () => console.log("clicked"),
};
57 changes: 57 additions & 0 deletions web/src/beta/components/Toggle/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useCallback } from "react";

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

type Props = {
checked: boolean;
onChange: (checked: boolean) => void;
disabled?: boolean;
};

const Toggle: React.FC<Props> = ({ checked, onChange, disabled = false }) => {
const handleClick = useCallback(
() => !disabled && onChange(checked),
[checked, onChange, disabled],
);

return (
<Wrapper>
<Switch checked={checked} disabled={disabled} onClick={handleClick}>
<TopSlider checked={checked} />
</Switch>
</Wrapper>
);
};

export default Toggle;

const Wrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`;
jashanbhullar marked this conversation as resolved.
Show resolved Hide resolved

const Switch = styled.label<{
checked: boolean;
disabled: boolean;
}>`
cursor: ${({ disabled }) => (!disabled ? "pointer" : "not-allowed")};
width: 24px;
height: 14px;
background: ${({ checked, theme }) => (checked ? theme.select.main : theme.secondary.main)};
border: 1px solid ${({ checked, theme }) => (checked ? theme.select.main : theme.secondary.main)};
border-radius: 12px;
opacity: ${({ disabled }) => (!disabled ? 1 : 0.5)};
transition: 0.4s;
`;

const TopSlider = styled.div<{
checked: boolean;
}>`
width: 14px;
height: 14px;
background: ${({ theme }) => theme.content.withBackground};
transition: 0.4s;
border-radius: 50%;
transform: ${({ checked }) => checked && "translateX(10px)"};
`;
65 changes: 40 additions & 25 deletions 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 ToggleField from "../ToggleField";

import useHooks from "./hooks";

Expand All @@ -18,31 +19,45 @@ const PropertyFields: React.FC<Props> = ({ propertyId, item }) => {
{item?.schemaFields.map(sf => {
const isList = item && "items" in item;
const value = !isList ? item.fields.find(f => f.id === sf.id)?.value : sf.defaultValue;
return sf.type === "string" ? (
sf.ui === "color" ? (
<ColorField
key={sf.id}
name={sf.name}
value={(value as string) ?? ""}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
) : sf.ui === "selection" || sf.choices ? (
<p key={sf.id}>Selection or choices field</p>
) : sf.ui === "buttons" ? (
<p key={sf.id}>Button radio field</p>
) : (
<TextInput
key={sf.id}
name={sf.name}
value={(value as string) ?? ""}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
)
) : (
<p key={sf.id}>{sf.name} field</p>
);

switch (sf.type) {
jashanbhullar marked this conversation as resolved.
Show resolved Hide resolved
case "string":
// TODO: Can also be turned into a switch and infact bunch of props are common
return sf.ui === "color" ? (
<ColorField
key={sf.id}
name={sf.name}
value={(value as string) ?? ""}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
) : sf.ui === "selection" || sf.choices ? (
<p key={sf.id}>Selection or choices field</p>
) : sf.ui === "buttons" ? (
<p key={sf.id}>Button radio field</p>
) : (
<TextInput
key={sf.id}
name={sf.name}
value={(value as string) ?? ""}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
);
case "bool":
return (
<ToggleField
key={sf.id}
name={sf.name}
checked={value as boolean}
description={sf.description}
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
);

default:
return <p key={sf.id}>{sf.name} field</p>;
}
})}
</>
);
Expand Down
91 changes: 0 additions & 91 deletions web/src/beta/components/fields/Toggle/index.tsx

This file was deleted.

69 changes: 69 additions & 0 deletions web/src/beta/components/fields/ToggleField/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useArgs } from "@storybook/preview-api";
import { Meta, StoryObj } from "@storybook/react";
import React, { useCallback } from "react";

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

import ToggleField from ".";

type Props = React.ComponentProps<typeof ToggleField>;

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

export default meta;

type Story = StoryObj<typeof ToggleField>;

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

const handleChange = useCallback(
(checked: boolean) => updateArgs({ checked: !checked }),
[updateArgs],
);

return (
<Wrapper>
<div>
<ToggleField {...args} onChange={handleChange} />
</div>
<div>
<ToggleField
{...args}
name="Reverse Toggle"
description={"Invesere of above"}
checked={!args.checked}
onChange={handleChange}
/>
</div>
<div>
<ToggleField
{...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: "Toggle Field",
description: "Sample description",
checked: true,
disabled: false,
onChange: () => console.log("clicked"),
};
21 changes: 21 additions & 0 deletions web/src/beta/components/fields/ToggleField/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
jashanbhullar marked this conversation as resolved.
Show resolved Hide resolved

import Property from "@reearth/beta/components/fields";
import Toggle from "@reearth/beta/components/Toggle";

type ToggleProps = React.ComponentProps<typeof Toggle>;
jashanbhullar marked this conversation as resolved.
Show resolved Hide resolved

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

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

export default ToggleField;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMemo } from "react";

import Button from "@reearth/beta/components/Button";
import ToggleButton from "@reearth/beta/components/fields/Toggle";
import Icon from "@reearth/beta/components/Icon";
import Modal from "@reearth/beta/components/Modal";
import Text from "@reearth/beta/components/Text";
import Toggle from "@reearth/beta/components/Toggle";
import { useT } from "@reearth/services/i18n";
import { styled, metricsSizes, useTheme } from "@reearth/services/theme";

Expand Down Expand Up @@ -174,7 +174,7 @@ const PublishModal: React.FC<Props> = ({
<HideableSection showOptions={showOptions}>
<Wrapper>
<Subtitle size="body">{t("Search engine indexing")}</Subtitle>
<ToggleButton checked={searchIndex} onChange={handleSearchIndexChange} />
<Toggle checked={searchIndex} onChange={handleSearchIndexChange} />
jashanbhullar marked this conversation as resolved.
Show resolved Hide resolved
</Wrapper>
</HideableSection>
</>
Expand Down
Loading
Loading