Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
blog-app
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Syed Abdul Rahman
blog-app
Commits
16708e12
Commit
16708e12
authored
Jul 01, 2025
by
Syed Abdul Rahman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Dark theme implementation complted
parent
fe4624c5
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
177 additions
and
116 deletions
+177
-116
preview.ts
.storybook/preview.ts
+35
-7
clear-icon.svg
public/imgaes/clear-icon.svg
+8
-0
sun.svg
public/imgaes/sun.svg
+8
-0
globals.css
src/app/globals.css
+9
-34
layout.tsx
src/app/layout.tsx
+1
-1
page.module.css
src/app/page.module.css
+0
-17
Button.module.css
src/components/Base/Button/Button.module.css
+9
-8
Button.stories.tsx
src/components/Base/Button/Button.stories.tsx
+0
-24
Input.module.css
src/components/Base/Input/Input.module.css
+33
-4
Input.stories.tsx
src/components/Base/Input/Input.stories.tsx
+2
-0
Input.tsx
src/components/Base/Input/Input.tsx
+26
-9
Header.module.css
src/components/Layout/Header/Header.module.css
+2
-1
Header.stories.tsx
src/components/Layout/Header/Header.stories.tsx
+1
-0
Header.tsx
src/components/Layout/Header/Header.tsx
+26
-2
BlogDetail.module.css
src/components/TopLevel/BlogDetail/BlogDetail.module.css
+3
-1
Card.module.css
src/components/TopLevel/CardList/Card/Card.module.css
+9
-4
Card.tsx
src/components/TopLevel/CardList/Card/Card.tsx
+5
-4
No files found.
.storybook/preview.ts
View file @
16708e12
import
type
{
Preview
}
from
'@storybook/nextjs'
import
{
useEffect
}
from
'react'
import
'../src/app/fonts.css'
const
preview
=
{
// Decorator to handle theme changes and update HTML attributes
const
ThemeDecorator
=
(
Story
:
any
,
context
:
any
)
=>
{
const
backgroundValue
=
context
.
globals
.
backgrounds
?.
value
console
.
log
(
backgroundValue
,
"backgroundValue"
)
// Determine theme based on background value
const
theme
=
backgroundValue
===
'dark'
?
'dark-theme'
:
'light-theme'
useEffect
(()
=>
{
// Update document root attributes
document
.
documentElement
.
setAttribute
(
'data-theme'
,
theme
)
// Update body attributes
document
.
body
.
setAttribute
(
'data-theme'
,
theme
)
// You can also update specific elements if needed
},
[
theme
])
console
.
log
(
"happening"
)
return
Story
()
}
const
preview
:
Preview
=
{
parameters
:
{
backgrounds
:
{
default
:
'
myCustomBlue
'
,
default
:
'
light
'
,
options
:
{
myCustomBlue
:
{
name
:
'cutom-color'
,
value
:
'#f8f9fa'
},
// Example
light
:
{
name
:
'light'
,
value
:
'#ffe788'
},
dark
:
{
name
:
'dark'
,
value
:
'black'
},
},
},
controls
:
{
...
...
@@ -14,14 +38,17 @@ const preview = {
date
:
/Date$/i
,
},
},
a11y
:
{
test
:
"todo"
}
},
// Add the theme decorator
decorators
:
[
ThemeDecorator
],
initialGlobals
:
{
backgrounds
:
{
value
:
'
myCustomBlue
'
},
backgrounds
:
{
value
:
'
#ffe788
'
},
},
}
;
}
export
default
preview
;
export
default
preview
\ No newline at end of file
public/imgaes/clear-icon.svg
0 → 100644
View file @
16708e12
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg
width=
"64px"
height=
"64px"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<g
id=
"SVGRepo_bgCarrier"
stroke-width=
"0"
/>
<g
id=
"SVGRepo_tracerCarrier"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
<g
id=
"SVGRepo_iconCarrier"
>
<path
d=
"M8 8L16 16"
stroke=
"#000000"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
<path
d=
"M16 8L8 16"
stroke=
"#000000"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</g>
</svg>
\ No newline at end of file
public/imgaes/sun.svg
0 → 100644
View file @
16708e12
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg
width=
"64px"
height=
"64px"
viewBox=
"0 0 24 24"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
stroke=
"#000000"
>
<g
id=
"SVGRepo_bgCarrier"
stroke-width=
"0"
/>
<g
id=
"SVGRepo_tracerCarrier"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
<g
id=
"SVGRepo_iconCarrier"
>
<path
d=
"M12 3V4M12 20V21M4 12H3M6.31412 6.31412L5.5 5.5M17.6859 6.31412L18.5 5.5M6.31412 17.69L5.5 18.5001M17.6859 17.69L18.5 18.5001M21 12H20M16 12C16 14.2091 14.2091 16 12 16C9.79086 16 8 14.2091 8 12C8 9.79086 9.79086 8 12 8C14.2091 8 16 9.79086 16 12Z"
stroke=
"#d6d6d6"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</g>
</svg>
\ No newline at end of file
src/app/globals.css
View file @
16708e12
:root
{
--background
:
#ffffff
;
--foreground
:
#171717
;
--primary-bg-color
:
#ffffff
;
--secondary-bg-color
:
#f8f9fa
;
--primary-text-color
:
#2d3748
;
--secondary-text-color
:
#9d99b3
;
}
@media
(
prefers-color-scheme
:
dark
)
{
:root
{
--background
:
#0a0a0a
;
--foreground
:
#ededed
;
}
[
data-theme
=
"dark-theme"
]
{
--primary-bg-color
:
#131617
;
--secondary-bg-color
:
#0b0d0e
;
--primary-text-color
:
#e4e4e4
;
--secondary-text-color
:
#8fa2ae
;
}
html
,
body
{
max-width
:
100vw
;
overflow-x
:
hidden
;
}
body
{
color
:
var
(
--foreground
);
background
:
var
(
--background
);
font-family
:
Arial
,
Helvetica
,
sans-serif
;
-webkit-font-smoothing
:
antialiased
;
-moz-osx-font-smoothing
:
grayscale
;
}
*
{
box-sizing
:
border-box
;
padding
:
0
;
margin
:
0
;
}
a
{
color
:
inherit
;
text-decoration
:
none
;
}
@media
(
prefers-color-scheme
:
dark
)
{
html
{
color-scheme
:
dark
;
}
}
src/app/layout.tsx
View file @
16708e12
...
...
@@ -29,7 +29,7 @@ export default function RootLayout({
<
body
className=
{
`${geistSans.variable} ${geistMono.variable}`
}
>
<
Header
/>
{
children
}
<
Pagination
currentPage=
{
1
}
totalPages=
{
12
}
/>
{
/* <Pagination currentPage={1} totalPages={12} /> */
}
</
body
>
</
html
>
);
...
...
src/app/page.module.css
View file @
16708e12
.page
{
--gray-rgb
:
0
,
0
,
0
;
--gray-alpha-200
:
rgba
(
var
(
--gray-rgb
),
0.08
);
--gray-alpha-100
:
rgba
(
var
(
--gray-rgb
),
0.05
);
--button-primary-hover
:
#383838
;
--button-secondary-hover
:
#f2f2f2
;
display
:
grid
;
grid-template-rows
:
20px
1
fr
20px
;
align-items
:
center
;
justify-items
:
center
;
min-height
:
100
svh
;
padding
:
80px
;
gap
:
64px
;
font-family
:
var
(
--font-geist-sans
);
background-color
:
rgb
(
228
,
223
,
248
);
}
src/components/Base/Button/Button.module.css
View file @
16708e12
...
...
@@ -19,8 +19,8 @@
}
.primary
{
background-color
:
white
;
color
:
rgb
(
98
,
97
,
97
);
background-color
:
var
(
--primary-bg-color
)
;
color
:
var
(
--primary-text-color
);
}
.primary
:hover
{
...
...
@@ -41,17 +41,17 @@
.sm
{
padding
:
0.5rem
1rem
;
font-size
:
1
5
px
;
font-size
:
1
4
px
;
}
.md
{
padding
:
0.
8rem
1.5
rem
;
font-size
:
1
8
px
;
padding
:
0.
7rem
1.2
rem
;
font-size
:
1
5
px
;
}
.lg
{
padding
:
1
.2
rem
2.2rem
;
font-size
:
1
5
px
;
padding
:
1rem
2.2rem
;
font-size
:
1
8
px
;
}
.button-active
{
...
...
@@ -84,7 +84,8 @@
}
.disabled
{
background-color
:
rgb
(
172
,
167
,
167
);
background-color
:
rgba
(
115
,
40
,
255
,
0.26
);
color
:
gray
;
pointer-events
:
none
;
}
...
...
src/components/Base/Button/Button.stories.tsx
View file @
16708e12
...
...
@@ -60,18 +60,6 @@ export const Primary = {
Button
</
Button
>
</
section
>
<
h2
style=
{
{
fontFamily
:
"Inter-Medium"
,
color
:
"gray"
}
}
>
Active
</
h2
>
<
section
className=
{
styles
[
"btn-wrapper"
]
}
>
<
Button
variant=
"primary"
size=
"sm"
active=
{
true
}
>
Button
</
Button
>
<
Button
variant=
"primary"
size=
"md"
active=
{
true
}
>
Button
</
Button
>
<
Button
variant=
"primary"
size=
"lg"
active=
{
true
}
>
Button
</
Button
>
</
section
>
</>
);
},
...
...
@@ -132,18 +120,6 @@ export const Secondary = {
Button
</
Button
>
</
section
>
<
h2
style=
{
{
fontFamily
:
"Inter-Medium"
,
color
:
"gray"
}
}
>
Active
</
h2
>
<
section
className=
{
styles
[
"btn-wrapper"
]
}
>
<
Button
variant=
"secondary"
size=
"sm"
active=
{
true
}
>
Button
</
Button
>
<
Button
variant=
"secondary"
size=
"md"
active=
{
true
}
>
Button
</
Button
>
<
Button
variant=
"secondary"
size=
"lg"
active=
{
true
}
>
Button
</
Button
>
</
section
>
</>
);
},
...
...
src/components/Base/Input/Input.module.css
View file @
16708e12
.inputWrapper
{
display
:
flex
;
align-items
:
center
;
border-radius
:
5px
;
border-radius
:
10px
;
border
:
0.2px
solid
rgba
(
255
,
255
,
255
,
0.451
);
}
.inputWrapper
input
{
...
...
@@ -13,12 +14,18 @@
width
:
100%
;
font-size
:
15px
;
color
:
black
;
background-color
:
#cccccc43
;
background-color
:
var
(
--secondary-bg-color
)
;
padding
:
1.1rem
0
;
font-family
:
"Inter-Medium"
;
}
input
::placeholder
{
.input-spl
{
padding
:
1.1rem
1rem
!important
;
border-top-left-radius
:
10px
;
border-bottom-left-radius
:
10px
;
}
.input
::placeholder
{
color
:
rgba
(
128
,
128
,
128
,
0.605
);
}
...
...
@@ -29,5 +36,27 @@ input::placeholder {
.svgWrapper
{
height
:
12px
;
padding
:
1.1rem
1rem
;
background-color
:
#cccccc43
;
/* background-color: #cccccc43; */
background-color
:
var
(
--secondary-bg-color
);
border-top-left-radius
:
10px
;
border-bottom-left-radius
:
10px
;
}
.disabled
{
display
:
none
;
}
.error
{
box-shadow
:
0px
0px
3px
3px
rgb
(
223
,
56
,
56
);
}
.clear-wrapper
{
border-top-right-radius
:
10px
;
border-bottom-right-radius
:
10px
;
background-color
:
var
(
--secondary-bg-color
);
padding
:
0.75rem
;
cursor
:
pointer
;
}
.input-style
{
border-top-right-radius
:
10px
!important
;
border-bottom-right-radius
:
10px
;
}
src/components/Base/Input/Input.stories.tsx
View file @
16708e12
...
...
@@ -12,5 +12,7 @@ export default {
export
const
Default
=
{
args
:
{
placeholder
:
"Discover news, articles and more.."
,
value
:
""
,
error
:
false
,
},
};
src/components/Base/Input/Input.tsx
View file @
16708e12
"use client"
;
import
Image
from
"next/image"
;
import
styles
from
"./Input.module.css"
;
import
img
from
"../../../../public/imgaes/clear-icon.svg"
;
type
InputProps
=
{
label
?:
string
;
placeholder
?:
string
;
onC
hange
?:
(
e
:
any
)
=>
void
;
error
?:
boolean
;
onC
lear
?:
(
)
=>
void
;
}
&
React
.
InputHTMLAttributes
<
HTMLInputElement
>
;
export
default
function
Input
({
label
,
onChange
,
placeholder
,
onClear
,
value
,
error
,
...
props
}:
InputProps
)
{
return
(
<>
{
label
&&
<
div
className=
{
styles
.
label
}
>
{
label
}
</
div
>
}
<
div
className=
{
styles
.
inputWrapper
}
>
<
div
className=
{
styles
.
svgWrapper
}
>
<
div
className=
{
`${styles.inputWrapper} ${error ? styles.error : ""}`
}
>
<
div
className=
{
`${styles.svgWrapper}
${value != "" ? styles.disabled : ""}`
}
>
<
svg
width=
"20px"
height=
"15px"
...
...
@@ -44,12 +52,21 @@ export default function Input({
</
svg
>
</
div
>
<
input
className=
{
styles
.
input
}
className=
{
`${styles.input} ${
value != "" ? styles["input-spl"] : styles["input-style"]
}`
}
value=
{
value
}
name=
"input"
placeholder=
{
placeholder
}
onChange=
{
(
e
)
=>
onChange
?.(
e
.
target
.
value
)
}
{
...
props
}
/>
<
div
className=
{
`${styles["clear-wrapper"]} ${
value == "" ? styles.disabled : ""
} `
}
onClick=
{
onClear
}
>
<
Image
height=
{
20
}
src=
{
img
}
alt=
"img"
/>
</
div
>
</
div
>
</>
);
...
...
src/components/Layout/Header/Header.module.css
View file @
16708e12
.header-wrapper
{
background-color
:
white
;
background-color
:
var
(
--primary-bg-color
)
;
font-family
:
"Inter-Bold"
;
display
:
flex
;
justify-content
:
space-around
;
...
...
@@ -17,6 +17,7 @@
.headerTitle
{
color
:
rgba
(
41
,
41
,
41
,
0.818
);
color
:
var
(
--primary-text-color
);
font-family
:
"Inter-Bold"
;
font-size
:
22px
;
}
...
...
src/components/Layout/Header/Header.stories.tsx
View file @
16708e12
import
Header
from
"./Header"
;
import
"../../../app/globals.css"
;
export
default
{
title
:
"Components/Layout/Header"
,
component
:
Header
,
...
...
src/components/Layout/Header/Header.tsx
View file @
16708e12
"use client"
;
import
Input
from
"@/components/Base/Input/Input"
;
import
themeLogo
from
"../../../../public/imgaes/moon-svgrepo-com.svg"
;
import
lightTheme
from
"../../../../public/imgaes/sun.svg"
;
import
styles
from
"./Header.module.css"
;
import
Image
from
"next/image"
;
import
{
useEffect
,
useState
}
from
"react"
;
export
default
function
Header
()
{
const
[
isDark
,
setIsDark
]
=
useState
(
"light-theme"
);
const
handleThemeToggle
=
()
=>
{
setIsDark
((
prev
)
=>
{
document
.
documentElement
.
setAttribute
(
"data-theme"
,
prev
===
"light-theme"
?
"dark-theme"
:
"light-theme"
);
return
prev
===
"light-theme"
?
"dark-theme"
:
"light-theme"
;
});
};
useEffect
(()
=>
{
console
.
log
(
"triggered"
);
},
[
isDark
]);
return
(
<
header
className=
{
styles
[
"header-wrapper"
]
}
>
<
div
className=
{
styles
.
headerTitle
}
>
NewsBlog
</
div
>
<
div
className=
{
styles
[
"input-container"
]
}
>
<
Input
placeholder=
{
"Discover news, articles and more..."
}
/>
<
Input
placeholder=
{
"Discover news, articles and more..."
}
value=
""
/>
</
div
>
<
div
className=
{
styles
[
"theme-switcher"
]
}
>
<
div
className=
{
styles
[
"theme-switcher"
]
}
onClick=
{
handleThemeToggle
}
>
{
isDark
==
"dark-theme"
?
(
<
Image
src=
{
themeLogo
}
alt=
"image"
width=
{
25
}
/>
)
:
(
<
Image
src=
{
lightTheme
}
alt=
"theme-img"
width=
{
25
}
/>
)
}
</
div
>
</
header
>
);
...
...
src/components/TopLevel/BlogDetail/BlogDetail.module.css
View file @
16708e12
...
...
@@ -7,6 +7,7 @@ article {
width
:
90%
;
font-size
:
26px
;
margin
:
0
auto
;
color
:
var
(
--primary-text-color
);
}
.meta-container
{
display
:
flex
;
...
...
@@ -27,5 +28,6 @@ article {
padding
:
2rem
;
font-family
:
"Inter-Medium"
;
border-radius
:
10px
;
background-color
:
white
;
background-color
:
var
(
--primary-bg-color
);
color
:
var
(
--primary-text-color
);
}
src/components/TopLevel/CardList/Card/Card.module.css
View file @
16708e12
.card
{
width
:
300px
;
border-radius
:
10px
;
background-color
:
rgb
(
252
,
252
,
252
);
background-color
:
var
(
--primary-bg-color
);
box-shadow
:
rgba
(
0
,
0
,
0
,
0.1
)
0px
4px
12px
;
}
.card-avatar
{
...
...
@@ -10,7 +10,6 @@
object-fit
:
cover
;
border-top-left-radius
:
10px
;
border-top-right-radius
:
10px
;
/* display: block; */
}
.card-content
{
...
...
@@ -22,11 +21,12 @@
border
:
1px
solid
black
;
}
.card-title
{
color
:
rgb
(
80
,
73
,
73
);
color
:
var
(
--primary-text-color
);
}
.card-description
{
color
:
gray
;
color
:
var
(
--secondary-text-color
);
font-size
:
18px
;
}
.card-footer
{
...
...
@@ -42,6 +42,9 @@
.author-name
{
color
:
rgb
(
95
,
89
,
89
);
color
:
var
(
--primary-text-color
);
font-family
:
"Inter-Regular"
;
font-family
:
"Inter-Bold"
;
}
.post-info
{
...
...
@@ -49,6 +52,8 @@
gap
:
1rem
;
font-family
:
"Inter-Regular"
;
color
:
rgba
(
128
,
128
,
128
,
0.53
);
color
:
var
(
--secondary-text-color
);
font-size
:
14px
;
padding
:
2px
0
;
}
...
...
src/components/TopLevel/CardList/Card/Card.tsx
View file @
16708e12
...
...
@@ -8,17 +8,18 @@ function Card({ img, cardTitle, cardDescription, author }: any) {
alt=
"Author photo"
/>
<
section
className=
{
styles
[
"card-content"
]
}
>
<
h3
className=
{
styles
[
"card-title"
]
}
>
Card Title
</
h3
>
<
h3
className=
{
styles
[
"card-title"
]
}
>
Lorem ipsum dolor sit amet, consectetur dolor amet
</
h3
>
<
p
className=
{
styles
[
"card-description"
]
}
>
This is a short description inside the This is a short description
inside the
Lorem ipsum dolor adipiscing amet, consectetur sit .
</
p
>
</
section
>
<
footer
className=
{
styles
[
"card-footer"
]
}
>
<
div
className=
{
styles
[
"author-details"
]
}
>
<
div
>
<
img
src=
"https://picsum.photos/
40/4
0"
src=
"https://picsum.photos/
50/5
0"
alt=
"Author photo"
className=
{
styles
[
"author-avatar"
]
}
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment