Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add search-field component #276

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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: 6 additions & 0 deletions .changeset/good-paws-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@pixelshades/styles": minor
"@pixelshades/ui": minor
---

add search-field component
10 changes: 10 additions & 0 deletions apps/docs/content/components/search-field.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: SearchField
description: Displays a SearchField

docLink: https://react-spectrum.adobe.com/react-aria/SearchField.html

slug: search-field
---

<ComponentPreview name="search-field/preview" />
9 changes: 9 additions & 0 deletions apps/docs/src/examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1822,6 +1822,15 @@ export function Example() {

return <RangeCalendar isDateUnavailable={(date) => isWeekend(date, locale)} />
}
`,
},
"search-field/preview": {
component: lazy(() => import("~/examples/search-field/preview.tsx")),
code: `import { SearchField } from "../../../../../packages/ui/src/components/ui/search-field"

export function Example() {
return <SearchField label="Projects" description="Search for a project" helperText="Helper Text" />
}
`,
},
"select/preview": {
Expand Down
5 changes: 5 additions & 0 deletions apps/docs/src/examples/search-field/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SearchField } from "../../../../../packages/ui/src/components/ui/search-field"

export default function Example() {
return <SearchField label="Projects" description="Search for a project" helperText="Helper Text" />
}
5 changes: 5 additions & 0 deletions packages/styles/src/components/search-field/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-FileCopyrightText: 2024 Deutsche Telekom AG
//
// SPDX-License-Identifier: Apache-2.0

export * from "./variants"
16 changes: 16 additions & 0 deletions packages/styles/src/components/search-field/variants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: 2024 Deutsche Telekom AG
//
// SPDX-License-Identifier: Apache-2.0

import { tv } from "tailwind-variants"
import { fieldBorderStyles } from "../form"

export const searchFieldVariants = tv({
slots: {
input: 'pl-[3.25rem] [&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-cancel-button]:size-5 [&::-webkit-search-cancel-button]:bg-[url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0NCIgaGVpZ2h0PSI0NCIgdmlld0JveD0iMCAwIDI0IDI0IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZT0iIzAwMCIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj4KICA8cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4KICA8cGF0aCBkPSJNMTIgMTJtLTkgMGE5IDkgMCAxIDAgMTggMGE5IDkgMCAxIDAgLTE4IDAiIC8+CiAgPHBhdGggZD0iTTEwIDEwbDQgNG0wIC00bC00IDQiIC8+Cjwvc3ZnPg==")] [&::-webkit-search-cancel-button]:bg-contain',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this value? pl-[3.25rem]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a complete rewrite of the docs, so sorry if you have to merge a bit here 😅

icon: "absolute top-1/2 left-4 size-5 -translate-y-1/2 z-[60]",
Comment on lines +10 to +11
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the embedded as a base64?

Comment on lines +10 to +11
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

z-60 is hacky and not wanted

},
variants: {
...fieldBorderStyles.variants,
},
})
5 changes: 5 additions & 0 deletions packages/ui/src/components/ui/search-field/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-FileCopyrightText: 2024 Deutsche Telekom AG
//
// SPDX-License-Identifier: Apache-2.0

export * from "./search-field"
58 changes: 58 additions & 0 deletions packages/ui/src/components/ui/search-field/search-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"use client"

// SPDX-FileCopyrightText: 2024 Deutsche Telekom AG
//
// SPDX-License-Identifier: Apache-2.0

import { forwardRef } from "@pixelshades/utils/jsx"
import type { ReactNode } from "react"
import type { SearchFieldProps as AriaSearchFieldProps } from "react-aria-components"
import { SearchField as AriaSearchField } from "react-aria-components"
import { If } from "../../utils"
import { FormDescription, FormFieldError } from "../form"
import { Input } from "../input"
import { searchFieldVariants } from "@pixelshades/styles/components/search-field"
import { type FormComponentLabelProps, Label } from "../label"
import { IconSearch } from "../../../icons"

const { input, icon } = searchFieldVariants()

export interface SearchFieldProps extends AriaSearchFieldProps, FormComponentLabelProps {
/** A helper text to be displayed below the search field. */
helperText?: ReactNode
/** The error message to be displayed when the search field is in an error state. */
errorMessage?: string
/** The placeholder text to be displayed in the search field. */
placeholder?: string
}

const SearchField = forwardRef(
({
label,
helperText,
description,
tooltip,
errorMessage,
placeholder,
ref,
isRequired,
...props
}: SearchFieldProps & { ref?: any }) => (
<AriaSearchField className={"flex flex-col gap-sm"} isRequired={isRequired} {...props}>
<If condition={label || description || tooltip}>
<Label tooltip={tooltip} description={description} isRequired={isRequired}>
{label}
</Label>
</If>
<div className="relative">
<IconSearch className={icon()} />
<Input placeholder={placeholder} ref={ref} className={input()} />
</div>

{helperText && <FormDescription>{helperText}</FormDescription>}
<FormFieldError>{errorMessage}</FormFieldError>
</AriaSearchField>
),
)

export { SearchField }
Loading