Skip to content

Commit

Permalink
Merge pull request #1709 from adevinta/1681-components-dropdown-dropd…
Browse files Browse the repository at this point in the history
…ownleadingicon-inside-dropdowntrigger
  • Loading branch information
andresin87 authored Dec 1, 2023
2 parents 799fd9b + fbbc9e3 commit 6f2d717
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 2 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/components/dropdown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"dependencies": {
"@radix-ui/react-id": "1.0.1",
"@spark-ui/form-field": "^1.4.0",
"@spark-ui/icon": "^2.1.0",
"@spark-ui/popover": "^1.2.7",
"@spark-ui/visually-hidden": "^1.2.0",
"class-variance-authority": "0.7.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/components/dropdown/src/Dropdown.doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ import { Dropdown } from '@spark-ui/dropdown'
description:
"The part that reflects the selected value. By default the selected item's text will be rendered. if you require more control, you can instead control the select and pass your own children. It should not be styled to ensure correct positioning. An optional placeholder prop is also available for when the select has no value.",
},
'Dropdown.LeadingIcon': {
of: Dropdown.LeadingIcon,
description: "Prepend a decorative icon inside the input (to the left).",
},
'Dropdown.Popover': {
of: Dropdown.Popover,
description: 'The part that is toggled and portaled when the trigger element is clicked.',
Expand Down
4 changes: 4 additions & 0 deletions packages/components/dropdown/src/Dropdown.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from '@spark-ui/button'
import { FormField } from '@spark-ui/form-field'
import { Book } from '@spark-ui/icons/dist/icons/Book'
import { Tag } from '@spark-ui/tag'
import { Meta, StoryFn } from '@storybook/react'
import { useState } from 'react'
Expand All @@ -18,6 +19,9 @@ export const Default: StoryFn = _args => {
<div className="w-sz-480 pb-[300px]">
<Dropdown>
<Dropdown.Trigger aria-label="Book">
<Dropdown.LeadingIcon>
<Book />
</Dropdown.LeadingIcon>
<Dropdown.Value placeholder="Pick a book" />
</Dropdown.Trigger>

Expand Down
9 changes: 9 additions & 0 deletions packages/components/dropdown/src/DropdownLeadingIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Icon } from '@spark-ui/icon'
import { ReactElement } from 'react'

export const LeadingIcon = ({ children }: { children: ReactElement }) => {
return <Icon>{children}</Icon>
}

LeadingIcon.id = 'LeadingIcon'
LeadingIcon.displayName = 'Dropdown.LeadingIcon'
10 changes: 9 additions & 1 deletion packages/components/dropdown/src/DropdownTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { cx } from 'class-variance-authority'
import { Fragment, ReactNode } from 'react'

import { useDropdownContext } from './DropdownContext'
import { findElement } from './utils'

interface TriggerProps {
'aria-label'?: string
Expand All @@ -18,6 +19,10 @@ export const Trigger = ({ 'aria-label': ariaLabel, children, className }: Trigge
? [Popover.Trigger, { asChild: true }]
: [Fragment, {}]

const finder = findElement(children)
const leadingIcon = finder('LeadingIcon')
const value = finder('Value')

return (
<>
{ariaLabel && (
Expand All @@ -34,7 +39,10 @@ export const Trigger = ({ 'aria-label': ariaLabel, children, className }: Trigge
)}
{...getToggleButtonProps()}
>
{children}
<span className="flex items-center justify-start gap-sm">
{leadingIcon}
{value}
</span>
<span className="px-sm">{isOpen ? <>&#8593;</> : <>&#8595;</>}</span>
</button>
</WrapperComponent>
Expand Down
4 changes: 4 additions & 0 deletions packages/components/dropdown/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Item } from './DropdownItem'
import { Items } from './DropdownItems'
import { ItemText } from './DropdownItemText'
import { Label } from './DropdownLabel'
import { LeadingIcon } from './DropdownLeadingIcon'
import { Popover } from './DropdownPopover'
import { Trigger } from './DropdownTrigger'
import { Value } from './DropdownValue'
Expand All @@ -24,6 +25,7 @@ export const Dropdown: FC<DropdownProps> & {
Divider: typeof Divider
Trigger: typeof Trigger
Value: typeof Value
LeadingIcon: typeof LeadingIcon
} = Object.assign(Root, {
Group,
Item,
Expand All @@ -34,6 +36,7 @@ export const Dropdown: FC<DropdownProps> & {
Divider,
Trigger,
Value,
LeadingIcon,
})

Dropdown.displayName = 'Dropdown'
Expand All @@ -46,3 +49,4 @@ Popover.displayName = 'Dropdown.Popover'
Divider.displayName = 'Dropdown.Divider'
Trigger.displayName = 'Dropdown.Trigger'
Value.displayName = 'Dropdown.Value'
LeadingIcon.displayName = 'Dropdown.LeadingIcon'
14 changes: 13 additions & 1 deletion packages/components/dropdown/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { type FC, isValidElement, type ReactElement, type ReactNode } from 'react'
import React, { Children, type FC, isValidElement, type ReactElement, type ReactNode } from 'react'

import { type ItemProps } from './DropdownItem'
import { type DropdownItem, type ItemsMap } from './types'
Expand Down Expand Up @@ -35,6 +35,18 @@ const getElementId = (element?: ReactElement) => {
return element ? (element.type as FC & { id?: string }).id : ''
}

export const findElement =
(children: React.ReactNode) =>
(...values: string[]) => {
const validChildren = Children.toArray(children).filter(isValidElement)

return validChildren.find(child => {
const displayName = getElementId(child)

return values.includes(displayName || '')
})
}

export const getOrderedItems = (
children: ReactNode,
result: DropdownItem[] = []
Expand Down

0 comments on commit 6f2d717

Please sign in to comment.