diff --git a/app/components/button.tsx b/app/components/button.tsx
index 41f998c..af5c9f7 100644
--- a/app/components/button.tsx
+++ b/app/components/button.tsx
@@ -1,3 +1,71 @@
-export const Button = () => {
- return
Button
+import { cva, type VariantProps } from 'class-variance-authority'
+import type {
+ ButtonHTMLAttributes,
+ HTMLAttributes,
+ MouseEventHandler,
+ ReactNode,
+} from 'react'
+import { twMerge } from 'tailwind-merge'
+
+const buttonVariants = cva(
+ 'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
+ {
+ variants: {
+ variant: {
+ newsPrimary: 'bg-[#2E2F7C] text-white text-lg',
+ newsSecondary: 'border-[3px] border-[#2E2F7C] text-[#2E2F7C] text-lg',
+ // 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',
+ // sm: 'h-8 rounded-md px-3 text-xs',
+ // lg: 'h-10 rounded-md px-8',
+ // icon: 'h-9 w-9',
+ },
+ },
+ defaultVariants: {
+ variant: 'newsPrimary',
+ size: 'default',
+ },
+ },
+)
+
+type TProperties = {
+ type?: ButtonHTMLAttributes['type']
+ onClick?: MouseEventHandler
+ className?: HTMLAttributes['className']
+ disabled?: boolean
+ children: ReactNode
+ variant?: VariantProps['variant']
+ size?: VariantProps['size']
+}
+
+export const Button = (properties: TProperties) => {
+ const {
+ type = 'button',
+ onClick,
+ className,
+ disabled,
+ children,
+ variant,
+ size,
+ } = properties
+ return (
+
+ )
}
diff --git a/app/configs/meta.ts b/app/configs/meta.ts
deleted file mode 100644
index a9047c6..0000000
--- a/app/configs/meta.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const HTML_TITLE = 'React Router'
diff --git a/app/data/dummy.ts b/app/data/dummy.ts
index 8999af2..150e7ee 100644
--- a/app/data/dummy.ts
+++ b/app/data/dummy.ts
@@ -1,4 +1,6 @@
export const DUMMY = {
+ title: 'React Router',
description:
'Bonus judex secundum aequum et\n bonum judicat et aequitatem stricto juri praefert',
+ logo: '/images/logo.svg',
}
diff --git a/app/pages/news/header-top.tsx b/app/pages/news/header-top.tsx
index 109448a..5773ef9 100644
--- a/app/pages/news/header-top.tsx
+++ b/app/pages/news/header-top.tsx
@@ -1,7 +1,6 @@
import { Link } from 'react-router'
import { Button } from '~/components/button'
-import { HTML_TITLE } from '~/configs/meta'
import { DUMMY } from '~/data/dummy'
export const HeaderTop = () => {
@@ -12,16 +11,24 @@ export const HeaderTop = () => {
className="h-full py-[5px]"
>
{DUMMY.description}
-
-
+
+
+
+
+

+
)
diff --git a/package.json b/package.json
index 48e1c34..1919de0 100644
--- a/package.json
+++ b/package.json
@@ -17,10 +17,12 @@
"@react-router/fs-routes": "^7.1.3",
"@react-router/node": "^7.1.3",
"@react-router/serve": "^7.1.3",
+ "class-variance-authority": "^0.7.1",
"isbot": "^5.1.17",
"react": "^19.0.0",
"react-dom": "^19.0.0",
- "react-router": "^7.1.3"
+ "react-router": "^7.1.3",
+ "tailwind-merge": "^3.0.1"
},
"devDependencies": {
"@commitlint/cli": "^19.6.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 34db265..62f33f7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,6 +17,9 @@ importers:
'@react-router/serve':
specifier: ^7.1.3
version: 7.1.3(react-router@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.3)
+ class-variance-authority:
+ specifier: ^0.7.1
+ version: 0.7.1
isbot:
specifier: ^5.1.17
version: 5.1.22
@@ -29,6 +32,9 @@ importers:
react-router:
specifier: ^7.1.3
version: 7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ tailwind-merge:
+ specifier: ^3.0.1
+ version: 3.0.1
devDependencies:
'@commitlint/cli':
specifier: ^19.6.1
@@ -1534,6 +1540,9 @@ packages:
resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==}
engines: {node: '>=8'}
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
classnames@2.5.1:
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
@@ -3624,6 +3633,9 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ tailwind-merge@3.0.1:
+ resolution: {integrity: sha512-AvzE8FmSoXC7nC+oU5GlQJbip2UO7tmOhOfQyOmPhrStOGXHU08j8mZEHZ4BmCqY5dWTCo4ClWkNyRNx1wpT0g==}
+
tailwindcss@4.0.1:
resolution: {integrity: sha512-UK5Biiit/e+r3i0O223bisoS5+y7ZT1PM8Ojn0MxRHzXN1VPZ2KY6Lo6fhu1dOfCfyUAlK7Lt6wSxowRabATBw==}
@@ -5450,6 +5462,10 @@ snapshots:
ci-info@4.1.0: {}
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
classnames@2.5.1: {}
clean-regexp@1.0.0:
@@ -7647,6 +7663,8 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ tailwind-merge@3.0.1: {}
+
tailwindcss@4.0.1: {}
tapable@2.2.1: {}
diff --git a/public/flags/en.svg b/public/flags/en.svg
new file mode 100644
index 0000000..a11cf5f
--- /dev/null
+++ b/public/flags/en.svg
@@ -0,0 +1,26 @@
+
+
\ No newline at end of file
diff --git a/public/flags/id.svg b/public/flags/id.svg
new file mode 100644
index 0000000..b559b63
--- /dev/null
+++ b/public/flags/id.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file