Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
aaeef96
Update pages/components/docs/Dropdown.md
Jul 22, 2019
d1c788e
use useEffect for event listener
Jul 24, 2019
fab9754
add open back
Jul 24, 2019
1e7d44d
fix typo
Jul 24, 2019
7e84a15
lint
Jul 24, 2019
36156a8
update tests
Jul 24, 2019
3fc3694
update tests
Jul 25, 2019
fcc55c7
update docs
Jul 25, 2019
5f7f1cd
byeee test
Jul 25, 2019
1bf0255
lint
Jul 25, 2019
f5d60db
lint
Jul 26, 2019
442a35e
Merge pull request #499 from primer/dropdown-fix
Jul 26, 2019
0dacf7e
only close Details on click outside
shawnbot Aug 6, 2019
5167292
add keys to Dropdown test output
shawnbot Aug 6, 2019
4b9c183
add tests for Details click inside + outside
shawnbot Aug 6, 2019
0b20032
fix useRef() usage, add note
shawnbot Aug 6, 2019
f9bfe2e
rebuild package-lock
shawnbot Aug 6, 2019
e7ec1ab
lint
shawnbot Aug 6, 2019
80ce5d9
use ref.current
shawnbot Aug 6, 2019
709733c
fix ref again
shawnbot Aug 6, 2019
ee5eeea
argh
shawnbot Aug 6, 2019
5c31f6e
Merge branch 'master' into release-14.0.0
shawnbot Aug 7, 2019
ddf8d1c
Have primer components extend props for their native elements.
dmarcey Sep 16, 2019
93fac79
remove prevent default
Sep 24, 2019
507612d
Merge branch 'master' into release-14.0.0
Sep 24, 2019
110d61f
Merge branch 'master' into details-event-fix
Sep 24, 2019
22841e3
Merge branch 'release-14.0.0' into details-event-fix
Sep 24, 2019
334c855
don't prevent default
Sep 24, 2019
5437ef0
lint
Sep 24, 2019
12688cf
don't need toggle
Sep 24, 2019
6b059a6
disable test for now
Sep 24, 2019
d70a101
Merge pull request #517 from primer/details-event-fix
Sep 24, 2019
23cc762
Merge pull request #544 from primer/users/dmarcey/nativeProps
Sep 24, 2019
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
24 changes: 3 additions & 21 deletions docs/content/Details.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,13 @@ You are responsible for rendering your own `<summary>`. To style your summary el
```

## With children as a function
The render function gets an object with two keys:

* `open` is a boolean reflecting the `<details>` element's `open` attribute, and can be used to conditionally show or hide content.
* `toggle` is a function that can be assigned to event handlers to trigger toggling of the `open` state.

If you use this form or the render prop (see below), **you must attach the `toggle` prop as an event listener**. If you don't the render function will not be called when the element is toggled by the native browser behavior.
The render function gets an object with the `open` prop to allow you to conditionally update UI based on the open state of the dropdown:

```jsx live
<Details>
{({open, toggle}) => (
{({open}) => (
<>
<Button as="summary" onClick={toggle}>
<Button as="summary">
{open ? 'Hide' : 'Show'}
</Button>
<p>This should show and hide</p>
Expand All @@ -39,18 +34,6 @@ If you use this form or the render prop (see below), **you must attach the `togg
</Details>
```

## With render prop
The Details component also accepts a `render` function prop.

```jsx live
<Details overlay render={({open, toggle}) => (
<>
<Button as="summary" onClick={toggle}>Open? {String(open)}</Button>
<p>This is the content.</p>
</>
)} />
```

## System props

Details components get `COMMON` system props. Read our [System Props](/system-props) doc page for a full list of available props.
Expand All @@ -60,5 +43,4 @@ Details components get `COMMON` system props. Read our [System Props](/system-pr
| Name | Type | Default | Description |
| :- | :- | :-: | :- |
| open | Boolean | | Sets the open/closed state of the Details component |
| render | Function | | Optional render function, to allow you to handle toggling and open/closed state from a container component.
| overlay | Boolean | false | Sets whether or not element will close when user clicks outside of it
82 changes: 34 additions & 48 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,34 @@ declare module '@primer/components' {
Item: React.FunctionComponent<FlexItemProps>
}

export interface BoxProps extends BaseProps, CommonProps, LayoutProps {}
export interface BoxProps extends BaseProps, CommonProps, LayoutProps, React.HTMLAttributes<HTMLDivElement> {}

export const Box: React.FunctionComponent<BoxProps>

export interface TextProps extends BaseProps, CommonProps, TypographyProps {}
export interface TextProps extends BaseProps, CommonProps, TypographyProps, React.HTMLAttributes<HTMLSpanElement> {}

export const Text: React.FunctionComponent<TextProps>

export interface HeadingProps extends BaseProps, CommonProps, TypographyProps {}
export interface HeadingProps
extends BaseProps,
CommonProps,
TypographyProps,
React.HTMLAttributes<HTMLHeadingElement> {}

export const Heading: React.FunctionComponent<HeadingProps>

type DetailsRenderFunction = (args: {open: boolean; toggle: () => void}) => React.ReactElement

export interface DetailsProps extends CommonProps {
open?: boolean
export interface DetailsProps extends CommonProps, React.HTMLAttributes<HTMLDetailsElement> {
render?: DetailsRenderFunction
children?: DetailsRenderFunction | React.ReactNode
overlay?: boolean
}

export const Details: React.FunctionComponent<DetailsProps>

export interface ButtonProps extends BaseProps, CommonProps {
disabled?: boolean
export interface ButtonProps extends BaseProps, CommonProps, React.HTMLAttributes<HTMLDetailsElement> {
grouped?: boolean
onClick?: Function
size?: 'sm' | 'large'
}

Expand All @@ -115,9 +116,7 @@ declare module '@primer/components' {
export const ButtonDanger: React.FunctionComponent<ButtonProps>
export const Button: React.FunctionComponent<ButtonProps>

export interface AvatarProps extends CommonProps {
alt: string
src: string
export interface AvatarProps extends CommonProps, React.HTMLAttributes<HTMLImageElement> {
isChild?: boolean
size?: number
}
Expand All @@ -128,7 +127,7 @@ declare module '@primer/components' {

export const BaseStyles: React.FunctionComponent<BaseStylesProps>

export interface BorderBoxProps extends CommonProps, LayoutProps {
export interface BorderBoxProps extends CommonProps, LayoutProps, BoxProps {
border?: string
borderColor?: string
borderRadius?: string | number
Expand All @@ -137,19 +136,17 @@ declare module '@primer/components' {

export const BorderBox: React.FunctionComponent<BorderBoxProps>

export interface BranchNameProps extends CommonProps {
href?: string
}
export interface BranchNameProps extends CommonProps, React.HTMLAttributes<HTMLAnchorElement> {}

export const BranchName: React.FunctionComponent<BranchNameProps>

export interface CircleBadgeProps extends CommonProps {
export interface CircleBadgeProps extends CommonProps, React.HTMLAttributes<HTMLDivElement> {
size?: string | number
}

export const CircleBadge: React.FunctionComponent<CircleBadgeProps>

export interface CircleOcticonProps extends CommonProps {
export interface CircleOcticonProps extends CommonProps, FlexProps {
size?: number
icon: React.ReactNode
}
Expand All @@ -163,9 +160,9 @@ declare module '@primer/components' {

export const StyledOcticon: React.FunctionComponent<StyledOcticonProps>

export interface DropdownProps extends CommonProps {}
export interface DropdownProps extends CommonProps, ButtonProps {}

export interface DropdownMenuProps extends CommonProps {
export interface DropdownMenuProps extends CommonProps, React.HTMLAttributes<HTMLUListElement> {
direction?: string
title: string
}
Expand All @@ -175,11 +172,11 @@ declare module '@primer/components' {
Item: React.FunctionComponent<DropdownProps>
}

export interface FilterListProps extends CommonProps {
export interface FilterListProps extends CommonProps, React.HTMLAttributes<HTMLUListElement> {
small?: boolean
}

export interface FilterListItemProps extends CommonProps {
export interface FilterListItemProps extends CommonProps, React.HTMLAttributes<HTMLAnchorElement> {
count?: number
selected?: boolean
}
Expand All @@ -188,41 +185,44 @@ declare module '@primer/components' {
Item: React.FunctionComponent<FilterListItemProps>
}

export interface FlashProps extends CommonProps {
export interface FlashProps extends CommonProps, React.HTMLAttributes<HTMLDivElement> {
full?: boolean
scheme?: string
}

export const Flash: React.FunctionComponent<FlashProps>

export interface CounterLabelProps extends CommonProps {
export interface CounterLabelProps extends CommonProps, React.HTMLAttributes<HTMLSpanElement> {
scheme?: string
}

export const CounterLabel: React.FunctionComponent<CounterLabelProps>

export interface LabelProps extends CommonProps {
export interface LabelProps extends CommonProps, React.HTMLAttributes<HTMLSpanElement> {
outline?: boolean
size?: 'small' | 'medium' | 'large' | 'xl'
dropshadow?: boolean
}

export const Label: React.FunctionComponent<LabelProps>

export interface LinkProps extends CommonProps, TypographyProps {
href?: string
export interface LinkProps extends CommonProps, TypographyProps, React.HTMLAttributes<HTMLAnchorElement> {
underline?: boolean
}

export const Link: React.FunctionComponent<LinkProps>

export interface PointerBoxProps extends CommonProps, LayoutProps {
export interface PointerBoxProps extends CommonProps, LayoutProps, BorderBoxProps {
caret?: string
}

export const PointerBox: React.FunctionComponent<PointerBoxProps>

export interface PositionComponentProps extends PositionProps, CommonProps, LayoutProps {}
export interface PositionComponentProps
extends PositionProps,
CommonProps,
LayoutProps,
React.HTMLAttributes<HTMLDivElement> {}

export const Relative: React.FunctionComponent<PositionComponentProps>
export const Absolute: React.FunctionComponent<PositionComponentProps>
Expand All @@ -236,38 +236,26 @@ declare module '@primer/components' {

export const StateLabel: React.FunctionComponent<StateLabelProps>

export interface TabNavProps extends CommonProps {
'aria-label'?: string
}
export interface TabNavProps extends CommonProps, React.HTMLAttributes<HTMLDivElement> {}

export interface TabNavLinkProps extends CommonProps {
href?: string
export interface TabNavLinkProps extends CommonProps, React.HTMLAttributes<HTMLAnchorElement> {
selected?: boolean
}

export const TabNav: React.FunctionComponent<TabNavProps> & {
Link: React.FunctionComponent<TabNavLinkProps>
}

export interface TextInputProps extends CommonProps {
export interface TextInputProps extends CommonProps, React.HTMLAttributes<HTMLInputElement> {
autocomplete?: string
'aria-label'?: string
block?: boolean
disabled?: boolean
id?: string
name?: string
onChange?: (evt: React.ChangeEvent<HTMLInputElement>) => void
placeholder?: string
required?: boolean
size?: 'small' | 'large'
value?: string
}

export const TextInput: React.FunctionComponent<TextInputProps>

export interface TooltipProps extends CommonProps {
export interface TooltipProps extends CommonProps, React.HTMLAttributes<HTMLSpanElement> {
align?: 'left' | 'right'
'aria-label'?: string
direction?: 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw'
noDelay?: boolean
text?: string
Expand All @@ -276,16 +264,14 @@ declare module '@primer/components' {

export const Tooltip: React.FunctionComponent<TooltipProps>

export interface UnderlineNavProps extends CommonProps {
export interface UnderlineNavProps extends CommonProps, React.HTMLAttributes<HTMLDivElement> {
actions?: React.ReactNode
align?: 'right'
'aria-label'?: string
full?: boolean
label?: string
}

export interface UnderlineNavLinkProps extends CommonProps {
href?: string
export interface UnderlineNavLinkProps extends CommonProps, React.HTMLAttributes<HTMLAnchorElement> {
selected?: boolean
}

Expand Down
14 changes: 11 additions & 3 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@primer/components",
"version": "13.5.0",
"version": "14.0.0",
"description": "Primer react components",
"main": "dist/index.umd.js",
"module": "dist/index.esm.js",
Expand Down
43 changes: 22 additions & 21 deletions src/Details.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useState} from 'react'
import React, {useState, useEffect, useRef} from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {COMMON} from './constants'
Expand All @@ -16,33 +16,34 @@ function getRenderer(children) {
return typeof children === 'function' ? children : () => children
}

function DetailsBase({children, overlay, render = getRenderer(children), ...rest}) {
const [open, setOpen] = useState(Boolean(rest.open))
function DetailsBase({children, overlay, render = getRenderer(children), defaultOpen = false, ...rest}) {
const [open, setOpen] = useState(defaultOpen)
const ref = useRef(null)

function toggle(event) {
if (event) event.preventDefault()
if (overlay) {
openMenu()
} else {
setOpen(!open)
}
}

function openMenu() {
if (!open) {
setOpen(true)
useEffect(() => {
if (overlay && open) {
document.addEventListener('click', closeMenu)
return () => {
document.removeEventListener('click', closeMenu)
}
}
}, [open, overlay])

function toggle(event) {
setOpen(event.target.open)
}

function closeMenu(event) {
if (event) event.preventDefault()
setOpen(false)
document.removeEventListener('click', closeMenu)
// only close the menu if we're clicking outside
if (event && event.target.closest('details') !== ref.current) {
setOpen(false)
document.removeEventListener('click', closeMenu)
}
}

return (
<DetailsReset {...rest} open={open} overlay={overlay}>
{render({open, toggle})}
<DetailsReset {...rest} ref={ref} open={open} onToggle={toggle} overlay={overlay}>
{render({open})}
</DetailsReset>
)
}
Expand All @@ -57,7 +58,7 @@ Details.defaultProps = {
Details.propTypes = {
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
className: PropTypes.string,
open: PropTypes.bool,
defaultOpen: PropTypes.bool,
overlay: PropTypes.bool,
render: PropTypes.func,
theme: PropTypes.object,
Expand Down
Loading