Skip to content

Commit

Permalink
chore(web): sketch layer UI implementation (#855)
Browse files Browse the repository at this point in the history
Co-authored-by: KaWaite <34051327+KaWaite@users.noreply.github.com>
Co-authored-by: keiya sasaki <keiya.s.0210@gmail.com>
Co-authored-by: nina992 <89770889+nina992@users.noreply.github.com>
Co-authored-by: nina992 <nouralali992@gmail.com>
Co-authored-by: pyshx <piyushchauhan1004@gmail.com>
  • Loading branch information
6 people committed Jan 16, 2024
1 parent 76ada0e commit 9b9d4bc
Show file tree
Hide file tree
Showing 24 changed files with 522 additions and 53 deletions.
12 changes: 8 additions & 4 deletions web/src/beta/components/Modal/index.tsx
Expand Up @@ -22,6 +22,7 @@ type Props = {
button2?: ReactNode;
children?: ReactNode;
isVisible?: boolean;
isContent?: boolean;
onClose?: () => void;
onTabChange?: (tabId: string) => void;
sidebarTabs?: SidebarTab[];
Expand All @@ -35,6 +36,7 @@ const Modal: React.FC<Props> = ({
button2,
children,
isVisible,
isContent,
onClose,
onTabChange,
sidebarTabs,
Expand Down Expand Up @@ -77,7 +79,7 @@ const Modal: React.FC<Props> = ({
)}
<ContentWrapper>
{tabs.length > 0 && <Content>{tabs.find(tab => tab.active === true)?.content}</Content>}
{children && <Content> {children}</Content>}
{children && <Content isContent={isContent}> {children}</Content>}
{button1 || button2 ? (
<ButtonWrapper>
{tabs.find(tab => tab.active === true)?.tabButton1 ?? button1}
Expand Down Expand Up @@ -117,9 +119,9 @@ const ContentWrapper = styled.div`
flex: 1;
`;

const Content = styled.div`
const Content = styled.div<{ isContent?: boolean }>`
display: flex;
padding: ${({ theme }) => theme.spacing.super}px;
padding: ${({ isContent, theme }) => (isContent ? theme.spacing.normal : theme.spacing.super)}px;
flex-direction: column;
gap: ${({ theme }) => theme.spacing.largest}px;
align-self: stretch;
Expand All @@ -130,9 +132,11 @@ const ButtonWrapper = styled.div`
flex-direction: row;
align-self: stretch;
justify-content: flex-end;
border-top: 1px solid ${({ theme }) => theme.bg[3]};
gap: ${({ theme }) => theme.spacing.normal}px;
padding: ${({ theme }) => theme.spacing.normal}px;
background: ${({ theme }) => theme.bg[1]};
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
`;

export default Modal;
44 changes: 28 additions & 16 deletions web/src/beta/components/TabMenu/index.tsx
Expand Up @@ -6,38 +6,42 @@ import { styled } from "@reearth/services/theme";

import Text from "../Text";

type menuAlignment = "top" | "left";

export type TabObject = {
id: string;
name?: string;
icon: keyof typeof Icons;
icon?: keyof typeof Icons;
component?: JSX.Element;
};

export type Props = {
tabs: TabObject[];
selectedTab: string;
onSelectedTabChange: (tab: string) => void;
menuAlignment?: menuAlignment;
};

const TabMenu: FC<Props> = ({ tabs, selectedTab, onSelectedTabChange }) => {
const TabMenu: FC<Props> = ({ tabs, selectedTab, onSelectedTabChange, menuAlignment }) => {
const selectedTabItem = useMemo(() => {
return tabs.find(({ id }) => id === selectedTab);
}, [selectedTab, tabs]);

return (
<Wrapper>
<Tabs>
{tabs.map(({ id, icon }) => (
<Wrapper menuAlignment={menuAlignment}>
<Tabs menuAlignment={menuAlignment}>
{tabs.map(({ id, icon, name }) => (
<TabIconWrapper
key={id}
onClick={() => onSelectedTabChange(id)}
selected={id === selectedTab}>
<Icon icon={icon} size={20} />
selected={id === selectedTab}
menuAlignment={menuAlignment}>
{icon ? <Icon icon={icon} size={20} /> : <TabHeader size="footnote">{name}</TabHeader>}
</TabIconWrapper>
))}
</Tabs>
<MainArea>
{selectedTabItem?.name && (
{selectedTabItem?.name && !menuAlignment && (
<Header>
<Text size="body">{selectedTabItem.name}</Text>
</Header>
Expand All @@ -50,27 +54,37 @@ const TabMenu: FC<Props> = ({ tabs, selectedTab, onSelectedTabChange }) => {

export default TabMenu;

const Wrapper = styled.div`
display: grid;
height: 100%;
const Wrapper = styled.div<{ menuAlignment?: menuAlignment }>`
display: ${({ menuAlignment }) => (menuAlignment === "top" ? "flex" : "grid")};
grid-template-columns: 28px 1fr;
height: 100%;
flex-flow: column nowrap;
position: relative;
background: ${({ theme }) => theme.bg[1]};
border-radius: 4px;
`;

const Tabs = styled.div`
const Tabs = styled.div<{ menuAlignment?: menuAlignment }>`
padding-top: 4px;
grid-column: 1/2;
background: ${({ theme }) => theme.bg[0]};
display: flex;
flex-flow: ${({ menuAlignment }) => (menuAlignment === "top" ? "row" : "column")} nowrap;
`;

const TabIconWrapper = styled.div<{ selected: boolean }>`
const TabIconWrapper = styled.div<{ selected: boolean; menuAlignment?: menuAlignment }>`
padding: 4px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
color: ${({ selected, theme }) => (selected ? theme.content.main : theme.content.weak)};
background: ${props => (props.selected ? props.theme.bg[1] : "inherit")};
border-top-right-radius: ${({ menuAlignment }) => (menuAlignment === "top" ? "4px" : "0")};
border-top-left-radius: ${({ menuAlignment }) => (menuAlignment === "top" ? "4px" : "0")};
`;

const TabHeader = styled(Text)`
padding: 4px;
`;

const Header = styled.div`
Expand All @@ -80,8 +94,6 @@ const Header = styled.div`
`;

const MainArea = styled.div`
grid-column: 2/-1;
display: block;
padding: 12px;
background: ${({ theme }) => theme.bg[1]};
`;
2 changes: 1 addition & 1 deletion web/src/beta/components/fields/SelectField/index.tsx
Expand Up @@ -164,7 +164,7 @@ const InputWrapper = styled.div<{ disabled: boolean }>`
`;

const Select = styled.div<{ open: boolean; selected: boolean }>`
padding: 7px 8px;
padding: 9px 8px;
/* The width + placement of the arrow icon */
padding-right: 22px;
border-radius: 4px;
Expand Down
10 changes: 5 additions & 5 deletions web/src/beta/features/Editor/DataSourceManager/Common/index.tsx
Expand Up @@ -6,10 +6,6 @@ import URLField from "@reearth/beta/components/fields/URLField";
import RadioGroup from "@reearth/beta/components/RadioGroup";
import Toggle from "@reearth/beta/components/Toggle";
import { AcceptedFileFormat } from "@reearth/beta/features/Assets/types";
import { DataType } from "@reearth/beta/lib/core/Map";
import { useT } from "@reearth/services/i18n";

import { DataProps, DataSourceOptType, SourceType } from "..";
import {
ColJustifyBetween,
AssetWrapper,
Expand All @@ -19,7 +15,11 @@ import {
SubmitWrapper,
TextArea,
generateTitle,
} from "../utils";
} from "@reearth/beta/features/Editor/utils";
import { DataType } from "@reearth/beta/lib/core/Map";
import { useT } from "@reearth/services/i18n";

import { DataProps, DataSourceOptType, SourceType } from "..";

const SelectDataType: React.FC<{
fileFormat: AcceptedFileFormat;
Expand Down
Expand Up @@ -4,9 +4,6 @@ import Button from "@reearth/beta/components/Button";
import URLField from "@reearth/beta/components/fields/URLField";
import RadioGroup from "@reearth/beta/components/RadioGroup";
import Text from "@reearth/beta/components/Text";
import { useT } from "@reearth/services/i18n";

import { DataProps, SourceType, DataSourceOptType } from "..";
import {
ColJustifyBetween,
AssetWrapper,
Expand All @@ -15,7 +12,10 @@ import {
SourceTypeWrapper,
SubmitWrapper,
generateTitle,
} from "../utils";
} from "@reearth/beta/features/Editor/utils";
import { useT } from "@reearth/services/i18n";

import { DataProps, SourceType, DataSourceOptType } from "..";

const DelimitedText: React.FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
const t = useT();
Expand Down
@@ -1,17 +1,17 @@
import { useState } from "react";

import Button from "@reearth/beta/components/Button";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
import {
ColJustifyBetween,
AssetWrapper,
InputGroup,
Input,
SubmitWrapper,
generateTitle,
} from "../utils";
} from "@reearth/beta/features/Editor/utils";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";

const ThreeDTiles: React.FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
const t = useT();
Expand Down
@@ -1,10 +1,6 @@
import { FC } from "react";

import Button from "@reearth/beta/components/Button";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
import useHooks from "../hooks";
import {
AddLayerWrapper,
AssetWrapper,
Expand All @@ -15,7 +11,11 @@ import {
LayerWrapper,
SubmitWrapper,
generateTitle,
} from "../utils";
} from "@reearth/beta/features/Editor/utils";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
import useHooks from "../hooks";

const VectorTiles: FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
const {
Expand Down
@@ -1,10 +1,6 @@
import { FC } from "react";

import Button from "@reearth/beta/components/Button";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
import useHooks from "../hooks";
import {
AddLayerWrapper,
AssetWrapper,
Expand All @@ -15,7 +11,11 @@ import {
LayerWrapper,
SubmitWrapper,
generateTitle,
} from "../utils";
} from "@reearth/beta/features/Editor/utils";
import { useT } from "@reearth/services/i18n";

import { DataProps } from "..";
import useHooks from "../hooks";

const WmsTiles: FC<DataProps> = ({ sceneId, onSubmit, onClose }) => {
const t = useT();
Expand Down
@@ -0,0 +1,110 @@
import { useCallback, useState } from "react";

import Button from "@reearth/beta/components/Button";
import {
ColJustifyBetween,
AssetWrapper,
InputGroup,
Input,
SubmitWrapper,
InputWrapper,
AddButtonWrapper,
SelectWrapper,
PropertyList,
PropertyListHeader,
StyledText,
DataTypeContent,
PropertyContent,
DataTypeText,
DeleteDataType,
PropertyContentWrapper,
} from "@reearth/beta/features/Editor/utils";
import { useT } from "@reearth/services/i18n";

import { SketchProps, dataTypes } from "..";

const CustomedProperties: React.FC<SketchProps> = ({ propertyList = [], setPropertyList }) => {
const t = useT();
const [propertyName, setPropertyName] = useState<string>("");
const [dataType, setDataType] = useState<string>("");

const handleAddToPropertyToList = useCallback(() => {
const newData = { [propertyName]: dataType };

setPropertyList?.([...propertyList, newData]);
setPropertyName("");
setDataType("");
}, [dataType, propertyName, propertyList, setPropertyList]);

const handleDeletePropertyToList = useCallback(
(idx: number) => {
const updatedPropertiesList = [...propertyList];
updatedPropertiesList.splice(idx, 1);
setPropertyList?.(updatedPropertiesList);
},
[propertyList, setPropertyList],
);

return (
<ColJustifyBetween>
<AssetWrapper>
<InputWrapper>
<InputGroup label={t("Name")} description={t("Property name you want to add.")}>
<Input
type="text"
placeholder={t("Input Text")}
value={propertyName}
onChange={e => setPropertyName(e.target.value)}
/>
</InputGroup>
<SelectWrapper
value={dataType}
name={t("Data Type")}
description={t("Type of data you want to add.")}
options={dataTypes.map(v => ({ key: v, label: v }))}
attachToRoot
onChange={setDataType}
/>
</InputWrapper>
<AddButtonWrapper>
<Button
text={t("Add to proprety list")}
buttonType="primary"
size="medium"
disabled={!propertyName}
onClick={handleAddToPropertyToList}
/>
</AddButtonWrapper>
</AssetWrapper>

<PropertyList>
<PropertyListHeader>
<StyledText size="footnote">{t("Name")}</StyledText>
<StyledText size="footnote">{t("Data Types")}</StyledText>
</PropertyListHeader>
<PropertyContentWrapper>
{propertyList?.length > 0 &&
propertyList?.map((item, i) => {
return (
<PropertyContent key={i}>
<StyledText size="footnote">{Object.keys(item)[0]}</StyledText>
<DataTypeContent>
<DataTypeText size="footnote">{Object.values(item)[0]}</DataTypeText>{" "}
<DeleteDataType
icon="bin"
size={16}
onClick={() => handleDeletePropertyToList(i)}
/>
</DataTypeContent>
</PropertyContent>
);
})}
</PropertyContentWrapper>
</PropertyList>

<SubmitWrapper />
</ColJustifyBetween>
);
};

export default CustomedProperties;

0 comments on commit 9b9d4bc

Please sign in to comment.