Files
Gildas GarciaandIvan Vasilov 96d43099bb chore: refactor Button API so that it can be used a standard button (#46880)
## Problem

Our `<Button>` component breaks the default `button` contract by
redefining the `type` prop to set its variant (`primary`, `default`,
etc) instead of the button type (`submit`, `button`, etc).
This is confusing and forces to write more code when using it with
shadcn components that expect/inject the standard button props.

## Solution

- rename the `type` prop to `variant`
- rename the `htmlType` prop to `type`
- propagate the changes where necessary
- format code

## How to test

As this is just prop renaming, if it builds it's ok

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-06-16 23:59:58 +02:00

86 lines
2.3 KiB
TypeScript

'use client'
import { usePathname } from 'next/navigation'
import { useEffect } from 'react'
import { useDocsSearch, type DocsSearchResult } from 'common'
import { Button, cn } from 'ui'
import { useSetCommandMenuOpen } from 'ui-patterns/CommandMenu'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import ButtonCard from '~/components/ButtonCard'
function SearchButton() {
const setCommandMenuOpen = useSetCommandMenuOpen()
return (
<Button variant="primary" size="small" onClick={() => setCommandMenuOpen(true)}>
Search for page
</Button>
)
}
function Recommendations() {
const pathname = usePathname()
const { searchState: state, handleDocsSearch: handleSearch } = useDocsSearch()
const loading = state.status === 'initial' || state.status === 'loading'
const recommendations =
state.status === 'partialResults' || state.status === 'fullResults' ? state.results : []
useEffect(() => {
if (!pathname) return
const query = decodeURIComponent(pathname.replace(/^\/(?:guides|reference)\//, '')).replace(
/[_\/-]/g,
' '
)
handleSearch(query)
}, [handleSearch, pathname])
return (
<section aria-labelledby="empty-page-recommendations" className="min-h-96 mt-20">
<h2 id="empty-page-recommendations">Are you looking for...?</h2>
{loading && <LoadingState />}
{!loading && recommendations.length === 0 && <NoResults />}
{!loading && recommendations.length > 0 && (
<RecommendationsList recommendations={recommendations} />
)}
</section>
)
}
function LoadingState() {
return <GenericSkeletonLoader />
}
function NoResults() {
return <span>No recommendations found.</span>
}
function RecommendationsList({
recommendations,
}: {
recommendations: Array<Omit<DocsSearchResult, 'sections'>>
}) {
return (
<ul className={cn('not-prose', 'grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] gap-4')}>
{recommendations
.filter(({ title }) => !!title)
.slice(0, 6)
.map(({ path, title, subtitle, description }) => (
<ButtonCard
key={path}
to={path}
title={title}
description={subtitle || description || undefined}
/>
))}
</ul>
)
}
export { Recommendations, SearchButton }