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
6 changes: 3 additions & 3 deletions src/components/ApiGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export default function ApiGallery() {
const name = window.location.hash.toLowerCase().slice(1)

if (name === "controller") {
router.push(`/docs/usecontroller/${name}`)
router.replace(`/docs/usecontroller/${name}`)
} else if (USEFORM_HASHES.includes(name)) {
router.push(`/docs/useform/${name}`)
router.replace(`/docs/useform/${name}`)
} else if (["useformcontext", "usefieldarray"].includes(name)) {
router.push(`/docs/${name}`)
router.replace(`/docs/${name}`)
}
}, [router])

Expand Down
308 changes: 155 additions & 153 deletions src/components/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,178 +112,180 @@ function HomePage({ monthlyDownloads = 0 }: { monthlyDownloads?: number }) {
<Builder showBuilder toggleBuilder={toggleBuilder} HomeRef={HomeRef} />
)}

<Hero />
<main>
<Hero />

<GeneralObserver
onEnter={() => {
setFeaturePlay(true)
}}
>
<FeaturesList isPlayFeature={featurePlay} />
</GeneralObserver>
<SponsorsList />

<GeneralObserver
onEnter={() => {
setCodeComparePlay(true)
}}
>
<CodeCompareSection isPlayCodeCompare={codeComparePlay} />
</GeneralObserver>
<GeneralObserver
onEnter={() => {
setIsolatePlay(true)
}}
>
<IsolateRender isIsolatePlay={isolatePlay} />
</GeneralObserver>
<GeneralObserver
onEnter={() => {
setWatchPlay(true)
}}
>
<Watcher isPlayWatch={watchPlay} />
</GeneralObserver>
<GeneralObserver
onEnter={() => {
setFeaturePlay(true)
}}
>
<FeaturesList isPlayFeature={featurePlay} />
</GeneralObserver>
<SponsorsList />

<GeneralObserver
onEnter={() => {
setRenderPlay(true)
}}
>
<CodePerfCompareSection isPlayRender={renderPlay} />
</GeneralObserver>
<GeneralObserver
onEnter={() => {
setCodeComparePlay(true)
}}
>
<CodeCompareSection isPlayCodeCompare={codeComparePlay} />
</GeneralObserver>
<GeneralObserver
onEnter={() => {
setIsolatePlay(true)
}}
>
<IsolateRender isIsolatePlay={isolatePlay} />
</GeneralObserver>
<GeneralObserver
onEnter={() => {
setWatchPlay(true)
}}
>
<Watcher isPlayWatch={watchPlay} />
</GeneralObserver>

