diff --git a/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx b/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx index fd593d4630..5e38e1f6c9 100644 --- a/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx +++ b/apps/dashboard/app/(app)/apis/_components/create-api-button.tsx @@ -59,7 +59,7 @@ export const CreateApiButton = ({ <> setIsOpen(true)}> - Create New API + Create new API -
- - - -
-
- - -
-
- - - -
- - +
+ {/* Navigation Bar */} + +
+ {/* Search and Controls Row - Using LogsLLMSearch and RefreshButton structures */} +
+
+
+
+ {/* LogsLLMSearch - Based on the component structure */} +
+
+
+
+ +
+
+ + Search API using name or ID + +
+
+
+
+
+
+ {/* Date filter */} +
+
+ {/* biome-ignore lint/a11y/useButtonType: */} + +
+
+
+
+
+ {/* RefreshButton - Based on the component structure but disabled */} +
+ {/* biome-ignore lint/a11y/useButtonType: */} + +
+
- - - - -
- - -
-
+
+ + {/* Cards Grid */} +
+ {Array.from({ length: 8 }).map((_, index) => ( +
+ key={index} + className="flex flex-col border border-gray-6 rounded-lg overflow-hidden" + > + {/* Chart area - 140px height */} +
+ {/* Bottom section with link, name, and stats */} +
+ {/* Name and icon row */} +
+
+
+ + + + +
+ +
+
+ {/* Stats row */} +
+ {/* Left side - metrics inline */} +
+
+
+
0
+
Valid
+
+
+
+
0
+
Invalid
+
+
+ {/* Right side - clock */} +
+ + No data +
+
+
+
+ ))} +
- +
); } diff --git a/apps/dashboard/app/(app)/authorization/_components/rbac-form.tsx b/apps/dashboard/app/(app)/authorization/_components/rbac-form.tsx index a43aa46b61..290c9ae247 100644 --- a/apps/dashboard/app/(app)/authorization/_components/rbac-form.tsx +++ b/apps/dashboard/app/(app)/authorization/_components/rbac-form.tsx @@ -1,12 +1,11 @@ "use client"; import { revalidateTag } from "@/app/actions"; import { DialogContainer } from "@/components/dialog-container"; -import { FormTextarea } from "@/components/form-textarea"; import { toast } from "@/components/ui/toaster"; import { tags } from "@/lib/cache"; import { trpc } from "@/lib/trpc/client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Button, FormInput } from "@unkey/ui"; +import { Button, FormInput, FormTextarea } from "@unkey/ui"; import { validation } from "@unkey/validation"; import { useRouter } from "next/navigation"; import type { PropsWithChildren, ReactNode } from "react"; diff --git a/apps/dashboard/app/(app)/ratelimits/loading.tsx b/apps/dashboard/app/(app)/ratelimits/loading.tsx index cde2adf520..08470cff6a 100644 --- a/apps/dashboard/app/(app)/ratelimits/loading.tsx +++ b/apps/dashboard/app/(app)/ratelimits/loading.tsx @@ -1,44 +1,174 @@ -import { PageContent } from "@/components/page-content"; import { Skeleton } from "@/components/ui/skeleton"; +import { Clock, Gauge, Magnifier, ProgressBar, Refresh3 } from "@unkey/icons"; export default function Loading() { return ( - -
- - - -
-
- - -
-
- - - -
- - +
+ {/* Navigation Bar */} + +
+ {/* Search and Controls Row - Using LogsLLMSearch and RefreshButton structures */} +
+
+
+
+ {/* LogsLLMSearch - Based on the component structure */} +
+
+
+
+ +
+
+ + Search namespaces + +
+
+
+
+
+
+ {/* Date filter */} +
+
+ {/* biome-ignore lint/a11y/useButtonType: */} + +
+
+
+
+
+ {/* RefreshButton - Based on the component structure but disabled */} +
+ {/* biome-ignore lint/a11y/useButtonType: */} + +
+
- - - - -
- - -
-
+
+ + {/* Cards Grid */} +
+ {Array.from({ length: 8 }).map((_, index) => ( +
+ key={index} + className="flex flex-col border border-gray-6 rounded-lg overflow-hidden" + > + {/* Chart area - 140px height */} +
+ {/* Bottom section with link, name, and stats */} +
+ {/* Name and icon row */} +
+
+
+ + + + +
+
+
+ {/* Stats row */} +
+ {/* Left side - metrics inline */} +
+
+
+
0
+
PASSED
+
+
+
+
0
+
BLOCKED
+
+
+ {/* Right side - clock */} +
+ + No data +
+
+
+
+ ))} +
- +
); } diff --git a/apps/engineering/content/design/components/form-input.mdx b/apps/engineering/content/design/components/form-input.mdx index dec8bddbf5..085c67f35f 100644 --- a/apps/engineering/content/design/components/form-input.mdx +++ b/apps/engineering/content/design/components/form-input.mdx @@ -5,6 +5,8 @@ description: A form input component with built-in label, description, and error import { DefaultFormInputVariant, RequiredFormInputVariant, + RequiredWithErrorFormInputVariant, + OptionalFormInputVariant, SuccessFormInputVariant, WarningFormInputVariant, ErrorFormInputVariant, @@ -15,9 +17,11 @@ import { } from "./form/form-input.variants" # FormInput + A comprehensive form input component that combines labels, descriptions, and validation states. Perfect for creating accessible, user-friendly forms with proper labeling and helpful context. ## Default + The default FormInput includes a label and optional description text, providing clear context for users. @@ -25,57 +29,78 @@ The default FormInput includes a label and optional description text, providing ## Input States ### Required Field -Use the required prop to indicate mandatory fields. This automatically adds an asterisk (*) to the label. + +Use the required prop to indicate mandatory fields. This automatically adds a "Required" tag to the label. +### Required Field with Error + +When a required field has an error, the "Required" tag changes to error styling to draw more attention. + + + +### Optional Field + +Use the optional prop to explicitly indicate non-mandatory fields. This adds an "Optional" tag to the label. + + + ### Success State + Indicates successful validation or acceptance of input value. The success icon and text provide positive feedback. ### Warning State + Used for potentially problematic inputs that don't prevent form submission. Includes a warning icon and explanatory text. ### Error State + Shows validation errors or other issues that need user attention. Features prominent error styling and message. ### Disabled State + Apply when the field should be non-interactive, such as during form submission or based on other field values. ### With Default Value + Pre-populated input with an initial value that users can modify. ### Read-only State + For displaying non-editable information while maintaining form layout consistency. ## Complex Usage + Example of a FormInput with multiple props configured for a specific use case. ## Props -The FormInput component extends the standard Input component props with additional form-specific properties: - - +The FormInput component extends the standard Input component props with additional form-specific properties: + ## Accessibility + FormInput is built with accessibility in mind: + - Labels are properly associated with inputs using htmlFor/id - Error messages are announced to screen readers using role="alert" - Required fields are marked both visually and via aria-required @@ -83,7 +108,9 @@ FormInput is built with accessibility in mind: - Error states are indicated using aria-invalid ## Best Practices + When using the FormInput component: + - Always provide clear, concise labels - Use description text to provide additional context when needed - Keep error messages specific and actionable @@ -96,6 +123,8 @@ When using the FormInput component: - Test with screen readers to ensure accessibility ## Layout Guidelines + - Labels should be clear and concise - Error messages should appear immediately below the input - Description text should be helpful but not too lengthy +- Consider using the optional tag for clarity in forms with many fields diff --git a/apps/engineering/content/design/components/form-textarea.mdx b/apps/engineering/content/design/components/form-textarea.mdx new file mode 100644 index 0000000000..d9916e4488 --- /dev/null +++ b/apps/engineering/content/design/components/form-textarea.mdx @@ -0,0 +1,130 @@ +--- +title: FormTextarea +description: A form textarea component with built-in label, description, and error handling capabilities. +--- +import { + DefaultFormTextareaVariant, + RequiredFormTextareaVariant, + RequiredWithErrorFormTextareaVariant, + OptionalFormTextareaVariant, + SuccessFormTextareaVariant, + WarningFormTextareaVariant, + ErrorFormTextareaVariant, + DisabledFormTextareaVariant, + DefaultValueFormTextareaVariant, + ReadonlyFormTextareaVariant, + ComplexFormTextareaVariant +} from "./form/form-textarea.variants" + +# FormTextarea + +A comprehensive multi-line text input component that combines labels, descriptions, and validation states. Perfect for creating accessible, user-friendly forms that require longer text inputs with proper labeling and helpful context. + +## Default + +The default FormTextarea includes a label and optional description text, providing clear context for users. + + + +## Textarea States + +### Required Field + +Use the required prop to indicate mandatory fields. This automatically adds a "Required" tag to the label. + + + +### Required Field with Error + +When a required field has an error, the "Required" tag changes to error styling to draw more attention. + + + +### Optional Field + +Use the optional prop to explicitly indicate non-mandatory fields. This adds an "Optional" badge to the label. + + + +### Success State + +Indicates successful validation or acceptance of input value. The success icon and text provide positive feedback. + + + +### Warning State + +Used for potentially problematic inputs that don't prevent form submission. Includes a warning icon and explanatory text. + + + +### Error State + +Shows validation errors or other issues that need user attention. Features prominent error styling and message. + + + +### Disabled State + +Apply when the field should be non-interactive, such as during form submission or based on other field values. + + + +### With Default Value + +Pre-populated textarea with an initial value that users can modify. + + + +### Read-only State + +For displaying non-editable information while maintaining form layout consistency. + + + +## Complex Usage + +Example of a FormTextarea with multiple props configured for a specific use case. + + + +## Props + +The FormTextarea component extends the standard Textarea component props with additional form-specific properties: + + + +## Accessibility + +FormTextarea is built with accessibility in mind: + +- Labels are properly associated with textareas using htmlFor/id +- Error messages are announced to screen readers using role="alert" +- Required fields are marked both visually and via aria-required +- Helper text is linked to textareas using aria-describedby +- Error states are indicated using aria-invalid + +## Best Practices + +When using the FormTextarea component: + +- Always provide clear, concise labels +- Use description text to provide additional context when needed +- Keep error messages specific and actionable +- Use required fields sparingly and logically +- Group related form elements using fieldset and legend when appropriate +- Consider the mobile experience when writing labels and descriptions +- Maintain consistent validation patterns across your form +- Consider character/word limits for lengthy inputs +- Use the rows attribute to set an appropriate initial height +- Test with screen readers to ensure accessibility + +## Layout Guidelines + +- Labels should be clear and concise +- Error messages should appear immediately below the textarea +- Description text should be helpful but not too lengthy +- Consider using the optional badge for clarity in forms with many fields diff --git a/apps/engineering/content/design/components/form/form-input.variants.tsx b/apps/engineering/content/design/components/form/form-input.variants.tsx index 2c5aec329e..78085b375f 100644 --- a/apps/engineering/content/design/components/form/form-input.variants.tsx +++ b/apps/engineering/content/design/components/form/form-input.variants.tsx @@ -27,6 +27,34 @@ export const RequiredFormInputVariant = () => { ); }; +// Required field with error variant +export const RequiredWithErrorFormInputVariant = () => { + return ( + + + + ); +}; + +// Optional field variant +export const OptionalFormInputVariant = () => { + return ( + + + + ); +}; + // Success variant export const SuccessFormInputVariant = () => { return ( diff --git a/apps/engineering/content/design/components/form/form-textarea.variants.tsx b/apps/engineering/content/design/components/form/form-textarea.variants.tsx new file mode 100644 index 0000000000..9a2d799858 --- /dev/null +++ b/apps/engineering/content/design/components/form/form-textarea.variants.tsx @@ -0,0 +1,159 @@ +import { RenderComponentWithSnippet } from "@/app/components/render"; +import { FormTextarea } from "@unkey/ui"; + +export const DefaultFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Required field variant +export const RequiredFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Required field with error variant +export const RequiredWithErrorFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Optional field variant +export const OptionalFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Success variant +export const SuccessFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Warning variant +export const WarningFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Error variant +export const ErrorFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Disabled variant +export const DisabledFormTextareaVariant = () => { + return ( + + + + ); +}; + +// With default value +export const DefaultValueFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Readonly variant +export const ReadonlyFormTextareaVariant = () => { + return ( + + + + ); +}; + +// Complex example with multiple props +export const ComplexFormTextareaVariant = () => { + return ( + + + + ); +}; diff --git a/apps/engineering/content/design/components/textarea.mdx b/apps/engineering/content/design/components/textarea.mdx new file mode 100644 index 0000000000..9230ce974f --- /dev/null +++ b/apps/engineering/content/design/components/textarea.mdx @@ -0,0 +1,93 @@ +--- +title: Textarea +description: A multi-line text input component with different states, validations, and icon support. +--- +import { RenderComponentWithSnippet } from "@/app/components/render" +import { + TextareaDefaultVariant, + TextareaSuccessVariant, + TextareaWarningVariant, + TextareaErrorVariant, + TextareaDisabledVariant, + TextareaWithDefaultValue, + TextareaWithCharacterCount, + TextareaWithBothIcons +} from "./textarea/textarea.variants.tsx" + +# Textarea + +A versatile multi-line text input component that supports various states, validations, and icon placements. Use it to collect longer user input with appropriate visual feedback and enhanced usability through icons. + +## Default + +The default textarea style with neutral colors. Can include optional icons for better visual context. + + + +## States + +Textarea components can reflect different states through visual styling: + +### Success State + +Use the success state to indicate valid input or successful validation. The checkmark icon provides immediate visual feedback. + + + +### Warning State + +The warning state can be used to show potential issues that don't prevent form submission. The alert icon draws attention to the warning state. + + + +### Error State + +Use the error state to indicate invalid input that needs correction. The alert icon emphasizes the error state. + + + +### Disabled State + +Use the disabled state when user interaction should be prevented, such as during form submission or when the input depends on other conditions. + + + +### With Default Value State + +Textarea pre-populated with an initial value that users can modify or build upon. + + + +## Interactive Elements + +### Character Count + +Example of a textarea with character count functionality to help users stay within length limits. + + + +### Textarea with Icons + +Example of a textarea with both leading and trailing icons for enhanced functionality. + + + +## Props + +The Textarea component accepts all standard HTML textarea attributes plus the following: + + + +## Icon Guidelines + +When using icons with the Textarea component: + +- Icons should be sized appropriately (recommended: 16x16px using `h-4 w-4` classes) +- Icons inherit colors based on the textarea's variant state +- Interactive icons should be wrapped in buttons +- Avoid using too many icons which might clutter the interface +- Left icons are typically used for input type indication (notes, description, etc.) +- Right icons are commonly used for interactive elements (expand/collapse, character count toggle, etc.) diff --git a/apps/engineering/content/design/components/textarea/textarea.variants.tsx b/apps/engineering/content/design/components/textarea/textarea.variants.tsx new file mode 100644 index 0000000000..d31e1c5340 --- /dev/null +++ b/apps/engineering/content/design/components/textarea/textarea.variants.tsx @@ -0,0 +1,86 @@ +"use client"; +import { RenderComponentWithSnippet } from "@/app/components/render"; +import { InputSearch } from "@unkey/icons"; +import { Textarea } from "@unkey/ui"; +import { useState } from "react"; + +export const TextareaDefaultVariant = () => { + return ( + +