77 RubyGemsIcon ,
88 ChevronLeftIcon ,
99} from "@/icons"
10- import { Card , Tag } from "@/components"
10+ import { Card } from "@/components"
1111import NextLink from "next/link"
1212import NextHead from "next/head"
1313import { useMounted } from "nextra/hooks"
@@ -30,6 +30,17 @@ import {
3030import { clsx } from "clsx"
3131import { getComponents } from "nextra-theme-docs"
3232import { RadioGroup , RadioGroupItem } from "@/components/radio"
33+ import { Button } from "@/app/conf/_design-system/button"
34+ import { Tag } from "@/app/conf/_design-system/tag"
35+
36+ type PackageInfo = {
37+ name : string
38+ description : string
39+ url : string
40+ github : string
41+ npm : string
42+ gem ?: string
43+ }
3344
3445type CodePageProps = {
3546 allTags : {
@@ -39,14 +50,7 @@ type CodePageProps = {
3950 } [ ]
4051 data : {
4152 tags : string [ ]
42- frontMatter : {
43- name : string
44- description : string
45- url : string
46- github : string
47- npm : string
48- gem ?: string
49- }
53+ frontMatter : PackageInfo
5054 stars ?: number
5155 formattedStars ?: string
5256 lastRelease ?: string
@@ -187,11 +191,9 @@ export function CodePage({ allTags, data }: CodePageProps) {
187191 key = "meta-og-description"
188192 />
189193 </ NextHead >
190- < div className = "container py-10 md:py-20" >
191- < h1 className = "text-4xl font-extrabold md:text-7xl" >
192- Code Using GraphQL
193- </ h1 >
194- < div className = "my-10 flex max-w-[700px] items-center border-b border-current pb-2.5 text-2xl font-extrabold" >
194+ < div className = "container py-8 md:pt-16" >
195+ < h1 className = "typography-h1" > Code Using GraphQL</ h1 >
196+ < div className = "typography-h3 my-10 flex max-w-[700px] items-center border-b border-current pb-2.5" >
195197 < div
196198 className = { clsx (
197199 "flex shrink-0" ,
@@ -201,6 +203,7 @@ export function CodePage({ allTags, data }: CodePageProps) {
201203 { inputTags }
202204 </ div >
203205 < input
206+ // TODO: This should also do a fuzzy full text search, not just search on tags.
204207 value = { search }
205208 onChange = { e => setSearch ( e . target . value ) }
206209 onKeyDown = { handleKeyDown }
@@ -213,26 +216,27 @@ export function CodePage({ allTags, data }: CodePageProps) {
213216 />
214217 < MagnifyingGlassIcon className = "shrink-0" />
215218 </ div >
216- < div className = "roboto-mono flex flex-wrap gap-3 md:gap-5 " >
219+ < div className = "flex flex-wrap gap-2 " >
217220 { queryTags . map ( ( { tag, count, name } ) => {
218221 const isTagMatchSearch =
219222 ! search || name . toLowerCase ( ) . includes ( search . toLowerCase ( ) )
220223 if ( ! isTagMatchSearch ) return
224+
221225 return (
222226 < NextLink
223227 href = { `/community/tools-and-libraries/?tags=${ tag } ` }
224228 key = { tag }
225229 data-tag = { tag }
226- className = { clsx (
227- "tag" ,
228- mounted &&
229- ( queryParamsTags as string [ ] ) . includes ( tag ) &&
230- "bg-primary" ,
231- ) }
232230 onClick = { handleQuery }
233231 title = { `${ mounted && ( queryParamsTags as string [ ] ) . includes ( tag ) ? "Remove" : "Add" } tag "${ name } "` }
232+ className = "flex"
234233 >
235- { name } ({ count } )
234+ < Tag
235+ className = "!capitalize lg:!text-sm [&:has(:hover)_.Tag--bg]:opacity-50"
236+ color = "hsl(var(--color-neu-500)/.8)"
237+ >
238+ { name } ({ count } )
239+ </ Tag >
236240 </ NextLink >
237241 )
238242 } ) }
@@ -258,7 +262,8 @@ export function CodePage({ allTags, data }: CodePageProps) {
258262 </ div >
259263 </ RadioGroup >
260264
261- < div className = "container grid gap-10 py-20 md:grid-cols-2" >
265+ { /* todo: add md:*:h-full when the readme opens in a modal */ }
266+ < div className = "container grid gap-2 py-8 md:grid-cols-2 md:gap-4" >
262267 { ( sort === "alphabetical"
263268 ? [ ...newData ] . sort ( ( a , b ) =>
264269 a . frontMatter . name . localeCompare ( b . frontMatter . name ) ,
@@ -273,75 +278,46 @@ export function CodePage({ allTags, data }: CodePageProps) {
273278 license,
274279 compiledSource,
275280 } ) => {
276- const { name, description, url , github , npm , gem } = frontMatter
281+ const { name, description } = frontMatter
277282 const hasMetadata = formattedStars || lastRelease || license
278283 return (
279284 < Card
280285 key = { `${ name } ${ tags . toString ( ) } ` }
281286 className = { clsx (
282- "h-max !p-0" ,
287+ "flex h-max flex-col !p-0" ,
283288 "min-w-0" , // hack to avoid overflow when opening details
284289 ) }
285290 >
286- < div className = "flex grow flex-col gap-7 p-8 lg:p-12" >
287- < div className = "flex items-center gap-6 [&_a:hover]:text-primary [&_a]:transition-colors" >
288- < span className = "grow break-all text-3xl font-extrabold" >
289- { name }
290- </ span >
291- { url && (
292- < a href = { url } target = "_blank" rel = "noreferrer" >
293- < GlobeIcon />
294- </ a >
295- ) }
296- { github && (
297- < a
298- href = { `https://github.com/${ github } ` }
299- target = "_blank"
300- rel = "noreferrer"
301- >
302- < GitHubIcon />
303- </ a >
304- ) }
305- { npm && (
306- < a
307- href = { `https://npmjs.com/package/${ npm } ` }
308- target = "_blank"
309- rel = "noreferrer"
310- >
311- < NPMIcon />
312- </ a >
313- ) }
314- { gem && (
315- < a
316- href = { `https://rubygems.org/gems/${ gem } ` }
317- target = "_blank"
318- rel = "noreferrer"
319- >
320- < RubyGemsIcon />
321- </ a >
322- ) }
323- </ div >
324- < div className = "roboto-mono flex gap-2" >
291+ < article className = "flex grow flex-col gap-7 p-4 lg:p-8" >
292+ < header className = "flex items-center gap-2" >
293+ < span className = "typography-h3 grow break-all" > { name } </ span >
294+ < PackageLinks data = { frontMatter } />
295+ </ header >
296+ < div className = "flex gap-2" >
325297 { tags . map ( tag => (
326- < Tag
298+ < NextLink
327299 key = { tag }
328- // @ts -expect-error -- fixme
329- as = { NextLink }
330300 href = { `/community/tools-and-libraries/?tags=${ tag } ` }
331- className = "cursor-pointer transition-colors hover:!bg-primary hover:text-white "
301+ className = "flex [&:has(: hover)_.Tag--bg]:opacity-50 "
332302 >
333- { allTagsMap . get ( tag ) ! . name }
334- </ Tag >
303+ < Tag
304+ className = "cursor-pointer !capitalize"
305+ color = "hsl(var(--color-neu-400))" // todo: tags could be color coded like on the conference page
306+ >
307+ { allTagsMap . get ( tag ) ! . name }
308+ </ Tag >
309+ </ NextLink >
335310 ) ) }
336311 </ div >
337312 < Markdown className = "line-clamp-4 grow lg:text-lg [&_a]:text-primary" >
338313 { description }
339314 </ Markdown >
315+ < div className = "flex-1" />
340316 { hasMetadata && (
341317 < div
342318 className = { clsx (
343319 "flex items-center gap-5 max-md:text-xs" ,
344- "[&>:not(:last-child)]:border-r [&>:not(:last-child)]:border-gray -500 [&>:not(:last-child)]:pr-5" ,
320+ "[&>:not(:last-child)]:border-r [&>:not(:last-child)]:border-neu -500 [&>:not(:last-child)]:pr-5" ,
345321 ) }
346322 >
347323 { lastRelease && < span > Last release { lastRelease } </ span > }
@@ -354,14 +330,14 @@ export function CodePage({ allTags, data }: CodePageProps) {
354330 { license && < span > { license } </ span > }
355331 </ div >
356332 ) }
357- </ div >
333+ </ article >
358334
359335 { compiledSource && (
360- < details className = "bg-[#f0f0f0] dark:bg-[#2f2f2f] " >
336+ < details className = "bg-neu-100 " >
361337 < summary
362338 className = { clsx (
363- "flex justify-between px-8 py-5 font-bold text-primary lg:px-12 dark:[[open]>&]:shadow-[-5px_10px_30px_20px_#1b1b1b4d]" ,
364- "[[open]>&]:shadow-[0_6px_21px_0_#1b1b1b33] " ,
339+ "flex justify-between px-8 py-5 text-primary lg:px-12 dark:[[open]>&]:shadow-[-5px_10px_30px_20px_#1b1b1b4d]" ,
340+ "[[open]>&]:bg-neu-200 " ,
365341 "cursor-pointer" ,
366342 ) }
367343 >
@@ -405,3 +381,44 @@ const RemoteContent = memo(function RemoteContent({
405381 } )
406382 return < MDXContent components = { components } />
407383} )
384+
385+ function PackageLinks ( { data } : { data : PackageInfo } ) {
386+ const { url, github, npm, gem } = data
387+
388+ return (
389+ < >
390+ { url && (
391+ < Button href = { url } variant = "tertiary" isIconButton >
392+ < GlobeIcon className = "size-5" />
393+ </ Button >
394+ ) }
395+ { github && (
396+ < Button
397+ href = { `https://github.com/${ github } ` }
398+ variant = "tertiary"
399+ isIconButton
400+ >
401+ < GitHubIcon className = "size-5" />
402+ </ Button >
403+ ) }
404+ { npm && (
405+ < Button
406+ href = { `https://npmjs.com/package/${ npm } ` }
407+ variant = "tertiary"
408+ isIconButton
409+ >
410+ < NPMIcon className = "size-5" viewBox = "0 0 30 30" />
411+ </ Button >
412+ ) }
413+ { gem && (
414+ < Button
415+ href = { `https://rubygems.org/gems/${ gem } ` }
416+ variant = "tertiary"
417+ isIconButton
418+ >
419+ < RubyGemsIcon className = "size-5" />
420+ </ Button >
421+ ) }
422+ </ >
423+ )
424+ }
0 commit comments