Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/sort-libraries/get-github-stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ type GitHubStatsFetchResponse =
}
}

type GitHubInfo = {
export type GitHubInfo = {
hasCommitsInLast3Months: boolean
stars: number
formattedStars: string
Expand Down
22 changes: 19 additions & 3 deletions src/app/conf/_design-system/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export declare namespace ButtonProps {
export interface BaseProps {
size?: Size
variant?: Variant
isIconButton?: boolean
}

export interface AnchorProps
Expand Down Expand Up @@ -58,13 +59,21 @@ export type ButtonProps =
export function Button(props: ButtonProps) {
const className = clsx(
"relative flex items-center justify-center gap-2.5 font-normal text-base/none text-neu-0 bg-neu-900 hover:bg-neu-800 active:bg-neu-700 font-sans h-14 px-8 data-[size=md]:h-12 data-[variant=secondary]:bg-neu-100 dark:data-[variant=secondary]:bg-neu-100/80 dark:data-[variant=secondary]:hover:bg-neu-200/50 data-[variant=secondary]:text-neu-900 data-[variant=secondary]:hover:bg-neu-200/75 data-[variant=secondary]:active:bg-neu-200/90 data-[variant=tertiary]:bg-neu-100 data-[variant=tertiary]:text-neu-900 data-[variant=tertiary]:hover:bg-neu-200 data-[variant=tertiary]:active:bg-neu-300 gql-focus-visible [aria-disabled]:bg-neu-800 aria-disabled:pointer-events-none dark:data-[variant=tertiary]:bg-neu-900/10 dark:data-[variant=tertiary]:text-neu-900 dark:data-[variant=tertiary]:hover:bg-neu-900/[.125] dark:data-[variant=tertiary]:active:bg-neu-800/20 dark:data-[variant=tertiary]:ring-1 dark:data-[variant=tertiary]:ring-inset dark:data-[variant=tertiary]:ring-neu-900/20",
props.isIconButton && "!p-2 h-min",
props.className,
)

const styleAttrs = { "data-size": props.size, "data-variant": props.variant }

if ("href" in props && typeof props.href === "string") {
const { className: _1, size: _2, disabled, children, ...rest } = props
const {
className: _1,
size: _2,
isIconButton: _3,
disabled,
children,
...rest
} = props

if (disabled) (rest as { href?: string }).href = undefined

Expand All @@ -81,7 +90,14 @@ export function Button(props: ButtonProps) {
}

if (props.as) {
const { className: _1, size: _2, children, as, ...rest } = props
const {
className: _1,
size: _2,
isIconButton: _3,
children,
as,
...rest
} = props
const Root = as as "span" // we don't need HTMLDivElement type
return (
<Root className={className} {...styleAttrs} {...rest}>
Expand All @@ -90,7 +106,7 @@ export function Button(props: ButtonProps) {
)
}

const { className: _1, size: _2, children, ...rest } = props
const { className: _1, size: _2, isIconButton: _3, children, ...rest } = props

return (
<button className={className} {...styleAttrs} {...rest}>
Expand Down
3 changes: 2 additions & 1 deletion src/app/conf/_design-system/tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export function Tag({ color, children, style, className, ...rest }: TagProps) {
{...rest}
>
<span
className="absolute inset-0 opacity-20"
// eslint-disable-next-line tailwindcss/no-custom-classname
className="Tag--bg absolute inset-0 opacity-20"
style={{
backgroundColor: color,
}}
Expand Down
2 changes: 1 addition & 1 deletion src/code/language-support/python/client/ql.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: ql
description: Non intrusive python GraphQL client wrapped around pydantic.
url: https://dsal3389.github.io/ql/
github: https://github.com/dsal3389/ql
github: dsal3389/ql
---

GraphQL client library, wrapped around pydantic classes for type validation,
Expand Down
2 changes: 1 addition & 1 deletion src/components/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function Card({
return (
<Component
className={clsx(
"border border-zinc-200 bg-white p-8 dark:border-[#414141] dark:bg-neutral-800 lg:p-12",
"border border-neu-200 bg-neu-0 p-8 dark:border-neu-50 lg:p-12",
"rounded-none",
isLink && [
"hover:!border-primary hover:shadow-2xl hover:shadow-primary/10 hover:dark:bg-neutral-700/50",
Expand Down
167 changes: 92 additions & 75 deletions src/components/tools-and-libraries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
RubyGemsIcon,
ChevronLeftIcon,
} from "@/icons"
import { Card, Tag } from "@/components"
import { Card } from "@/components"
import NextLink from "next/link"
import NextHead from "next/head"
import { useMounted } from "nextra/hooks"
Expand All @@ -30,6 +30,17 @@ import {
import { clsx } from "clsx"
import { getComponents } from "nextra-theme-docs"
import { RadioGroup, RadioGroupItem } from "@/components/radio"
import { Button } from "@/app/conf/_design-system/button"
import { Tag } from "@/app/conf/_design-system/tag"

type PackageInfo = {
name: string
description: string
url: string
github: string
npm: string
gem?: string
}

type CodePageProps = {
allTags: {
Expand All @@ -39,14 +50,7 @@ type CodePageProps = {
}[]
data: {
tags: string[]
frontMatter: {
name: string
description: string
url: string
github: string
npm: string
gem?: string
}
frontMatter: PackageInfo
stars?: number
formattedStars?: string
lastRelease?: string
Expand Down Expand Up @@ -187,11 +191,9 @@ export function CodePage({ allTags, data }: CodePageProps) {
key="meta-og-description"
/>
</NextHead>
<div className="container py-10 md:py-20">
<h1 className="text-4xl font-extrabold md:text-7xl">
Code Using GraphQL
</h1>
<div className="my-10 flex max-w-[700px] items-center border-b border-current pb-2.5 text-2xl font-extrabold">
<div className="container py-8 md:pt-16">
<h1 className="typography-h1">Code Using GraphQL</h1>
<div className="typography-h3 my-10 flex max-w-[700px] items-center border-b border-current pb-2.5">
<div
className={clsx(
"flex shrink-0",
Expand All @@ -201,6 +203,7 @@ export function CodePage({ allTags, data }: CodePageProps) {
{inputTags}
</div>
<input
// TODO: This should also do a fuzzy full text search, not just search on tags.
value={search}
onChange={e => setSearch(e.target.value)}
onKeyDown={handleKeyDown}
Expand All @@ -213,26 +216,27 @@ export function CodePage({ allTags, data }: CodePageProps) {
/>
<MagnifyingGlassIcon className="shrink-0" />
</div>
<div className="roboto-mono flex flex-wrap gap-3 md:gap-5">
<div className="flex flex-wrap gap-2">
{queryTags.map(({ tag, count, name }) => {
const isTagMatchSearch =
!search || name.toLowerCase().includes(search.toLowerCase())
if (!isTagMatchSearch) return

return (
<NextLink
href={`/community/tools-and-libraries/?tags=${tag}`}
key={tag}
data-tag={tag}
className={clsx(
"tag",
mounted &&
(queryParamsTags as string[]).includes(tag) &&
"bg-primary",
)}
onClick={handleQuery}
title={`${mounted && (queryParamsTags as string[]).includes(tag) ? "Remove" : "Add"} tag "${name}"`}
className="flex"
>
{name} ({count})
<Tag
className="!capitalize lg:!text-sm [&:has(:hover)_.Tag--bg]:opacity-50"
color="hsl(var(--color-neu-500)/.8)"
>
{name} ({count})
</Tag>
</NextLink>
)
})}
Expand All @@ -258,7 +262,8 @@ export function CodePage({ allTags, data }: CodePageProps) {
</div>
</RadioGroup>

<div className="container grid gap-10 py-20 md:grid-cols-2">
{/* todo: add md:*:h-full when the readme opens in a modal */}
<div className="container grid gap-2 py-8 md:grid-cols-2 md:gap-4">
{(sort === "alphabetical"
? [...newData].sort((a, b) =>
a.frontMatter.name.localeCompare(b.frontMatter.name),
Expand All @@ -273,75 +278,46 @@ export function CodePage({ allTags, data }: CodePageProps) {
license,
compiledSource,
}) => {
const { name, description, url, github, npm, gem } = frontMatter
const { name, description } = frontMatter
const hasMetadata = formattedStars || lastRelease || license
return (
<Card
key={`${name}${tags.toString()}`}
className={clsx(
"h-max !p-0",
"flex h-max flex-col !p-0",
"min-w-0", // hack to avoid overflow when opening details
)}
>
<div className="flex grow flex-col gap-7 p-8 lg:p-12">
<div className="flex items-center gap-6 [&_a:hover]:text-primary [&_a]:transition-colors">
<span className="grow break-all text-3xl font-extrabold">
{name}
</span>
{url && (
<a href={url} target="_blank" rel="noreferrer">
<GlobeIcon />
</a>
)}
{github && (
<a
href={`https://github.com/${github}`}
target="_blank"
rel="noreferrer"
>
<GitHubIcon />
</a>
)}
{npm && (
<a
href={`https://npmjs.com/package/${npm}`}
target="_blank"
rel="noreferrer"
>
<NPMIcon />
</a>
)}
{gem && (
<a
href={`https://rubygems.org/gems/${gem}`}
target="_blank"
rel="noreferrer"
>
<RubyGemsIcon />
</a>
)}
</div>
<div className="roboto-mono flex gap-2">
<article className="flex grow flex-col gap-7 p-4 lg:p-8">
<header className="flex items-center gap-2">
<span className="typography-h3 grow break-all">{name}</span>
<PackageLinks data={frontMatter} />
</header>
<div className="flex gap-2">
{tags.map(tag => (
<Tag
<NextLink
key={tag}
// @ts-expect-error -- fixme
as={NextLink}
href={`/community/tools-and-libraries/?tags=${tag}`}
className="cursor-pointer transition-colors hover:!bg-primary hover:text-white"
className="flex [&:has(:hover)_.Tag--bg]:opacity-50"
>
{allTagsMap.get(tag)!.name}
</Tag>
<Tag
className="cursor-pointer !capitalize"
color="hsl(var(--color-neu-400))" // todo: tags could be color coded like on the conference page
>
{allTagsMap.get(tag)!.name}
</Tag>
</NextLink>
))}
</div>
<Markdown className="line-clamp-4 grow lg:text-lg [&_a]:text-primary">
{description}
</Markdown>
<div className="flex-1" />
{hasMetadata && (
<div
className={clsx(
"flex items-center gap-5 max-md:text-xs",
"[&>:not(:last-child)]:border-r [&>:not(:last-child)]:border-gray-500 [&>:not(:last-child)]:pr-5",
"[&>:not(:last-child)]:border-r [&>:not(:last-child)]:border-neu-500 [&>:not(:last-child)]:pr-5",
)}
>
{lastRelease && <span>Last release {lastRelease}</span>}
Expand All @@ -354,14 +330,14 @@ export function CodePage({ allTags, data }: CodePageProps) {
{license && <span>{license}</span>}
</div>
)}
</div>
</article>

{compiledSource && (
<details className="bg-[#f0f0f0] dark:bg-[#2f2f2f]">
<details className="bg-neu-100">
<summary
className={clsx(
"flex justify-between px-8 py-5 font-bold text-primary lg:px-12 dark:[[open]>&]:shadow-[-5px_10px_30px_20px_#1b1b1b4d]",
"[[open]>&]:shadow-[0_6px_21px_0_#1b1b1b33]",
"flex justify-between px-8 py-5 text-primary lg:px-12 dark:[[open]>&]:shadow-[-5px_10px_30px_20px_#1b1b1b4d]",
"[[open]>&]:bg-neu-200",
"cursor-pointer",
)}
>
Expand Down Expand Up @@ -405,3 +381,44 @@ const RemoteContent = memo(function RemoteContent({
})
return <MDXContent components={components} />
})

function PackageLinks({ data }: { data: PackageInfo }) {
const { url, github, npm, gem } = data

return (
<>
{url && (
<Button href={url} variant="tertiary" isIconButton>
<GlobeIcon className="size-5" />
</Button>
)}
{github && (
<Button
href={`https://github.com/${github}`}
variant="tertiary"
isIconButton
>
<GitHubIcon className="size-5" />
</Button>
)}
{npm && (
<Button
href={`https://npmjs.com/package/${npm}`}
variant="tertiary"
isIconButton
>
<NPMIcon className="size-5" viewBox="0 0 30 30" />
</Button>
)}
{gem && (
<Button
href={`https://rubygems.org/gems/${gem}`}
variant="tertiary"
isIconButton
>
<RubyGemsIcon className="size-5" />
</Button>
)}
</>
)
}
Loading