-
-
Notifications
You must be signed in to change notification settings - Fork 53
feat: add Label component with docs and tests #1544
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // Import API documentation | ||
| import label_api_SourceCode from './component_api/label.tsx'; | ||
|
|
||
| const code = { | ||
| javascript: { | ||
| code: `import Label from "@radui/ui/Label"\n\nconst LabelExample = () => (\n <div>\n <Label htmlFor="email">Email</Label>\n <input id="email" type="email" />\n </div>\n)`, | ||
| }, | ||
|
Comment on lines
+6
to
+7
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainKeep docs import path consistent with package scope. Ensure the usage snippet’s 🏁 Script executed: #!/bin/bash
# Inspect package.json exports to confirm Label entry
fd package.json | xargs -I{} jq -r '.name, .exports' {} 2>/dev/null | sed -n '1,120p'Length of output: 24 🏁 Script executed: #!/bin/bash
# List all package.json files to locate @radui/ui package.json
find . -type f -name package.jsonLength of output: 34 🏁 Script executed: #!/bin/bash
# Show main and exports in root package.json
jq '{main: .main, exports: .exports}' package.jsonLength of output: 37 Use package root import for Label In docs/app/docs/components/label/docs/codeUsage.js (lines 6–7), replace import Label from "@radui/ui/Label"with import Label from "@radui/ui"to match the package’s published entry point. 🤖 Prompt for AI Agents |
||
| css: { | ||
| code: `.rad-ui-label{\n display: block;\n font-weight: 500;\n margin-bottom: 4px;\n}` | ||
| }, | ||
| }; | ||
|
|
||
| // API documentation | ||
| export const api_documentation = { | ||
| label: label_api_SourceCode | ||
| }; | ||
|
|
||
| // Component features | ||
| export const features = [ | ||
| "Pairs text with form controls using htmlFor/id attributes", | ||
| "Clicking the label focuses the associated field", | ||
| "Improves accessibility and assistive technology support", | ||
| "Supports custom root class names", | ||
| ]; | ||
|
|
||
| export default code; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| const data = { | ||
| name: "Label", | ||
| description: "Associates text with form controls for accessibility.", | ||
| columns: [ | ||
| { name: "Prop", id: "prop" }, | ||
| { name: "Type", id: "type" }, | ||
| { name: "Default", id: "default" } | ||
| ], | ||
| data: [ | ||
| { | ||
| prop: { | ||
| name: "htmlFor", | ||
| info_tooltips: "ID of the form element this label describes", | ||
| }, | ||
| type: "string", | ||
| default: "undefined", | ||
| }, | ||
| { | ||
| prop: { | ||
| name: "children", | ||
| info_tooltips: "The label content", | ||
| }, | ||
| type: "ReactNode", | ||
| default: "--", | ||
| }, | ||
| { | ||
| prop: { | ||
| name: "className", | ||
| info_tooltips: "Additional CSS class names to apply", | ||
| }, | ||
| type: "string", | ||
| default: "''", | ||
| }, | ||
| { | ||
| prop: { | ||
| name: "customRootClass", | ||
| info_tooltips: "Custom root class name to override default styling", | ||
| }, | ||
| type: "string", | ||
| default: "''", | ||
| } | ||
| ] | ||
| }; | ||
|
|
||
| export default data; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import PageDetails from '@/components/seo/PageDetails'; | ||
| import Documentation from "@/components/layout/Documentation/Documentation"; | ||
| import Label from "@radui/ui/Label"; | ||
| import codeUsage, { api_documentation, features } from "./docs/codeUsage"; | ||
| import labelMetadata from "./seo"; | ||
|
|
||
| export const metadata = labelMetadata; | ||
|
|
||
| <Documentation | ||
| title="Label" | ||
| description="Labels provide accessible names for form fields and ensure proper associations." | ||
| > | ||
| {/* Component Hero */} | ||
| <Documentation.ComponentHero codeUsage={codeUsage}> | ||
| <div className='text-gray-1000 p-5 space-y-2'> | ||
| <Label htmlFor="email">Email</Label> | ||
| <input id="email" type="email" className='border border-gray-400 rounded p-1' /> | ||
| </div> | ||
| </Documentation.ComponentHero> | ||
|
|
||
| {/* Component Features */} | ||
| <Documentation.ComponentFeatures | ||
| features={features} | ||
| /> | ||
|
|
||
| {/* API Documentation */} | ||
| <Documentation.Section title="API Documentation" as="h2" /> | ||
| <Documentation.Table | ||
| title="Label" | ||
| description={api_documentation.label.description} | ||
| columns={api_documentation.label.columns} | ||
| data={api_documentation.label.data} | ||
| /> | ||
| </Documentation> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import generateSeoMetadata from "@/utils/seo/generateSeoMetadata"; | ||
|
|
||
| const labelMetadata = generateSeoMetadata({ | ||
| title: "Label - Rad UI", | ||
| description: "Accessible label component for pairing text with form inputs and improving usability.", | ||
| }); | ||
|
|
||
| export default labelMetadata; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ const RELEASED_COMPONENTS = [ | |
| 'Heading', | ||
| 'Text', | ||
| 'Kbd', | ||
| 'Label', | ||
| 'Progress', | ||
| 'Separator', | ||
| 'Strong', | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| 'use client'; | ||
| import React, { ElementRef, ComponentPropsWithoutRef } from 'react'; | ||
| import { clsx } from 'clsx'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect clsx import will break build. clsx has a default export; named import Apply this fix: -import { clsx } from 'clsx';
+import clsx from 'clsx';🤖 Prompt for AI Agents |
||
| import { customClassSwitcher } from '~/core'; | ||
|
|
||
| const COMPONENT_NAME = 'Label'; | ||
|
|
||
| export interface LabelProps extends ComponentPropsWithoutRef<'label'> { | ||
| /** | ||
| * Custom root class to override default styling. | ||
| */ | ||
| customRootClass?: string; | ||
| } | ||
|
|
||
| type LabelElement = ElementRef<'label'>; | ||
|
|
||
| const Label = React.forwardRef<LabelElement, LabelProps>( | ||
| ({ className, customRootClass, htmlFor, ...props }, ref) => { | ||
| const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME); | ||
| return ( | ||
| <label | ||
| ref={ref} | ||
| htmlFor={htmlFor} | ||
| className={clsx(rootClass, className)} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| Label.displayName = COMPONENT_NAME; | ||
|
|
||
| export default Label; | ||
| export type { LabelElement }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import React from 'react'; | ||
| import { render, screen } from '@testing-library/react'; | ||
| import userEvent from '@testing-library/user-event'; | ||
| import Label from '../Label'; | ||
|
|
||
| /** | ||
| * Tests for Label component ensuring proper linkage and accessibility. | ||
| */ | ||
| describe('Label', () => { | ||
| test('associates with form field via htmlFor', () => { | ||
| render( | ||
| <div> | ||
| <Label htmlFor="email">Email</Label> | ||
| <input id="email" /> | ||
| </div> | ||
| ); | ||
| const input = screen.getByLabelText('Email'); | ||
| expect(input).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| test('clicking label focuses associated input', async () => { | ||
| const user = userEvent.setup(); | ||
| render( | ||
| <div> | ||
| <Label htmlFor="name">Name</Label> | ||
| <input id="name" /> | ||
| </div> | ||
| ); | ||
| const label = screen.getByText('Name'); | ||
| const input = screen.getByLabelText('Name'); | ||
| await user.click(label); | ||
| expect(document.activeElement).toBe(input); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .rad-ui-label { | ||
| display: block; | ||
| font-weight: 500; | ||
| margin-bottom: 4px; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid importing TSX with explicit extension from JS.
Explicit “.tsx” in JS imports can fail depending on module resolution. Prefer extensionless import.
📝 Committable suggestion
🤖 Prompt for AI Agents