11import { MantineTheme , rem , useMantineTheme } from '@mantine/core' ;
2- import type { CSSProperties } from 'react' ; // Use React's CSSProperties
2+ import { useMemo } from 'react' ;
33
4- // Note: createStyles is deprecated. Using object syntax directly.
5- // This hook will provide the styles object based on the current theme.
4+ // Utility to create a simple styles class naming system
65export const useStyles = ( ) => {
76 const theme = useMantineTheme ( ) ;
87
9- // Defensive check for theme and colorScheme
10- const isDark = theme . black === '#000' ;
11-
12- // If theme is somehow unavailable, return empty styles to prevent crash
13- if ( ! theme ) {
14- console . error ( 'Mantine theme context is missing. Ensure MantineProvider wraps this component.' ) ;
15- return { classes : { } , cx : ( ...args : any [ ] ) => args . filter ( Boolean ) . join ( ' ' ) } ;
16- }
17-
18- const styles : Record < string , CSSProperties & Record < string , any > > = {
19- detailedContentContainer : {
20- width : '100%' ,
21- margin : `${ theme . spacing . xl } 0 ${ rem ( 64 ) } ` ,
22- paddingBottom : rem ( 70 ) ,
23- opacity : 0 ,
24- transform : 'translateY(20px)' ,
25- transition : 'opacity 0.5s ease-out, transform 0.5s ease-out' ,
26-
27- '&.visible' : {
28- opacity : 1 ,
29- transform : 'translateY(0)' ,
30- } ,
31- } ,
32-
33- visible : {
34- opacity : 1 ,
35- transform : 'translateY(0)' ,
36- } ,
37-
38- titleWrapper : {
39- display : 'flex' ,
40- flexDirection : 'row' ,
41- alignItems : 'center' ,
42- gap : theme . spacing . md ,
43- marginBottom : theme . spacing . lg ,
44- } ,
45-
46- sectionIcon : {
47- display : 'flex' ,
48- alignItems : 'center' ,
49- justifyContent : 'center' ,
50- width : rem ( 48 ) ,
51- height : rem ( 48 ) ,
52- borderRadius : '50%' ,
53- backgroundColor : isDark ? theme . colors . dark [ 6 ] : theme . black ,
54- padding : theme . spacing . xs ,
55- flexShrink : 0 ,
56-
57- '& svg, & img' : {
58- width : '100%' ,
59- height : '100%' ,
60- objectFit : 'contain' ,
61- fill : theme . white ,
62- } ,
63-
64- [ `@media (max-width: ${ theme . breakpoints . xs } )` ] : {
65- width : rem ( 40 ) ,
66- height : rem ( 40 ) ,
67- } ,
68- } ,
69-
70- detailedContentTitle : {
71- fontSize : theme . headings . sizes . h2 . fontSize ,
72- fontWeight : theme . headings . sizes . h2 . fontWeight ,
73- color : isDark ? theme . white : theme . black ,
74- wordBreak : 'break-word' ,
75- overflowWrap : 'break-word' ,
76- flex : 1 ,
77- minWidth : 0 ,
78- margin : 0 ,
79-
80- [ `@media (max-width: ${ theme . breakpoints . md } )` ] : {
81- fontSize : `calc(${ theme . headings . sizes . h2 . fontSize } * 0.875)` ,
82- } ,
83- [ `@media (max-width: ${ theme . breakpoints . sm } )` ] : {
84- fontSize : `calc(${ theme . headings . sizes . h2 . fontSize } * 0.75)` ,
85- } ,
86- } ,
87-
88- detailedContentText : {
89- fontSize : theme . fontSizes . lg ,
90- lineHeight : 1.6 ,
91- marginBottom : theme . spacing . lg ,
92- color : isDark ? theme . colors . dark [ 1 ] : theme . colors . gray [ 7 ] ,
93- } ,
94-
95- detailedContentList : {
96- fontSize : theme . fontSizes . lg ,
97- lineHeight : 1.6 ,
98- marginBottom : theme . spacing . lg ,
99- color : isDark ? theme . colors . dark [ 1 ] : theme . colors . gray [ 7 ] ,
100- paddingLeft : theme . spacing . xl ,
101- listStylePosition : 'inside' ,
102-
103- '& ul' : {
104- listStyle : 'disc' ,
105- margin : 0 ,
106- paddingLeft : theme . spacing . md ,
107- } ,
108- '& li' : {
109- marginBottom : theme . spacing . sm ,
8+ // Create a css-in-js classNames object that will work with the component
9+ return useMemo ( ( ) => {
10+ // Each key in this object will be a className string that can be applied to elements
11+ const classes = {
12+ sectionIcon : 'detailed-content-section-icon' ,
13+ detailedContentTitle : 'detailed-content-title' ,
14+ detailedContentText : 'detailed-content-text' ,
15+ detailedContentList : 'detailed-content-list' ,
16+ detailedContentSubtitle : 'detailed-content-subtitle' ,
17+ codeBlock : 'detailed-content-code-block' ,
18+ sectionTitle : 'detailed-content-section-title' ,
19+ sectionSubtitle : 'detailed-content-section-subtitle' ,
20+ subtitleWrapper : 'detailed-content-subtitle-wrapper' ,
21+ textContent : 'detailed-content-text-content' ,
22+ listContent : 'detailed-content-list-content' ,
23+ } ;
24+
25+ // Add global styles for these classes - would normally be in a separate GlobalStyles component
26+ // but this ensures the styles are applied
27+ if ( typeof document !== 'undefined' ) {
28+ const styleId = 'detailed-content-dynamic-styles' ;
29+ let styleEl = document . getElementById ( styleId ) as HTMLStyleElement ;
30+
31+ if ( ! styleEl ) {
32+ styleEl = document . createElement ( 'style' ) ;
33+ styleEl . id = styleId ;
34+ document . head . appendChild ( styleEl ) ;
11035 }
111- } ,
112-
113- iconWrapper : {
114- display : 'flex' ,
115- alignItems : 'center' ,
116- justifyContent : 'center' ,
117- width : rem ( 32 ) ,
118- height : rem ( 32 ) ,
119- borderRadius : '50%' ,
120- backgroundColor : isDark ? theme . colors . dark [ 6 ] : theme . black ,
121- padding : rem ( 6 ) ,
122- flexShrink : 0 ,
123-
124- '& svg' : {
125- fill : theme . white ,
126- } ,
127- } ,
128-
129- titleWithIconWrapper : {
130- display : 'flex' ,
131- alignItems : 'center' ,
132- gap : theme . spacing . sm ,
133- marginBottom : theme . spacing . md ,
134- } ,
135-
136- sectionTitle : {
137- fontSize : theme . headings . sizes . h3 . fontSize ,
138- fontWeight : theme . headings . sizes . h3 . fontWeight ,
139- color : isDark ? theme . white : theme . black ,
140- margin : 0 ,
141- wordBreak : 'break-word' ,
142- overflowWrap : 'break-word' ,
143- flex : 1 ,
144- minWidth : 0 ,
145-
146- [ `@media (max-width: ${ theme . breakpoints . md } )` ] : {
147- fontSize : `calc(${ theme . headings . sizes . h3 . fontSize } * 0.85)` ,
148- } ,
149- [ `@media (max-width: ${ theme . breakpoints . sm } )` ] : {
150- fontSize : `calc(${ theme . headings . sizes . h3 . fontSize } * 0.75)` ,
151- } ,
152- } ,
153-
154- sectionSubtitle : {
155- fontSize : theme . fontSizes . xl ,
156- color : isDark ? theme . colors . dark [ 1 ] : theme . colors . gray [ 7 ] ,
157- margin : `0 0 ${ theme . spacing . md } 0` ,
158- fontWeight : 500 ,
159- } ,
160-
161- subtitleWrapper : {
162- display : 'flex' ,
163- alignItems : 'center' ,
164- gap : theme . spacing . xs ,
165- marginBottom : theme . spacing . xs ,
166- } ,
167-
168- textContent : {
169- fontSize : theme . fontSizes . lg ,
170- lineHeight : 1.6 ,
171- marginBottom : theme . spacing . lg ,
172- color : isDark ? theme . colors . dark [ 1 ] : theme . colors . gray [ 7 ] ,
173- } ,
174-
175- listContent : {
176- marginBottom : theme . spacing . lg ,
177- paddingLeft : theme . spacing . xl ,
178- listStylePosition : 'inside' ,
179-
180- '& ul' : {
181- listStyle : 'disc' ,
182- margin : 0 ,
183- paddingLeft : theme . spacing . md ,
184- } ,
185- '& li' : {
186- fontSize : theme . fontSizes . lg ,
187- lineHeight : 1.6 ,
188- color : isDark ? theme . colors . dark [ 1 ] : theme . colors . gray [ 7 ] ,
189- marginBottom : theme . spacing . sm ,
190- }
191- } ,
192-
193- codeBlock : {
194- backgroundColor : isDark ? theme . colors . dark [ 8 ] : theme . colors . gray [ 0 ] ,
195- borderRadius : theme . radius . md ,
196- padding : theme . spacing . lg ,
197- overflowX : 'auto' ,
198- marginBottom : theme . spacing . lg ,
199- fontFamily : theme . fontFamilyMonospace ,
200- fontSize : theme . fontSizes . sm ,
201- lineHeight : 1.5 ,
202- color : isDark ? theme . white : theme . black ,
203- whiteSpace : 'pre' ,
204- } ,
205- } ;
206-
207- // Create a classes object mapping keys to empty strings to satisfy types
208- const classNames : Record < string , string > = { } ;
209- for ( const key in styles ) {
210- classNames [ key ] = '' ; // Assign empty string
211- }
212-
213- // Mantine's hooks usually return { classes, cx, theme, etc. }
214- // To maintain compatibility with how it's used in DetailedContent.tsx ({ classes, cx } = useStyles()),
215- // we wrap the styles object.
216- // A proper `cx` function would be needed if conditional classes are complex.
217- const cx = ( ...args : any [ ] ) => args . filter ( Boolean ) . join ( ' ' ) ;
21836
219- // Return the object mapping keys to empty strings
220- return { classes : classNames , cx } ;
37+ const css = `
38+ .${ classes . sectionIcon } {
39+ display: flex;
40+ align-items: center;
41+ justify-content: center;
42+ width: ${ rem ( 48 ) } ;
43+ height: ${ rem ( 48 ) } ;
44+ border-radius: 50%;
45+ background-color: ${ theme . black } ;
46+ padding: ${ theme . spacing . xs } ;
47+ flex-shrink: 0;
48+ }
49+ .${ classes . sectionIcon } svg, .${ classes . sectionIcon } img {
50+ width: 100%;
51+ height: 100%;
52+ object-fit: contain;
53+ fill: ${ theme . white } ;
54+ }
55+
56+ .${ classes . detailedContentTitle } {
57+ font-size: ${ theme . headings . sizes . h2 . fontSize } ;
58+ font-weight: ${ theme . headings . sizes . h2 . fontWeight } ;
59+ line-height: 1.3;
60+ margin: 0;
61+ color: ${ theme . black } ;
62+ }
63+
64+ .${ classes . detailedContentText } {
65+ font-size: ${ theme . fontSizes . md } ;
66+ line-height: 1.7;
67+ margin-top: ${ theme . spacing . md } ;
68+ color: ${ theme . colors . gray [ 7 ] } ;
69+ overflow-wrap: break-word;
70+ word-break: break-word;
71+ }
72+
73+ .${ classes . detailedContentList } {
74+ margin-top: ${ theme . spacing . md } ;
75+ margin-bottom: ${ theme . spacing . lg } ;
76+ }
77+
78+ .${ classes . detailedContentList } ul {
79+ padding-left: ${ theme . spacing . xl } ;
80+ margin: 0;
81+ }
82+
83+ .${ classes . detailedContentList } li {
84+ line-height: 1.7;
85+ margin-bottom: ${ theme . spacing . xs } ;
86+ font-size: ${ theme . fontSizes . md } ;
87+ color: ${ theme . colors . gray [ 7 ] } ;
88+ }
89+
90+ .${ classes . codeBlock } {
91+ background-color: ${ theme . colors . gray [ 0 ] } ;
92+ border-radius: ${ theme . radius . md } ;
93+ padding: ${ theme . spacing . lg } ;
94+ overflow-x: auto;
95+ margin-top: ${ theme . spacing . lg } ;
96+ margin-bottom: ${ theme . spacing . lg } ;
97+ font-family: ${ theme . fontFamilyMonospace } ;
98+ font-size: ${ theme . fontSizes . sm } ;
99+ line-height: 1.5;
100+ color: ${ theme . black } ;
101+ white-space: pre;
102+ }
103+ ` ;
104+
105+ styleEl . innerHTML = css ;
106+ }
107+
108+ return {
109+ classes,
110+ cx : ( ...args : string [ ] ) => args . filter ( Boolean ) . join ( ' ' )
111+ } ;
112+ } , [ theme ] ) ;
221113} ;
0 commit comments