Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing styled components #291

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/web/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/* Highlight all styled components to remove */
/* *[class^="sc-"] {
background-color: rgba(255, 0, 0, 0.1);
outline: 1px solid red;
} */
2 changes: 2 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"react-dom": "^18.3.1",
"react-iiif-vault": "^1.2.1",
"react-lazy-load-image-component": "^1.6.0",
"react-transition-group": "^4.4.5",
"tailwind-merge": "^2.3.0"
},
"devDependencies": {
Expand All @@ -66,6 +67,7 @@
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-lazy-load-image-component": "^1.6.4",
"@types/react-transition-group": "^4.4.4",
"@vitejs/plugin-react-swc": "^3.6.0",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
Expand Down
200 changes: 200 additions & 0 deletions packages/components/src/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import type { TransitionStatus } from "react-transition-group";
import { HTMLAttributes, forwardRef } from "react";
import { twMerge } from "tailwind-merge";

// export const OuterWrapper = styled.div`
// display: flex;
// flex-direction: column;
// flex: 1;
// min-height: 0;

// max-width: 100%;
// min-width: 0;
// overflow: hidden;
// `;
function OuterWrapper(props: HTMLAttributes<HTMLDivElement>) {
return (
<div
{...props}
className={twMerge("flex flex-col flex-1 min-h-0 max-w-full min-w-0 overflow-hidden", props.className)}
/>
);
}

function Header(props: HTMLAttributes<HTMLElement>) {
return <header {...props} className={twMerge("z-200", props.className)} />;
}

function Footer(props: HTMLAttributes<HTMLDivElement>) {
return <div {...props} className={twMerge("bg-white", props.className)} />;
}

const Main = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function Main(props, ref) {
return <div ref={ref} {...props} className={twMerge("flex flex-1 min-h-0", props.className)} />;
});

function LeftPanel(
props: HTMLAttributes<HTMLDivElement> & { $state?: TransitionStatus; $width: string; $motion?: boolean }
) {
const { $state, $width, $motion, ...rest } = props;
const stateStyle = () => {
switch ($state) {
case "entering":
return { maxWidth: $width };
case "exiting":
case "unmounted":
case "exited":
return { maxWidth: "0" };
default:
return {};
}
};
return (
<div
{...rest}
className={twMerge(
"bg-white flex flex-col overflow-hidden max-w-[720px] items-end",
$motion ? "transition-max-width duration-400" : "",
rest.className
)}
style={stateStyle()}
/>
);
}

function CenterPanel(props: HTMLAttributes<HTMLDivElement>) {
return (
<div
{...props}
className={twMerge(
"flex flex-1 bg-[#e3e7f0] pt-1 min-w-[320px] min-h-0 overflow-hidden",
"> *:min-w-0",
props.className
)}
/>
);
}

function RightPanel(
props: HTMLAttributes<HTMLDivElement> & { $state?: TransitionStatus; $width: string; $motion?: boolean }
) {
const { $state, $width, $motion, ...rest } = props;
const stateClasses = () => {
switch ($state) {
case "entering":
return `max-w-[${$width}]`;
case "exiting":
case "unmounted":
case "exited":
return "max-w-0";
default:
return "";
}
};
return (
<div
{...rest}
className={twMerge(
"bg-white flex flex-col overflow-hidden max-w-[720px]",
$motion ? "transition-max-width duration-400" : "",
stateClasses(),
rest.className
)}
/>
);
}
export type MenuPositions = "left" | "right" | "bottom" | "top";
const PanelContainer = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement> & { $menu?: MenuPositions }>(
function PanelContainer(props, ref) {
const { $menu, ...rest } = props;
const menuClasses = () => {
switch ($menu) {
case "top":
return "flex-col";
case "left":
return "flex-row";
case "bottom":
return "flex-col-reverse";
case "right":
return "flex-row-reverse";
default:
return "";
}
};
return (
<div
ref={ref}
{...rest}
className={twMerge(
"flex flex-1 h-full min-w-[50px] transition-min-width duration-400 overflow-hidden",
menuClasses(),
rest.className
)}
/>
);
}
);

function PanelSideMenu(props: HTMLAttributes<HTMLDivElement>) {
return (
<div
{...props}
className={twMerge("bg-white border-t border-r border-[#e3e7f0] flex flex-col w-[3em]", props.className)}
/>
);
}

function PanelSideMenuItem(props: HTMLAttributes<HTMLButtonElement>) {
return (
<button
{...props}
className={twMerge(
"cursor-pointer aspect-square w-[3em] h-[3em] flex justify-center items-center hover:bg-[#fff6f9]",
"[data-selected=true]:bg-[#b84c74] [data-selected=true] svg:text-white",
"svg:text-[#999] svg:text-[1.5em]",
props.className
)}
/>
);
}

