NestedFolders: Add invalid state to NestedFolderPicker (#72175)

* chore: add invalid state to NestedFolderPicker

* NestedFolderPicker: pass invalid state to trigger

* fix: remove redundant sharedInputStyle
This commit is contained in:
Karol Stawowski 2023-07-26 12:47:58 +02:00 committed by GitHub
parent 7a97bf7f15
commit 600b930c47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 6 deletions

View File

@ -31,6 +31,9 @@ export interface NestedFolderPickerProps {
/* Folder UID to show as selected */
value?: string;
/** Show an invalid state around the folder picker */
invalid?: boolean;
/* Whether to show the root 'Dashboards' (formally General) folder as selectable */
showRootFolder?: boolean;
@ -43,7 +46,13 @@ export interface NestedFolderPickerProps {
const EXCLUDED_KINDS = ['empty-folder' as const, 'dashboard' as const];
export function NestedFolderPicker({ value, showRootFolder = true, excludeUIDs, onChange }: NestedFolderPickerProps) {
export function NestedFolderPicker({
value,
invalid,
showRootFolder = true,
excludeUIDs,
onChange,
}: NestedFolderPickerProps) {
const styles = useStyles2(getStyles);
const dispatch = useDispatch();
const selectedFolder = useGetFolderQuery(value || skipToken);
@ -212,6 +221,7 @@ export function NestedFolderPicker({ value, showRootFolder = true, excludeUIDs,
return (
<Trigger
label={label}
invalid={invalid}
isLoading={selectedFolder.isLoading}
autoFocus={autoFocusButton}
ref={setTriggerRef}
@ -234,6 +244,7 @@ export function NestedFolderPicker({ value, showRootFolder = true, excludeUIDs,
prefix={label ? <Icon name="folder" /> : null}
placeholder={label ?? t('browse-dashboards.folder-picker.search-placeholder', 'Search folders')}
value={search}
invalid={invalid}
className={styles.search}
onKeyDown={handleKeyDown}
onChange={(e) => setSearch(e.currentTarget.value)}

View File

@ -3,18 +3,20 @@ import React, { forwardRef, ReactNode, ButtonHTMLAttributes } from 'react';
import Skeleton from 'react-loading-skeleton';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, Icon, getInputStyles } from '@grafana/ui';
import { Icon, getInputStyles, useTheme2 } from '@grafana/ui';
import { focusCss } from '@grafana/ui/src/themes/mixins';
import { Text } from '@grafana/ui/src/unstable';
import { Trans } from 'app/core/internationalization';
interface TriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
isLoading: boolean;
invalid?: boolean;
label?: ReactNode;
}
function Trigger({ isLoading, label, ...rest }: TriggerProps, ref: React.ForwardedRef<HTMLButtonElement>) {
const styles = useStyles2(getStyles);
function Trigger({ isLoading, invalid, label, ...rest }: TriggerProps, ref: React.ForwardedRef<HTMLButtonElement>) {
const theme = useTheme2();
const styles = getStyles(theme, invalid);
return (
<div className={styles.wrapper}>
@ -52,8 +54,8 @@ function Trigger({ isLoading, label, ...rest }: TriggerProps, ref: React.Forward
export default forwardRef(Trigger);
const getStyles = (theme: GrafanaTheme2) => {
const baseStyles = getInputStyles({ theme });
const getStyles = (theme: GrafanaTheme2, invalid = false) => {
const baseStyles = getInputStyles({ theme, invalid });
return {
wrapper: baseStyles.wrapper,