-
Notifications
You must be signed in to change notification settings - Fork 72
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
[RFC][FEATURE] SplitButton for an action "with alternatives" #1187
Comments
How do we consider managing default state and last selected state |
Default state is Primary state. I'll be writing more detail on this shortly. For Last-selected state, which would be the "replacement" context -- state will not be kept between refreshes or page navigations. Like the ImmediateAction context (the default), the button presents its Primary action on any new render. |
So persisting state across refreshs is possible in only one of two ways, either through the URL (Highly discouraged) or using browser storage. I think OUI has a few components that store state locally but this is a pattern that i dont think OUI should follow and leave state storage up to the application that renders it. This makes OUI more UI focussed while leaving framework specific tasks like this to the application (i.e. like controlled components from react) @pjfitzgibbons What would the props of this component look like? |
@ashwin-pc Thanks for asking about props! I have updated the Description above with a sample documentation of the widget and some technical details of its construction. |
@shanilpa Could you look at the updated Description, especially "Primary and Secondarie scan replace each other with secondaryAction" As you can see, this is very complicated to describe. I'm wondering if it would be much easier to copy the SuperSelect functionality more directly -- meaning that "replace" mode as the UI samples describe it would be the only functionality of SplitButton. This is exactly as SuperSelect works already, and is also how our reference-sample works : If you agree, I would like to just have the 'replace' mode, and will update doc to remove the concept of Your thoughts? |
Cc: @canascar |
Thanks @pjfitzgibbons, just a few thoughts an questions about the implementation:
Why are we cloning that component? Its an opinionated component if im not wrong.
Nice! I like this feature. One comment i have is to make this clear earlier in the design. It wasnt obvious to me until i came down to this section that both immediately triggering a secondary option was possible since you talk mostly about replace in the beginning. Also you mention
Why do we need this? I also noticed here that you are thinking about only having the |
Would the |
@ashwin-pc @canascar @kgcreative @shanilpa Please re-read the Discussion as if this is a first iteration. The comment thread here is of course, still relevant. |
I think this looks good to me from the UX side @pjfitzgibbons. I do have a question about the props - does the primary button have a prop for an icon as well? I only see one for the dropdown. |
Having gone though this proposal a second time i'm wondering if we even need the replace feature? Cant we achieve the same with the immediate button? e.g. When i want to make the button behave in a replace mode, all the secondary options have the same callback, it simply tells the parent component which secondary action was clicked and the parent component is responsible for updating the primary and secondary options of the button. This makes the OUI component a lot simpler and eliminates a lot of unnecessary props. |
@ashwin-pc I think I see where you're going with this. Would you suggest we should include a doc example of this? I'ts an important feature and we have a direct use-case for it in Olly/Assistant. |
@shanilpa the entire content of the PrimaryButton, including an icon, is determined by the input of |
Yeah for sure! we can show the ways it can be used in the doc and that can also be used as a reference implementation for Olly :) |
@ashwin-pc @shanilpa I updated Description again, with a much simplified SplitButton API. I agree, with a couple of examples, this will be a useful control to have in the library. |
This looks good, a few small suggestions:
|
This feature will re-introduce the SplitButton to the OUI widget library.
The SplitButton is expected to have two immediate use-cases :
The original SplitButton was removed at #805, as the original code has been unused by OpenSearch Dashboards and it's known-plugins.
Anatomy
A split button consists of:
Primary action button width will be determined by the label (and icon and/or combination) consistent with our existing button pattern. Secondary button width should be proportional and use only an icon to denote action of dropdown expansion (in most cases, a down arrow icon but we can allow customizing if necessary.)
We can have split buttons for all our button states and types:
Technical Design
Documentation
Documentation for Split Button should be added to the documentation site : https://oui.opensearch.org/1.x/navigation/split-button
See Split Button below.
Widget construction
SplitButton will consist of a PrimaryControl, and a drop-down of SelectionItems.
PrimaryControl
The primary control of SplitButton will be two buttons, arranged side-by-side, and styled to appear as one continuous control, with a hairline separator between.
The left-side button will be the PrimaryButton. This button is the base of SplitButton's props. SplitButton's function and behaviour is a subset of OuiButton.
The right-side button will control the SplitButton's drop-down display. It is styled using the styling directed by SplitButton's props, matching the PrimaryButton. The RightButton will behave as expected of a drop-down activator -- it's onClick will toggle the display of the drop-down widget.
SelectionItems - drop-down control
The SplitButton drop-down list will be constructed of an OuiInputPopover containing a list of OuiContextMenuItem, each containing items of the
options
component list.Action of click on SelectionItems
All SelectionItems, upon click, will be handled by the SplitButton, which will call the
onChange
callback with a single argument - the integer index of the SelectionItem that was clicked.Action of click on PrimaryButton
When the PrimaryButton is clicked, the SplitButton control will call the
onClick
callback, with no arguments.Selection state
The index of
options
item that will be the PrimaryButton will be controlled with theselectedIndex
property. If undefined, no item will be selected. The selected item will be marked with a "check" OuiIcon.Split Button (for documentation site)
This replacement for OuiButton provides advanced options for contexts where several actions should be available. Simply pass an array of strings or React components as
options
:FunctionComponent<{}>
|ComponentClass<{}>
OuiSplitButton comes in two styles. The
fill
style should be reserved for the main action and limited in number for a single page. Be sure to read the full button usage guidelines.Selection Items
The array of
options
provides a list of selection items, displayed in a drop-down style popover. This popoer is toggled by the SplitButton's styled drop-down button.When a SelectionItem is clicked, the
onChange
callback will be called with the index of that item's position in theoptions
list.A SelectionItem may be marked as selected with the prop
selectedIndex
. The selected itme will be marked with a "check" OuiIconProps
FunctionComponent<{}>
Use
s
in confined spacess
,m
Make button a solid color for prominence
boolean
Any of our named colors.
disabled
is also allowedboolean
Extends the button to 100% width
boolean
Override the default minimum width
string | number
Use an alternate Icon on the Secondary button
s
,m
Applied to the outermost wrapper (popover)
string
string
Controls whether the options are shown
boolean
Index of
options
that is markedCallback to notify an item in the drop-down has been selected.
Callback to notify that the PrimaryButton has been clicked.
@see aria-labeledby
string
Design Options
These options were considered during the iterative design process of this RFC
"replace" action
In this option, a
selectionAction
prop would place the SplitButton into different "modes" :execute
(default) -- Inexecute
mode, selecting an item from the drop-down list will immediately execute that item'sonClick
handler, as provided by that item's definition in theoptions
prop.select
-- inselect
mode, selecting an item from the drop-down list willselect
that item to be the SplitButton PrimaryButton. By default, the first item in theoptions
prop is always selected as PrimaryButton.The
select
mode is an interaction that was named "replace" in earlier iterations.Pros :
selectionAction
and listen to a callback.Cons :
Advanced
options
propsIn earlier iteration, the
options
array was defined in a way to attempt to support the "replace" action. It was defined as :primaryDisplay
: string |FunctionComponent<{}>
|ComponentClass<{}>
selectionDisplay
: string |FunctionComponent<{}>
|ComponentClass<{}>
href
: string<a>
onClick
:((event: MouseEvent<HTMLButtonElement, MouseEvent>) => void) | ((event: MouseEvent<HTMLAnchorElement, MouseEvent>) => void)
buttonRef
:(instance: HTMLInputElement) => void
ariaLabel
:string
data-test-subj
:string
Pros :
Cons :
Immediate Secondary Action vs Selection
Two forms of SplitButton appear "in the wild".
Immediate Action
[NEED AN EXAMPLE]
Replacement of Primary Button
a. Navigation on selection of option without button click, or single click as opposed to 2 click function. (Possibly not recommended unless action can be cancelled or delayed.)
b. Using only an icon for the action button (Possibly not recommended or used sparingly unless icon clearly defines the action.)
c. Popover v Dropdown container - most examples opt for a dropdown container as opposed to a popover container.
Options advanced features - "disabled", etc
Options items for this iteration are simple
string | ReactNode
. We want to allow flexible use-cases and alternate states of option items. The reference implementation for this is SuperSelect.In a future iteration, Options can be extended -- see #1195
FAQ
Conversations of note
Originally posted by @canascar in opensearch-project/OpenSearch-Dashboards#3621 (comment)
Reference implementations
Definition: A split button is a button with two components: a label and an arrow; clicking on the label selects a default action, and clicking on the arrow opens up a list of other possible actions. (Reference)
The text was updated successfully, but these errors were encountered: