فهرست منبع

Merge pull request #32393 from overleaf/mfb-improve-styling-on-support-custom-bibtex-entry-types

Mfb improve styling on support custom bibtex entry types

GitOrigin-RevId: 091518fd80777521b2f04a6f262109ee70213cd0
Maria Florencia Besteiro Gonzalez 4 ماه پیش
والد
کامیت
71b303863b

+ 25 - 2
services/web/frontend/js/shared/components/ol/ol-autocomplete.tsx

@@ -31,6 +31,7 @@ export type OLAutocompleteProps = {
   createOptionPrefix?: string
   useFuzzySearch?: boolean
   inputRef?: React.ForwardedRef<HTMLInputElement>
+  expandUp?: boolean
 }
 
 type OLAutocompleteDisplayItem =
@@ -55,6 +56,7 @@ function OLAutocompleteInternal({
   createOptionPrefix = '+ Create',
   useFuzzySearch = false,
   inputRef,
+  expandUp = false,
 }: OLAutocompleteProps) {
   const { t } = useTranslation()
 
@@ -163,8 +165,8 @@ function OLAutocompleteInternal({
     onChange('')
   }
 
-  return (
-    <div className={classnames('dropdown', 'd-block', 'ol-autocomplete')}>
+  const getSearchBar = () => (
+    <div className={classnames({ 'mb-3': !expandUp, 'mt-3': expandUp })}>
       <OLFormLabel
         {...getLabelProps()}
         className={showLabel ? '' : 'visually-hidden'}
@@ -191,11 +193,16 @@ function OLAutocompleteInternal({
           </OLButton>
         )}
       </div>
+    </div>
+  )
 
+  const getResultsList = () => (
+    <>
       <ul
         {...getMenuProps()}
         className={classnames('dropdown-menu', 'select-dropdown-menu', {
           show: shouldShowDropdown,
+          'select-dropdown-menu-expand-up': expandUp,
         })}
       >
         {hasGroupedItems ? (
@@ -304,6 +311,22 @@ function OLAutocompleteInternal({
           })
         )}
       </ul>
+    </>
+  )
+
+  return (
+    <div className={classnames('dropdown', 'd-block', 'ol-autocomplete')}>
+      {expandUp ? (
+        <>
+          {getResultsList()}
+          {getSearchBar()}
+        </>
+      ) : (
+        <>
+          {getSearchBar()}
+          {getResultsList()}
+        </>
+      )}
     </div>
   )
 }

+ 30 - 0
services/web/frontend/stories/shared/autocomplete.stories.tsx

@@ -239,6 +239,30 @@ export const GroupedFuzzySearch: StoryObj<Args> = {
   },
 }
 
+export const ExpandUp: StoryObj<Args> = {
+  render: args => <InteractiveAutocomplete {...args} />,
+  args: {
+    items: sampleItems,
+    label: 'Framework (expand up)',
+    placeholder: 'Dropdown expands upward',
+    showLabel: true,
+    allowCreate: true,
+    expandUp: true,
+  },
+}
+
+export const ExpandUpGrouped: StoryObj<Args> = {
+  render: args => <InteractiveAutocomplete {...args} />,
+  args: {
+    items: entryTypeItems,
+    label: 'Entry type (expand up)',
+    placeholder: 'Grouped items expanding upward',
+    showLabel: true,
+    allowCreate: true,
+    expandUp: true,
+  },
+}
+
 const meta: Meta<typeof OLAutocomplete> = {
   title: 'Shared / Components / Autocomplete',
   component: OLAutocomplete,
@@ -254,6 +278,7 @@ const meta: Meta<typeof OLAutocomplete> = {
         'disabled',
         'createOptionPrefix',
         'useFuzzySearch',
+        'expandUp',
       ],
     },
   },
@@ -300,6 +325,11 @@ const meta: Meta<typeof OLAutocomplete> = {
       control: 'boolean',
       description: 'Enable fuzzy search matching for suggestions',
     },
+    expandUp: {
+      control: 'boolean',
+      description:
+        'When true, the dropdown expands upward and the search bar appears below the results list',
+    },
   },
 }
 

+ 1 - 1
services/web/frontend/stylesheets/components/all.scss

@@ -47,5 +47,5 @@
 @import 'group-members';
 @import 'upgrade-benefits';
 @import 'labeled-divider';
-@import 'ol-autocomplete';
+@import 'autocomplete';
 @import 'group-users';

+ 5 - 0
services/web/frontend/stylesheets/components/ol-autocomplete.scss → services/web/frontend/stylesheets/components/autocomplete.scss

@@ -9,5 +9,10 @@
     margin: 0;
     margin-top: 2px;
     max-height: 400px;
+
+    &.select-dropdown-menu-expand-up {
+      margin-top: 0;
+      margin-bottom: 2px;
+    }
   }
 }

+ 51 - 0
services/web/test/frontend/components/shared/ol-autocomplete.spec.tsx

@@ -58,6 +58,7 @@ function render(props: RenderProps) {
           disabled={props.disabled}
           createOptionPrefix={props.createOptionPrefix}
           useFuzzySearch={props.useFuzzySearch}
+          expandUp={props.expandUp}
         />
         <button type="submit">submit</button>
       </form>
@@ -528,4 +529,54 @@ describe('<OLAutocomplete />', function () {
       cy.contains('+ Create').should('exist')
     })
   })
+
+  describe('expandUp prop', function () {
+    it('renders search bar before results list when expandUp is false', function () {
+      render({ items: testItems, expandUp: false })
+      cy.findByRole('combobox').click()
+
+      cy.get('.ol-autocomplete').within(() => {
+        cy.get('.dropdown-menu').then($menu => {
+          cy.findByRole('combobox').then($input => {
+            const inputTop = $input[0].getBoundingClientRect().top
+            const menuTop = $menu[0].getBoundingClientRect().top
+            expect(inputTop).to.be.lessThan(menuTop)
+          })
+        })
+      })
+    })
+
+    it('renders results list before search bar when expandUp is true', function () {
+      render({ items: testItems, expandUp: true })
+      cy.findByRole('combobox').click()
+
+      cy.get('.ol-autocomplete').within(() => {
+        cy.get('.dropdown-menu').then($menu => {
+          cy.findByRole('combobox').then($input => {
+            const inputTop = $input[0].getBoundingClientRect().top
+            const menuTop = $menu[0].getBoundingClientRect().top
+            expect(menuTop).to.be.lessThan(inputTop)
+          })
+        })
+      })
+    })
+
+    it('applies correct margin class when expandUp is false', function () {
+      render({ items: testItems, expandUp: false })
+
+      cy.get('.ol-autocomplete').within(() => {
+        cy.get('.mb-3').should('exist')
+        cy.get('.mt-3').should('not.exist')
+      })
+    })
+
+    it('applies correct margin class when expandUp is true', function () {
+      render({ items: testItems, expandUp: true })
+
+      cy.get('.ol-autocomplete').within(() => {
+        cy.get('.mt-3').should('exist')
+        cy.get('.mb-3').should('not.exist')
+      })
+    })
+  })
 })