diff --git a/packages/design-system/atoms/tab-view/TabView.styled.ts b/packages/design-system/atoms/tab-view/TabView.styled.ts
index c570534..e5901d3 100644
--- a/packages/design-system/atoms/tab-view/TabView.styled.ts
+++ b/packages/design-system/atoms/tab-view/TabView.styled.ts
@@ -65,5 +65,9 @@ export const TabContentTitle = styled.div`
${text500}
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
- padding: 10px;
+ padding: 0.5em 7px;
+`;
+
+export const TabDepth = styled.div`
+ margin-left: 7px;
`;
diff --git a/packages/design-system/molecules/editor-category-short/EditorCategoryShort.spec.tsx b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.spec.tsx
new file mode 100644
index 0000000..e6c6cf7
--- /dev/null
+++ b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.spec.tsx
@@ -0,0 +1,12 @@
+import { mockCategory } from '@roleypoly/design-system/fixtures/storyData';
+import { render } from '@testing-library/react';
+import { EditorCategoryShort } from './EditorCategoryShort';
+
+it('triggers onOpen when clicked', async () => {
+ const onOpen = jest.fn();
+ const view = render();
+
+ view.getByRole('menuitem')?.click();
+
+ expect(onOpen).toHaveBeenCalled();
+});
diff --git a/packages/design-system/molecules/editor-category-short/EditorCategoryShort.stories.tsx b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.stories.tsx
new file mode 100644
index 0000000..bc2b0a5
--- /dev/null
+++ b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.stories.tsx
@@ -0,0 +1,30 @@
+import { mockCategory } from '@roleypoly/design-system/fixtures/storyData';
+import ReactTooltip from 'react-tooltip';
+import styled from 'styled-components';
+import { EditorCategoryShort } from './EditorCategoryShort';
+
+const decorator = (story) => (
+
+ {story()}
+
+
+);
+
+export default {
+ title: 'Molecules/Short Category',
+ component: EditorCategoryShort,
+ args: {
+ category: mockCategory,
+ },
+ decorators: [decorator],
+};
+
+const Wrapper = styled.div`
+ box-shadow: 0 0 10px #000;
+`;
+
+export const shortEditor = (args) => ;
+export const shortEditorHidden = (args) => ;
+shortEditorHidden.args = {
+ category: { ...mockCategory, hidden: true },
+};
diff --git a/packages/design-system/molecules/editor-category-short/EditorCategoryShort.styled.ts b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.styled.ts
new file mode 100644
index 0000000..2b9c2a0
--- /dev/null
+++ b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.styled.ts
@@ -0,0 +1,60 @@
+import { transitions } from '@roleypoly/design-system/atoms/timings';
+import styled from 'styled-components';
+
+export const GrabberBox = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 1em;
+ flex: 0;
+ cursor: grab;
+ position: relative;
+
+ ::before {
+ content: '';
+ position: absolute;
+ top: -5px;
+ left: -8px;
+ width: 32px;
+ height: 32px;
+ background-color: rgba(0, 0, 0, 0.25);
+ opacity: 0;
+ border-radius: 50%;
+ transition: opacity ${transitions.actionable}s ease-in-out;
+ }
+
+ &:hover {
+ ::before {
+ opacity: 1;
+ }
+ }
+`;
+
+export const Opener = styled.div`
+ opacity: 0;
+ transition: opacity ${transitions.actionable}s ease-in-out;
+`;
+
+export const Container = styled.div`
+ display: flex;
+ padding: 1em;
+ cursor: pointer;
+
+ &:hover {
+ ${Opener} {
+ opacity: 1;
+ }
+ }
+`;
+
+export const Name = styled.div`
+ position: relative;
+ top: -2px;
+ margin-right: 1em;
+`;
+
+export const Flags = styled.div``;
+
+export const Void = styled.div`
+ flex: 1;
+`;
diff --git a/packages/design-system/molecules/editor-category-short/EditorCategoryShort.tsx b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.tsx
new file mode 100644
index 0000000..67f1712
--- /dev/null
+++ b/packages/design-system/molecules/editor-category-short/EditorCategoryShort.tsx
@@ -0,0 +1,31 @@
+import { Category } from '@roleypoly/types';
+import { DragEventHandler, MouseEventHandler } from 'react';
+import { GoEyeClosed, GoGrabber, GoKebabHorizontal } from 'react-icons/go';
+import {
+ Container,
+ Flags,
+ GrabberBox,
+ Name,
+ Opener,
+ Void,
+} from './EditorCategoryShort.styled';
+
+type ShortProps = {
+ category: Category;
+ onDrag?: DragEventHandler;
+ onOpen?: MouseEventHandler;
+};
+
+export const EditorCategoryShort = (props: ShortProps) => (
+
+
+
+
+ {props.category.name}
+ {props.category.hidden && }
+
+
+
+
+
+);
diff --git a/packages/design-system/molecules/editor-category-short/index.ts b/packages/design-system/molecules/editor-category-short/index.ts
new file mode 100644
index 0000000..e69de29
diff --git a/packages/design-system/organisms/editor-categories-tab/EditorCategoriesTab.tsx b/packages/design-system/organisms/editor-categories-tab/EditorCategoriesTab.tsx
index b535ed9..3ce66d0 100644
--- a/packages/design-system/organisms/editor-categories-tab/EditorCategoriesTab.tsx
+++ b/packages/design-system/organisms/editor-categories-tab/EditorCategoriesTab.tsx
@@ -1,18 +1,39 @@
+import { TabDepth } from '@roleypoly/design-system/atoms/tab-view/TabView.styled';
import { EditorCategory } from '@roleypoly/design-system/molecules/editor-category';
+import { EditorCategoryShort } from '@roleypoly/design-system/molecules/editor-category-short/EditorCategoryShort';
import { EditorShellProps } from '@roleypoly/design-system/organisms/editor-shell';
+import { Category } from '@roleypoly/types';
+import { sortBy } from 'lodash';
+import * as React from 'react';
import { CategoryContainer } from './EditorCategoriesTab.styled';
-export const EditorCategoriesTab = (props: EditorShellProps) => (
-
- {props.guild.data.categories.map((category, idx) => (
-
- console.log(x)}
- />
-
- ))}
-
-);
+export const EditorCategoriesTab = (props: EditorShellProps) => {
+ const [openStates, setOpenStates] = React.useState([]);
+
+ const onCategoryOpen = (id: Category['id']) => () => {
+ setOpenStates([...new Set(openStates).add(id)]);
+ };
+
+ return (
+
+ {sortBy(props.guild.data.categories, ['position', 'id']).map((category, idx) =>
+ openStates.includes(category.id) ? (
+
+ props.onCategoryChange?.(category)}
+ />
+
+ ) : (
+
+ )
+ )}
+
+ );
+};
diff --git a/packages/design-system/organisms/editor-details-tab/EditorDetailsTab.tsx b/packages/design-system/organisms/editor-details-tab/EditorDetailsTab.tsx
index 041c605..e647c61 100644
--- a/packages/design-system/organisms/editor-details-tab/EditorDetailsTab.tsx
+++ b/packages/design-system/organisms/editor-details-tab/EditorDetailsTab.tsx
@@ -1,16 +1,20 @@
+import { Space } from '@roleypoly/design-system/atoms/space';
+import { TabDepth } from '@roleypoly/design-system/atoms/tab-view/TabView.styled';
import { MultilineTextInput } from '@roleypoly/design-system/atoms/text-input';
+import { Text } from '@roleypoly/design-system/atoms/typography';
import { EditorShellProps } from '@roleypoly/design-system/organisms/editor-shell';
import * as React from 'react';
export const EditorDetailsTab = (props: EditorShellProps) => {
- const [serverMessage, updateServerMessage] = React.useState(props.guild.data.message);
return (
-
- Server Message
+
+
+ Server Message
updateServerMessage(eventData.target.value)}
+ value={props.guild.data.message}
+ onChange={(eventData) => props.onMessageChange?.(eventData.target.value)}
/>
-
+
+
);
};
diff --git a/packages/design-system/organisms/editor-shell/EditorShell.tsx b/packages/design-system/organisms/editor-shell/EditorShell.tsx
index 93a2ac4..1398037 100644
--- a/packages/design-system/organisms/editor-shell/EditorShell.tsx
+++ b/packages/design-system/organisms/editor-shell/EditorShell.tsx
@@ -1,16 +1,56 @@
import { Tab, TabView } from '@roleypoly/design-system/atoms/tab-view';
import { EditorCategoriesTab } from '@roleypoly/design-system/organisms/editor-categories-tab';
import { EditorDetailsTab } from '@roleypoly/design-system/organisms/editor-details-tab';
-import { PresentableGuild } from '@roleypoly/types';
+import { Category, PresentableGuild } from '@roleypoly/types';
+import React from 'react';
export type EditorShellProps = {
guild: PresentableGuild;
+ onGuildChange?: (guild: PresentableGuild) => void;
+ onCategoryChange?: (category: Category) => void;
+ onMessageChange?: (message: PresentableGuild['data']['message']) => void;
};
-export const EditorShell = (props: EditorShellProps) => (
-
- {() => }
- {() => }
- {() => hi2!
}
-
-);
+export const EditorShell = (props: EditorShellProps) => {
+ const [guild, setGuild] = React.useState(props.guild);
+
+ const reset = () => {
+ setGuild(props.guild);
+ };
+
+ const onCategoryChange = (category: Category) => {
+ setGuild((currentGuild) => {
+ const categories = [
+ ...currentGuild.data.categories.filter((x) => x.id !== category.id),
+ category,
+ ];
+ return { ...currentGuild, data: { ...currentGuild.data, categories } };
+ });
+ };
+
+ const onMessageChange = (message: PresentableGuild['data']['message']) => {
+ setGuild((currentGuild) => {
+ return { ...currentGuild, data: { ...guild.data, message } };
+ });
+ };
+
+ return (
+
+
+ {() => (
+
+ )}
+
+
+ {() => (
+
+ )}
+
+ {() => hi2!
}
+
+ );
+};