Skip to content
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

Shadcn migration - button dropdown #13971

Merged
merged 6 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-compose-refs": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-portal": "^1.1.1",
Expand Down
128 changes: 54 additions & 74 deletions src/components/ButtonDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import React, { MouseEvent, useState } from "react"
import { useTranslation } from "next-i18next"
import React, { useState } from "react"
import { MdMenu } from "react-icons/md"
import {
Button,
ButtonProps,
Menu,
MenuButton,
MenuItem,
MenuList,
} from "@chakra-ui/react"

// Utils
import { cn } from "@/lib/utils/cn"
import { trackCustomEvent } from "@/lib/utils/matomo"

// Components
import { BaseLink } from "./Link"
import { Button } from "./ui/buttons/Button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "./ui/dropdown-menu"
import { BaseLink } from "./ui/Link"

export interface ListItem {
text: string
Expand All @@ -33,91 +30,74 @@ export interface List {
items: Array<ListItem>
}

export type ButtonDropdownProps = ButtonProps & {
export type ButtonDropdownProps = {
list: List
className?: string
}

const ButtonDropdown = ({ list, ...rest }: ButtonDropdownProps) => {
const { t } = useTranslation("common")
const ButtonDropdown = ({ list, className }: ButtonDropdownProps) => {
const [selectedItem, setSelectedItem] = useState(list.text)
const handleClick = (
e: MouseEvent<HTMLElement>,
item: ListItem,
idx: number
) => {
const handleClick = (item: ListItem, idx: number) => {
const { matomo, callback } = item

if (matomo) {
trackCustomEvent(matomo)
}

if (callback) {
e.preventDefault()
callback(idx)
}
setSelectedItem(item.text)
}

return (
<Menu matchWidth>
<MenuButton
as={Button}
leftIcon={<MdMenu />}
variant="outline"
_active={{ bg: "transparent" }}
{...rest}
>
{t(selectedItem)}
</MenuButton>
<MenuList
py={2}
borderRadius="base"
border="1px"
borderColor="text"
bg="dropdownBackground"
zIndex="popover"
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
className={cn("flex justify-between", className)}
>
<MdMenu />
<span className="flex-1 text-center">{selectedItem}</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-[var(--radix-dropdown-menu-trigger-width)]"
sideOffset={8}
>
{list.items.map((item, idx) => {
const { text, href } = item

return href ? (
<BaseLink
key={idx}
href={href!}
isPartiallyActive={false}
textDecor="none"
color="text"
fontWeight="normal"
_hover={{ textDecor: "none", color: "primary.base" }}
_focus={{ textDecor: "none", color: "primary.base" }}
>
<MenuItem
as="span"
onClick={(e) => handleClick(e, item, idx)}
p={2}
textAlign="center"
justifyContent="center"
bg="dropdownBackground"
_hover={{
color: "primary.base",
bg: "dropdownBackgroundHover",
}}
_focus={{
color: "primary.base",
bg: "dropdownBackgroundHover",
}}
if (href) {
return (
<DropdownMenuItem
key={item.text}
className="justify-center"
onClick={() => handleClick(item, idx)}
asChild
>
{t(text)}
</MenuItem>
</BaseLink>
) : (
<MenuItem key={idx} onClick={(e) => handleClick(e, item, idx)}>
{t(text)}
</MenuItem>
<BaseLink
href={item.href!}
className="text-body no-underline focus-visible:outline-0"
>
<span>{text}</span>
</BaseLink>
</DropdownMenuItem>
)
}

return (
<DropdownMenuItem
key={item.text}
className="justify-center"
onClick={() => handleClick(item, idx)}
>
<span>{text}</span>
</DropdownMenuItem>
)
})}
</MenuList>
</Menu>
</DropdownMenuContent>
</DropdownMenu>
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/FeedbackWidget/FixedDot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const FixedDot = forwardRef<HTMLButtonElement, FixedDotProps>(
data-testid="feedback-widget-button"
aria-label={t("feedback-widget")}
className={cn(
"lg:mt-inherit sticky bottom-4 z-20 me-4 ms-auto flex size-12 items-center gap-0 rounded-full text-white shadow-table-item-box",
"lg:mt-inherit sticky bottom-4 z-overlay me-4 ms-auto flex size-12 items-center gap-0 rounded-full text-white shadow-table-item-box",
"transition-all duration-200 hover:shadow-none hover:transition-transform hover:duration-200",
!suppressScale && "hover:scale-110",
offsetBottom && "bottom-31 lg:bottom-4",
Expand Down
5 changes: 4 additions & 1 deletion src/components/LeftNavBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const LeftNavBar = ({
>
{dropdownLinks && (
<div className="relative mb-8 flex items-end justify-end">
<ButtonDropdown list={dropdownLinks} w="full" minW="240px" />
<ButtonDropdown
list={dropdownLinks}
className="w-full min-w-[240px]"
/>
</div>
)}
<h2 className="mb-8 text-3xl leading-xs">
Expand Down
59 changes: 0 additions & 59 deletions src/components/MdComponents/MdComponents.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import pickBy from "lodash/pickBy"
import type { Meta, StoryObj } from "@storybook/react/*"

import type { List as ButtonDropdownList } from "@/components/ButtonDropdown"

import { viewportModes } from "../../../.storybook/modes"

import MdComponentSet from "."
Expand Down Expand Up @@ -34,8 +32,6 @@ const {
hr: HR,
pre: Pre,
Page,
MobileButton,
MobileButtonDropdown,
} = MdComponentSet

const Para = () => (
Expand All @@ -53,9 +49,6 @@ export const MdComponents: StoryObj = {
<div className="mx-auto max-w-screen-lg">
<Page>
<ContentContainer>
<MobileButton>
<MobileButtonDropdown list={roadmapDropdownLinks} />
</MobileButton>
<Heading1>Heading1</Heading1>
<Para />
<Heading2>Heading2</Heading2>
Expand All @@ -75,55 +68,3 @@ export const MdComponents: StoryObj = {
</div>
),
}

const roadmapDropdownLinks: ButtonDropdownList = {
text: "nav-roadmap-options",
ariaLabel: "nav-roadmap-options-alt",
items: [
{
text: "nav-roadmap-home",
href: "/roadmap/",
matomo: {
eventCategory: `Roadmap dropdown`,
eventAction: `Clicked`,
eventName: "clicked roadmap home",
},
},
{
text: "nav-roadmap-security",
href: "/roadmap/security",
matomo: {
eventCategory: `Roadmap security dropdown`,
eventAction: `Clicked`,
eventName: "clicked roadmap security",
},
},
{
text: "nav-roadmap-scaling",
href: "/roadmap/scaling",
matomo: {
eventCategory: `Roadmap scaling dropdown`,
eventAction: `Clicked`,
eventName: "clicked roadmap scaling home",
},
},
{
text: "nav-roadmap-user-experience",
href: "/roadmap/user-experience/",
matomo: {
eventCategory: `Roadmap user experience dropdown`,
eventAction: `Clicked`,
eventName: "clicked roadmap user experience home",
},
},
{
text: "nav-roadmap-future-proofing",
href: "/roadmap/future-proofing",
matomo: {
eventCategory: `Roadmap future-proofing dropdown`,
eventAction: `Clicked`,
eventName: "clicked roadmap future-proofing home",
},
},
],
}
34 changes: 1 addition & 33 deletions src/components/MdComponents/index.tsx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { ComponentProps, type HTMLAttributes } from "react"
import { type HTMLAttributes } from "react"
import { Badge, Box, type BoxProps } from "@chakra-ui/react"

import type { ChildOnlyProp } from "@/lib/types"

import ButtonDropdown, {
type ButtonDropdownProps,
} from "@/components/ButtonDropdown"
import Contributors from "@/components/Contributors"
import MarkdownImage from "@/components/MarkdownImage"
import TooltipLink from "@/components/TooltipLink"
Expand Down Expand Up @@ -155,32 +152,6 @@ export const ContentContainer = (props: Pick<BoxProps, "id" | "children">) => {
)
}

export const MobileButton = (props: ChildOnlyProp) => {
return (
<div
className="sticky bottom-0 z-sticky w-full bg-background p-8 shadow-md lg:hidden"
{...props}
/>
)
}

export const StyledButtonDropdown = ({
list,
className,
...rest
}: HTMLAttributes<HTMLDivElement> & Pick<ButtonDropdownProps, "list">) => (
<Flex className={cn("mb-8 items-end justify-end", className)} {...rest}>
<ButtonDropdown list={list} w={{ base: "full", lg: "auto" }} minW="240px" />
</Flex>
)

export const MobileButtonDropdown = ({
className,
...props
}: ComponentProps<typeof StyledButtonDropdown>) => (
<StyledButtonDropdown className={cn("mb-0", className)} {...props} />
)

// All custom React components
export const reactComponents = {
Badge,
Expand All @@ -196,11 +167,8 @@ export const reactComponents = {
FeaturedText,
GlossaryTooltip,
InfoBanner,
MobileButton,
MobileButtonDropdown,
Page,
QuizWidget: StandaloneQuizWidget,
StyledButtonDropdown,
IssuesList,
Title,
YouTube,
Expand Down
11 changes: 11 additions & 0 deletions src/components/MobileButtonDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import ButtonDropdown, { type ButtonDropdownProps } from "./ButtonDropdown"

const MobileButtonDropdown = (props: ButtonDropdownProps) => {
return (
<div className="sticky bottom-0 z-sticky w-full bg-background p-8 shadow-md lg:hidden">
<ButtonDropdown {...props} className="w-full lg:w-auto" />
</div>
)
}

export default MobileButtonDropdown
2 changes: 1 addition & 1 deletion src/components/Staking/StakingConsiderations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const StakingConsiderations = ({ page }: StakingConsiderationsProps) => {

return (
<Flex flexDir={{ base: "column", md: "row" }}>
<ButtonDropdown list={dropdownLinks} hideFrom={mdBp} />
<ButtonDropdown list={dropdownLinks} className="mb-4 md:hidden" />
{/* TODO: Improve a11y */}
<Box flex={1} hideBelow={mdBp}>
{!!pageData && (
Expand Down
Loading
Loading