@splunk/react-ui 5.8.0 → 5.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Anchor.js +2 -1
- package/ButtonSimple.js +1 -1
- package/CHANGELOG.md +38 -0
- package/Calendar.js +134 -134
- package/Clickable.js +131 -94
- package/Code.js +177 -170
- package/CollapsiblePanel.js +173 -135
- package/ColumnLayout.js +69 -45
- package/ComboBox.js +1 -0
- package/Dropdown.js +87 -72
- package/File.js +35 -35
- package/LICENSE +1 -1
- package/MIGRATION.md +40 -0
- package/Markdown.js +331 -306
- package/Menu.js +259 -215
- package/Modal.js +174 -181
- package/Monogram.js +2 -2
- package/Multiselect.js +414 -334
- package/Number.js +237 -242
- package/Search.js +15 -14
- package/SelectBase.js +777 -719
- package/SimpleTable.d.ts +2 -0
- package/SimpleTable.js +433 -0
- package/SlidingPanels.js +224 -153
- package/SpotLight.d.ts +2 -0
- package/SpotLight.js +687 -0
- package/Table.js +1232 -1238
- package/Text.js +26 -26
- package/docker-compose.yml +12 -18
- package/docs-llm/Avatar.md +2 -8
- package/docs-llm/Collapsible Panel.md +11 -57
- package/docs-llm/Column Layout.md +2 -2
- package/docs-llm/Divider.md +33 -0
- package/docs-llm/Message Bar.md +4 -1
- package/docs-llm/Multiselect.md +185 -162
- package/docs-llm/Notifications.md +46 -0
- package/docs-llm/Table.md +7 -7
- package/docs-llm/Tree.md +7 -2
- package/docs-llm/Typography.md +1 -1
- package/docs-llm/llms.txt +7 -3
- package/package.json +9 -11
- package/test-runner-jest.config.js +4 -53
- package/types/src/CollapsiblePanel/docs/examples/Actions.d.ts +1 -1
- package/types/src/ColumnLayout/ColumnLayout.d.ts +2 -2
- package/types/src/Divider/docs/examples/VerticalWithAlignItems.d.ts +8 -0
- package/types/src/Markdown/Markdown.d.ts +14 -2
- package/types/src/Markdown/renderers/MarkdownTable.d.ts +2 -22
- package/types/src/Markdown/renderers/MarkdownWrapper.d.ts +11 -0
- package/types/src/Markdown/renderers/index.d.ts +3 -1
- package/types/src/Multiselect/Compact.d.ts +12 -3
- package/types/src/Multiselect/Multiselect.d.ts +12 -3
- package/types/src/Multiselect/Normal.d.ts +8 -3
- package/types/src/Multiselect/Option.d.ts +6 -3
- package/types/src/Multiselect/docs/examples/Disabled.d.ts +1 -0
- package/types/src/Multiselect/docs/examples/LoadMoreWithSelectAll.d.ts +9 -0
- package/types/src/SelectBase/SelectBase.d.ts +5 -1
- package/types/src/SimpleTable/Body.d.ts +25 -0
- package/types/src/SimpleTable/Cell.d.ts +20 -0
- package/types/src/SimpleTable/Head.d.ts +20 -0
- package/types/src/SimpleTable/HeadCell.d.ts +20 -0
- package/types/src/SimpleTable/Row.d.ts +20 -0
- package/types/src/SimpleTable/SimpleTable.d.ts +37 -0
- package/types/src/SimpleTable/index.d.ts +3 -0
- package/types/src/SpotLight/SpotLight.d.ts +88 -0
- package/types/src/SpotLight/index.d.ts +2 -0
- package/types/src/Table/Row.d.ts +1 -1
- package/types/src/Table/Table.d.ts +1 -1
- package/types/src/Typography/Typography.d.ts +1 -1
- package/types/src/Multiselect/docs/examples/LoadMoreOnScrollBottom.d.ts +0 -7
package/docs-llm/Multiselect.md
CHANGED
|
@@ -229,6 +229,8 @@ function NewValues() {
|
|
|
229
229
|
'Line Chart',
|
|
230
230
|
'Map',
|
|
231
231
|
'Table',
|
|
232
|
+
'Bar chart',
|
|
233
|
+
'Bubble chart',
|
|
232
234
|
]);
|
|
233
235
|
|
|
234
236
|
const handleChange: MultiselectChangeHandler = useCallback((e, { values }) => {
|
|
@@ -324,6 +326,8 @@ export default MultiselectError;
|
|
|
324
326
|
|
|
325
327
|
### Disabled
|
|
326
328
|
|
|
329
|
+
If you absolutely need to disable a `Multiselect` use `"disabled="dimmed"`. This ensures the `Multiselect` does not respond to events, but can still receive focus to so that users can navigate to the `Multiselect` when using assistive technologies.
|
|
330
|
+
|
|
327
331
|
```typescript
|
|
328
332
|
import React, { useCallback, useState } from 'react';
|
|
329
333
|
|
|
@@ -338,7 +342,7 @@ function Disabled() {
|
|
|
338
342
|
}, []);
|
|
339
343
|
|
|
340
344
|
return (
|
|
341
|
-
<Multiselect values={selectedValues} onChange={handleChange} disabled inline>
|
|
345
|
+
<Multiselect values={selectedValues} onChange={handleChange} disabled="dimmed" inline>
|
|
342
346
|
<Multiselect.Option label="Area chart" value="1" />
|
|
343
347
|
<Multiselect.Option label="Bar chart" value="2" />
|
|
344
348
|
<Multiselect.Option label="Bubble chart" value="3" />
|
|
@@ -613,163 +617,6 @@ export default Fetching;
|
|
|
613
617
|
|
|
614
618
|
|
|
615
619
|
|
|
616
|
-
### Load more on scroll bottom
|
|
617
|
-
|
|
618
|
-
Similar example as fetching but it's also possible to append more Options from a server when the list is scrolled to the bottom. Here, that behavior is simulated. The onScrollBottom prop is a function that should fetch more results and append them to the current Options. Once all items are loaded, the onScrollBottom prop should be set to null.
|
|
619
|
-
|
|
620
|
-
```typescript
|
|
621
|
-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
622
|
-
|
|
623
|
-
import useFetchOptions, {
|
|
624
|
-
isMovieOption,
|
|
625
|
-
Movie,
|
|
626
|
-
MovieOption,
|
|
627
|
-
} from '@splunk/react-ui/fixtures/useFetchOptions';
|
|
628
|
-
import Multiselect, {
|
|
629
|
-
MultiselectChangeHandler,
|
|
630
|
-
MultiselectFilterChangeHandler,
|
|
631
|
-
} from '@splunk/react-ui/Multiselect';
|
|
632
|
-
import { _ } from '@splunk/ui-utils/i18n';
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
function LoadMoreOnScrollBottom() {
|
|
636
|
-
const [fullCount, setFullCount] = useState(0);
|
|
637
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
638
|
-
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
639
|
-
const [options, setOptions] = useState<MovieOption[]>([]);
|
|
640
|
-
const [selectedValues, setSelectedValues] = useState<(string | number | boolean)[]>([10, 30]);
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
const { fetch, fetchMore, getFullCount, getSelectedOptions, stop } = useFetchOptions();
|
|
644
|
-
|
|
645
|
-
const handleFetch = useCallback(
|
|
646
|
-
(keyword?: string) => {
|
|
647
|
-
setIsLoading(true);
|
|
648
|
-
|
|
649
|
-
fetch(keyword)
|
|
650
|
-
.then((fetchedOptions) => {
|
|
651
|
-
setIsLoading(false);
|
|
652
|
-
setOptions(fetchedOptions);
|
|
653
|
-
setFullCount(getFullCount());
|
|
654
|
-
})
|
|
655
|
-
.catch((error) => {
|
|
656
|
-
if (!error.isCanceled) throw error;
|
|
657
|
-
});
|
|
658
|
-
},
|
|
659
|
-
[fetch, getFullCount]
|
|
660
|
-
);
|
|
661
|
-
|
|
662
|
-
const handleChange: MultiselectChangeHandler = useCallback(
|
|
663
|
-
(e, { values }) => {
|
|
664
|
-
setSelectedValues(values);
|
|
665
|
-
handleFetch();
|
|
666
|
-
},
|
|
667
|
-
[handleFetch]
|
|
668
|
-
);
|
|
669
|
-
|
|
670
|
-
const handleFetchMore = useCallback(
|
|
671
|
-
(currentOptions: MovieOption[]) => {
|
|
672
|
-
setIsLoadingMore(true);
|
|
673
|
-
|
|
674
|
-
fetchMore(currentOptions)
|
|
675
|
-
.then((fetchedOptions) => {
|
|
676
|
-
setOptions(fetchedOptions);
|
|
677
|
-
setIsLoading(false);
|
|
678
|
-
setIsLoadingMore(false);
|
|
679
|
-
setFullCount(getFullCount());
|
|
680
|
-
})
|
|
681
|
-
.catch((error) => {
|
|
682
|
-
if (!error.isCanceled) {
|
|
683
|
-
throw error;
|
|
684
|
-
}
|
|
685
|
-
});
|
|
686
|
-
},
|
|
687
|
-
[fetchMore, getFullCount]
|
|
688
|
-
);
|
|
689
|
-
|
|
690
|
-
const handleFilterChange: MultiselectFilterChangeHandler = useCallback(
|
|
691
|
-
(e, { keyword }) => {
|
|
692
|
-
handleFetch(keyword);
|
|
693
|
-
},
|
|
694
|
-
[handleFetch]
|
|
695
|
-
);
|
|
696
|
-
|
|
697
|
-
const handleScrollBottom = useCallback(() => {
|
|
698
|
-
if (!isLoadingMore) {
|
|
699
|
-
handleFetchMore(options);
|
|
700
|
-
}
|
|
701
|
-
}, [handleFetchMore, isLoadingMore, options]);
|
|
702
|
-
|
|
703
|
-
useEffect(() => {
|
|
704
|
-
handleFetch();
|
|
705
|
-
|
|
706
|
-
return () => {
|
|
707
|
-
stop();
|
|
708
|
-
};
|
|
709
|
-
}, [handleFetch, stop]);
|
|
710
|
-
|
|
711
|
-
const createOption = useCallback(
|
|
712
|
-
(movie: Movie | MovieOption, isSelected = false) => (
|
|
713
|
-
|
|
714
|
-
<Multiselect.Option
|
|
715
|
-
hidden={isSelected}
|
|
716
|
-
key={isSelected ? `selected-${movie.id}` : movie.id}
|
|
717
|
-
label={movie.title}
|
|
718
|
-
matchRanges={isMovieOption(movie) ? movie.matchRanges : undefined}
|
|
719
|
-
value={movie.id}
|
|
720
|
-
/>
|
|
721
|
-
),
|
|
722
|
-
[]
|
|
723
|
-
);
|
|
724
|
-
|
|
725
|
-
const generateOptions = useMemo(() => {
|
|
726
|
-
// The selected items always have to be in the option list, but can be hidden
|
|
727
|
-
let selectedOptions: React.ReactElement[] = [];
|
|
728
|
-
if (selectedValues.length) {
|
|
729
|
-
const selectedMovies = getSelectedOptions(selectedValues as number[]);
|
|
730
|
-
selectedOptions = selectedMovies.map((movie) => createOption(movie, true));
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (isLoading) {
|
|
734
|
-
// Only return the select items
|
|
735
|
-
return selectedOptions;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
const list = options.map((movie) => createOption(movie));
|
|
739
|
-
return list.concat(selectedOptions);
|
|
740
|
-
}, [createOption, getSelectedOptions, isLoading, options, selectedValues]);
|
|
741
|
-
|
|
742
|
-
const footerMessage = useMemo(() => {
|
|
743
|
-
if (fullCount > options.length && !isLoading) {
|
|
744
|
-
return _('%1 of %2 movies')
|
|
745
|
-
.replace('%1', options.length.toString())
|
|
746
|
-
.replace('%2', fullCount.toString());
|
|
747
|
-
}
|
|
748
|
-
return null;
|
|
749
|
-
}, [fullCount, options.length, isLoading]);
|
|
750
|
-
|
|
751
|
-
return (
|
|
752
|
-
<Multiselect
|
|
753
|
-
values={selectedValues}
|
|
754
|
-
placeholder={_('Select a movie...')}
|
|
755
|
-
onChange={handleChange}
|
|
756
|
-
controlledFilter
|
|
757
|
-
onFilterChange={handleFilterChange}
|
|
758
|
-
onScrollBottom={fullCount === options.length ? undefined : handleScrollBottom} // Disable when all items are loaded.
|
|
759
|
-
isLoadingOptions={isLoading}
|
|
760
|
-
footerMessage={footerMessage}
|
|
761
|
-
inline
|
|
762
|
-
>
|
|
763
|
-
{generateOptions}
|
|
764
|
-
</Multiselect>
|
|
765
|
-
);
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
export default LoadMoreOnScrollBottom;
|
|
769
|
-
```
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
620
|
### data
|
|
774
621
|
|
|
775
622
|
```typescript
|
|
@@ -837,6 +684,182 @@ export default Compact;
|
|
|
837
684
|
|
|
838
685
|
|
|
839
686
|
|
|
687
|
+
### movies
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
691
|
+
|
|
692
|
+
import moviesJson from '@splunk/react-ui/fixtures/movies.json';
|
|
693
|
+
import Multiselect, {
|
|
694
|
+
MultiselectChangeHandler,
|
|
695
|
+
MultiselectFilterChangeHandler,
|
|
696
|
+
MultiselectScrollBottomHandler,
|
|
697
|
+
} from '@splunk/react-ui/Multiselect';
|
|
698
|
+
import { keywordLocations, stringToKeywords, testPhrase } from '@splunk/ui-utils/filter';
|
|
699
|
+
import { sprintf } from '@splunk/ui-utils/format';
|
|
700
|
+
import { _ } from '@splunk/ui-utils/i18n';
|
|
701
|
+
|
|
702
|
+
type Movie = {
|
|
703
|
+
id: number;
|
|
704
|
+
title: string;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
type OptionItem = {
|
|
708
|
+
hidden?: boolean;
|
|
709
|
+
label: string;
|
|
710
|
+
matchRanges?: { start: number; end: number }[];
|
|
711
|
+
value: string | number | boolean;
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
const { movies } = moviesJson as { movies: Movie[] };
|
|
715
|
+
|
|
716
|
+
const pageSize = 20;
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
function LoadMoreWithSelectAll() {
|
|
720
|
+
const [keyword, setKeyword] = useState('');
|
|
721
|
+
const [loadedCount, setLoadedCount] = useState(pageSize);
|
|
722
|
+
const [values, setValues] = useState<(string | number | boolean)[]>([]);
|
|
723
|
+
const keywords = useMemo(() => stringToKeywords(keyword), [keyword]);
|
|
724
|
+
|
|
725
|
+
const allOptions = useMemo<OptionItem[]>(() => {
|
|
726
|
+
const hasKeyword = keywords.length > 0;
|
|
727
|
+
return movies
|
|
728
|
+
.filter((movie) => !hasKeyword || testPhrase(movie.title, keywords))
|
|
729
|
+
.map((movie) => ({
|
|
730
|
+
label: movie.title,
|
|
731
|
+
matchRanges: hasKeyword
|
|
732
|
+
? keywordLocations(movie.title, keywords) || undefined
|
|
733
|
+
: undefined,
|
|
734
|
+
value: movie.id,
|
|
735
|
+
}));
|
|
736
|
+
}, [keywords]);
|
|
737
|
+
|
|
738
|
+
const visibleCount = Math.min(loadedCount, allOptions.length);
|
|
739
|
+
const loadedOptions = useMemo(
|
|
740
|
+
() => allOptions.slice(0, visibleCount),
|
|
741
|
+
[allOptions, visibleCount]
|
|
742
|
+
);
|
|
743
|
+
const allOptionValues = useMemo(() => allOptions.map((option) => option.value), [allOptions]);
|
|
744
|
+
const selectedValueSet = useMemo(() => new Set(values), [values]);
|
|
745
|
+
const movieById = useMemo(() => {
|
|
746
|
+
const map = new Map<string | number | boolean, Movie>();
|
|
747
|
+
movies.forEach((movie) => {
|
|
748
|
+
map.set(movie.id, movie);
|
|
749
|
+
});
|
|
750
|
+
return map;
|
|
751
|
+
}, []);
|
|
752
|
+
|
|
753
|
+
const options = useMemo<OptionItem[]>(() => {
|
|
754
|
+
const loadedValueSet = new Set(loadedOptions.map((option) => option.value));
|
|
755
|
+
const hiddenSelectedOptions = values
|
|
756
|
+
.filter((value) => !loadedValueSet.has(value))
|
|
757
|
+
.map((value) => movieById.get(value))
|
|
758
|
+
.filter((movie): movie is Movie => !!movie)
|
|
759
|
+
.map((movie) => ({
|
|
760
|
+
hidden: true,
|
|
761
|
+
label: movie.title,
|
|
762
|
+
matchRanges: keywordLocations(movie.title, keywords) || undefined,
|
|
763
|
+
value: movie.id,
|
|
764
|
+
}));
|
|
765
|
+
|
|
766
|
+
return [...loadedOptions, ...hiddenSelectedOptions];
|
|
767
|
+
}, [keywords, loadedOptions, movieById, values]);
|
|
768
|
+
|
|
769
|
+
const handleChange = useCallback<MultiselectChangeHandler>(
|
|
770
|
+
(_e, { values: nextValues, reason }) => {
|
|
771
|
+
if (reason === 'selectAll') {
|
|
772
|
+
setValues(allOptionValues);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
setValues(nextValues);
|
|
777
|
+
},
|
|
778
|
+
[allOptionValues]
|
|
779
|
+
);
|
|
780
|
+
|
|
781
|
+
const handleScrollBottom = useCallback<MultiselectScrollBottomHandler>(() => {
|
|
782
|
+
setLoadedCount((currentCount) => Math.min(currentCount + pageSize, allOptions.length));
|
|
783
|
+
}, [allOptions.length]);
|
|
784
|
+
|
|
785
|
+
const handleFilterChange = useCallback<MultiselectFilterChangeHandler>(
|
|
786
|
+
(_e, { keyword: nextKeyword }) => {
|
|
787
|
+
setKeyword(nextKeyword);
|
|
788
|
+
setLoadedCount(pageSize);
|
|
789
|
+
},
|
|
790
|
+
[]
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
const footerMessage = useMemo(() => {
|
|
794
|
+
const selectedInFilteredCount = allOptions.filter((option) =>
|
|
795
|
+
selectedValueSet.has(option.value)
|
|
796
|
+
).length;
|
|
797
|
+
const hasKeyword = keywords.length > 0;
|
|
798
|
+
const allLoaded = visibleCount >= allOptions.length;
|
|
799
|
+
const selectedCountDisplay = hasKeyword ? selectedInFilteredCount : values.length;
|
|
800
|
+
|
|
801
|
+
if (hasKeyword) {
|
|
802
|
+
if (allLoaded) {
|
|
803
|
+
return sprintf(_('%(selected)d selected / %(matches)d matches'), {
|
|
804
|
+
matches: allOptions.length,
|
|
805
|
+
selected: selectedCountDisplay,
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
return sprintf(_('%(selected)d selected (%(loaded)d loaded / %(matches)d matches)'), {
|
|
810
|
+
loaded: visibleCount,
|
|
811
|
+
matches: allOptions.length,
|
|
812
|
+
selected: selectedCountDisplay,
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (allLoaded) {
|
|
817
|
+
return sprintf(_('%(selected)d selected / %(total)d total'), {
|
|
818
|
+
selected: selectedCountDisplay,
|
|
819
|
+
total: allOptions.length,
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
return sprintf(_('%(selected)d selected (%(loaded)d loaded / %(total)d total)'), {
|
|
824
|
+
loaded: visibleCount,
|
|
825
|
+
selected: selectedCountDisplay,
|
|
826
|
+
total: allOptions.length,
|
|
827
|
+
});
|
|
828
|
+
}, [allOptions, keywords.length, selectedValueSet, values.length, visibleCount]);
|
|
829
|
+
|
|
830
|
+
return (
|
|
831
|
+
<Multiselect
|
|
832
|
+
compact
|
|
833
|
+
filter="controlled"
|
|
834
|
+
values={values}
|
|
835
|
+
placeholder={_('Select movies...')}
|
|
836
|
+
menuStyle={{ maxHeight: 640 }}
|
|
837
|
+
onChange={handleChange}
|
|
838
|
+
onFilterChange={handleFilterChange}
|
|
839
|
+
onScrollBottom={visibleCount < allOptions.length ? handleScrollBottom : undefined}
|
|
840
|
+
footerMessage={footerMessage}
|
|
841
|
+
selectAllAppearance="checkbox"
|
|
842
|
+
inline
|
|
843
|
+
>
|
|
844
|
+
{options.map(({ hidden, label, matchRanges, value }) => (
|
|
845
|
+
<Multiselect.Option
|
|
846
|
+
key={`${hidden ? 'selected-' : ''}${value}`}
|
|
847
|
+
// hidden options represent selected values outside the current loaded slice to avoid treating them as new values
|
|
848
|
+
hidden={hidden}
|
|
849
|
+
label={label}
|
|
850
|
+
matchRanges={matchRanges}
|
|
851
|
+
value={value}
|
|
852
|
+
/>
|
|
853
|
+
))}
|
|
854
|
+
</Multiselect>
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
export default LoadMoreWithSelectAll;
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
|
|
840
863
|
|
|
841
864
|
## API
|
|
842
865
|
|
|
@@ -856,7 +879,7 @@ export default Compact;
|
|
|
856
879
|
| defaultPlacement | 'above' \| 'below' \| 'vertical' | no | 'vertical' | The default placement of the dropdown menu. It might be rendered in a different direction depending upon the space available. |
|
|
857
880
|
| defaultValues | (string \| number \| boolean)[] | no | | Set this property instead of value to keep the value uncontrolled. |
|
|
858
881
|
| describedBy | string | no | | The id of the description. When placed in a ControlGroup, this is automatically set to the ControlGroup's help component. |
|
|
859
|
-
| disabled | boolean | no | |
|
|
882
|
+
| disabled | boolean \| 'dimmed' \| 'disabled' | no | | Prevents user interaction and adds disabled styling. If set to `dimmed`, the component is able to receive focus. If set to `disabled`, the component is unable to receive focus. |
|
|
860
883
|
| elementRef | React.Ref<HTMLButtonElement \| HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts, and null when it unmounts. |
|
|
861
884
|
| error | boolean | no | | Display as in an error. |
|
|
862
885
|
| filter | boolean \| 'controlled' | no | | Determines whether to show the filter box. When true, the children are automatically filtered based on the label. When controlled, the parent component must provide a onFilterChange callback and update the children. Only supported when `compact=true`. |
|
|
@@ -870,7 +893,7 @@ export default Compact;
|
|
|
870
893
|
| menuStyle | React.CSSProperties | no | | Style properties to apply to the Menu. This is primarily used to override the width of the menu should it need to be wider than the toggle Button. |
|
|
871
894
|
| name | string | no | | The name is returned with onChange events, which can be used to identify the control when multiple controls share an onChange callback. |
|
|
872
895
|
| noOptionsMessage | React.ReactNode | no | _('No matches') | The noOptionsMessage is shown when there are no children and it's not loading, such as when there are no Options matching the filter. This can be customized to the type of content, for example: "No matching dashboards". You can insert other content, such as an error message, or communicate a minimum number of characters to enter to see results. |
|
|
873
|
-
| onChange | MultiselectChangeHandler | no | | A callback to receive the change events. If values is set, this callback is required. This must set the values prop to retain the change. |
|
|
896
|
+
| onChange | MultiselectChangeHandler | no | | A callback to receive the change events. If values is set, this callback is required. This must set the values prop to retain the change. Supports custom selection behavior. |
|
|
874
897
|
| onClose | () => void | no | | A callback function invoked when the popover closes. |
|
|
875
898
|
| onFilterChange | MultiselectFilterChangeHandler | no | | A callback with the change event and value of the filter box. Providing this callback and setting controlledFilter to true enables you to filter and update the children by other criteria. |
|
|
876
899
|
| onOpen | () => void | no | | A callback function invoked when the popover opens. |
|
|
@@ -879,7 +902,7 @@ export default Compact;
|
|
|
879
902
|
| placeholder | string | no | _('Select...') | If 'value' is undefined or doesn't match an item, the Button will display this text. |
|
|
880
903
|
| prepend | boolean | no | | Prepend removes rounded borders from the left side. |
|
|
881
904
|
| repositionMode | 'none' \| 'flip' | no | 'flip' | See `repositionMode` on `Popover` for details. |
|
|
882
|
-
| selectAllAppearance | 'buttongroup' \| 'checkbox' \| 'none' | no | | **DEPRECATED**: Value 'buttongroup' Determines how to display Select all/Clear all. Only supported when `compact=true`. The 'buttongroup' value is deprecated and will be removed in a future major version. |
|
|
905
|
+
| selectAllAppearance | 'buttongroup' \| 'checkbox' \| 'none' | no | | **DEPRECATED**: Value 'buttongroup' Determines how to display Select all/Clear all. Only supported when `compact=true`. By default, selection applies only to currently loaded options. Use `onChange` for custom selection behavior. The 'buttongroup' value is deprecated and will be removed in a future major version. |
|
|
883
906
|
| showSelectedValuesFirst | 'nextOpen' \| 'immediately' \| 'never' | no | | When `compact=true`, move selected values to the top of the list on next open (default), immediately, or not at all. |
|
|
884
907
|
| tabConfirmsNewValue | boolean | no | | Pressing Tab while entering an input confirms the new value. Requires `allowNewValues`. |
|
|
885
908
|
| values | (string \| number \| boolean)[] | no | | Value will be matched to one of the children to deduce the label and/or icon for the toggle. |
|
|
@@ -905,7 +928,7 @@ An option within a `Multiselect`.
|
|
|
905
928
|
| children | React.ReactNode | no | | When provided, `children` is rendered instead of the `label`. Caution: The element(s) passed here must be pure. |
|
|
906
929
|
| description | string | no | | Additional information to explain the option, such as "Recommended". |
|
|
907
930
|
| descriptionPosition | 'right' \| 'bottom' | no | 'bottom' | The description text may appear to the right of the label or under the label. |
|
|
908
|
-
| disabled | boolean | no | |
|
|
931
|
+
| disabled | boolean \| 'dimmed' \| 'disabled' | no | | Prevents user interaction and adds disabled styling. If set to `dimmed`, the component is able to receive focus. If set to `disabled`, the component is unable to receive focus. |
|
|
909
932
|
| hidden | boolean | no | | Adding hidden options can be useful for resolving the selected display label and icon, when the option should not be in the list. This scenario can arise when Select's filter is controlled, because the selected item may be filtered out; and when a legacy option is valid, but should no longer be displayed as a selectable option. |
|
|
910
933
|
| icon | React.ReactNode | no | | The icon to show before the label. See the @splunk/react-icons package for drop in icons. Caution: The element(s) passed here must be pure. All icons in the react-icons package are pure. |
|
|
911
934
|
| label | string | yes | | The text to show for the option when `children` is not defined. When filtering, the `label` is used for matching to the filter text. |
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Notifications
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
# Notifications
|
|
6
|
+
|
|
7
|
+
Notifications help users understand what happened, what needs attention, and what to do next.
|
|
8
|
+
|
|
9
|
+
There are two notification components in Splunk UI:
|
|
10
|
+
- [Message](./Message) is used for inline, contextual feedback near the content it refers to.
|
|
11
|
+
- [Message Bar](./MessageBar) is used for page-level or system-level communication.
|
|
12
|
+
|
|
13
|
+
These components use standardized icons and [`notificationColors` design tokens](../themes/variables#notification-colors) to communicate consistent tone and urgency, so users can quickly understand what to expect.
|
|
14
|
+
|
|
15
|
+
## Toast Notifications (Deprecated)
|
|
16
|
+
|
|
17
|
+
Toast notifications are **deprecated** and should not be used for new experiences.
|
|
18
|
+
Even with careful implementation, this pattern still creates significant accessibility and usability barriers.
|
|
19
|
+
|
|
20
|
+
Use persistent, user-dismissible notifications instead:
|
|
21
|
+
- Use [Message](./Message) for inline, contextual feedback.
|
|
22
|
+
- Use [Message Bar](./MessageBar) for page-level or system-level communication.
|
|
23
|
+
|
|
24
|
+
### Migration Guide
|
|
25
|
+
|
|
26
|
+
Review the CRUD Blueprint sections for [Create confirmation](../../DesignSystem/Blueprints/CRUD/Create#3-confirmation), [Update confirmation](../../DesignSystem/Blueprints/CRUD/Update#3-confirmation) and [Delete feedback](../../DesignSystem/Blueprints/CRUD/Delete#3-feedback) for guidance on scenarios where the toast pattern may have previously been used.
|
|
27
|
+
|
|
28
|
+
Below are suggestions for how to migrate common scenarios:
|
|
29
|
+
|
|
30
|
+
| Current Toast Pattern | Recommended Alternative | Reason |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| Success message after form submission | Message Bar at top of page, or inline Message next to changed element | Persistent confirmation is visible to all users regardless of timing |
|
|
33
|
+
| Error feedback | Inline Message in form field, or Message Bar at top | Direct association with the error source helps users understand and fix the problem |
|
|
34
|
+
| Temporary status updates | Message Bar for page-level updates, or Message for task-level updates | Clear scope and persistent visibility ensure all users receive the information |
|
|
35
|
+
| Real-time alerts | Message Bar with optional dismiss action | Ensures users see critical information before it's dismissed |
|
|
36
|
+
|
|
37
|
+
### Further Reading
|
|
38
|
+
|
|
39
|
+
Below are additional resources to understand the issues with toast patterns:
|
|
40
|
+
|
|
41
|
+
- [GitHub Primer: Accessible Notifications and Messages](https://primer.style/accessibility/patterns/accessible-notifications-and-messages/#toasts)
|
|
42
|
+
- [Defining Toast Messages (Adrian Roselli)](https://adrianroselli.com/2020/01/defining-toast-messages.html)
|
|
43
|
+
- [A Toast to an Accessible Toast... to Notifications (Scott O'Hara)](https://www.scottohara.me/blog/2019/07/08/a-toast-to-a11y-toasts.html)
|
|
44
|
+
- [The Problem with Toast Messages and What to Do Instead (Adam Silver)](https://adamsilver.io/blog/the-problem-with-toast-messages-and-what-to-do-instead/)
|
|
45
|
+
|
|
46
|
+
|
package/docs-llm/Table.md
CHANGED
|
@@ -2452,14 +2452,14 @@ export default Complex;
|
|
|
2452
2452
|
|
|
2453
2453
|
| Name | Type | Required | Default | Description |
|
|
2454
2454
|
|------|------|------|------|------|
|
|
2455
|
-
| actions | React.ReactElement[] | no |
|
|
2455
|
+
| actions | React.ReactElement[] | no | [] | Adds table-level actions. Not compatible with `onRequestResize`. |
|
|
2456
2456
|
| actionsColumnWidth | number | no | | Specifies the width of the actions column. Adds an empty header for row actions if no table-level actions are present. |
|
|
2457
2457
|
| children | React.ReactNode | no | | Must be `Table.Head`, `Table.Body`, or `Table.Caption`. |
|
|
2458
|
-
| dockOffset | number | no |
|
|
2458
|
+
| dockOffset | number | no | 0 | Sets the offset from the top of the window. Only applies when `headType` is 'docked'. |
|
|
2459
2459
|
| dockScrollBar | boolean | no | | Docks the horizontal scroll bar at the bottom of the window when the bottom of the table is below the viewport. |
|
|
2460
2460
|
| elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
|
|
2461
|
-
| headType | 'docked' \| 'fixed' \| 'inline' | no |
|
|
2462
|
-
| horizontalOverflow | 'auto' \| 'scroll' | no |
|
|
2461
|
+
| headType | 'docked' \| 'fixed' \| 'inline' | no | 'inline' | Sets the table head type: * `docked`: The head is docked against the window * `fixed` : The head is fixed in the table. The table can scroll independently from the head. * `inline`: The head isn't fixed, but can scroll with the rest of the table. |
|
|
2462
|
+
| horizontalOverflow | 'auto' \| 'scroll' | no | 'auto' | Controls how the Table handles horizontal content overflow: * `auto`: The default behavior for overflow. `HeadCell` content will truncate and `Cell` content will wrap. The Table will scroll horizontally when the container's width exceeds the Table's width. * `scroll`: The Table will scroll horizontally. `HeadCell` content will not truncate and `Cell` content will wrap only for word breaks. |
|
|
2463
2463
|
| innerStyle | React.CSSProperties | no | | Style specification for the inner container, which is the scrolling container. |
|
|
2464
2464
|
| onRequestMoveColumn | TableRequestMoveColumnHandler | no | | An event handler for handle the re-order action of Table. The function is passed an options object with `fromIndex` and `toIndex`. |
|
|
2465
2465
|
| onRequestMoveRow | TableRequestMoveRowHandler | no | | An event handler to handle the reorder rows action of Table. The function is passed an options object with `fromIndex` and `toIndex`. |
|
|
@@ -2468,10 +2468,10 @@ export default Complex;
|
|
|
2468
2468
|
| onScroll | React.UIEventHandler<HTMLDivElement> | no | | Callback invoked when a scroll event occurs on the inner scrolling container. |
|
|
2469
2469
|
| outerStyle | React.CSSProperties | no | | Style specification for the outer container. |
|
|
2470
2470
|
| pinnedColumns | PinnedColumnsProp | no | | Optionally pin the actions column to the end of the table by passing `pinnedColumns={{ actions: true }}.` When using pinned columns `horizontalOverflow` should be set to `scroll`. |
|
|
2471
|
-
| primaryColumnIndex | number | no |
|
|
2471
|
+
| primaryColumnIndex | number | no | 0 | Indicates the column to use as the primary label for each row. |
|
|
2472
2472
|
| resizableFillLayout | boolean | no | | Table will fill parent container. Resizable columns can have a `width` of `auto` only with this prop enabled. |
|
|
2473
|
-
| rowExpansion | 'single' \| 'multi' \| 'controlled' \| 'none' | no |
|
|
2474
|
-
| rowSelection | 'all' \| 'some' \| 'none' | no |
|
|
2473
|
+
| rowExpansion | 'single' \| 'multi' \| 'controlled' \| 'none' | no | 'none' | Adds a column to the table with an expansion button for each row that has expansion content. Supported values: * `single`: Only one row can be expanded at a time. If another expansion button is clicked, the currently expanded row closes and the new one opens. * `multi`: Allows multiple rows to be expanded at the same time. * `controlled`: Allows the expanded state to be externally managed by `expanded` prop of `Row`. * `none`: The default with no row expansion. |
|
|
2474
|
+
| rowSelection | 'all' \| 'some' \| 'none' | no | 'none' | When an `onRequestToggleAllRows` handler is defined, this prop determines the appearance of the toggle all rows button. |
|
|
2475
2475
|
| stripeRows | boolean | no | | Alternate rows are given a darker background to improve readability. |
|
|
2476
2476
|
| tableStyle | React.CSSProperties | no | | The style attribute for the table. This is primarily useful for setting the CSS table-layout property. |
|
|
2477
2477
|
|
package/docs-llm/Tree.md
CHANGED
|
@@ -163,8 +163,10 @@ import { variables } from '@splunk/themes';
|
|
|
163
163
|
|
|
164
164
|
const StyledExpansionToggleWrapper = styled.span`
|
|
165
165
|
display: inline-flex;
|
|
166
|
-
padding-inline-end: ${variables.spacingSmall};
|
|
167
166
|
width: 16px;
|
|
167
|
+
justify-content: center;
|
|
168
|
+
align-items: center;
|
|
169
|
+
padding-inline: ${variables.spacingMedium};
|
|
168
170
|
`;
|
|
169
171
|
const StyledSpan = styled.span`
|
|
170
172
|
display: inline-flex;
|
|
@@ -314,9 +316,12 @@ import { variables } from '@splunk/themes';
|
|
|
314
316
|
const StyledExpansionToggleWrapper = styled.span`
|
|
315
317
|
display: inline-flex;
|
|
316
318
|
width: 16px;
|
|
319
|
+
justify-content: center;
|
|
320
|
+
align-items: center;
|
|
321
|
+
padding-inline: ${variables.spacingMedium};
|
|
317
322
|
`;
|
|
318
323
|
const StyledCheckbox = styled(Checkbox)`
|
|
319
|
-
padding-inline: ${variables.spacingSmall};
|
|
324
|
+
padding-inline-end: ${variables.spacingSmall};
|
|
320
325
|
`;
|
|
321
326
|
const StyledSpan = styled.span`
|
|
322
327
|
align-items: center;
|
package/docs-llm/Typography.md
CHANGED
|
@@ -68,7 +68,7 @@ Typography renders text content with styling based on the Splunk Design System.
|
|
|
68
68
|
|
|
69
69
|
| Name | Type | Required | Default | Description |
|
|
70
70
|
|------|------|------|------|------|
|
|
71
|
-
| as | \| 'p' \| 'h1' \| 'h2' \| 'h3' \| 'h4' \| 'h5' \| 'h6' \| 'span' \| 'blockquote' \| 'dd' \| 'dl' \| 'dt' \| 'figcaption' \| 'figure' \| 'li' \| 'ol' \| 'ul' \| 'pre' \| 'abbr' \| 'cite' \| 'code' \| 'data' \| 'dfn' \| 'em' \| 'u' \| 'time' \| 'sup' \| 'sub' \| 'strong' \| 'small' \| 'samp' \| 's' \| 'var' \| 'ruby' \| 'rt' \| 'rp' | yes | | Tag for the element to render children content into. Use the most semantically appropriate tag. Layout elements like `div` are not allowed; use the `typography` mixin from `@splunk/themes` instead. |
|
|
71
|
+
| as | \| 'p' \| 'h1' \| 'h2' \| 'h3' \| 'h4' \| 'h5' \| 'h6' \| 'span' \| 'blockquote' \| 'dd' \| 'dl' \| 'dt' \| 'figcaption' \| 'figure' \| 'li' \| 'ol' \| 'ul' \| 'pre' \| 'abbr' \| 'cite' \| 'code' \| 'data' \| 'dfn' \| 'em' \| 'label' \| 'u' \| 'time' \| 'sup' \| 'sub' \| 'strong' \| 'small' \| 'samp' \| 's' \| 'var' \| 'ruby' \| 'rt' \| 'rp' | yes | | Tag for the element to render children content into. Use the most semantically appropriate tag. Layout elements like `div` are not allowed; use the `typography` mixin from `@splunk/themes` instead. |
|
|
72
72
|
| children | React.ReactNode | yes | | Text and inline icons |
|
|
73
73
|
| color | 'active' \| 'default' \| 'disabled' \| 'inverted' \| 'muted' \| 'inherit' | no | | Set the color to a system-standard color: e.g. `active` for `@splunk/themes/variables.contentColorActive`. |
|
|
74
74
|
| elementRef | React.Ref<HTMLElement> | no | | A React ref which is set to the DOM element when the component mounts, and null when it unmounts. |
|
package/docs-llm/llms.txt
CHANGED
|
@@ -17,8 +17,6 @@ A library of UI components, all independent of the Splunk Enterprise environment
|
|
|
17
17
|
- **JSON Tree**
|
|
18
18
|
- **Link**
|
|
19
19
|
- **Markdown**
|
|
20
|
-
- **Message**
|
|
21
|
-
- **Message Bar**
|
|
22
20
|
- **Modal**
|
|
23
21
|
- **Paginator**
|
|
24
22
|
- **Progress**
|
|
@@ -68,12 +66,17 @@ A library of UI components, all independent of the Splunk Enterprise environment
|
|
|
68
66
|
- **Anchor Menu**
|
|
69
67
|
- **Breadcrumbs**
|
|
70
68
|
|
|
69
|
+
## Notifications
|
|
70
|
+
|
|
71
|
+
- **Notifications**
|
|
72
|
+
- **Message**
|
|
73
|
+
- **Message Bar**
|
|
74
|
+
|
|
71
75
|
## Utilities
|
|
72
76
|
|
|
73
77
|
- **AnimationToggle**
|
|
74
78
|
- **Button Group**
|
|
75
79
|
- **Clickable**
|
|
76
|
-
- **Column Layout**
|
|
77
80
|
- **Divider**
|
|
78
81
|
- **Dropdown**
|
|
79
82
|
- **Layer**
|
|
@@ -93,5 +96,6 @@ A library of UI components, all independent of the Splunk Enterprise environment
|
|
|
93
96
|
## Deprecated
|
|
94
97
|
|
|
95
98
|
- **Accordion**
|
|
99
|
+
- **Column Layout**
|
|
96
100
|
- **Monogram**
|
|
97
101
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@splunk/react-ui",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.1",
|
|
4
4
|
"description": "Library of React components that implement the Splunk design language",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Splunk Inc.",
|
|
@@ -45,17 +45,16 @@
|
|
|
45
45
|
"@dnd-kit/sortable": "^8.0.0",
|
|
46
46
|
"@dnd-kit/utilities": "^3.2.2",
|
|
47
47
|
"@react-spring/web": "^9.7.5",
|
|
48
|
-
"@splunk/react-icons": "^5.
|
|
49
|
-
"@splunk/themes": "^1.
|
|
50
|
-
"@splunk/ui-utils": "^1.
|
|
48
|
+
"@splunk/react-icons": "^5.10.0",
|
|
49
|
+
"@splunk/themes": "^1.7.0",
|
|
50
|
+
"@splunk/ui-utils": "^1.13.0",
|
|
51
51
|
"decimal.js-light": "^2.5.1",
|
|
52
52
|
"intl-tel-input": "^25.3.2",
|
|
53
|
-
"lodash": "^4.
|
|
53
|
+
"lodash": "^4.18.1",
|
|
54
54
|
"moment": "^2.29.4",
|
|
55
55
|
"prop-types": "^15.6.2",
|
|
56
56
|
"react-markdown": "^8.0.7",
|
|
57
57
|
"remark-gfm": "^1.0.0",
|
|
58
|
-
"tinycolor2": "^1.4.1",
|
|
59
58
|
"use-sync-external-store": "^1.6.0",
|
|
60
59
|
"use-typed-event-listener": "^3.0.0"
|
|
61
60
|
},
|
|
@@ -63,10 +62,10 @@
|
|
|
63
62
|
"@babel/core": "^7.28.0",
|
|
64
63
|
"@babel/plugin-transform-runtime": "^7.28.0",
|
|
65
64
|
"@splunk/babel-preset": "^4.0.0",
|
|
66
|
-
"@splunk/docs-gen": "^1.
|
|
67
|
-
"@splunk/eslint-config": "^5.
|
|
68
|
-
"@splunk/eslint-plugin-splunk-ui": "^0.
|
|
69
|
-
"@splunk/react-docs": "^1.
|
|
65
|
+
"@splunk/docs-gen": "^1.5.0",
|
|
66
|
+
"@splunk/eslint-config": "^5.1.0",
|
|
67
|
+
"@splunk/eslint-plugin-splunk-ui": "^0.2.0",
|
|
68
|
+
"@splunk/react-docs": "^1.7.0",
|
|
70
69
|
"@splunk/stylelint-config": "^5.0.0",
|
|
71
70
|
"@splunk/test-runner-utils": "^0.4.1",
|
|
72
71
|
"@splunk/webpack-configs": "^7.0.3",
|
|
@@ -90,7 +89,6 @@
|
|
|
90
89
|
"@types/react": "^18.2.0",
|
|
91
90
|
"@types/react-dom": "^18.2.0",
|
|
92
91
|
"@types/styled-components": "^5.1.0",
|
|
93
|
-
"@types/tinycolor2": "^1.4.2",
|
|
94
92
|
"@types/use-sync-external-store": "^1.5.0",
|
|
95
93
|
"@types/webpack-env": "^1.15.2",
|
|
96
94
|
"@typescript-eslint/eslint-plugin": "^8.29.1",
|