Skip to content

Commit

Permalink
console: New design of dropdown implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
PavelJankoski committed Nov 29, 2023
1 parent bd1776b commit f6c9889
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pkg/webui/components/button-v2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import classnames from 'classnames'
import { useIntl } from 'react-intl'

import Icon from '@ttn-lw/components/icon'
import Dropdown from '@ttn-lw/components/dropdown'
import Dropdown from '@ttn-lw/components/dropdown-v2'

import Message from '@ttn-lw/lib/components/message'

Expand Down
2 changes: 1 addition & 1 deletion pkg/webui/components/button-v2/story.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import React, { useRef } from 'react'

import Dropdown from '@ttn-lw/components/dropdown'
import Dropdown from '@ttn-lw/components/dropdown-v2'

import Button from '.'

Expand Down
93 changes: 93 additions & 0 deletions pkg/webui/components/dropdown-v2/dropdown.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright © 2023 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

ul.dropdown
transition: color $ad.s, background $ad.s
transition-timing-function: ease-out
border-radius: $br.l
border: 1px solid $c.grey-200
background: $c.white
box-shadow: 0px 3px 16px 0px rgba(0, 0, 0, 0.06)
z-index: $zi.nav
right: 0
position: absolute
padding: $cs.s
min-width: 14rem
z-index: $zi.dropdown
margin: 0

&.larger
li.dropdown-item
& > a.button, & > button.button
padding: $cs.l

hr
margin-top: 0
height: .1rem
background-color: $c-divider

li.dropdown-header-item
display: block
margin-bottom: 0
font-weight: $fw.bold

span
line-height: 1
display: block
padding: $cs.m

li.dropdown-item
display: block
margin-bottom: 0
text-align: left

button.button
reset-button()

& > a.button, & > button.button
box-sizing: border-box
line-height: 1
display: block
text-decoration: none
padding: 0.5rem
width: 100%
&:not(.active)
color: $c.grey-700
transition: color 0.2s ease

.icon
color: $c.grey-700
transition: color 0.2s ease

&.active
border-radius: $br.m
background: $c.tts-primary-150
transition: background 0.2s ease
color: $tc-deep-gray

.icon
color: $tc-deep-gray

&:hover
color: $tc-deep-gray

.icon
color: $tc-deep-gray

.icon
margin-right: $cs.xs

&:hover
color: $tc-deep-gray
text-decoration: none
138 changes: 138 additions & 0 deletions pkg/webui/components/dropdown-v2/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright © 2023 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import React, { useCallback } from 'react'
import classnames from 'classnames'
import { NavLink } from 'react-router-dom'

import Icon from '@ttn-lw/components/icon'
import Link from '@ttn-lw/components/link'

import Message from '@ttn-lw/lib/components/message'

import PropTypes from '@ttn-lw/lib/prop-types'

import style from './dropdown.styl'

const Dropdown = React.forwardRef(({ className, children, larger, onItemsClick }, ref) => (
<ul
onClick={onItemsClick}
className={classnames(style.dropdown, className, { [style.larger]: larger })}
ref={ref}
>
{children}
</ul>
))

Dropdown.propTypes = {
children: PropTypes.node.isRequired,
className: PropTypes.string,
larger: PropTypes.bool,
onItemsClick: PropTypes.func,
}

Dropdown.defaultProps = {
className: undefined,
larger: false,
onItemsClick: () => null,
}

const DropdownItem = ({
active,
icon,
title,
path,
action,
exact,
showActive,
tabIndex,
external,
...rest
}) => {
const iconElement = icon && <Icon className={style.icon} icon={icon} nudgeUp />
const activeClassName = classnames({
[style.active]: (!Boolean(action) && showActive) || active,
})
const cls = useCallback(
({ isActive }) => classnames(style.button, { [activeClassName]: isActive }),
[activeClassName],
)
const ItemElement = action ? (
<button
onClick={action}
onKeyPress={action}
role="tab"
tabIndex={tabIndex}
className={classnames(style.button, activeClassName)}
>
{iconElement}
<Message content={title} />
</button>
) : external ? (
<Link.Anchor href={path} external tabIndex={tabIndex} className={style.button}>
{Boolean(iconElement) ? iconElement : null}
<Message content={title} />
</Link.Anchor>
) : (
<NavLink className={cls} to={path} end={exact} tabIndex={tabIndex}>
{iconElement}
<Message content={title} />
</NavLink>
)
return (
<li className={style.dropdownItem} key={title.id || title} {...rest}>
{ItemElement}
</li>
)
}

DropdownItem.propTypes = {
action: PropTypes.func,
active: PropTypes.bool,
exact: PropTypes.bool,
external: PropTypes.bool,
icon: PropTypes.string,
path: PropTypes.string,
showActive: PropTypes.bool,
tabIndex: PropTypes.string,
title: PropTypes.message.isRequired,
}

DropdownItem.defaultProps = {
active: false,
action: undefined,
exact: false,
external: false,
icon: undefined,
path: undefined,
showActive: true,
tabIndex: '0',
}

const DropdownHeaderItem = ({ title }) => (
<li className={style.dropdownHeaderItem}>
<span>
<Message content={title} />
</span>
</li>
)

DropdownHeaderItem.propTypes = {
title: PropTypes.message.isRequired,
}

Dropdown.Item = DropdownItem
Dropdown.HeaderItem = DropdownHeaderItem

export default Dropdown
32 changes: 32 additions & 0 deletions pkg/webui/components/dropdown-v2/story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright © 2023 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import React from 'react'

import Dropdown from '.'

export default {
title: 'Dropdown V2',
component: Dropdown,
}

export const Default = () => (
<div style={{ height: '6rem' }}>
<Dropdown>
<Dropdown.HeaderItem title={'dropdown items'} />
<Dropdown.Item title={'Example'} path={'example/path'} icon="favorite" />
<Dropdown.Item title={'Add'} path={'add/path'} icon="add" />
</Dropdown>
</div>
)

0 comments on commit f6c9889

Please sign in to comment.