Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
fix: timeline styles (#352)
Browse files Browse the repository at this point in the history
* feat: add reearth favicon

* fix styles in main timeline component

* fix scale styles

* update scale time size

* make publishedTheme optional

* fix minimizing/extending

* Timeline defaults to opened
  • Loading branch information
KaWaite committed Nov 11, 2022
1 parent 9be75ad commit c76d368
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 59 deletions.
23 changes: 16 additions & 7 deletions src/components/atoms/Timeline/ScaleList.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { memo } from "react";

import Text from "@reearth/components/atoms/Text";
import { styled } from "@reearth/theme";
import { PublishTheme, styled } from "@reearth/theme";

import { EPOCH_SEC, STRONG_SCALE_WIDTH, NORMAL_SCALE_WIDTH, PADDING_HORIZONTAL } from "./constants";
import { formatDateForTimeline } from "./utils";

type Props = {
publishedTheme?: PublishTheme;
gapHorizontal: number;
} & ScaleListInnerProps;

const ScaleList: React.FC<Props> = ({ gapHorizontal, ...props }) => {
const ScaleList: React.FC<Props> = ({ publishedTheme, gapHorizontal, ...props }) => {
return (
<ScaleContainer style={{ gap: `0 ${gapHorizontal}px` }}>
<ScaleListInner {...props} />
<ScaleListInner publishedTheme={publishedTheme} {...props} />
</ScaleContainer>
);
};

type ScaleListInnerProps = {
publishedTheme?: PublishTheme;
start: Date;
scaleCount: number;
hoursCount: number;
Expand All @@ -27,6 +29,7 @@ type ScaleListInnerProps = {
};

const ScaleListInner: React.FC<ScaleListInnerProps> = memo(function ScaleListPresenter({
publishedTheme,
start,
scaleCount,
hoursCount,
Expand All @@ -45,7 +48,9 @@ const ScaleListInner: React.FC<ScaleListInnerProps> = memo(function ScaleListPre

return (
<LabeledScale key={idx}>
<ScaleLabel size="xs">{label}</ScaleLabel>
<ScaleLabel size="2xs" customColor publishedTheme={publishedTheme}>
{label}
</ScaleLabel>
<Scale isHour={isHour} isStrongScale={isStrongScale} />
</LabeledScale>
);
Expand All @@ -56,6 +61,10 @@ const ScaleListInner: React.FC<ScaleListInnerProps> = memo(function ScaleListPre
);
});

export type StyledColorProps = {
publishedTheme: PublishTheme | undefined;
};

const ScaleContainer = styled.div`
display: flex;
width: 0;
Expand All @@ -67,7 +76,7 @@ const ScaleContainer = styled.div`
::after {
content: "";
display: block;
padding-right: ${PADDING_HORIZONTAL}px;
padding-right: 1px;
height: 1px;
}
`;
Expand All @@ -79,11 +88,11 @@ const LabeledScale = styled.div`
height: 100%;
`;

const ScaleLabel = styled(Text)`
const ScaleLabel = styled(Text)<StyledColorProps>`
position: absolute;
top: 0;
left: 0;
color: ${({ theme }) => theme.colors.publish.dark.text.main};
color: ${({ theme, publishedTheme }) => publishedTheme?.mainText || theme.main.text};
white-space: nowrap;
`;

Expand Down
5 changes: 4 additions & 1 deletion src/components/atoms/Timeline/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,10 @@ const useTimelinePlayer = ({
const lastIdx = textDate.lastIndexOf(" ");
const date = textDate.slice(0, lastIdx);
const time = textDate.slice(lastIdx);
return `${date}\n${time}`;
return {
date,
time,
};
}, [currentTime]);

useEffect(() => {
Expand Down
100 changes: 58 additions & 42 deletions src/components/atoms/Timeline/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import Text from "@reearth/components/atoms/Text";
// eslint-disable-next-line no-restricted-imports
import type { SceneProperty } from "@reearth/components/molecules/Visualizer";
import { useT } from "@reearth/i18n";
import { PublishTheme, styled, usePublishTheme } from "@reearth/theme";
import { styled, usePublishTheme } from "@reearth/theme";

import { BORDER_WIDTH, PADDING_HORIZONTAL, KNOB_SIZE } from "./constants";
import { useTimeline } from "./hooks";
import ScaleList from "./ScaleList";
import ScaleList, { StyledColorProps } from "./ScaleList";
import { Range, TimeEventHandler } from "./types";

export type Props = {
Expand All @@ -24,30 +24,30 @@ export type Props = {
*/
range?: { [K in keyof Range]?: Range[K] };
speed?: number;
isOpened?: boolean;
sceneProperty?: SceneProperty;
onClick?: TimeEventHandler;
onDrag?: TimeEventHandler;
onPlay?: (isPlaying: boolean) => void;
onPlayReversed?: (isPlaying: boolean) => void;
onOpen?: () => void;
onClose?: () => void;
onSpeedChange?: (speed: number) => void;
isOpened?: boolean;
sceneProperty?: SceneProperty;
};

const Timeline: React.FC<Props> = memo(function TimelinePresenter({
currentTime,
range,
speed,
isOpened,
sceneProperty,
onClick,
onDrag,
onPlay,
onPlayReversed,
isOpened,
onOpen,
onClose,
onSpeedChange: onSpeedChangeProps,
sceneProperty,
}) {
const {
startDate,
Expand Down Expand Up @@ -79,10 +79,12 @@ const Timeline: React.FC<Props> = memo(function TimelinePresenter({
const t = useT();

return isOpened ? (
<Container>
<CloseButton publishedTheme={publishedTheme} onClick={onClose}>
<Icon alt={t("Close timeline")} icon="cancel" size={16} />
</CloseButton>
<Container publishedTheme={publishedTheme}>
<div style={{ width: "32px" }}>
<CloseButton publishedTheme={publishedTheme} onClick={onClose}>
<Icon alt={t("Close timeline")} icon="cancel" size={16} />
</CloseButton>
</div>
<ToolBox>
<li>
<PlayButton
Expand All @@ -103,7 +105,9 @@ const Timeline: React.FC<Props> = memo(function TimelinePresenter({
</li>
<li>
<InputRangeLabel>
<InputRangeLabelText size="xs">{speed}x</InputRangeLabelText>
<InputRangeLabelText size="xs" customColor publishedTheme={publishedTheme}>
{speed}X
</InputRangeLabelText>
<InputRange
publishedTheme={publishedTheme}
type="range"
Expand All @@ -115,9 +119,14 @@ const Timeline: React.FC<Props> = memo(function TimelinePresenter({
</InputRangeLabel>
</li>
</ToolBox>
<CurrentTime size="xs" weight="bold">
{formattedCurrentTime}
</CurrentTime>
<CurrentTimeWrapper>
<CurrentTime size="xs" customColor publishedTheme={publishedTheme}>
{formattedCurrentTime.date}
</CurrentTime>
<CurrentTime size="xs" customColor publishedTheme={publishedTheme}>
{formattedCurrentTime.time}
</CurrentTime>
</CurrentTimeWrapper>
{/**
* TODO: Support keyboard operation for accessibility
* see: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role
Expand All @@ -130,6 +139,7 @@ const Timeline: React.FC<Props> = memo(function TimelinePresenter({
gapHorizontal={gapHorizontal}
scaleInterval={scaleInterval}
strongScaleHours={strongScaleHours}
publishedTheme={publishedTheme}
/>
<IconWrapper
data-testid="knob-icon"
Expand All @@ -142,19 +152,16 @@ const Timeline: React.FC<Props> = memo(function TimelinePresenter({
</ScaleBox>
</Container>
) : (
<OpenButton onClick={onOpen}>
<OpenButton publishedTheme={publishedTheme} onClick={onOpen}>
<Icon alt={t("Open timeline")} icon="timeline" size={24} />
</OpenButton>
);
});

type StyledColorProps = {
publishedTheme: PublishTheme | undefined;
};

const Container = styled.div`
background: ${({ theme }) => theme.main.deepBg};
const Container = styled.div<StyledColorProps>`
background: ${({ theme, publishedTheme }) => publishedTheme?.background || theme.main.deepBg};
width: 100%;
height: 40px;
display: flex;
box-sizing: border-box;
-webkit-user-select: none;
Expand All @@ -163,16 +170,15 @@ const Container = styled.div`
user-select: none;
`;

const OpenButton = styled.button`
background: ${({ theme }) => theme.main.deepBg};
color: ${({ theme }) => theme.main.text};
const OpenButton = styled.button<StyledColorProps>`
background: ${({ theme, publishedTheme }) => publishedTheme?.background || theme.main.deepBg};
color: ${({ theme, publishedTheme }) => publishedTheme?.mainText || theme.main.text};
padding: 8px 12px;
`;

const CloseButton = styled.button<StyledColorProps>`
background: ${({ theme, publishedTheme }) => publishedTheme?.select || theme.main.select};
padding: 4px;
color: ${({ theme }) => theme.main.text};
color: ${({ theme, publishedTheme }) => publishedTheme?.mainText || theme.main.text};
display: flex;
align-items: center;
justify-content: center;
Expand All @@ -191,10 +197,13 @@ const ToolBox = styled.ul`

const PlayButton = styled.button<{ isRight?: boolean; isPlaying?: boolean } & StyledColorProps>`
border-radius: 50%;
width: 24px;
height: 24px;
border: ${({ theme }) => `1px solid ${theme.main.weak}`};
color: ${({ theme }) => theme.main.text};
border-width: 1px;
border-style: solid;
border-color: ${({ theme, isPlaying, publishedTheme }) =>
isPlaying ? publishedTheme?.select : publishedTheme?.mainText || theme.main.text};
width: 22px;
height: 22px;
color: ${({ theme, publishedTheme }) => publishedTheme?.mainText || theme.main.text};
display: flex;
align-items: center;
justify-content: center;
Expand All @@ -207,11 +216,11 @@ const InputRangeLabel = styled.label`
display: flex;
align-items: center;
justify-content: center;
margin: ${({ theme }) => `0 ${theme.metrics.s}px 0 ${theme.metrics.m}px`};
margin: ${({ theme }) => `0 ${theme.metrics["2xs"]}px 0 ${theme.metrics["2xs"]}px`};
`;

const InputRangeLabelText = styled(Text)`
color: ${({ theme }) => theme.main.text};
const InputRangeLabelText = styled(Text)<StyledColorProps>`
color: ${({ theme, publishedTheme }) => publishedTheme?.mainText || theme.main.text};
/* space for preventing layout shift by increasing speed label. */
width: 37px;
text-align: right;
Expand All @@ -233,40 +242,47 @@ const InputRange = styled.input<StyledColorProps>`
}
`;

const CurrentTime = styled(Text)`
const CurrentTimeWrapper = styled.div`
border: ${({ theme }) => `1px solid ${theme.main.weak}`};
border-radius: 5px;
color: ${({ theme }) => theme.main.text};
border-radius: 4px;
padding: ${({ theme }) => `0 ${theme.metrics.s}px`};
margin: ${({ theme }) => `${theme.metrics.s}px 0`};
margin: ${({ theme }) => `${theme.metrics.xs}px 0`};
flex-shrink: 0;
`;

const CurrentTime = styled(Text)<StyledColorProps>`
color: ${({ theme, publishedTheme }) => publishedTheme?.mainText || theme.main.text};
line-height: 16px;
white-space: pre-line;
`;

const ScaleBox = styled.div`
border: ${({ theme }) => `${BORDER_WIDTH}px solid ${theme.colors.publish.dark.icon.weak}`};
border: ${({ theme }) => `${BORDER_WIDTH}px solid ${theme.main.weak}`};
border-radius: 5px;
box-sizing: border-box;
position: relative;
overflow-x: auto;
overflow-x: overlay;
overflow-y: hidden;
width: 100%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
::-webkit-scrollbar {
height: 5px;
transition: -webkit-scrollbar 1s;
:hover::-webkit-scrollbar {
height: 2px;
}
::-webkit-scrollbar-track {
background-color: transparent;
background-color: red;
display: none;
}
::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: ${({ theme }) => theme.colors.publish.dark.icon.main};
}
margin: ${({ theme }) =>
`${theme.metrics.s}px ${theme.metrics.m}px ${theme.metrics.s}px ${theme.metrics.xs}px`};
`${theme.metrics.xs}px ${theme.metrics.s}px ${theme.metrics.xs}px ${theme.metrics.xs}px`};
`;

const IconWrapper = styled.div<StyledColorProps>`
Expand Down
18 changes: 14 additions & 4 deletions src/components/molecules/Visualizer/Widget/Timeline/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState, useCallback, useEffect, useRef } from "react";

import { TimeEventHandler } from "@reearth/components/atoms/Timeline/types";
import { Widget } from "@reearth/components/molecules/Visualizer/Plugin";

import { useContext } from "../../Plugin";

Expand All @@ -14,13 +15,19 @@ const makeRange = (startTime?: number, stopTime?: number) => {

const DEFAULT_SPEED = 1;

export const useTimeline = () => {
export const useTimeline = ({
widget,
onExtend,
}: {
widget: Widget;
onExtend?: (id: string, extended: boolean | undefined) => void;
}) => {
const ctx = useContext();
const clock = ctx?.reearth.clock;
const [range, setRange] = useState(() =>
makeRange(clock?.startTime.getTime(), clock?.stopTime.getTime()),
);
const [isOpened, setIsOpened] = useState(false);
const [isOpened, setIsOpened] = useState(true);
const [currentTime, setCurrentTime] = useState(() => getOrNewDate(clock?.currentTime).getTime());
const isClockInitialized = useRef(false);
const clockCurrentTime = clock?.currentTime.getTime();
Expand All @@ -31,11 +38,14 @@ export const useTimeline = () => {
const [speed, setSpeed] = useState(clockSpeed);

const handleOnOpen = useCallback(() => {
onExtend?.(widget.id, true);
setIsOpened(true);
}, []);
}, [widget.id, onExtend]);

const handleOnClose = useCallback(() => {
onExtend?.(widget.id, false);
setIsOpened(false);
}, []);
}, [widget.id, onExtend]);

const handleTimeEvent: TimeEventHandler = useCallback(
currentTime => {
Expand Down
Loading

0 comments on commit c76d368

Please sign in to comment.