Skip to content

Commit

Permalink
feat: add IconButton component (only for navbar use tbh) (#411)
Browse files Browse the repository at this point in the history
* feat: add IconButton component (only for navbar use tbh)

* feat: use IconButton in Navbar

* fix: use custom tv

* fix: make padding right slightly smaller on mobile on navbar

for alignment of buttons with navbar
  • Loading branch information
karrui authored Aug 5, 2024
1 parent 6f8d74c commit 31871b6
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 55 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Meta, StoryObj } from "@storybook/react"
import { BiSearch } from "react-icons/bi"

import { IconButton } from "./IconButton"

const meta: Meta<typeof IconButton> = {
title: "Next/Internal Components/IconButton",
component: IconButton,
parameters: {
themes: {
themeOverride: "Isomer Next",
},
},
}
export default meta
type Story = StoryObj<typeof IconButton>

export const Default: Story = {
args: {
icon: BiSearch,
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"use client"

import type { ButtonProps as AriaButtonProps } from "react-aria-components"
import type { IconType } from "react-icons"
import type { VariantProps } from "tailwind-variants"
import type { SetRequired } from "type-fest"
import { forwardRef } from "react"
import { Button as AriaButton, composeRenderProps } from "react-aria-components"

import { tv } from "~/lib/tv"
import { focusRing } from "~/utils/focusRing"

export const iconButtonStyles = tv({
base: "box-border w-fit cursor-pointer rounded text-center transition",
extend: focusRing,
variants: {
variant: {
clear:
"bg-transparent hover:bg-base-canvas-backdrop/50 active:bg-base-canvas-backdrop/80",
},
isDisabled: {
true: "cursor-not-allowed",
},
colorScheme: {
default: "",
},
size: {
base: "flex h-12 w-12 items-center justify-center p-2",
},
},
compoundVariants: [
{
variant: "clear",
colorScheme: "default",
className: "text-base-content",
},
],
defaultVariants: {
size: "base",
variant: "clear",
colorScheme: "default",
},
})

export const iconButtonIconStyles = tv({
base: "h-6 w-6",
})

export interface IconButtonProps
extends SetRequired<Omit<AriaButtonProps, "children">, "aria-label">,
VariantProps<typeof iconButtonStyles> {
icon: IconType
}

export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
({ icon: Icon, className, variant, size, colorScheme, ...props }, ref) => {
return (
<AriaButton
{...props}
ref={ref}
className={composeRenderProps(className, (className, renderProps) =>
iconButtonStyles({
...renderProps,
variant,
size,
className,
colorScheme,
}),
)}
>
<Icon className={iconButtonIconStyles()} />
</AriaButton>
)
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./IconButton"

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@

import { useCallback, useLayoutEffect, useRef, useState } from "react"
import { usePreventScroll } from "react-aria"
import { BiSearch, BiX } from "react-icons/bi"
import { BiMenu, BiSearch, BiX } from "react-icons/bi"
import { useOnClickOutside, useResizeObserver } from "usehooks-ts"

import type { NavbarProps } from "~/interfaces"
import { tv } from "~/lib/tv"
import { LocalSearchInputBox, SearchSGInputBox } from "../../internal"
import { HamburgerIcon } from "./HamburgerIcon"
import { IconButton } from "../IconButton"
import { MobileNavMenu } from "./MobileNavMenu"
import { NavItem } from "./NavItem"

const navbarStyles = tv({
slots: {
overlay: "fixed inset-0 bg-canvas-overlay bg-opacity-40",
icon: "my-3 flex items-center justify-center text-[1.25rem] lg:my-[1.1875rem] lg:h-[2.125rem] lg:w-[2.125rem]",
icon: "my-3 lg:my-[1.1875rem]",
logo: "my-3 h-10 w-32 max-w-[6.625rem] object-contain object-center lg:h-12 lg:max-w-32",
navbarContainer: "flex min-h-16 w-full bg-white lg:min-h-[4.25rem]",
navbar:
"mx-auto flex w-full max-w-screen-xl gap-x-4 px-6 lg:gap-x-6 lg:px-10",
"mx-auto flex w-full max-w-screen-xl gap-x-4 pl-6 pr-3 lg:gap-x-6 lg:px-10",
navItemContainer: "hidden flex-wrap items-center gap-x-6 lg:flex",
},
})
Expand Down Expand Up @@ -132,53 +132,49 @@ export const Navbar = ({
{/* Spacer */}
<div className="flex-1" />

{/* Search icon */}
{search && !isHamburgerOpen && (
<>
{isSearchOpen ? (
<button
onClick={() => setIsSearchOpen(!isSearchOpen)}
aria-label="Close search bar"
className={icon({ className: "text-[1.5rem]" })}
>
<BiX />
</button>
) : (
<button
onClick={() => setIsSearchOpen(!isSearchOpen)}
aria-label="Open search bar"
className={icon()}
>
<BiSearch />
</button>
)}
</>
)}
<div className="flex flex-row gap-1">
{/* Search icon */}
{search && !isHamburgerOpen && (
<>
{isSearchOpen ? (
<IconButton
onPress={() => setIsSearchOpen(!isSearchOpen)}
aria-label="Close search bar"
icon={BiX}
className={icon()}
/>
) : (
<IconButton
onPress={() => setIsSearchOpen(!isSearchOpen)}
aria-label="Open search bar"
icon={BiSearch}
className={icon()}
/>
)}
</>
)}

{/* Hamburger menu for small screens */}
<div className="flex lg:hidden">
{/* Hamburger menu for small screens */}
{isHamburgerOpen ? (
<button
onClick={() => {
<IconButton
onPress={() => {
setIsHamburgerOpen(false)
setOpenNavItemIdx(-1)
}}
className={icon({ className: "text-[1.5rem]" })}
aria-label="Close navigation menu"
>
<BiX />
</button>
icon={BiX}
className={icon({ className: "lg:hidden" })}
/>
) : (
<button
onClick={() => {
<IconButton
onPress={() => {
setIsHamburgerOpen(true)
setIsSearchOpen(false)
}}
className={icon({ className: "lg:hidden" })}
aria-label="Open navigation menu"
className={icon()}
>
<HamburgerIcon />
</button>
icon={BiMenu}
/>
)}
</div>
</div>
Expand Down

0 comments on commit 31871b6

Please sign in to comment.