{monthlyDownloads > 0 && (
<GeneralObserver
onEnter={() => {
setCounterPlay(true)
setRenderPlay(true)
}}
>
<HomeSection
eyebrow="Adoption"
title="Strong Adoption"
lead="One of the most downloaded React form libraries, trusted by developers and enterprises worldwide."
<CodePerfCompareSection isPlayRender={renderPlay} />
</GeneralObserver>

{monthlyDownloads > 0 && (
<GeneralObserver
onEnter={() => {
setCounterPlay(true)
}}
>
<div className={styles.downloadCard}>
<div className={styles.downloadCount}>
<FlipNumbers
play={renderCounter}
numbers={formatDownloads(monthlyDownloads)}
height={counterHeight}
width={counterHeight * 0.625}
color="#ec5990"
perspective={1500}
duration={4}
numberStyle={{ fontWeight: 800 }}
nonNumberStyle={{
fontSize: counterHeight,
fontWeight: 900,
color: "#ec5990",
lineHeight: `${counterHeight}px`,
verticalAlign: "bottom",
}}
/>
<HomeSection
eyebrow="Adoption"
title="Strong Adoption"
lead="One of the most downloaded React form libraries, trusted by developers and enterprises worldwide."
>
<div className={styles.downloadCard}>
<div className={styles.downloadCount}>
<FlipNumbers
play={renderCounter}
numbers={formatDownloads(monthlyDownloads)}
height={counterHeight}
width={counterHeight * 0.625}
color="#ec5990"
perspective={1500}
duration={4}
numberStyle={{ fontWeight: 800 }}
nonNumberStyle={{
fontSize: counterHeight,
fontWeight: 900,
color: "#ec5990",
lineHeight: `${counterHeight}px`,
verticalAlign: "bottom",
}}
/>
</div>
<p className={styles.downloadSub}>
Monthly{" "}
<a
href="https://www.npmjs.com/package/react-hook-form"
target="_blank"
rel="noopener noreferrer"
>
npm downloads
</a>
</p>
</div>
<p className={styles.downloadSub}>
Monthly{" "}
</HomeSection>
</GeneralObserver>
)}

<HomeSection
eyebrow="Recognition"
title="Highlights"
lead="This project is getting recognized by the community and industry. It's helping more developers to build forms in React than ever."
>
<div className={styles.cards}>
<article className={styles.card}>
<TrophyIcon />
<h3>Javascript Rising Star</h3>
<p>
React Hook Form have matured and evolved around hooks.
Simplifies a piece of React development.
</p>
</article>
<article className={styles.card}>
<TrophyIcon />
<h3>React Open Source Awards</h3>
<p>
The winner of 2020 GitNation React OS Award for the category of
Productivity Booster.
</p>
</article>
<article className={styles.card}>
<TrophyIcon />
<h3>Technology Radar</h3>
<p>
Featured in the{" "}
<a
href="https://www.npmjs.com/package/react-hook-form"
href="https://www.thoughtworks.com/en-au/radar/languages-and-frameworks/react-hook-form"
target="_blank"
rel="noopener noreferrer"
>
npm downloads
</a>
Thoughtworks Technology Radar
</a>{" "}
under Languages & Frameworks, adopted since 2025.
</p>
</div>
</HomeSection>
</GeneralObserver>
)}

<HomeSection
eyebrow="Recognition"
title="Highlights"
lead="This project is getting recognized by the community and industry. It's helping more developers to build forms in React than ever."
>
<div className={styles.cards}>
<article className={styles.card}>
<TrophyIcon />
<h3>Javascript Rising Star</h3>
<p>
React Hook Form have matured and evolved around hooks. Simplifies
a piece of React development.
</p>
</article>
<article className={styles.card}>
<TrophyIcon />
<h3>React Open Source Awards</h3>
<p>
The winner of 2020 GitNation React OS Award for the category of
Productivity Booster.
</p>
</article>
<article className={styles.card}>
<TrophyIcon />
<h3>Technology Radar</h3>
<p>
Featured in the{" "}
<a
href="https://www.thoughtworks.com/en-au/radar/languages-and-frameworks/react-hook-form"
target="_blank"
rel="noopener noreferrer"
>
Thoughtworks Technology Radar
</a>{" "}
under Languages & Frameworks, adopted since 2025.
</p>
</article>
</div>
</HomeSection>
</article>
</div>
</HomeSection>

<HomeSection
eyebrow="Community"
title="The Community"
lead="Built and driven by the community. On a mission to make every React developer's life easier when it comes to building forms."
>
<div className={styles.cards}>
{TESTIMONIALS.map((quote) => (
<figure key={quote.slice(0, 24)} className={styles.quote}>
<ChatIcon />
<blockquote>{quote}</blockquote>
</figure>
))}
</div>
</HomeSection>
<HomeSection
eyebrow="Community"
title="The Community"
lead="Built and driven by the community. On a mission to make every React developer's life easier when it comes to building forms."
>
<div className={styles.cards}>
{TESTIMONIALS.map((quote) => (
<figure key={quote.slice(0, 24)} className={styles.quote}>
<ChatIcon />
<blockquote>{quote}</blockquote>
</figure>
))}
</div>
</HomeSection>

