-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/reearth/reearth into feat/a…
…dd-spaing-input-field
- Loading branch information
Showing
134 changed files
with
5,283 additions
and
676 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React from "react"; | ||
import { | ||
AccordionItem as AccordionItemComponent, | ||
AccordionItemButton, | ||
AccordionItemHeading, | ||
AccordionItemPanel, | ||
AccordionItemState, | ||
} from "react-accessible-accordion"; | ||
|
||
import { styled, useTheme } from "@reearth/services/theme"; | ||
|
||
import Icon from "../Icon"; | ||
|
||
export type Props = { | ||
className?: string; | ||
id: string; | ||
heading?: React.ReactNode; | ||
content?: React.ReactNode; | ||
bg?: string; | ||
}; | ||
|
||
const AccordionItem: React.FC<Props> = ({ className, id, heading, content, bg }) => { | ||
const theme = useTheme(); | ||
return ( | ||
<Wrapper key={id} className={className} bg={bg} data-testid="atoms-accordion-item"> | ||
<AccordionItemComponent> | ||
<AccordionItemHeading> | ||
<StyledAccordionItemButton data-testid="atoms-accordion-item-header"> | ||
<AccordionItemStateWrapper> | ||
<AccordionItemState> | ||
{({ expanded }) => ( | ||
<> | ||
<StyledIcon | ||
color={theme.content.main} | ||
icon="arrowToggle" | ||
size={16} | ||
open={!!expanded} | ||
/> | ||
{heading} | ||
</> | ||
)} | ||
</AccordionItemState> | ||
</AccordionItemStateWrapper> | ||
</StyledAccordionItemButton> | ||
</AccordionItemHeading> | ||
<AccordionItemPanel data-testid="atoms-accordion-item-content"> | ||
{content} | ||
</AccordionItemPanel> | ||
</AccordionItemComponent> | ||
</Wrapper> | ||
); | ||
}; | ||
|
||
const Wrapper = styled.div<{ bg?: string }>` | ||
margin: ${({ theme }) => theme.metrics["2xl"]}px 0; | ||
background-color: ${({ bg }) => bg}; | ||
border-radius: ${({ theme }) => theme.metrics["l"]}px; | ||
`; | ||
|
||
const AccordionItemStateWrapper = styled.div` | ||
display: flex; | ||
align-items: center; | ||
padding: ${({ theme }) => theme.metrics["xl"]}px; | ||
`; | ||
|
||
const StyledIcon = styled(Icon)<{ open: boolean }>` | ||
transition: transform 0.15s ease; | ||
transform: ${({ open }) => open && "translateY(10%) rotate(90deg)"}; | ||
margin-right: 24px; | ||
`; | ||
|
||
const StyledAccordionItemButton = styled(AccordionItemButton)` | ||
outline: none; | ||
cursor: pointer; | ||
`; | ||
export default AccordionItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import Accordion from "."; | ||
|
||
const meta: Meta<typeof Accordion> = { | ||
component: Accordion, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof Accordion>; | ||
|
||
const SampleHeading = <div style={{ color: "white", background: "black" }}>heading</div>; | ||
|
||
const SampleContent = ( | ||
<div style={{ color: "white", background: "black", padding: "20px" }}>hoge</div> | ||
); | ||
|
||
export const Default: Story = { | ||
render: () => ( | ||
<Accordion | ||
items={[ | ||
{ | ||
id: "hoge", | ||
heading: SampleHeading, | ||
content: SampleContent, | ||
}, | ||
{ | ||
id: "hogefuga", | ||
heading: SampleHeading, | ||
content: SampleContent, | ||
}, | ||
]} | ||
/> | ||
), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { expect, test } from "vitest"; | ||
|
||
import { fireEvent, render, screen } from "@reearth/test/utils"; | ||
|
||
import Accordion, { AccordionItemType } from "./index"; | ||
|
||
const sampleContents: AccordionItemType[] = [ | ||
{ | ||
id: "1", | ||
heading: <div>This is heading1</div>, | ||
content: <div>This is content1</div>, | ||
}, | ||
{ | ||
id: "2", | ||
heading: <div>This is heading2</div>, | ||
content: <div>This is content2</div>, | ||
}, | ||
]; | ||
|
||
test("should be rendered", () => { | ||
render(<Accordion items={sampleContents} />); | ||
}); | ||
|
||
test("should display items header", () => { | ||
render(<Accordion items={sampleContents} />); | ||
expect(screen.getByTestId("atoms-accordion")).toBeInTheDocument(); | ||
expect(screen.getByText(/heading1/)).toBeInTheDocument(); | ||
expect(screen.getByText(/heading2/)).toBeInTheDocument(); | ||
}); | ||
|
||
test("should display items content", () => { | ||
render(<Accordion items={sampleContents} />); | ||
expect(screen.getByText(/content1/)).toBeInTheDocument(); | ||
expect(screen.getByText(/content2/)).toBeInTheDocument(); | ||
}); | ||
|
||
test("should open when header button is clicked", () => { | ||
render(<Accordion items={sampleContents} />); | ||
expect(screen.getAllByTestId("atoms-accordion-item-content")[0]).not.toBeVisible(); | ||
fireEvent.click(screen.getAllByTestId("atoms-accordion-item-header")[0]); | ||
expect(screen.getAllByTestId("atoms-accordion-item-content")[0]).toBeVisible(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Accordion as AccordionComponent } from "react-accessible-accordion"; | ||
|
||
import AccordionItem from "./AccordionItem"; | ||
|
||
export type Props = { | ||
className?: string; | ||
items?: AccordionItemType[]; | ||
allowZeroExpanded?: boolean; | ||
allowMultipleExpanded?: boolean; | ||
itemBgColor?: string; | ||
}; | ||
|
||
export type AccordionItemType = { | ||
id: string; | ||
heading?: React.ReactNode; | ||
content?: React.ReactNode; | ||
}; | ||
|
||
const Accordion: React.FC<Props> = ({ | ||
className, | ||
items, | ||
allowMultipleExpanded, | ||
allowZeroExpanded = true, | ||
itemBgColor, | ||
}) => { | ||
return ( | ||
<AccordionComponent | ||
className={className} | ||
allowZeroExpanded={allowZeroExpanded} | ||
data-testid="atoms-accordion" | ||
allowMultipleExpanded={allowMultipleExpanded}> | ||
{items?.map(i => { | ||
return ( | ||
<AccordionItem | ||
key={i.id} | ||
id={i.id} | ||
heading={i.heading} | ||
content={i.content} | ||
bg={itemBgColor} | ||
/> | ||
); | ||
})} | ||
</AccordionComponent> | ||
); | ||
}; | ||
|
||
export default Accordion; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import Collapse from "."; | ||
|
||
const meta: Meta<typeof Collapse> = { | ||
component: Collapse, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof Collapse>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
title: "Title", | ||
children: <p>Item</p>, | ||
}, | ||
}; | ||
|
||
export const AlwaysOpen: Story = { | ||
args: { | ||
title: "Title", | ||
alwaysOpen: true, | ||
children: <p>Item</p>, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { useState, ReactNode, useCallback } from "react"; | ||
|
||
import { styled, useTheme } from "@reearth/services/theme"; | ||
|
||
import Icon from "../Icon"; | ||
import Text from "../Text"; | ||
|
||
const Collapse: React.FC<{ | ||
title?: string; | ||
alwaysOpen?: boolean; | ||
children?: ReactNode; | ||
}> = ({ title, alwaysOpen, children }) => { | ||
const theme = useTheme(); | ||
const [opened, setOpened] = useState(true); | ||
const handleOpen = useCallback(() => { | ||
if (!alwaysOpen) { | ||
setOpened(!opened); | ||
} | ||
}, [alwaysOpen, opened]); | ||
|
||
return ( | ||
<Field> | ||
{title && ( | ||
<Header onClick={handleOpen} clickable={!alwaysOpen}> | ||
<Text size="body" color={theme.content.main}> | ||
{title} | ||
</Text> | ||
{!alwaysOpen && ( | ||
<ArrowIcon icon="arrowToggle" size={12} color={theme.content.main} opened={opened} /> | ||
)} | ||
</Header> | ||
)} | ||
{opened && children && <Content>{children}</Content>} | ||
</Field> | ||
); | ||
}; | ||
|
||
const Field = styled.div` | ||
background: ${({ theme }) => theme.bg[1]}; | ||
`; | ||
|
||
const Header = styled.div<{ clickable?: boolean }>` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
cursor: ${({ clickable }) => (clickable ? "pointer" : "cursor")}; | ||
padding: ${({ theme }) => theme.spacing.normal}px; | ||
`; | ||
|
||
const ArrowIcon = styled(Icon)<{ opened: boolean }>` | ||
transform: rotate(${props => (props.opened ? 90 : 180)}deg); | ||
transition: all 0.2s; | ||
`; | ||
|
||
const Content = styled.div` | ||
padding: ${({ theme }) => `${theme.spacing.largest}px ${theme.spacing.super}px`}; | ||
`; | ||
|
||
export default Collapse; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.