From ddd6a9da960be7e927216a123197592091dd7ffe Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Fri, 16 Jun 2023 19:00:57 -0700 Subject: [PATCH] Implement raid combobox (#311) * Add ellipsis icon * Reduce size of tokens * Move UpdateToast to toasts folder * Update variables.scss * Add reps for grid objects These reps act like the existing PartyRep except for Characters and Summons, as well as a new component just for Weapons. They only render the grid of objects and nothing else. Eventually PartyRep will use WeaponRep * Added RepSegment This is a Character, Weapon or Summon rep wrapped with an input and label for use in a SegmentedControl * Modify PartySegmentedControl to use RepSegments This will not work on mobile yet, where it should gracefully degrade to a normal SegmentedControl with only text * Extract URL copied and Remixed toasts into files * Extract delete team alert into a file Also, to support this: * Added `Destructive` class to Button * Added `primaryActionClassName` prop to Alert * Added an alert for when remixing teams * Began refactoring PartyDetails into several files * PartyHeader will live at the top, above the new segmented control * PartyDetails stays below, only showing remixed teams and the description * PartyDropdown handles the new ... menu * Remove duplicated code This is description and remix code that is still in `PartyDetails` * Small fixes for weapon grid * Add placeholder image for guidebooks * Add localizations * Add Guidebook type and update other types * Update gitignore Don't commit guidebook images * Indicate if a dialog is scrollable We had broken paging in the infinite scroll component. Turning off "scrolling" at the dialog levels fixes it without adding scrollbars in environments that persistently show them * Add ExtraContainer This is the purple container that will contain additional weapons and sephira guidebooks * Move ExtraWeapons to ExtraWeaponsGrid And put it in ExtraContainer * Added GuidebooksGrid and GuidebookUnit These are the display components for Guidebooks in the WeaponGrid * Visual adjustments to summon grid * Add Empty class to weapons when unit is unfilled * Implement GuidebooksGrid in WeaponGrid * Remove extra switch * Remove old dependencies and props * Implement searching for/adding guidebooks to party * Update styles * Fix dependency * Properly determine when extra container should display * Change to 1-indexing for guidebooks * Add support for removing guidebooks * Display guidebook validation error * Move read only buttons to PartyHeader Also broke up tokens and made them easier to render * Add guidebooks to DetailsObject * Add raid placeholder string to locale * Update .gitignore * Update and reorganize localization files * Update types Added RaidGroup and updated Raid, then updated dependent types and objects * Update dependencies * Update react and react-dom to at least 18.0.0 * Install cmdk * Rename Arrow.svg to Chevron.svg Also added a new Arrow.svg with a stem * Add api call for raidGroups and update pages Pages fetch raids and store them in the app state. We needed to update this to pull raid groups instead * Update SegmentedControl component * Add className and blended properties * Segment gets flex-grow * Update Select component * data-placeholder style should match only if true * Adjust corner radius to match cards instead of inputs * Fix classNames call in SelectItem * Remove raid prop from Party * Add Popover component * Popover is a wrapper of Radix's Popover component that we will use to wrap the combobox. * Move styles that were in PopoverContent.scss to Popover.scss * Add Command component The Command component is a wrapper over CMDK's Command component. Pretty much every object in that library is wrapped here. We will use this for the guts of our combobox. * Add RaidCombobox and RaidItem components * RaidCombobox combines Popover and Command to create an experience where users can browse through raids by section, search them and sort them. * RaidItem is effectively a copy-paste of SelectItem using CommandItem, adding some raid-specific styles and elements * Updates themes and variables * Replace RaidDropdown with RaidCombobox * Add small shadow to Tooltip * Update side offset for Popover * Update CharLimitedFieldset class name * Add clear button to Combobox input * It only shows up when there is text in the input * Clicking it clears the text in the input * It uses CharLimitedFieldset's classes * ChatGPT helped me refactor RaidCombobox * Further refactoring of RaidCombobox * Deploy content update (#309) * Update the updates page with new items (#306) * Add Nier and Estarriola uncaps (#308) * Update the updates page with new items (#306) (#307) * Update .gitignore * Add Nier and Estarriola uncaps * Fix uncaps treated as new characters * Make combobox keyboard accessible * Style updates * Refactor accessibility code * Add translation for "Selected" text * Change selects to be poppers for consistency We can't make the new Raid combobox appear over the input like the macOS behavior, so we change all selects to be normal popper behavior * Set raid groups on teams page * Implement in FilterBar * Fix styles for combobox input * Remove RaidDropdown component * Update index.scss * Remove preview when on mobile sizes * Fix some mobile styles * Add farming raid option * Increase height slightly --- .gitignore | 1 + components/FilterBar/index.scss | 2 +- components/FilterBar/index.tsx | 71 +- components/GridRepCollection/index.scss | 1 + components/Header/index.tsx | 4 +- components/RaidDropdown/index.tsx | 144 - components/RaidSelect/index.scss | 22 + components/RaidSelect/index.tsx | 170 + components/common/Button/index.scss | 2 +- .../common/CharLimitedFieldset/index.scss | 38 - .../common/CharLimitedFieldset/index.tsx | 2 +- .../Command}/index.scss | 0 components/common/Command/index.tsx | 128 + components/common/Popover/index.scss | 30 + components/common/Popover/index.tsx | 106 + components/common/PopoverContent/index.scss | 17 - components/common/Segment/index.scss | 1 + components/common/Segment/index.tsx | 17 +- components/common/SegmentedControl/index.scss | 9 + components/common/SegmentedControl/index.tsx | 31 +- components/common/Select/index.scss | 10 +- components/common/Select/index.tsx | 10 +- components/common/SelectItem/index.scss | 3 +- components/common/SelectItem/index.tsx | 2 +- components/common/Tooltip/index.scss | 1 + components/party/Party/index.tsx | 1 - components/party/PartyHeader/index.tsx | 15 +- components/raids/RaidCombobox/index.scss | 197 + components/raids/RaidCombobox/index.tsx | 568 + components/raids/RaidItem/index.scss | 53 + components/raids/RaidItem/index.tsx | 87 + components/search/SearchFilter/index.tsx | 4 +- package-lock.json | 12971 ++++++++++++---- package.json | 25 +- pages/[username].tsx | 12 +- pages/new/index.tsx | 17 +- pages/p/[party].tsx | 18 +- pages/saved.tsx | 12 +- pages/teams.tsx | 13 +- public/icons/Arrow.svg | 4 +- public/icons/Chevron.svg | 3 + .../icons/{ArrowDark.svg => ChevronDark.svg} | 0 public/locales/en/common.json | 258 +- public/locales/ja/common.json | 288 +- styles/globals.scss | 53 + styles/themes.scss | 24 +- styles/variables.scss | 18 +- types/Raid.d.ts | 2 +- types/RaidGroup.d.ts | 14 + types/index.d.ts | 3 +- utils/api.tsx | 5 + utils/appState.tsx | 4 +- utils/extractFilters.tsx | 8 +- utils/organizeRaids.tsx | 16 - 54 files changed, 12188 insertions(+), 3327 deletions(-) delete mode 100644 components/RaidDropdown/index.tsx create mode 100644 components/RaidSelect/index.scss create mode 100644 components/RaidSelect/index.tsx rename components/{RaidDropdown => common/Command}/index.scss (100%) create mode 100644 components/common/Command/index.tsx create mode 100644 components/common/Popover/index.scss create mode 100644 components/common/Popover/index.tsx create mode 100644 components/raids/RaidCombobox/index.scss create mode 100644 components/raids/RaidCombobox/index.tsx create mode 100644 components/raids/RaidItem/index.scss create mode 100644 components/raids/RaidItem/index.tsx create mode 100644 public/icons/Chevron.svg rename public/icons/{ArrowDark.svg => ChevronDark.svg} (100%) create mode 100644 types/RaidGroup.d.ts delete mode 100644 utils/organizeRaids.tsx diff --git a/.gitignore b/.gitignore index e3403051..9bb7f6d8 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ public/images/accessory* public/images/mastery* public/images/updates* public/images/guidebooks* +public/images/raids* # Typescript v1 declaration files typings/ diff --git a/components/FilterBar/index.scss b/components/FilterBar/index.scss index b8bde51e..5cfb852f 100644 --- a/components/FilterBar/index.scss +++ b/components/FilterBar/index.scss @@ -72,7 +72,7 @@ select, .SelectTrigger { - // background: url("/icons/Arrow.svg"), $grey-90; + // background: url("/icons/Chevron.svg"), $grey-90; // background-repeat: no-repeat; // background-position-y: center; // background-position-x: 95%; diff --git a/components/FilterBar/index.tsx b/components/FilterBar/index.tsx index 11b5332f..5d94deb9 100644 --- a/components/FilterBar/index.tsx +++ b/components/FilterBar/index.tsx @@ -4,7 +4,6 @@ import classNames from 'classnames' import equals from 'fast-deep-equal' import FilterModal from '~components/FilterModal' -import RaidDropdown from '~components/RaidDropdown' import Select from '~components/common/Select' import SelectItem from '~components/common/SelectItem' import Button from '~components/common/Button' @@ -15,6 +14,8 @@ import FilterIcon from '~public/icons/Filter.svg' import './index.scss' import { getCookie } from 'cookies-next' +import RaidCombobox from '~components/raids/RaidCombobox' +import { appState } from '~utils/appState' interface Props { children: React.ReactNode @@ -29,6 +30,8 @@ const FilterBar = (props: Props) => { // Set up translation const { t } = useTranslation('common') + const [currentRaid, setCurrentRaid] = useState() + const [recencyOpen, setRecencyOpen] = useState(false) const [elementOpen, setElementOpen] = useState(false) @@ -47,6 +50,16 @@ const FilterBar = (props: Props) => { FiltersActive: !matchesDefaultFilters, }) + // Convert raid slug to Raid object on mount + useEffect(() => { + const raid = appState.raidGroups + .filter((group) => group.section > 0) + .flatMap((group) => group.raids) + .find((raid) => raid.slug === props.raidSlug) + + setCurrentRaid(raid) + }, [props.raidSlug]) + useEffect(() => { // Fetch user's advanced filters const filtersCookie = getCookie('filters') @@ -76,8 +89,8 @@ const FilterBar = (props: Props) => { props.onFilter({ recency: recencyValue, ...advancedFilters }) } - function raidSelectChanged(slug?: string) { - props.onFilter({ raidSlug: slug, ...advancedFilters }) + function raidSelectChanged(raid?: Raid) { + props.onFilter({ raidSlug: raid?.slug, ...advancedFilters }) } function handleAdvancedFiltersChanged(filters: FilterSet) { @@ -90,6 +103,25 @@ const FilterBar = (props: Props) => { setRecencyOpen(name === 'recency' ? !recencyOpen : false) } + function generateSelectItems() { + const elements = [ + { element: 'all', key: -1, value: -1, text: t('elements.full.all') }, + { element: 'null', key: 0, value: 0, text: t('elements.full.null') }, + { element: 'wind', key: 1, value: 1, text: t('elements.full.wind') }, + { element: 'fire', key: 2, value: 2, text: t('elements.full.fire') }, + { element: 'water', key: 3, value: 3, text: t('elements.full.water') }, + { element: 'earth', key: 4, value: 4, text: t('elements.full.earth') }, + { element: 'dark', key: 5, value: 5, text: t('elements.full.dark') }, + { element: 'light', key: 6, value: 6, text: t('elements.full.light') }, + ] + + return elements.map(({ element, key, value, text }) => ( + + {text} + + )) + } + return ( <>
@@ -97,47 +129,26 @@ const FilterBar = (props: Props) => {
- setOpen(!open)} - onClick={openRaidSelect} - onValueChange={handleChange} - > - {Array.from(Array(sortedRaids?.length)).map((x, i) => - renderRaidGroup(i) - )} - - - ) - } -) - -export default RaidDropdown diff --git a/components/RaidSelect/index.scss b/components/RaidSelect/index.scss new file mode 100644 index 00000000..e6eaa60f --- /dev/null +++ b/components/RaidSelect/index.scss @@ -0,0 +1,22 @@ +.Raid.Select { + min-width: 420px; + + .Top { + display: flex; + flex-direction: column; + gap: $unit; + padding: $unit 0; + + .SegmentedControl { + width: 100%; + } + + .Input.Bound { + background-color: var(--select-contained-bg); + + &:hover { + background-color: var(--select-contained-bg-hover); + } + } + } +} diff --git a/components/RaidSelect/index.tsx b/components/RaidSelect/index.tsx new file mode 100644 index 00000000..8d114b59 --- /dev/null +++ b/components/RaidSelect/index.tsx @@ -0,0 +1,170 @@ +import React, { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import * as RadixSelect from '@radix-ui/react-select' +import classNames from 'classnames' + +import Overlay from '~components/common/Overlay' + +import ChevronIcon from '~public/icons/Chevron.svg' + +import './index.scss' +import SegmentedControl from '~components/common/SegmentedControl' +import Segment from '~components/common/Segment' +import Input from '~components/common/Input' + +// Props +interface Props + extends React.DetailedHTMLProps< + React.SelectHTMLAttributes, + HTMLSelectElement + > { + altText?: string + currentSegment: number + iconSrc?: string + open: boolean + trigger?: React.ReactNode + children?: React.ReactNode + onOpenChange?: () => void + onValueChange?: (value: string) => void + onSegmentClick: (segment: number) => void + onClose?: () => void + triggerClass?: string + overlayVisible?: boolean +} + +const RaidSelect = React.forwardRef(function Select( + props: Props, + forwardedRef +) { + // Import translations + const { t } = useTranslation('common') + + const searchInput = React.createRef() + + const [open, setOpen] = useState(false) + const [value, setValue] = useState('') + const [query, setQuery] = useState('') + + const triggerClasses = classNames( + { + SelectTrigger: true, + Disabled: props.disabled, + }, + props.triggerClass + ) + + useEffect(() => { + setOpen(props.open) + }, [props.open]) + + useEffect(() => { + if (props.value && props.value !== '') setValue(`${props.value}`) + else setValue('') + }, [props.value]) + + function onValueChange(newValue: string) { + setValue(`${newValue}`) + if (props.onValueChange) props.onValueChange(newValue) + } + + function onCloseAutoFocus() { + setOpen(false) + if (props.onClose) props.onClose() + } + + function onEscapeKeyDown() { + setOpen(false) + if (props.onClose) props.onClose() + } + + function onPointerDownOutside() { + setOpen(false) + if (props.onClose) props.onClose() + } + + return ( + + + {props.iconSrc ? {props.altText} : ''} + + {!props.disabled ? ( + + + + ) : ( + '' + )} + + + + <> + + + +
+ {}} + /> + + props.onSegmentClick(1)} + > + {t('raids.sections.events')} + + props.onSegmentClick(0)} + > + {t('raids.sections.raids')} + + props.onSegmentClick(2)} + > + {t('raids.sections.solo')} + + +
+ {props.children} +
+ +
+
+ ) +}) + +RaidSelect.defaultProps = { + overlayVisible: true, +} + +export default RaidSelect diff --git a/components/common/Button/index.scss b/components/common/Button/index.scss index ce7399b7..ac4d42d0 100644 --- a/components/common/Button/index.scss +++ b/components/common/Button/index.scss @@ -1,7 +1,7 @@ .Button { align-items: center; background: var(--button-bg); - border: none; + border: 2px solid transparent; border-radius: $input-corner; color: var(--button-text); display: inline-flex; diff --git a/components/common/CharLimitedFieldset/index.scss b/components/common/CharLimitedFieldset/index.scss index 446453f1..e69de29b 100644 --- a/components/common/CharLimitedFieldset/index.scss +++ b/components/common/CharLimitedFieldset/index.scss @@ -1,38 +0,0 @@ -.Limited { - $offset: 2px; - - align-items: center; - background: var(--input-bg); - border-radius: $input-corner; - border: $offset solid transparent; - box-sizing: border-box; - display: flex; - gap: $unit; - padding-top: 2px; - padding-bottom: 2px; - padding-right: calc($unit-2x - $offset); - - &:focus-within { - border: $offset solid $blue; - // box-shadow: 0 2px rgba(255, 255, 255, 1); - } - - .Counter { - color: $grey-55; - font-weight: $bold; - line-height: 42px; - } - - .Input { - background: transparent; - border: none; - border-radius: 0; - padding: $unit * 1.5 $unit-2x; - padding-left: calc($unit-2x - $offset); - - &:focus { - border: none; - outline: none; - } - } -} diff --git a/components/common/CharLimitedFieldset/index.tsx b/components/common/CharLimitedFieldset/index.tsx index cb822299..16cbef3e 100644 --- a/components/common/CharLimitedFieldset/index.tsx +++ b/components/common/CharLimitedFieldset/index.tsx @@ -32,7 +32,7 @@ const CharLimitedFieldset = React.forwardRef( return (
-
+
, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Command.displayName = CommandPrimitive.displayName + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + {children} + + + ) +} + +const CommandInput = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ +
+)) + +CommandInput.displayName = CommandPrimitive.Input.displayName + +const CommandList = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandList.displayName = CommandPrimitive.List.displayName + +const CommandEmpty = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)) + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName + +const CommandGroup = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandGroup.displayName = CommandPrimitive.Group.displayName + +const CommandSeparator = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName + +const CommandItem = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandItem.displayName = CommandPrimitive.Item.displayName + +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +CommandShortcut.displayName = 'CommandShortcut' + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +} diff --git a/components/common/Popover/index.scss b/components/common/Popover/index.scss new file mode 100644 index 00000000..79d7b808 --- /dev/null +++ b/components/common/Popover/index.scss @@ -0,0 +1,30 @@ +.Popover { + animation: scaleIn $duration-zoom ease-out; + background: var(--dialog-bg); + border-radius: $card-corner; + border: 0.5px solid rgba(0, 0, 0, 0.18); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24); + outline: none; + padding: $unit; + transform-origin: var(--radix-popover-content-transform-origin); + width: var(--radix-popover-trigger-width); + min-width: 440px; + z-index: 5; + + @include breakpoint(phone) { + min-width: auto; + } + + &.Flush { + padding: 0; + } + + .Arrow { + fill: var(--dialog-bg); + filter: drop-shadow(0px 1px 1px rgb(0 0 0 / 0.18)); + margin-top: -1px; + } +} + +[data-radix-popper-content-wrapper] { +} diff --git a/components/common/Popover/index.tsx b/components/common/Popover/index.tsx new file mode 100644 index 00000000..f334b6a7 --- /dev/null +++ b/components/common/Popover/index.tsx @@ -0,0 +1,106 @@ +import React, { + ComponentProps, + PropsWithChildren, + ReactNode, + useEffect, + useState, +} from 'react' +import classNames from 'classnames' + +import * as PopoverPrimitive from '@radix-ui/react-popover' +import ChevronIcon from '~public/icons/Chevron.svg' + +import './index.scss' + +interface Props extends ComponentProps<'div'> { + open: boolean + disabled?: boolean + icon?: { + src: string + alt: string + } + trigger?: { + className?: string + placeholder?: string + } + value?: { + element: ReactNode + rawValue: string + } + onOpenChange?: () => void +} + +const Popover = React.forwardRef(function Popover( + { children, ...props }: PropsWithChildren, + forwardedRef +) { + // Component state + const [open, setOpen] = useState(false) + + // Element classes + const triggerClasses = classNames( + { + SelectTrigger: true, + Disabled: props.disabled, + }, + props.trigger?.className + ) + + // Hooks + useEffect(() => { + setOpen(props.open) + }, [props.open]) + + // Elements + const value = props.value ? ( + + {props.value?.element} + + ) : ( + {props.placeholder} + ) + + const icon = props.icon ? ( + {props.icon.alt} + ) : ( + '' + ) + + const arrow = !props.disabled ? ( + + + + ) : ( + '' + ) + + return ( + + + {icon} + {value} + {arrow} + + + {children} + + + ) +}) + +Popover.defaultProps = { + disabled: false, +} + +export default Popover diff --git a/components/common/PopoverContent/index.scss b/components/common/PopoverContent/index.scss index eb2f80c9..e69de29b 100644 --- a/components/common/PopoverContent/index.scss +++ b/components/common/PopoverContent/index.scss @@ -1,17 +0,0 @@ -.Popover { - animation: scaleIn $duration-zoom ease-out; - background: var(--dialog-bg); - border-radius: $card-corner; - border: 0.5px solid rgba(0, 0, 0, 0.18); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24); - outline: none; - padding: $unit; - transform-origin: var(--radix-popover-content-transform-origin); - z-index: 5; - - .Arrow { - fill: var(--dialog-bg); - filter: drop-shadow(0px 1px 1px rgb(0 0 0 / 0.18)); - margin-top: -1px; - } -} diff --git a/components/common/Segment/index.scss b/components/common/Segment/index.scss index fa148d4e..cb0aa7e8 100644 --- a/components/common/Segment/index.scss +++ b/components/common/Segment/index.scss @@ -1,6 +1,7 @@ .Segment { color: $grey-55; cursor: pointer; + flex-grow: 1; font-size: 1.4rem; font-weight: $normal; min-width: 100px; diff --git a/components/common/Segment/index.tsx b/components/common/Segment/index.tsx index 3135f88f..cfc0b3f6 100644 --- a/components/common/Segment/index.tsx +++ b/components/common/Segment/index.tsx @@ -6,11 +6,20 @@ interface Props { groupName: string name: string selected: boolean + tabIndex?: number children: string onClick: (event: React.ChangeEvent) => void } const Segment: React.FC = (props: Props) => { + // Selects the segment when the user presses the spacebar + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === ' ') { + event.preventDefault() + event.currentTarget.click() + } + } + return (
= (props: Props) => { checked={props.selected} onChange={props.onClick} /> - +
) } diff --git a/components/common/SegmentedControl/index.scss b/components/common/SegmentedControl/index.scss index ad209992..6a357216 100644 --- a/components/common/SegmentedControl/index.scss +++ b/components/common/SegmentedControl/index.scss @@ -21,6 +21,15 @@ border-radius: 100px; } + &.Blended { + background: var(--input-bound-bg); + border-radius: $full-corner; + + .Segment input:checked + label { + background: var(--card-bg); + } + } + &.fire { .Segment input:checked + label { background: var(--fire-bg); diff --git a/components/common/SegmentedControl/index.tsx b/components/common/SegmentedControl/index.tsx index 379f18d2..edb6534f 100644 --- a/components/common/SegmentedControl/index.tsx +++ b/components/common/SegmentedControl/index.tsx @@ -1,19 +1,38 @@ import React from 'react' - +import classNames from 'classnames' import './index.scss' interface Props { + className?: string elementClass?: string + blended?: boolean + tabIndex?: number } -const SegmentedControl: React.FC = ({ elementClass, children }) => { +const SegmentedControl: React.FC = ({ + className, + elementClass, + blended, + tabIndex, + children, +}) => { + const classes = classNames( + { + SegmentedControl: true, + Blended: blended, + }, + className, + elementClass + ) return ( -
-
- {children} -
+
+
{children}
) } +SegmentedControl.defaultProps = { + blended: false, +} + export default SegmentedControl diff --git a/components/common/Select/index.scss b/components/common/Select/index.scss index 19426a62..170dba71 100644 --- a/components/common/Select/index.scss +++ b/components/common/Select/index.scss @@ -2,7 +2,7 @@ align-items: center; background-color: var(--input-bg); border-radius: $input-corner; - border: none; + border: 2px solid transparent; display: flex; gap: $unit; padding: ($unit * 1.5) $unit-2x; @@ -34,7 +34,7 @@ cursor: not-allowed; } - &[data-placeholder] > span:not(.SelectIcon) { + &[data-placeholder='true'] > span:not(.SelectIcon) { color: var(--text-secondary); } @@ -73,13 +73,13 @@ } .Select { - background: var(--select-bg); - border-radius: $input-corner; + background: var(--dialog-bg); + border-radius: $card-corner; border: $hover-stroke; box-shadow: $hover-shadow; padding: 0 $unit; z-index: 40; - + min-width: var(--radix-select-trigger-width); .Scroll.Up, .Scroll.Down { padding: $unit 0; diff --git a/components/common/Select/index.tsx b/components/common/Select/index.tsx index d633b155..b36d3503 100644 --- a/components/common/Select/index.tsx +++ b/components/common/Select/index.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames' import Overlay from '~components/common/Overlay' -import ArrowIcon from '~public/icons/Arrow.svg' +import ChevronIcon from '~public/icons/Chevron.svg' import './index.scss' @@ -86,7 +86,7 @@ const Select = React.forwardRef(function Select( {!props.disabled ? ( - + ) : ( '' @@ -102,16 +102,18 @@ const Select = React.forwardRef(function Select( - + {props.children} - + diff --git a/components/common/SelectItem/index.scss b/components/common/SelectItem/index.scss index a7efa35f..ce481d8a 100644 --- a/components/common/SelectItem/index.scss +++ b/components/common/SelectItem/index.scss @@ -8,7 +8,8 @@ font-size: $font-regular; padding: ($unit * 1.5) $unit-2x; - &:hover { + &:hover, + &:focus { background-color: var(--option-bg-hover); color: var(--text-primary); cursor: pointer; diff --git a/components/common/SelectItem/index.tsx b/components/common/SelectItem/index.tsx index 60b3e4e3..79b7ddef 100644 --- a/components/common/SelectItem/index.tsx +++ b/components/common/SelectItem/index.tsx @@ -17,8 +17,8 @@ const SelectItem = React.forwardRef(function selectItem( const { altText, iconSrc, ...rest } = props return ( diff --git a/components/common/Tooltip/index.scss b/components/common/Tooltip/index.scss index 06c05070..a0333340 100644 --- a/components/common/Tooltip/index.scss +++ b/components/common/Tooltip/index.scss @@ -3,6 +3,7 @@ animation: scaleIn $duration-zoom ease-out; background: var(--dialog-bg); border-radius: $input-corner; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18); color: var(--text-tertiary); font-size: $font-tiny; font-weight: $medium; diff --git a/components/party/Party/index.tsx b/components/party/Party/index.tsx index 042c8ad2..a50da9a6 100644 --- a/components/party/Party/index.tsx +++ b/components/party/Party/index.tsx @@ -29,7 +29,6 @@ import './index.scss' interface Props { new?: boolean team?: Party - raids: Raid[][] selectedTab: GridType pushHistory?: (path: string) => void } diff --git a/components/party/PartyHeader/index.tsx b/components/party/PartyHeader/index.tsx index e45a67c7..33f806e0 100644 --- a/components/party/PartyHeader/index.tsx +++ b/components/party/PartyHeader/index.tsx @@ -9,7 +9,7 @@ import Button from '~components/common/Button' import CharLimitedFieldset from '~components/common/CharLimitedFieldset' import DurationInput from '~components/common/DurationInput' import Input from '~components/common/Input' -import RaidDropdown from '~components/RaidDropdown' +import RaidCombobox from '~components/raids/RaidCombobox' import Switch from '~components/common/Switch' import Tooltip from '~components/common/Tooltip' import Token from '~components/common/Token' @@ -227,8 +227,8 @@ const PartyHeader = (props: Props) => { setOpen(!open) } - function receiveRaid(slug?: string) { - if (slug) setRaidSlug(slug) + function receiveRaid(raid?: Raid) { + if (raid) setRaidSlug(raid?.slug) } function switchValue(value: boolean) { @@ -260,7 +260,8 @@ const PartyHeader = (props: Props) => { function updateDetails(event: React.MouseEvent) { const descriptionValue = descriptionInput.current?.value - const raid = raids.find((raid) => raid.slug === raidSlug) + const allRaids = appState.raidGroups.flatMap((group) => group.raids) + const raid = allRaids.find((raid) => raid.slug === raidSlug) const details: DetailsObject = { fullAuto: fullAuto, @@ -498,9 +499,9 @@ const PartyHeader = (props: Props) => { error={errors.name} ref={nameInput} /> -
    @@ -650,7 +651,7 @@ const PartyHeader = (props: Props) => {
{renderUserBlock()} - {party.raid ? linkedRaidBlock(party.raid) : ''} + {appState.party.raid ? linkedRaidBlock(appState.party.raid) : ''} {party.created_at != '' ? (