Skip to content

Commit

Permalink
chore(web): story page settings (#639)
Browse files Browse the repository at this point in the history
  • Loading branch information
KaWaite authored Aug 31, 2023
1 parent fdc0569 commit 0eaeed2
Show file tree
Hide file tree
Showing 53 changed files with 836 additions and 364 deletions.
3 changes: 3 additions & 0 deletions web/src/beta/components/Icon/Icons/storyPage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions web/src/beta/components/Icon/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import WorkspaceAdd from "./Icons/workspaceAdd.svg";
import Workspaces from "./Icons/workspaces.svg";

// Storytelling tab
import StoryPage from "./Icons/storyPage.svg";
import Square from "./Icons/square.svg";
import Swiper from "./Icons/swiper.svg";
import Book from "./Icons/book.svg";
Expand Down Expand Up @@ -128,6 +129,7 @@ export default {
ellipse: Ellipse,
playRight: PlayRight,
playLeft: PlayLeft,
storyPage: StoryPage,
square: Square,
swiper: Swiper,
book: Book,
Expand Down
4 changes: 2 additions & 2 deletions web/src/beta/components/Icon/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import svgToMiniDataURI from "mini-svg-data-uri";
import React, { AriaAttributes, AriaRole, CSSProperties, memo, useMemo } from "react";
import React, { AriaAttributes, AriaRole, CSSProperties, MouseEvent, memo, useMemo } from "react";
import SVG from "react-inlinesvg";

import { ariaProps } from "@reearth/beta/utils/aria";
Expand All @@ -20,7 +20,7 @@ export type Props = {
role?: AriaRole;
notransition?: boolean;
transitionDuration?: string;
onClick?: () => void;
onClick?: (e?: MouseEvent<Element>) => void;
} & AriaAttributes;

const Icon: React.FC<Props> = ({
Expand Down
7 changes: 2 additions & 5 deletions web/src/beta/components/fields/ColorField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ import Property from "..";
import useHooks from "./hooks";
import { Props, RGBA } from "./types";

// Constants
const channels = ["r", "g", "b", "a"];
const hexPlaceholder = "#RRGGBBAA";

// Component
const ColorField: React.FC<Props> = ({ name, description, value, onChange }) => {
const t = useT();
const theme = useTheme();
Expand Down Expand Up @@ -60,14 +58,14 @@ const ColorField: React.FC<Props> = ({ name, description, value, onChange }) =>
<PickerWrapper>
<HeaderWrapper>
<PickerTitle size="footnote" weight="regular" color={theme.content.main}>
Color Picker
{t("Color Picker")}
</PickerTitle>
{handleClose && <CloseIcon icon="cancel" size={12} onClick={handleClose} />}
</HeaderWrapper>
<SelectorPickerWrapper>
<ColorPicker className="colorPicker" color={rgba} onChange={handleChange} />
<RgbaInputWrapper>
<Text size="footnote"> RGBA</Text>
<Text size="footnote">RGBA</Text>
<ValuesWrapper>
{channels.map(channel => (
<Input
Expand Down Expand Up @@ -104,7 +102,6 @@ const ColorField: React.FC<Props> = ({ name, description, value, onChange }) =>
);
};

// Styled Components
const Wrapper = styled.div`
text-align: center;
width: 100%;
Expand Down
206 changes: 206 additions & 0 deletions web/src/beta/features/Editor/StoryPanel/ActionPanel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import { Dispatch, Fragment, MouseEvent, SetStateAction, useMemo } from "react";

import FieldComponents from "@reearth/beta/components/fields/PropertyFields";
import Icon, { Icons } from "@reearth/beta/components/Icon";
import * as Popover from "@reearth/beta/components/Popover";
import PopoverMenuContent from "@reearth/beta/components/PopoverMenuContent";
import Text from "@reearth/beta/components/Text";
import { stopClickPropagation } from "@reearth/beta/utils/events";
import { Item } from "@reearth/services/api/propertyApi/utils";
import { useT } from "@reearth/services/i18n";
import { styled } from "@reearth/services/theme";

export type ActionItem = {
icon: string;
name?: string;
hide?: boolean;
onClick?: (e: MouseEvent<HTMLDivElement>) => void;
};

export type ActionPosition = "left-top" | "left-bottom" | "right-top" | "right-bottom";

type Props = {
isSelected?: boolean;
showSettings?: boolean;
showPadding?: boolean;
propertyId?: string;
panelSettings?: Item;
actionItems: ActionItem[];
dndEnabled?: boolean;
position?: ActionPosition;
setShowPadding: Dispatch<SetStateAction<boolean>>;
onSettingsToggle?: () => void;
onRemove?: () => void;
};

const ActionPanel: React.FC<Props> = ({
isSelected,
showSettings,
showPadding,
propertyId,
panelSettings,
actionItems,
dndEnabled,
position,
setShowPadding,
onSettingsToggle,
onRemove,
}) => {
const t = useT();

const popoverContent = useMemo(() => {
const menuItems: { name: string; icon: Icons; onClick: () => void }[] = [
{
name: t("Padding settings"),
icon: "padding",
onClick: () => setShowPadding(true),
},
];
if (onRemove) {
menuItems.push({
name: t("Remove"),
icon: "trash",
onClick: onRemove,
});
}
return menuItems;
}, [t, setShowPadding, onRemove]);

return (
<Wrapper isSelected={isSelected} position={position} onClick={stopClickPropagation}>
{dndEnabled && <DndHandle icon="dndHandle" size={16} />}
<Popover.Provider
open={showSettings}
onOpenChange={() => onSettingsToggle?.()}
placement="bottom-start">
<BlockOptions isSelected={isSelected}>
{actionItems.map(
(a, idx) =>
!a.hide && (
<Fragment key={idx}>
<Popover.Trigger asChild>
<OptionWrapper
showPointer={!isSelected || !!a.onClick}
onClick={a.onClick ?? stopClickPropagation}>
<OptionIcon icon={a.icon} size={16} border={idx !== 0} />
{a.name && (
<OptionText size="footnote" customColor>
{a.name}
</OptionText>
)}
</OptionWrapper>
</Popover.Trigger>
</Fragment>
),
)}
</BlockOptions>
<Popover.Content>
{showPadding ? (
<SettingsDropdown>
<SettingsHeading>
<Text size="footnote" customColor>
{panelSettings?.title}
</Text>
<CancelIcon icon="cancel" size={14} onClick={() => setShowPadding(false)} />
</SettingsHeading>
{propertyId && panelSettings && (
<SettingsContent>
<FieldComponents propertyId={propertyId} item={panelSettings} />
</SettingsContent>
)}
</SettingsDropdown>
) : (
<PopoverMenuContent size="sm" items={popoverContent} />
)}
</Popover.Content>
</Popover.Provider>
</Wrapper>
);
};

export default ActionPanel;

const Wrapper = styled.div<{ isSelected?: boolean; position?: ActionPosition }>`
color: ${({ theme }) => theme.select.main};
display: flex;
align-items: center;
gap: 4px;
height: 24px;
position: absolute;
${({ position }) =>
position === "left-top"
? `
left: -1px;
top: -25px;
`
: position === "left-bottom"
? `
left: -1px;
top: 0;
`
: position === "right-bottom"
? `
top: 0;
right: -1px;
`
: `
right: -1px;
top: -25px;
`}
transition: all 0.2s;
`;

const BlockOptions = styled.div<{ isSelected?: boolean }>`
background: ${({ isSelected, theme }) => (isSelected ? theme.select.main : "transparent")};
color: ${({ isSelected, theme }) => (isSelected ? theme.content.main : theme.select.main)};
display: flex;
align-items: center;
height: 24px;
transition: all 0.2s;
`;

const OptionWrapper = styled.div<{ showPointer?: boolean }>`
display: flex;
align-items: center;
cursor: ${({ showPointer }) => (showPointer ? "pointer" : "default")};
`;

const OptionText = styled(Text)`
padding-right: 4px;
`;

const OptionIcon = styled(Icon)<{ border?: boolean }>`
padding: 4px;
${({ border }) => border && "border-left: 1px solid #f1f1f1;"}
`;

const SettingsDropdown = styled.div`
z-index: 999;
background: ${({ theme }) => theme.bg[1]};
border-radius: 2px;
border: 1px solid ${({ theme }) => theme.bg[3]};
`;

const SettingsHeading = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid ${({ theme }) => theme.outline.weak};
height: 28px;
padding: 0 8px;
`;

const SettingsContent = styled.div`
height: 100px;
width: 200px;
padding: 8px;
box-sizing: border-box;
`;

const CancelIcon = styled(Icon)`
cursor: pointer;
`;

const DndHandle = styled(Icon)`
cursor: move;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { useMemo } from "react";
import { ValueTypes } from "@reearth/beta/utils/value";
import { styled } from "@reearth/services/theme";

import { getFieldValue } from "../../../utils";
import { CommonProps as BlockProps } from "../../types";
import BlockWrapper from "../common/Wrapper";
import { getFieldValue } from "../utils";

const ImageBlock: React.FC<BlockProps> = ({ block, isSelected, ...props }) => {
const src = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { useMemo } from "react";
import Text from "@reearth/beta/components/Text";
import { ValueTypes } from "@reearth/beta/utils/value";

import { getFieldValue } from "../../../utils";
import { CommonProps as BlockProps } from "../../types";
import BlockWrapper from "../common/Wrapper";
import { getFieldValue } from "../utils";

export type Props = BlockProps;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useMemo } from "react";

import Text from "@reearth/beta/components/Text";
import { ValueTypes } from "@reearth/beta/utils/value";
import { useT } from "@reearth/services/i18n";
import { styled } from "@reearth/services/theme";

import { getFieldValue } from "../../../utils";
import { CommonProps as BlockProps } from "../../types";
import BlockWrapper from "../common/Wrapper";

export type Props = BlockProps;

const TitleBlock: React.FC<Props> = ({ block, isSelected, ...props }) => {
const t = useT();
const text = useMemo(
() => getFieldValue(block?.property?.items ?? [], "title") as ValueTypes["string"],
[block?.property?.items],
);

const color = useMemo(
() => getFieldValue(block?.property?.items ?? [], "color") as ValueTypes["string"],
[block?.property?.items],
);

return (
<BlockWrapper
title={block?.title}
icon={block?.extensionId}
isSelected={isSelected}
propertyId={block?.property?.id}
propertyItems={block?.property?.items}
dndEnabled={false}
{...props}>
<Title size="h2" hasText={!!text} color={color} customColor>
{text ?? t("Untitled")}
</Title>
</BlockWrapper>
);
};

export default TitleBlock;

const Title = styled(Text)<{ hasText?: boolean; color?: string }>`
color: ${({ color, hasText, theme }) => (hasText ? color ?? "black" : theme.content.weak)};
`;
Loading

0 comments on commit 0eaeed2

Please sign in to comment.