-
Notifications
You must be signed in to change notification settings - Fork 3
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
styled-components.dropdown menu items #616
base: feature/config-provider
Are you sure you want to change the base?
Changes from all commits
8f3e2a7
bda00ac
2728d89
5e99df2
0eff0aa
7b9cfd5
bfba41d
14b493f
c7b0ae1
60bbf94
8a8cc43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import React from "react"; | ||
import { Link, LinkProps } from "react-router-dom"; | ||
import styled, { css } from "styled-components"; | ||
import { ArrowRight } from "../Icons"; | ||
|
||
// Dropdown items can be of a few component | ||
// varieties, including buttons, router links, and | ||
// anchor tags. This file unifies their styling, | ||
// and then divides them into three component exports | ||
// for semantically explicit usage in dropdowns. | ||
|
||
// Common styles | ||
const baseStyles = css` | ||
font-family: ${(props) => props.theme.typography}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does TS pick up that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to intellisense the type isn't I'm not getting a typescript error, do you type props more explicitly in your implementation of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't used the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It did, and the ThemeProvider is a essentially a context |
||
background: none; | ||
border: 2px solid ${({ theme }) => theme.colors.dropdown.background}; | ||
border-radius: 3px; | ||
color: ${({ theme }) => theme.colors.dropdown.text}; | ||
cursor: pointer; | ||
height: 28px; | ||
padding: 6px; | ||
width: 100%; | ||
min-width: 177px; | ||
font-size: 14px; | ||
|
||
&&& { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. && (or here &&&) This is a nice way in https://styled-components.com/docs/basics#adapting-based-on-props |
||
&:focus-visible, | ||
&:focus-visible:hover { | ||
outline: 1.5px solid ${({ theme }) => theme.colors.dropdown.active}; | ||
border: 2px solid ${({ theme }) => theme.colors.dropdown.background}; | ||
color: ${({ theme }) => theme.colors.dropdown.activeTextColor}; | ||
background-color: ${({ theme }) => theme.colors.dropdown.active}; | ||
|
||
svg { | ||
fill: ${({ theme }) => theme.colors.dropdown.background}; | ||
} | ||
} | ||
|
||
&:hover:not(:focus-visible) { | ||
background-color: ${({ theme }) => theme.colors.dropdown.active}; | ||
color: ${({ theme }) => theme.colors.dropdown.activeTextColor}; | ||
border-color: ${({ theme }) => theme.colors.dropdown.active}; | ||
|
||
svg { | ||
fill: ${({ theme }) => theme.colors.dropdown.background}; | ||
} | ||
} | ||
} | ||
`; | ||
|
||
const contentStyles = css` | ||
display: flex; | ||
align-items: center; | ||
gap: 8px; | ||
justify-content: space-between; | ||
color: inherit; | ||
|
||
svg { | ||
font-size: 10px; | ||
} | ||
`; | ||
|
||
// Styled components | ||
const StyledDropdownButton = styled.button` | ||
${baseStyles} | ||
${contentStyles} | ||
`; | ||
|
||
const StyledRouterLink = styled(Link)` | ||
${baseStyles} | ||
${contentStyles} | ||
`; | ||
|
||
const StyledExternalLink = styled.a` | ||
${baseStyles} | ||
${contentStyles} | ||
`; | ||
Comment on lines
+64
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✨✨✨✨✨✨ |
||
|
||
// Typing for the props of each variant | ||
interface BaseDropdownItemProps { | ||
children: React.ReactNode; | ||
onClick?: () => void; | ||
className?: string; | ||
} | ||
|
||
interface ButtonProps extends BaseDropdownItemProps { | ||
isSubmenuTrigger?: boolean; | ||
} | ||
|
||
interface RouterProps extends BaseDropdownItemProps { | ||
to: LinkProps["to"]; | ||
newTab?: boolean; | ||
} | ||
|
||
interface AnchorProps extends Omit<BaseDropdownItemProps, "onClick"> { | ||
href: string; | ||
newTab?: boolean; | ||
} | ||
|
||
const getNewTabAttributes = (newTab?: boolean) => | ||
newTab ? { target: "_blank", rel: "noopener noreferrer" } : {}; | ||
|
||
// Components for use in dropdown menus: | ||
export const DropdownButton: React.FC<ButtonProps> = ({ | ||
children, | ||
className, | ||
onClick, | ||
isSubmenuTrigger, | ||
}) => ( | ||
<StyledDropdownButton type="button" onClick={onClick} className={className}> | ||
{children} | ||
{isSubmenuTrigger && ArrowRight} | ||
</StyledDropdownButton> | ||
); | ||
|
||
export const DropdownRouterLink: React.FC<RouterProps> = ({ | ||
children, | ||
className, | ||
to, | ||
newTab, | ||
}) => ( | ||
<StyledRouterLink | ||
to={to} | ||
className={className} | ||
{...getNewTabAttributes(newTab)} | ||
> | ||
{children} | ||
</StyledRouterLink> | ||
); | ||
|
||
export const DropdownAnchor: React.FC<AnchorProps> = ({ | ||
children, | ||
className, | ||
href, | ||
newTab, | ||
}) => ( | ||
<StyledExternalLink | ||
href={href} | ||
className={className} | ||
{...getNewTabAttributes(newTab)} | ||
> | ||
{children} | ||
</StyledExternalLink> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,18 @@ | ||
.menu { | ||
.menu-wrapper { | ||
width: fit-content; | ||
background-color: var(--dark-theme-dropdown-menu-bg); | ||
border-radius: 3px; | ||
padding: 8px; | ||
} | ||
|
||
.menu svg { | ||
fill: var(--dark-theme-menu-text-color); | ||
padding: 4px; | ||
} | ||
|
||
.menu :global(.ant-dropdown-menu-item), | ||
.menu :global(.ant-dropdown-menu-submenu) { | ||
border: 2px solid var(--dark-theme-dropdown-menu-item-bg); | ||
border-radius: 4px; | ||
height: 32px; | ||
.menu { | ||
background-color: inherit; | ||
display: flex; | ||
flex-direction: column; | ||
gap: 4px; | ||
} | ||
|
||
.menu :global(.ant-dropdown-menu-item) :global(.ant-btn) { | ||
color: var(--dark-theme-dropdown-menu-item-color); | ||
.menu-wrapper .menu :global(.ant-dropdown-menu-submenu-title), | ||
.menu-wrapper .menu :global(.ant-dropdown-menu-item-only-child) { | ||
padding: 0px; | ||
} | ||
|
||
.menu :global(.ant-dropdown-menu-item):hover, | ||
.menu :global(.ant-dropdown-menu-submenu):hover { | ||
background-color: var(--dark-theme-dropdown-menu-item-hover-bg); | ||
} | ||
|
||
.menu :global(.ant-dropdown-menu-item):hover *, | ||
.menu :global(.ant-dropdown-menu-submenu):hover * { | ||
color: var(--dark-theme-dropdown-menu-item-hover-color); | ||
fill: var(--dark-theme-dropdown-menu-item-hover-color); | ||
} | ||
|
||
.menu :global(.ant-dropdown-menu-item):focus-within, | ||
.menu :global(.ant-dropdown-menu-submenu):focus-within { | ||
z-index: 1000; | ||
background-color: var(--dark-theme-dropdown-menu-item-focus-bg); | ||
outline: 1px solid var(--dark-theme-dropdown-menu-item-focus-outline); | ||
} | ||
|
||
.menu :global(.ant-dropdown-menu-item) *:focus-visible { | ||
color: var(--dark-theme-dropdown-menu-item-focus-color); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is our only styled component for now, but we will probably want to add a
GlobalStyles
provider to get things like basic fonts into all styled components, and it could potentially replace some or all of the global style rules instyle.css
if we do that.