"Native" Gif Search
Problem Summary
Section titled “Problem Summary”The current dropdown menu component (whose current behavior can be seen here) only allows the display of “text + (optional) icon” options. In order to use it for GIF search (and, in the future, emoji/sticker selection), we need to expand it to include the ability to select between images.
Current Status
Section titled “Current Status”Component Props
Section titled “Component Props”interface DropdownProps { // The trigger button. children: React.ReactElement; // An extra component to optionally display above the set of options. header?: React.ReactElement; // An array of options to display within the dropdown. If no option is present, // the trigger button (children prop) is returned as is. options?: ({ name: string; icon?: IconDefinition | string; color?: string; } & ( | // Click action OR... { link: LinkWithAction } // ...the recursive set of options for the next page. | { options: DropdownProps["options"] } ))[]; /* irrelevant stuff */}Desktop View
Section titled “Desktop View”
Mobile View
Section titled “Mobile View”
Final Result
Section titled “Final Result”Mockup
Section titled “Mockup”
Considerations
Section titled “Considerations”- Q: Can the same “selection page” be comprised of both images and textual
options?
- No.
- Q: Can an image selection page be displayed AFTER a textual options page?
- Yes, and we can use the same
DropdownContent.previousOptionprop we already have coded to allow returning to the previous page.
- Yes, and we can use the same
- Q: Can “image selection” have multiple pages?
- Technically yes, but I would skip it for now.
- Q: Which “codebase” should be in charge of making requests to the gifs
endpoint?
- This has historically been part of the editor itself. It will likely need to change, and I’ll spend more brainpower on how once we’re closer to tying everything up together. The initial component should not be tied to any particular image provider. Ideally we could reuse it for Tenor, Giphy or even our own internal search.
- Q: Do we want it to be simply image selection or also allow selecting videos
(bc of the gif size vs mp4 size issue)?
- I guess we’ll have to support passing videos for gifs, but I’d look at what react-tenor does.
- Q: Do we want a masonry-style display for images or a grid-like style one?
- React-tenor currently uses grid, and I’d keep it that way for now because it’s easier.
- Q: What are the accessibility considerations for something like this?
- What happens if people pause automatic gif playing? Should they still be
playing in the selector?
- IMO, yes.
- Dropdown should have correct tab order (double-check) but is missing ARIA states. We can fix this if we want, but at least adding image selection doesn’t make accessibility worse.
- TBD.
- What happens if people pause automatic gif playing? Should they still be
playing in the selector?
What We Have
Section titled “What We Have”- An example of a dropdown with filterable options in BoardSelector.
- A gif search component (Tenor Keyboard in the editor codebase) made by shamefully hacking React Tenor to suit our needs.
- If we want to have a masonry-style image layout we can reuse MasonryView.
Roadmap
Section titled “Roadmap”- Change DropdownListMenu to allow a series of images as a potential option.
- Create an
ImageSearchcomponent that wraps a DropdownList + a filter, and potentially allows choosing between a changing list of suggestions (like in react-tenor). - Decide the data flow from user input to the display of the correct list of images for GIF search.
- Implement the right calls to the Tenor API.
- Change
Editor
to call to an external component for GIF search.
- Example branch of how this could be done by using context.
Proposed Code Changes
Section titled “Proposed Code Changes”Current
Section titled “Current”interface DropdownProps { // The trigger button. children: React.ReactElement; // Am extra component to optionally display above the set of options. header?: React.ReactElement; // An array of options to display the dropdown. If no option is present, // the trigger button is displayed as it is. options?: ({ name: string; icon?: IconDefinition | string; color?: string; } & ( | // Click action OR... { link: LinkWithAction } // ...the recursive set of options for the next page. | { options: DropdownProps["options"] } ))[]; /* irrelevant stuff */}Text Option Types
Section titled “Text Option Types”interface TextOptionWithLink { name: string; icon?: IconDefinition | string; color?: string; link: LinkWithAction;};
interface TextOptionWithNesting { name: string; icon?: IconDefinition | string; color?: string; options: DropdownProps["options"]}
interface TextOption = TextOptionWithLink | TextOptionWithNesting;Image Option Type
Section titled “Image Option Type”interface ImageOption { // If we support video, we likely need to add another option here. image: string; // For accessibility reasons? name?: string; // This could just be "onClick" if we don't support "open in a new page". link: LinkWithAction; // Note: images don't support nesting.}Final Dropdown Type
Section titled “Final Dropdown Type”interface DropdownProps { /* All the same*/
// Note: array of images OR array of texts, not mixing them together in the same list. // Other note: having a ImageOption[][] would easily enable multiple pages of images, // but this doesn't help us for GIF search cause we don't want to fetch all the pages // at the same time, so we'd still have to figure out how to do it only on request. options?: ImageOption[] | TextOption[];
/* irrelevant stuff */}Component Code
Section titled “Component Code”I think the easiest way of doing this would be to have two separate
DropdownContent implementations, one for TextOption[] and one for
ImageOption[]. DropdownContent can then be a mostly-empty wrapper that just
delegates to DropdownImageContent or DropdownTextContent according to the
type of the options array. This means DropdownMenu’s code won’t have to
change.
I think it might make sense to also move the Dropdown code to its own folder and split components in their own files.