Commit 04c06f22 by Jack Westbrook Committed by GitHub

Grafana/ui: pass html attributes to segment (#28316)

* feat(grafana-ui): introduce rest props to segment components

* docs(grafana-ui): add segment stories for html attributes
parent 5bc6c447
......@@ -131,3 +131,21 @@ export const CustomLabelField = () => {
</SegmentFrame>
);
};
export const HtmlAttributes = () => {
const [value, setValue] = useState<any>(options[0]);
return (
<SegmentFrame options={options}>
<Segment
data-testid="segment-test"
id="segment-id"
value={value}
options={groupedOptions}
onChange={({ value }) => {
setValue(value);
action('Segment value changed')(value);
}}
/>
</SegmentFrame>
);
};
import React from 'react';
import React, { HTMLProps } from 'react';
import { cx } from 'emotion';
import _ from 'lodash';
import { SelectableValue } from '@grafana/data';
import { SegmentSelect, useExpandableLabel, SegmentProps } from './';
export interface SegmentSyncProps<T> extends SegmentProps<T> {
export interface SegmentSyncProps<T> extends SegmentProps<T>, Omit<HTMLProps<HTMLDivElement>, 'value' | 'onChange'> {
value?: T | SelectableValue<T>;
onChange: (item: SelectableValue<T>) => void;
options: Array<SelectableValue<T>>;
......@@ -18,6 +18,7 @@ export function Segment<T>({
className,
allowCustomValue,
placeholder,
...rest
}: React.PropsWithChildren<SegmentSyncProps<T>>) {
const [Label, width, expanded, setExpanded] = useExpandableLabel(false);
......@@ -38,6 +39,7 @@ export function Segment<T>({
return (
<SegmentSelect
{...rest}
value={value && !_.isObject(value) ? { value } : value}
options={options}
width={width}
......
......@@ -123,3 +123,21 @@ export const CustomLabel = () => {
</SegmentFrame>
);
};
export const HtmlAttributes = () => {
const [value, setValue] = useState<any>(options[0]);
return (
<SegmentFrame loadOptions={() => loadOptions(options)}>
<SegmentAsync
data-testid="segment-async-test"
id="segment-async"
value={value}
loadOptions={() => loadOptions(options)}
onChange={item => {
setValue(item);
action('Segment value changed')(item.value);
}}
/>
</SegmentFrame>
);
};
import React from 'react';
import React, { HTMLProps } from 'react';
import { cx } from 'emotion';
import _ from 'lodash';
import { SegmentSelect } from './SegmentSelect';
......@@ -7,7 +7,7 @@ import { useExpandableLabel, SegmentProps } from '.';
import { useAsyncFn } from 'react-use';
import { AsyncState } from 'react-use/lib/useAsync';
export interface SegmentAsyncProps<T> extends SegmentProps<T> {
export interface SegmentAsyncProps<T> extends SegmentProps<T>, Omit<HTMLProps<HTMLDivElement>, 'value' | 'onChange'> {
value?: T | SelectableValue<T>;
loadOptions: (query?: string) => Promise<Array<SelectableValue<T>>>;
onChange: (item: SelectableValue<T>) => void;
......@@ -21,6 +21,7 @@ export function SegmentAsync<T>({
className,
allowCustomValue,
placeholder,
...rest
}: React.PropsWithChildren<SegmentAsyncProps<T>>) {
const [state, fetchOptions] = useAsyncFn(loadOptions, [loadOptions]);
const [Label, width, expanded, setExpanded] = useExpandableLabel(false);
......@@ -43,6 +44,7 @@ export function SegmentAsync<T>({
return (
<SegmentSelect
{...rest}
value={value && !_.isObject(value) ? { value } : value}
options={state.value ?? []}
width={width}
......
......@@ -49,6 +49,23 @@ export const BasicInputWithPlaceholder = () => {
);
};
export const BasicInputWithHtmlAttributes = () => {
const [value, setValue] = useState('some text');
return (
<SegmentFrame>
<SegmentInput
data-testid="segment-input-test"
id="segment-input"
value={value}
onChange={text => {
setValue(text as string);
action('Segment value changed')(text);
}}
/>
</SegmentFrame>
);
};
const InputComponent = ({ initialValue }: any) => {
const [value, setValue] = useState(initialValue);
return (
......
import React, { useRef, useState } from 'react';
import React, { HTMLProps, useRef, useState } from 'react';
import { cx, css } from 'emotion';
import useClickAway from 'react-use/lib/useClickAway';
import { measureText } from '../../utils/measureText';
import { useExpandableLabel, SegmentProps } from '.';
export interface SegmentInputProps<T> extends SegmentProps<T> {
export interface SegmentInputProps<T> extends SegmentProps<T>, Omit<HTMLProps<HTMLInputElement>, 'value' | 'onChange'> {
value: string | number;
onChange: (text: string | number) => void;
autofocus?: boolean;
......@@ -19,6 +19,7 @@ export function SegmentInput<T>({
className,
placeholder,
autofocus = false,
...rest
}: React.PropsWithChildren<SegmentInputProps<T>>) {
const ref = useRef<HTMLInputElement>(null);
const [value, setValue] = useState<number | string>(initialValue);
......@@ -50,6 +51,7 @@ export function SegmentInput<T>({
return (
<input
{...rest}
ref={ref}
autoFocus
className={cx(`gf-form gf-form-input`, inputWidthStyle)}
......
import React, { useRef } from 'react';
import React, { HTMLProps, useRef } from 'react';
import { css, cx } from 'emotion';
import useClickAway from 'react-use/lib/useClickAway';
import { SelectableValue } from '@grafana/data';
import { Select } from '../Forms/Legacy/Select/Select';
export interface Props<T> {
export interface Props<T> extends Omit<HTMLProps<HTMLDivElement>, 'value' | 'onChange'> {
value?: SelectableValue<T>;
options: Array<SelectableValue<T>>;
onChange: (item: SelectableValue<T>) => void;
......@@ -22,6 +22,7 @@ export function SegmentSelect<T>({
width,
noOptionsMessage = '',
allowCustomValue = false,
...rest
}: React.PropsWithChildren<Props<T>>) {
const ref = useRef<HTMLDivElement>(null);
......@@ -39,7 +40,7 @@ export function SegmentSelect<T>({
});
return (
<div ref={ref}>
<div {...rest} ref={ref}>
<Select
className={cx(
css`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment