diff --git a/app/components/ui/banner.tsx b/app/components/ui/banner.tsx new file mode 100644 index 0000000..a20d0eb --- /dev/null +++ b/app/components/ui/banner.tsx @@ -0,0 +1,25 @@ +import { Link } from 'react-router' + +import { APP } from '~/data/meta' + +export const Banner = () => { + return ( +
+
+ + {APP.title} + +

+ Lorem ipsum dolor sit, amet consectetur +

+
+
+ ) +} diff --git a/app/components/ui/button.tsx b/app/components/ui/button.tsx index d63cf17..56026c0 100644 --- a/app/components/ui/button.tsx +++ b/app/components/ui/button.tsx @@ -1,10 +1,5 @@ import { cva, type VariantProps } from 'class-variance-authority' -import type { - ButtonHTMLAttributes, - HTMLAttributes, - MouseEventHandler, - ReactNode, -} from 'react' +import type { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react' import { twMerge } from 'tailwind-merge' const buttonVariants = cva( @@ -16,21 +11,13 @@ const buttonVariants = cva( newsPrimaryOutline: 'border-[3px] border-white text-white text-lg', newsSecondary: 'border-[3px] border-[#2E2F7C] text-[#2E2F7C] text-lg', icon: '', - // destructive: - // 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', - // outline: - // 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', - // secondary: - // 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', - // ghost: 'hover:bg-accent hover:text-accent-foreground', - // link: 'text-primary underline-offset-4 hover:underline', }, size: { default: 'h-[50px] w-[150px]', block: 'h-[50px] w-full', icon: 'h-9 w-9', - // sm: 'h-8 rounded-md px-3 text-xs', - // lg: 'h-10 rounded-md px-8', + sm: 'h-8 rounded-md px-3 text-xs', + lg: 'h-10 rounded-md px-8', }, }, defaultVariants: { @@ -40,34 +27,38 @@ const buttonVariants = cva( }, ) -type TProperties = { - type?: ButtonHTMLAttributes['type'] - onClick?: MouseEventHandler - className?: HTMLAttributes['className'] - disabled?: boolean +type ButtonBaseProperties = { children: ReactNode variant?: VariantProps['variant'] size?: VariantProps['size'] + className?: string } -export const Button = (properties: TProperties) => { - const { - type = 'button', - onClick, - className, - disabled, - children, - variant, - size, - } = properties +type PolymorphicReference = + ComponentPropsWithoutRef['ref'] + +type ButtonProperties = ButtonBaseProperties & { + as?: C + ref?: PolymorphicReference +} & Omit, keyof ButtonBaseProperties> + +export const Button = ({ + as, + children, + variant, + size, + className, + ...properties +}: ButtonProperties) => { + const Component = as || 'button' + const classes = twMerge(buttonVariants({ variant, size, className })) + return ( - + ) } diff --git a/app/components/ui/carousel.tsx b/app/components/ui/carousel.tsx index c4582ed..47ddb14 100644 --- a/app/components/ui/carousel.tsx +++ b/app/components/ui/carousel.tsx @@ -1,3 +1,4 @@ +import { Link } from 'react-router' import { twMerge } from 'tailwind-merge' import { CarouselNextIcon } from '~/components/icons/carousel-next' @@ -9,37 +10,44 @@ import { Button } from './button' export const Carousel = (properties: TNews) => { const { title, description, items, type } = properties return ( -
-
+
+
-

{title}

-

+

+ {title} +

+

{description}

+
- {items.map(({ image, title, content }, index) => ( + {items.map(({ featured, title, content, tag, slug }, index) => (
{ 'w-full object-cover', type === 'hero' ? 'col-span-2 aspect-[174/100]' - : 'aspect-[5/4]', + : 'aspect-[5/4] rounded-md', )} - src={image} + src={featured} alt={title} />
{ type === 'hero' ? 'gap-7' : 'gap-4', )} > +
+ {tag?.map((item) => ( + + {item} + + ))} +
+

{title}

-

{content}

+

+ {content} +

- +
))} diff --git a/app/components/ui/newsletter.tsx b/app/components/ui/newsletter.tsx new file mode 100644 index 0000000..a21793b --- /dev/null +++ b/app/components/ui/newsletter.tsx @@ -0,0 +1,44 @@ +import { Button } from '~/components/ui/button' +import { APP } from '~/data/meta' + +export const Newsletter = () => { + return ( + <> +
+
+

+ Join Our Newsletter +

+

+ Tidak ingin ketinggalan Berita Hukum terhangat? ingin mendapat + informasi kajian dan networking terbaru? ikuti Newsletter kami and + Stay up to Speed! +

+
+
+ {APP.title} +
+
+
+ + +
+
+
+ + ) +} diff --git a/app/layouts/footer-links.tsx b/app/layouts/footer-links.tsx index 0730917..afaf2cc 100644 --- a/app/layouts/footer-links.tsx +++ b/app/layouts/footer-links.tsx @@ -6,20 +6,22 @@ import { COPYRIGHT_MENU, FOOTER_MENU } from './menu' export const FooterLinks = () => { return ( -
-
+
+
{FOOTER_MENU.map(({ group, items }, index) => (
-

{group}

-
+

{group}

+
{items.map(({ url, icon: Icon, title }, subIndex) => ( {Icon && ( {
))}
-
-
- {new Date().getFullYear()} {APP.title}. All rights reserved. -
+
{COPYRIGHT_MENU.map(({ url, title }, index) => ( {title} ))}
+
+ {new Date().getFullYear()} {APP.title}. All rights reserved. +
) diff --git a/app/layouts/footer-newsletter.tsx b/app/layouts/footer-newsletter.tsx index 34648b2..eded96b 100644 --- a/app/layouts/footer-newsletter.tsx +++ b/app/layouts/footer-newsletter.tsx @@ -5,39 +5,56 @@ import { APP } from '~/data/meta' export const FooterNewsletter = () => { return ( -
-
- - {APP.title} +
+
+ + {APP.title} + +
+ +

Join Our Newsletter

+

+ Tidak ingin ketinggalan Berita Hukum terhangat? ingin mendapat + informasi kajian dan networking terbaru? ikuti Newsletter kami and + Stay up to Speed! +

+
+ - + +
-

Join Our Newsletter

-

- Tidak ingin ketinggalan Berita Hukum terhangat? ingin mendapat informasi - kajian dan networking terbaru? ikuti Newsletter kami and Stay up to - Speed! -

-
- - -
-
+
+
+ + {APP.title} + +
+
+ ) } diff --git a/app/layouts/header-menu-mobile.tsx b/app/layouts/header-menu-mobile.tsx new file mode 100644 index 0000000..da37062 --- /dev/null +++ b/app/layouts/header-menu-mobile.tsx @@ -0,0 +1,88 @@ +import { useState } from 'react' +import { Link } from 'react-router' + +import { HeaderSearch } from '~/layouts/header-search' + +import { MENU } from './menu' + +export default function HeaderMenuMobile() { + const [isMenuOpen, setIsMenuOpen] = useState(false) + + const handleToggleMenu = (): void => { + setIsMenuOpen(!isMenuOpen) + } + return ( + <> +
+
+ {/* Menu */} +
+ {/* Tombol Close */} + + + {/* List Menu */} +
    + {MENU.map((item) => ( +
  • + + {item.title} + +
  • + ))} + + +
+
+ + {/* Search dan Toggle Button */} +
+ +
+ +
+
+
+
+ + ) +} diff --git a/app/layouts/header-menu.tsx b/app/layouts/header-menu.tsx index a679d32..aca354e 100644 --- a/app/layouts/header-menu.tsx +++ b/app/layouts/header-menu.tsx @@ -1,23 +1,28 @@ import { Link } from 'react-router' +import HeaderMenuMobile from '~/layouts/header-menu-mobile' + import { HeaderSearch } from './header-search' import { MENU } from './menu' export const HeaderMenu = () => { return ( -
- {MENU.map((item) => ( - - {item.title} - - ))} - -
+ <> +
+ {MENU.map((item) => ( + + {item.title} + + ))} + +
+ + ) } diff --git a/app/layouts/header-search.tsx b/app/layouts/header-search.tsx index 844019e..adfa2dc 100644 --- a/app/layouts/header-search.tsx +++ b/app/layouts/header-search.tsx @@ -6,14 +6,14 @@ export const HeaderSearch = () => {
diff --git a/app/layouts/header-top.tsx b/app/layouts/header-top.tsx index 5c1cefe..66e49f5 100644 --- a/app/layouts/header-top.tsx +++ b/app/layouts/header-top.tsx @@ -5,24 +5,31 @@ import { APP } from '~/data/meta' export const HeaderTop = () => { return ( -
+
{APP.title} -
+
{APP.description}
- - -
+ + +
language { + const { title } = CONTENT + return ( +
+ +

+ {title} +

+ News Detail +
+
+ ) +} diff --git a/app/pages/news/data.ts b/app/pages/news/data.ts index c06af15..9888613 100644 --- a/app/pages/news/data.ts +++ b/app/pages/news/data.ts @@ -9,7 +9,8 @@ export const SPOTLIGHT: TNews = { title: 'Hotman Paris Membuka Perpustakaan di tengah Diskotik', content: 'Pengacara Kondang, Hotman Paris Hutapea, membuka sebuah perpustakaan baru di dalam diskotik nya yang berlokasi di daerah Jakarta Pusat, Hotman berkata Perpustakaan ini dibuka dengan harapan untuk meningkatkan gairah membaca masyarakat Indonesia, namun sayangnya..', - image: '/images/news-1.jpg', + featured: '/images/news-1.jpg', + slug: 'hotman-paris-membuka-perpustakaan-di-tengah-diskotik', }, ], } @@ -23,19 +24,25 @@ export const BERITA: TNews = { title: 'Travelling as a way of self-discovery and progress', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-2.jpg', + featured: '/images/news-2.jpg', + tag: ['Hukum Property'], + slug: 'travelling-as-a-way-of-self-discovery-and-progress', }, { title: 'How does writing influence your personal brand?', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-3.jpg', + featured: '/images/news-3.jpg', + tag: ['Hukum'], + slug: 'how-does-writing-influence-your-personal-brand', }, { title: 'Helping a local business reinvent itself', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-4.jpg', + featured: '/images/news-4.jpg', + tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'helping-a-local-business-reinvent-itself', }, ], } @@ -49,19 +56,25 @@ export const KAJIAN: TNews = { title: 'Travelling as a way of self-discovery and progress', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-2.jpg', + featured: '/images/news-2.jpg', + tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'travelling-as-a-way-of-self-discovery-and-progress', }, { title: 'How does writing influence your personal brand?', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-3.jpg', + featured: '/images/news-3.jpg', + tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'how-does-writing-influence-your-personal-brand', }, { title: 'Helping a local business reinvent itself', content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.', - image: '/images/news-4.jpg', + featured: '/images/news-4.jpg', + tag: ['Hukum Property', 'PREMIUM CONTENT'], + slug: 'helping-a-local-business-reinvent-itself', }, ], } diff --git a/app/pages/news/index.tsx b/app/pages/news/index.tsx index 04c8dee..2528b4c 100644 --- a/app/pages/news/index.tsx +++ b/app/pages/news/index.tsx @@ -1,8 +1,8 @@ import { Card } from '~/components/ui/card' import { Carousel } from '~/components/ui/carousel' +import { Newsletter } from '~/components/ui/newsletter' import { BERITA, KAJIAN, SPOTLIGHT } from './data' -import { Newsletter } from './newsletter' export const NewsPage = () => { return ( diff --git a/app/pages/news/newsletter.tsx b/app/pages/news/newsletter.tsx deleted file mode 100644 index 53057e9..0000000 --- a/app/pages/news/newsletter.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const Newsletter = () => { - return
Newsletter
-} diff --git a/app/routes/_layout.news.$slug.tsx b/app/routes/_layout.news.$slug.tsx new file mode 100644 index 0000000..93d567b --- /dev/null +++ b/app/routes/_layout.news.$slug.tsx @@ -0,0 +1,7 @@ +import { NewsDetailPage } from '~/pages/news-detail' + +const NewsDetailLayout = () => { + return +} + +export default NewsDetailLayout diff --git a/app/routes/_layout.news.tsx b/app/routes/_layout.news.tsx index fc5a9a2..1977241 100644 --- a/app/routes/_layout.news.tsx +++ b/app/routes/_layout.news.tsx @@ -1,5 +1,6 @@ import { Outlet } from 'react-router' +import { Banner } from '~/components/ui/banner' import { FooterLinks } from '~/layouts/footer-links' import { FooterNewsletter } from '~/layouts/footer-newsletter' import { HeaderMenu } from '~/layouts/header-menu' @@ -12,15 +13,12 @@ const NewsLayout = () => { -
- banner +
+
-