<HomeSection
eyebrow="Video"
title="Watch the tutorial"
lead="A quick walkthrough of React Hook Form for React Web and React Native."
>
<IntroVideo />
</HomeSection>
<HomeSection
eyebrow="Video"
title="Watch the tutorial"
lead="A quick walkthrough of React Hook Form for React Web and React Native."
>
<IntroVideo />
</HomeSection>

<div ref={HomeRef} />
<div ref={HomeRef} />

<Form
methods={methods}
onSubmit={onSubmit}
submitData={submitData}
toggleBuilder={toggleBuilder}
formUpdated={formUpdated}
/>
<Form
methods={methods}
onSubmit={onSubmit}
submitData={submitData}
toggleBuilder={toggleBuilder}
formUpdated={formUpdated}
/>

<section className={styles.cta}>
<h2>{home.findInteresting.heading}</h2>
<p>{home.findInteresting.description}</p>
<div className={styles.ctaActions}>
<Link href="/get-started" className={styles.ctaPrimary}>
{home.getStarted}
</Link>
<Link href="/docs" className={styles.ctaSecondary}>
API Documentation
</Link>
</div>
</section>
<section className={styles.cta}>
<h2>{home.findInteresting.heading}</h2>
<p>{home.findInteresting.description}</p>
<div className={styles.ctaActions}>
<Link href="/get-started" className={styles.ctaPrimary}>
{home.getStarted}
</Link>
<Link href="/docs" className={styles.ctaSecondary}>
API Documentation
</Link>
</div>
</section>
</main>

<FooterContent />
</div>
Expand Down
1 change: 1 addition & 0 deletions src/components/Watcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const WatchGroup = ({
<div className={styles.watchGroup}>
<input
type="checkbox"
aria-label="Watch the input value"
checked={check}
onChange={() => {
setChecked(!check)
Expand Down
1 change: 1 addition & 0 deletions src/components/mdx/youtube.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const YouTube: FunctionComponent<YouTubeProps> = (
data-testid="youtube"
title={`youTube-${youTubeId}`}
src={src}
loading="lazy"
frameBorder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
Expand Down
8 changes: 7 additions & 1 deletion src/components/seo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ function SEO({
title,
description,
jsonLd = [],
noindex = false,
}: {
title: string
description?: string
jsonLd?: object[]
noindex?: boolean
}) {
const router = useRouter()
const metaTitle = title ? `${title} | ${SITE_NAME}` : DEFAULT_TITLE
Expand All @@ -46,7 +48,11 @@ function SEO({
<Head>
<title>{metaTitle}</title>
<meta name="description" content={metaDescription} key="description" />
<link rel="canonical" href={canonical} />
{noindex ? (
<meta name="robots" content="noindex" />
) : (
<link rel="canonical" href={canonical} />
)}

<meta property="og:site_name" content={SITE_NAME} />
<meta property="og:title" content={metaTitle} />
Expand Down
1 change: 1 addition & 0 deletions src/content/docs/usecontroller.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The following table contains information about properties which `useController`
| `fieldState` | `invalid` | <TypeText>boolean</TypeText> | Invalid state for current input. |
| `fieldState` | `isTouched` | <TypeText>boolean</TypeText> | Touched state for current controlled input. |
| `fieldState` | `isDirty` | <TypeText>boolean</TypeText> | Dirty state for current controlled input. |
| `fieldState` | `isValidating` | <TypeText>boolean</TypeText> | Validating state for current controlled input. |
| `fieldState` | `error` | <TypeText>object</TypeText> | <Since version="7.0.0" /> error for this specific input. |
| `formState` | `isDirty` | <TypeText>boolean</TypeText> | Set to `true` after the user modifies any of the inputs. **Important:** Make sure to provide all inputs' `defaultValues` at `useForm`, so hook form can have a single source of truth to compare whether the form is dirty. |
| `formState` | `dirtyFields` | <TypeText>object</TypeText> | An object with the user-modified fields. Make sure to provide all inputs' `defaultValues` via `useForm`, so the library can compare against the `defaultValues`. |
Expand Down
Loading
Loading