@@ -84,8 +84,10 @@ export function DynamicTabs(
8484 ) ;
8585 } , [ id , tabs , tabsState ] ) ;
8686
87- const position : string = 'top' ; // TODO: Get position from tab block options
88- const description = null ; // TODO: Get description from tabs
87+ const orientation : string = 'horizontal' ; // TODO: Get orientation from tab block options
88+ const position : string = 'start' ; // TODO: Get position from tab block options
89+
90+ const description = null ; //'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'; // null; // TODO: Get description from tabs
8991
9092 // To avoid issue with hydration, we only use the state from localStorage
9193 // once the component has been mounted.
@@ -148,21 +150,16 @@ export function DynamicTabs(
148150 className = { tcls (
149151 'flex' ,
150152 'flex-col' ,
151- position === 'left' && 'gap-4 md:flex-row' ,
152- position === 'right' && 'gap-4 md:flex-row-reverse' ,
153153 'overflow-hidden' ,
154+ 'pb-1' ,
155+
156+ orientation === 'horizontal' && position === 'start' && 'flex-col' ,
157+ orientation === 'vertical' && position === 'start' && 'md:flex-row' ,
158+ orientation === 'vertical' && position === 'end' && 'md:flex-row-reverse' ,
154159
155- style ,
160+ style
156161 // We need to inset the tabs container to make edge-to-edge scrolling work, since this container has overflow:hidden
157162 // Also important to put this after the `style` to override those.
158- '-mx-4' ,
159- 'px-4' ,
160- 'sm:-mx-6' ,
161- 'sm:px-6' ,
162- 'md:mx-auto' ,
163- 'md:px-0' ,
164- 'w-auto' ,
165- 'md:w-full'
166163 ) }
167164 >
168165 < div
@@ -174,93 +171,161 @@ export function DynamicTabs(
174171
175172 'overflow-x-auto' ,
176173 'md:overflow-hidden' ,
174+ // 'items-end',
177175
178- 'gap-1' ,
179- 'pb-2' ,
176+ 'gap-x-1' ,
180177 'flex-row' ,
181178
182- position === 'left' || position === 'right'
183- ? 'gap-2 md:max-w-[40%] md:flex-col'
184- : '' ,
179+ orientation === 'vertical' && 'gap-1.5 md:max-w-[40%] md:flex-col' ,
185180 'snap-x' ,
186181 'snap-mandatory' ,
182+ '-mb-px' ,
183+
184+ 'peer' ,
185+
186+ orientation === 'vertical' && position === 'start' && 'md:-mr-px md:mb-0' ,
187+ orientation === 'vertical' && position === 'end' && 'md:-ml-px md:mb-0'
187188
188189 // We need to inset the tablist to make edge-to-edge scrolling work.
189- '-mx-4' ,
190- 'px-4' ,
191- 'scroll-px-4' ,
192- 'sm:-mx-6' ,
193- 'sm:px-6' ,
194- 'sm:scroll-px-6' ,
195- 'md:mx-0' ,
196- 'md:px-0' ,
197- 'md:scroll-px-0'
190+ // '-mx-4',
191+ // 'px-4',
192+ // 'scroll-px-4',
193+ // 'sm:-mx-6',
194+ // 'sm:px-6',
195+ // 'sm:scroll-px-6',
196+ // 'md:mx-0',
197+ // 'md:px-0',
198+ // 'md:scroll-px-0',
198199 ) }
199200 >
200201 { tabs . map ( ( tab ) => (
201- < button
202+ < div
202203 key = { tab . id }
203- type = "button"
204- role = "tab"
205- aria-selected = { active . id === tab . id }
206- aria-controls = { getTabPanelId ( tab . id ) }
207- id = { getTabButtonId ( tab . id ) }
208- onClick = { ( ) => {
209- onSelectTab ( tab ) ;
210- } }
211204 className = { tcls (
212- hashLinkButtonWrapperStyles ,
213- description
214- ? 'px-4 py-4 max-md:min-w-64 max-md:max-w-[calc(50%-0.25rem)] '
215- : 'px-4 py-1' ,
216- description && position === 'top'
217- ? 'max-w-[calc(50%-0.25rem)] max-md:min-w-64'
218- : 'max-w-full ' ,
219-
220- 'max-md:shrink-0' ,
221- 'transition-colors' ,
222- 'text-left' ,
223- 'flex' ,
224- 'flex-col' ,
225- 'gap-1' ,
226-
227- 'rounded-md' ,
228- 'straight-corners:rounded-none' ,
229- 'circular-corners:rounded-2xl' ,
230- 'focus:outline-none' ,
231- 'focus-visible:ring-2' ,
232- 'ring-inset' ,
233-
234- 'text-tint' ,
235- 'snap-start' ,
236- active . id === tab . id
237- ? 'active-tab bg-primary-active text-primary-strong focus-visible:ring-primary-hover'
238- : 'hover:bg-tint-hover hover:text-tint-strong focus-visible:bg-tint-hover focus-visible:text-tint-strong focus-visible:ring-tint-hover'
205+ 'tab -mx-4 flex overflow-hidden px-4 max-md:max-w-[calc(33.33%+1.75rem)] max-md:shrink-0 max-md:last:pr-0 [&:first-child>button]:before:hidden' ,
206+ active . id === tab . id && 'active-tab z-20' ,
207+ description && [
208+ 'min-w-56' ,
209+ orientation === 'horizontal' && 'md:max-w-[calc(33.33%+1.75rem)]' ,
210+ ]
239211 ) }
240212 >
241- < div
213+ < button
214+ type = "button"
215+ role = "tab"
216+ aria-orientation = { orientation }
217+ aria-selected = { active . id === tab . id }
218+ aria-controls = { getTabPanelId ( tab . id ) }
219+ id = { getTabButtonId ( tab . id ) }
220+ onClick = { ( ) => {
221+ onSelectTab ( tab ) ;
222+ } }
242223 className = { tcls (
243- 'flex flex-row items-center gap-1' ,
244- description ? 'font-semibold text-base' : 'font-medium text-sm'
224+ hashLinkButtonWrapperStyles ,
225+ description ? 'p-4' : 'px-4 py-1.5' ,
226+
227+ 'grow' ,
228+ 'transition-colors' ,
229+ 'text-left' ,
230+ 'flex' ,
231+ 'flex-col' ,
232+ 'gap-1' ,
233+
234+ 'rounded-md' ,
235+ 'straight-corners:rounded-none' ,
236+ 'circular-corners:rounded-2xl' ,
237+ 'focus:outline-none' ,
238+ 'focus-visible:ring-2' ,
239+ 'ring-inset' ,
240+ 'border' ,
241+ 'relative' ,
242+
243+ // Flared corners
244+ orientation === 'horizontal' &&
245+ position === 'start' && [
246+ 'before:absolute before:size-4 before:transition-all before:content-[""] focus-visible:before:hidden' ,
247+ 'before:end-full' ,
248+ 'before:bottom-0' ,
249+ 'before:rounded-ee-md' ,
250+ 'circular-corners:before:rounded-ee-2xl' ,
251+ 'before:border-e before:border-b' ,
252+ 'before:shadow-[4px_4px_0_1px_var(--tw-shadow-color)]' ,
253+
254+ 'after:absolute after:size-4 after:transition-all after:content-[""] focus-visible:after:hidden' ,
255+ 'after:start-full' ,
256+ 'after:bottom-0' ,
257+ 'after:rounded-es-md' ,
258+ 'circular-corners:after:rounded-es-2xl' ,
259+ 'after:border-s after:border-b' ,
260+ 'after:shadow-[-4px_4px_0_1px_var(--tw-shadow-color)]' ,
261+
262+ active . id === tab . id
263+ ? [
264+ 'before:border-tint-subtle after:border-tint-subtle' ,
265+ 'before:shadow-tint-1 after:shadow-tint-1' ,
266+ ]
267+ : [
268+ 'before:border-tint-subtle after:border-tint-subtle' ,
269+ 'before:shadow-tint-2 after:shadow-tint-2' ,
270+ 'hover:after:shadow-tint-4 hover:before:shadow-tint-4' ,
271+ ] ,
272+ ] ,
273+
274+ 'max-md:!rounded-b-none max-md:border-b-0' ,
275+
276+ // Position-specific adjustments
277+ orientation === 'horizontal' &&
278+ position === 'start' &&
279+ 'md:!rounded-b-none md:border-b-0' ,
280+ orientation === 'vertical' &&
281+ position === 'start' &&
282+ 'md:!rounded-r-none md:border-r-0' ,
283+ orientation === 'vertical' &&
284+ position === 'end' &&
285+ 'md:!rounded-l-none md:border-l-0' ,
286+
287+ 'text-tint' ,
288+ 'snap-start' ,
289+ active . id === tab . id
290+ ? [ 'border-tint-subtle bg-tint-base text-tint-strong' ]
291+ : [
292+ 'border-tint-subtle bg-tint-subtle' ,
293+ 'hover:z-10 hover:border-tint-subtle hover:bg-tint-hover hover:text-tint-strong' ,
294+ 'focus-visible:z-10 focus-visible:bg-tint-hover focus-visible:text-tint-strong' ,
295+ ]
245296 ) }
246297 >
247- < div className = "line-clamp-2" > { tab . title } </ div >
248- < HashLinkButton
249- id = { getTabButtonId ( tab . id ) }
250- block = { block }
251- label = "Direct link to tab"
298+ < div
252299 className = { tcls (
253- '-mt-px ml-auto' ,
254- position === 'left' || position === 'right' || description
255- ? 'max-md:-mr-3'
256- : '-mr-3'
300+ 'flex flex-row items-center gap-1' ,
301+ description ? 'font-semibold text-base' : 'font-medium text-sm'
257302 ) }
258- />
259- </ div >
260- { description ? (
261- < span className = "line-clamp-5 text-sm" > { description } </ span >
262- ) : null }
263- </ button >
303+ >
304+ < div
305+ className = { tcls (
306+ 'line-clamp-2' ,
307+ active . id === tab . id && 'text-primary-subtle'
308+ ) }
309+ >
310+ { tab . title }
311+ </ div >
312+ < HashLinkButton
313+ id = { getTabButtonId ( tab . id ) }
314+ block = { block }
315+ label = "Direct link to tab"
316+ className = { tcls (
317+ '-mt-px ml-auto' ,
318+ orientation === 'vertical' || description
319+ ? 'max-md:-mr-3'
320+ : '-mr-3'
321+ ) }
322+ />
323+ </ div >
324+ { description ? (
325+ < p className = "line-clamp-5 text-sm" > { description } </ p >
326+ ) : null }
327+ </ button >
328+ </ div >
264329 ) ) }
265330 </ div >
266331 { tabs . map ( ( tab , index ) => (
@@ -271,14 +336,22 @@ export function DynamicTabs(
271336 aria-labelledby = { getTabButtonId ( tab . id ) }
272337 className = { tcls (
273338 'p-4' ,
274- 'rounded-lg' ,
275- 'flex-1' ,
339+ 'rounded-md' ,
276340 'straight-corners:rounded-none' ,
277341 'circular-corners:rounded-2xl' ,
278- 'grow' ,
342+ 'z-10' ,
343+ 'bg-tint-base' ,
344+ position === 'start' && '!rounded-tl-none' ,
345+ position === 'end' && '!rounded-tr-none' ,
346+ // index === 0 && active.id === tab.id
347+ // ? '!rounded-tl-none'
348+ // : '[.peer:has(.tab:first-child:hover)~&]:rounded-tl-none',
349+ 'transition-all' ,
279350 'ring-1' ,
280351 'ring-inset' ,
281352 'ring-tint-subtle' ,
353+ 'grow' ,
354+ 'depth-subtle:shadow-sm' ,
282355 tab . id !== active . id ? 'hidden' : null
283356 ) }
284357 >
0 commit comments