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
53 changes: 53 additions & 0 deletions web/src/beta/components/Toggle/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useArgs } from "@storybook/preview-api";
import { Meta, StoryObj } from "@storybook/react";
import { useCallback } from "react";

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

import Toggle, { Props } from ".";

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";

export 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)"};
`;
10 changes: 10 additions & 0 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,6 +19,7 @@ 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
Expand All @@ -40,6 +42,14 @@ const PropertyFields: React.FC<Props> = ({ propertyId, item }) => {
onChange={handlePropertyValueUpdate(item.schemaGroup, propertyId, sf.id, sf.type)}
/>
)
) : 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)}
/>
) : (
<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.

67 changes: 67 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,67 @@
import { useArgs } from "@storybook/preview-api";
import { Meta, StoryObj } from "@storybook/react";
import { useCallback } from "react";

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

import ToggleField, { Props } from ".";

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"),
};
17 changes: 17 additions & 0 deletions web/src/beta/components/fields/ToggleField/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Property from "@reearth/beta/components/fields";
import Toggle, { Props as ToggleProps } from "@reearth/beta/components/Toggle";

export 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,7 +1,7 @@
import { useMemo } from "react";

import Button from "@reearth/beta/components/Button";
import ToggleButton from "@reearth/beta/components/fields/Toggle";
import ToggleField from "@reearth/beta/components/fields/ToggleField";
import Icon from "@reearth/beta/components/Icon";
import Modal from "@reearth/beta/components/Modal";
import Text from "@reearth/beta/components/Text";
Expand Down Expand Up @@ -172,10 +172,12 @@ const PublishModal: React.FC<Props> = ({
<ArrowIcon icon="arrowToggle" size={16} open={showOptions} />
</OptionsToggle>
<HideableSection showOptions={showOptions}>
<Wrapper>
<Subtitle size="body">{t("Search engine indexing")}</Subtitle>
<ToggleButton checked={searchIndex} onChange={handleSearchIndexChange} />
</Wrapper>
<ToggleField
name={t("Search engine indexing")}
description={t("Page will be available as result on search engines")}
checked={searchIndex}
onChange={handleSearchIndexChange}
/>
</HideableSection>
</>
) : (
Expand Down Expand Up @@ -244,9 +246,3 @@ const UrlText = styled(Text)`
const HideableSection = styled(Section)<{ showOptions?: boolean }>`
display: ${props => (props.showOptions ? null : "none")};
`;

const Wrapper = styled.div`
display: flex;
justify-content: space-between;
align-content: center;
`;
16 changes: 8 additions & 8 deletions web/src/beta/features/Editor/tabs/widgets/Nav/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect } from "react";

import Toggle from "@reearth/beta/components/fields/Toggle";
import Text from "@reearth/beta/components/Text";
import Toggle from "@reearth/beta/components/Toggle";
import SecondaryNav from "@reearth/beta/features/Editor/SecondaryNav";
import { useT } from "@reearth/services/i18n";
import { selectedWidgetAreaVar } from "@reearth/services/state";
Expand Down Expand Up @@ -37,12 +38,8 @@ const Nav: React.FC<Props> = ({
<StyledSecondaryNav>
<Devices selectedDevice={selectedDevice} onDeviceChange={onDeviceChange} />
<AlignSystem>
<Toggle
label={t("Align System")}
size="sm"
checked={!!showWidgetEditor}
onChange={onShowWidgetEditor}
/>
<Text size="body">{t("Align System")}</Text>
<Toggle checked={!!showWidgetEditor} onChange={onShowWidgetEditor} />
</AlignSystem>
</StyledSecondaryNav>
);
Expand All @@ -57,4 +54,7 @@ const StyledSecondaryNav = styled(SecondaryNav)`
padding-left: 8px;
`;

const AlignSystem = styled.div``;
const AlignSystem = styled.div`
display: flex;
gap: 10px;
`;
1 change: 1 addition & 0 deletions web/src/services/i18n/translations/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Embed Code: Embed Code
'* Please use this code if you want to embed your project into a webpage': '* Please use this code if you want to embed your project into a webpage'
more options: more options
Search engine indexing: Search engine indexing
Page will be available as result on search engines: ''
Your project will be unpublished.: Your project will be unpublished.
This means that anybody with the URL will become unable to view this project.: This means that anybody with the URL will become unable to view this project.
'**Warning**: This includes websites where this project is embedded.': '**Warning**: This includes websites where this project is embedded.'
Expand Down
Loading
Loading