diff --git a/public/images/arrow_04.png b/public/images/arrow_04.png new file mode 100644 index 00000000..f3831c3a Binary files /dev/null and b/public/images/arrow_04.png differ diff --git a/public/images/arrow_07.png b/public/images/arrow_07.png new file mode 100644 index 00000000..ec1208cd Binary files /dev/null and b/public/images/arrow_07.png differ diff --git a/public/images/arrow_26.png b/public/images/arrow_26.png new file mode 100644 index 00000000..d40e4c9d Binary files /dev/null and b/public/images/arrow_26.png differ diff --git a/src/app/(authed)/(home)/(welcome)/layout.tsx b/src/app/(authed)/(home)/(welcome)/layout.tsx new file mode 100644 index 00000000..2d2c055c --- /dev/null +++ b/src/app/(authed)/(home)/(welcome)/layout.tsx @@ -0,0 +1,21 @@ +import SecondarySplitHeader from "@/features/sidebar/view/SecondarySplitHeader" +import { Box } from "@mui/material" + +export default function Page({ children }: { children: React.ReactNode }) { + return ( + <> + + + + + {children} + + + ) +} \ No newline at end of file diff --git a/src/app/(authed)/(home)/(welcome)/page.tsx b/src/app/(authed)/(home)/(welcome)/page.tsx new file mode 100644 index 00000000..cd8e0515 --- /dev/null +++ b/src/app/(authed)/(home)/(welcome)/page.tsx @@ -0,0 +1,22 @@ +import WelcomePage from "@/features/welcome" +import { Box } from "@mui/material" + +const Page = () => { + + return ( + + + + ) +} + +export default Page + diff --git a/src/app/(authed)/(home)/[[...slug]]/layout.tsx b/src/app/(authed)/(home)/[...slug]/layout.tsx similarity index 69% rename from src/app/(authed)/(home)/[[...slug]]/layout.tsx rename to src/app/(authed)/(home)/[...slug]/layout.tsx index 2e89f12a..4de3d599 100644 --- a/src/app/(authed)/(home)/[[...slug]]/layout.tsx +++ b/src/app/(authed)/(home)/[...slug]/layout.tsx @@ -4,11 +4,21 @@ import SecondarySplitHeader from "@/features/sidebar/view/SecondarySplitHeader" import TrailingToolbarItem from "@/features/projects/view/toolbar/TrailingToolbarItem" import MobileToolbar from "@/features/projects/view/toolbar/MobileToolbar" import { useProjectSelection } from "@/features/projects/data" +import NotFound from "@/features/projects/view/NotFound" export default function Page({ children }: { children: React.ReactNode }) { const { project } = useProjectSelection() if (!project) { - return <> + return ( + <> + + + +
+ +
+ + ) } return ( <> diff --git a/src/app/(authed)/(home)/[[...slug]]/page.tsx b/src/app/(authed)/(home)/[...slug]/page.tsx similarity index 100% rename from src/app/(authed)/(home)/[[...slug]]/page.tsx rename to src/app/(authed)/(home)/[...slug]/page.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a22f3c64..03a4808a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -17,7 +17,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( - + {children} diff --git a/src/common/ui/HighlightText.tsx b/src/common/ui/HighlightText.tsx index 0f3cd9ed..c61b309b 100644 --- a/src/common/ui/HighlightText.tsx +++ b/src/common/ui/HighlightText.tsx @@ -7,18 +7,18 @@ type CustomTypographyVariant = TypographyVariant | 'body0' | 'body3'; interface HighlightTextProps { content: string - highlight: string - color: string + highlight: string[] + color: string[] height?: string - isSolidOpacity?: boolean + opacity?: number isBoldText?: boolean variant?: CustomTypographyVariant sx?: SxProps } const HighlightSpan = styled.span<{ - color: string; isSolidOpacity: boolean; height: string; isBoldText: boolean - }>` + color: string; opacity: number; height: string; isBoldText: boolean +}>` position: relative; display: inline-block; ${({ isBoldText }) => isBoldText && "font-weight: 600"}; @@ -31,7 +31,7 @@ const HighlightSpan = styled.span<{ width: 102%; background-color: ${({ color }) => color}; z-index: -10; - opacity: ${({ isSolidOpacity }) => isSolidOpacity ? .7 : .3}; + opacity: ${({ opacity }) => opacity * 0.1}; transform: skewX(-2deg); } }`; @@ -41,12 +41,21 @@ const HighlightText = ({ highlight, color, height="50%", - isSolidOpacity=false, + opacity=3, isBoldText=false, variant, sx }: HighlightTextProps) => { - const parts = content.split(new RegExp(`(${highlight})`, 'gi')) + if (!highlight.length || !color.length) { + return ( + + {content} + + ); + } + + const parts = content.split(new RegExp(`(${highlight.join('|')})`, 'gi')); + const getColor = (index: number) => color[index % color.length]; return ( - {parts.map((part, index) => - part.toLowerCase() === highlight.toLowerCase() ? ( + {parts.map((part, index) => { + const highlightIndex = highlight.findIndex(h => h.toLowerCase() === part.toLowerCase()); + return highlightIndex !== -1 ? ( {part} @@ -70,7 +80,7 @@ const HighlightText = ({ ) : ( part ) - )} + })} ); }; diff --git a/src/features/new-project/NewProject.tsx b/src/features/new-project/NewProject.tsx index 69092ae0..e58673b5 100644 --- a/src/features/new-project/NewProject.tsx +++ b/src/features/new-project/NewProject.tsx @@ -35,10 +35,10 @@ return ( > + + + We couldn't find the project or page you're looking for. + It might have been moved or doesn't exist. + + + + ) +} \ No newline at end of file diff --git a/src/features/welcome/index.tsx b/src/features/welcome/index.tsx new file mode 100644 index 00000000..13f1e2e0 --- /dev/null +++ b/src/features/welcome/index.tsx @@ -0,0 +1,33 @@ +import { grey } from "@mui/material/colors" +import MessageLinkFooter from "@/common/ui/MessageLinkFooter" +import ShowSectionsLayer from "@/features/welcome/view/ShowSectionsLayer" +import WelcomeContent from "@/features/welcome/view/WelcomeContent" +import { env } from "@/common" +import { Box } from "@mui/material" + +const HELP_URL = env.get("NEXT_PUBLIC_SHAPE_DOCS_HELP_URL") + +const WelcomePage = () => { + return ( + <> + + + + {HELP_URL && + + + + } + + ) +} + +export default WelcomePage \ No newline at end of file diff --git a/src/features/welcome/view/ShowSectionsLayer.tsx b/src/features/welcome/view/ShowSectionsLayer.tsx new file mode 100644 index 00000000..554503ba --- /dev/null +++ b/src/features/welcome/view/ShowSectionsLayer.tsx @@ -0,0 +1,149 @@ +"use client" + +import { Box, Typography } from "@mui/material" +import Image from "next/image" +import { grey } from "@mui/material/colors" +import ARROW_26 from "../../../../public/images/arrow_26.png" +import ARROW_04 from "../../../../public/images/arrow_04.png" +import ARROW_07 from "../../../../public/images/arrow_07.png" +import { useSession } from "next-auth/react" +import { useContext } from "react" +import { ProjectsContainerContext } from "@/common" + +const ShowSectionsLayer = () => { + const { data: session, status } = useSession() + const { projects, isLoading } = useContext(ProjectsContainerContext) + const isLoadingSession = status == "loading" + + return ( + <> + + + arrow + + + Find your projects here! + + + + + + arrow + + + Start a new project here! + + + + {!isLoading && + 0 ? 120 : 90} + left={350} + gap={2} + sx={{ color: grey[500] }} + > + + arrow + + {projects.length > 0 && + + Find your projects here + + } + + } + {!isLoadingSession && session && session.user && + + + arrow + + + And explore more features here + + + } + + ) +} + +export default ShowSectionsLayer \ No newline at end of file diff --git a/src/features/welcome/view/WelcomeContent.tsx b/src/features/welcome/view/WelcomeContent.tsx new file mode 100644 index 00000000..658cc203 --- /dev/null +++ b/src/features/welcome/view/WelcomeContent.tsx @@ -0,0 +1,51 @@ +import HighlightText from "@/common/ui/HighlightText" +import { Box, Typography } from "@mui/material" +import { BASE_COLORS } from "@/common/theme/theme" +import { env } from "@/common" +import { grey } from "@mui/material/colors" + +const SITE_NAME = env.getOrThrow("NEXT_PUBLIC_SHAPE_DOCS_TITLE") + +const WelcomeContent = () => { + const title = "Welcome to " + const description = [ + "Centralizes your OpenAPI documentation and streamlines spec-driven development" + ] + + return ( + <> + + + {description.map((line, index) => ( + + {line} + + ))} + + + ) +} + +export default WelcomeContent \ No newline at end of file