function PanelMenu(
props: HTMLAttributes<HTMLDivElement> & { $position: "bottom" | "top" | "left" | "right"; $open: boolean }
) {
const { $position, $open, ...rest } = props;
const positionClasses = () => {
if (!$open && ($position === "top" || $position === "bottom")) {
return "hidden";
}
return "";
};
return (
<div
{...rest}
className={twMerge(
"flex shadow-[0_-3px_2px_0_rgba(0,0,0,0.04),0_-1px_0_0_rgba(0,0,0,0.17)]",
positionClasses(),
rest.className
)}
/>
);
}

function PanelContent(props: HTMLAttributes<HTMLDivElement>) {
return <div {...props} className={twMerge("flex flex-col flex-1 min-w-0 overflow-hidden", props.className)} />;
}

export const Layout = {
OuterWrapper,
Header,
Footer,
Main,
LeftPanel,
CenterPanel,
RightPanel,
PanelContainer,
PanelSideMenu,
PanelSideMenuItem,
PanelMenu,
PanelContent,
};
28 changes: 28 additions & 0 deletions packages/components/src/ModularPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { twMerge } from "tailwind-merge";
import { clsx } from "clsx";
import { HtmlHTMLAttributes } from "react";
import type { TransitionStatus } from "react-transition-group";

export function ModularPanelWrapper(
props: HtmlHTMLAttributes<HTMLDivElement> & {
"data-state"?: TransitionStatus;
"data-flipped"?: boolean;
floating?: boolean;
header?: boolean;
}
) {
const { className, floating, ...rest } = props;

const classes = twMerge(
clsx(
"flex flex-col relative h-full overflow-hidden ModularPanel",
{
"border-t border-solid border-gray-200": !props.header,
"m-2 rounded overflow-hidden bg-white": floating,
},
className
)
);

return <div className={classes} {...rest} />;
}
50 changes: 50 additions & 0 deletions packages/components/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,53 @@
.shape-line:hover {
stroke: rgba(119, 24, 196, 0.5);
}

/** Modular Panel transition logic **/
.ModularPanel {
transition: transform 400ms;

&[data-header="false"] {
border-top: 1px solid #e4e7f0;
}

&[data-floating="true"] {
margin: 10px;
border-radius: 5px;
overflow: hidden;
background: #fff;
}

&[data-state="entering"],
&[data-state="entered"] {
transform: translateX(0);
}

&[data-state="exiting"],
&[data-state="exited"] {
transform: translateX(100%);
}

&[data-state="exiting"][data-flipped="true"],
&[data-state="exited"][data-flipped="true"] {
transform: translateX(0);
}

&[data-state="exiting"][data-flipped="false"],
&[data-state="exited"][data-flipped="false"] {
transform: translateX(100%);
}

&[data-state="entering"][data-flipped="true"],
&[data-state="entered"][data-flipped="true"] {
transform: translateX(0);
}

&[data-state="entering"][data-flipped="false"],
&[data-state="entered"][data-flipped="false"] {
transform: translateX(100%);
}

&[data-state="unmounted"] {
transform: translateX(100%);
}
}
2 changes: 2 additions & 0 deletions packages/components/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export * from "./MetadataContainer";
export * from "./EmptyState";
export * from "./ManifestEditorLogo";
export * from "./Forms";
export * from "./Layout";
export * from "./ModularPanel";

// Icons
export * from "./icons/CreateCanvasIcon";
Expand Down
8 changes: 8 additions & 0 deletions packages/components/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ module.exports = {
fadeInDelayed: "fadeInDelayed 2000ms ease-in-out",
},

transitionProperty: {
"max-width": "max-width",
"min-width": "min-width",
},

transitionDuration: {
400: "400ms",
},
// that is actual animation
keyframes: () => ({
fadeIn: {
Expand Down
4 changes: 1 addition & 3 deletions packages/shell/src/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import { useAppState } from "../AppContext/AppContext";
import { useLayoutProvider } from "./Layout.context";
import { panelSizing, renderHelper } from "./Layout.helpers";
import * as M from "./Layout.mobile";
import * as L from "./Layout.styles";
import { HandleControls } from "./components/HandleControls";
import { ModularPanel } from "./components/ModularPanel";
import { useResizeLayout } from "./components/use-resize-layouts";
import { useMatchMedia } from "../hooks/use-match-media";
import { StarIcon } from "@manifest-editor/ui/icons/StarIcon";
import { Modal, PanelSideMenu } from "@manifest-editor/components";
import { Modal, PanelSideMenu, Layout as L } from "@manifest-editor/components";

interface LayoutProps {
header?: React.ReactNode;
Expand Down
Loading
Loading