Skip to content

Commit

Permalink
feat: implement dropdown menu with checkboxes
Browse files Browse the repository at this point in the history
  • Loading branch information
berezinant committed Aug 14, 2024
1 parent fb44e16 commit 1184fbf
Show file tree
Hide file tree
Showing 25 changed files with 601 additions and 44 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,3 @@
*/

import './styles.scss';

function onToggleDropdown(event: PointerEvent): void {
(event.target as HTMLButtonElement).classList.toggle('button_dropdown_active');
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).onToggleDropdown = onToggleDropdown;
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@

&:hover,
.theme-dark &:hover {
background-color: lighten(rgb(48, 127, 255), 10%);
background-color: lighten(rgb(48, 127, 255), 10%); // color-key-blue
}

&::after {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

import './styles.scss';
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*!
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@import '../tokens/index';

.checkbox {
position: relative;

display: inline-block;

width: 18px;
height: 18px;

cursor: pointer;

input[type='checkbox'] {
width: 0;
height: 0;

opacity: 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<#macro display>
<div class="dropdown">
<button class="button button_dropdown" role="combobox"
aria-controls="id-of-listbox"
aria-haspopup="listbox"
aria-expanded="false"
></button>
<ul role="listbox" id="id-of-listbox" class="dropdown--list">
<li role="option" class="dropdown--option" tabindex="0">
<input type="checkbox" class="checkbox dropdown--checkbox" id="option-1" tabindex="-1"/>
Option 1
</li>
<li role="option" class="dropdown--option" tabindex="0">
<input type="checkbox" class="checkbox dropdown--checkbox" id="option-2" tabindex="-1"/>
Option 2
</li>
</#list>
</ul>
</div>
</#macro>
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

import './styles.scss';
import { hasAncestorWithClass } from '../utils';

// page objects selectors
const DROPDOWN = '[data-role="dropdown"]';
const DROPDOWN_TOGGLE = '[data-role="dropdown-toggle"]';
const DROPDOWN_LIST = '[data-role="dropdown-listbox"]';

function initDropdowns(): void {
const dropdowns = document.querySelectorAll(DROPDOWN);
dropdowns.forEach((dropdown: Element) =>
dropdown.querySelectorAll(DROPDOWN_TOGGLE)?.forEach((button: Element) => {
button.addEventListener('click', (event) => onToggleDropdown(event, dropdown));
})
);
}

function onToggleDropdown(event: Event, dropdown: Element): void {
const buttons = dropdown.querySelectorAll(DROPDOWN_TOGGLE);
buttons?.forEach(toggleDropdownButton);
const list = dropdown.querySelector(DROPDOWN_LIST);
toggleDropdownList(list);
}

function toggleDropdownButton(button: Element): void {
if (button.classList.contains('button_dropdown')) {
button.classList.toggle('button_dropdown_active');
}
}

function toggleDropdownList(list: Element | null): void {
console.log(list);
list?.classList.toggle('dropdown--list_expanded');
}

document.addEventListener('DOMContentLoaded', () => {
initDropdowns();

document.addEventListener('click', (event) => {
const target = event.target as HTMLElement;
if (!hasAncestorWithClass(target, 'dropdown')) {
const dropdowns = document.querySelectorAll('.button_dropdown');
dropdowns.forEach((dropdown) => {
dropdown.classList.remove('button_dropdown_active');
dropdown.parentNode?.querySelector('.dropdown--list')?.classList.remove('dropdown--list_expanded');
});
}
});
});

// function onToggleDropdown(event: PointerEvent): void {
// const target = event.target as HTMLButtonElement;
// if (target.classList.contains('button_dropdown')) {
// target.classList.toggle('button_dropdown_active');
// }
// target.parentNode
// ?.querySelector('.dropdown')
// ?.querySelector('.dropdown--list')
// ?.classList.toggle('dropdown--list_expanded');
// }

function onToggleOption(event: PointerEvent): void {
const target = event.target as HTMLButtonElement;
target.classList.toggle('dropdown--option_active');
target.querySelector('.dropdown--checkbox')?.toggleAttribute('checked');
}

function onToggleOptionByKey(event: KeyboardEvent): void {
const target = event.target as HTMLButtonElement;
if (event.key === 'Enter' || event.key === ' ') {
target.classList.toggle('dropdown--option_active');
target.querySelector('.dropdown--checkbox')?.toggleAttribute('checked');
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).onToggleOption = onToggleOption;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).onToggleOptionByKey = onToggleOptionByKey;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).initDropdowns = initDropdowns;
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*!
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@import '../tokens/index';

.dropdown {
position: relative;

&--list {
position: absolute;
z-index: 9;
top: 44px;

right: 0;

display: none;

min-width: 272px;
max-width: 360px;
max-height: 400px;
padding: 0;

border: 1px solid lighten(rgb(50, 50, 55), 15%); // color-background-nav-dt

box-shadow: 0 2px 8px 0 #00000040;

&_expanded {
display: block;
}

@media (width < $breakpoint-desktop-min) {
top: 0;
right: -52px;

width: 100vw;
max-width: unset;
}
}

&--option {
position: relative;

display: block;

padding: var(--size-s2) 44px;

list-style-type: none;

cursor: pointer;
letter-spacing: -0.03em;

text-transform: capitalize;

border: none;
background-color: var(--color-background-nav-dt);

font: var(--font-text-m);

&:hover {
background-color: lighten(rgb(50, 50, 55), 10%); // color-background-nav-dt
}

&:focus-visible {
z-index: 1;

outline: 4px solid var(--color-key-blue-05);
}

&_active {
background-color: var(--color-key-blue);

&:hover {
background-color: lighten(rgb(48, 127, 255), 10%); // color-key-blue
}
}
}

&--checkbox {
position: absolute;

top: 50%;

left: 12px;

margin-top: -9px;

pointer-events: none;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,19 @@
margin-right: 12px;
gap: 2px;

@media (width <= $breakpoint-desktop-min) {
@media (width < $breakpoint-desktop-min) {
display: none;
}

&--header {
display: flex;
align-items: center;
justify-content: space-between;

padding: 12px;

background-color: var(--color-background-nav-dt);
}
}

.no-js .filter-section {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@
.ui-kit-icon_placeholder {
background-image: url('./assets/placeholder.svg');
}

.ui-kit-icon_cross {
background-image: url('./assets/cross.svg');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import './dropdown/styles';
@import './checkbox/styles';
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import * as button from './button/index';
import * as checkbox from './checkbox/index';
import * as dropdown from './dropdown/index';
import * as filterSection from './filter-section/index';
import * as icon from './icon/index';
import * as libraryName from './library-name/index';
Expand All @@ -16,6 +18,8 @@ import './global.scss';

export {
button,
checkbox,
dropdown,
filterSection,
icon,
libraryName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

font: var(--font-h4);

@media (width <= $breakpoint-desktop-min) {
@media (width < $breakpoint-desktop-min) {
height: 52px;

margin-left: 12px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

font: var(--font-text-s);

@media (width <= $breakpoint-desktop-min) {
@media (width < $breakpoint-desktop-min) {
display: flex;
align-items: center;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

margin-left: auto;

@media (width <= $breakpoint-desktop-min) {
@media (width < $breakpoint-desktop-min) {
flex-grow: 1;
justify-content: flex-end;

Expand Down Expand Up @@ -51,7 +51,7 @@
background-color: var(--color-w10);
}

@media (width <= $breakpoint-desktop-min) {
@media (width < $breakpoint-desktop-min) {
width: 52px;
height: 52px;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
color: var(--color-text-dt);
background-color: var(--color-background-nav);

@media (width <= $breakpoint-desktop-min) {
@media (width < $breakpoint-desktop-min) {
height: auto;
padding: 0;
}
Expand Down
13 changes: 13 additions & 0 deletions dokka-subprojects/plugin-base-frontend/src/main/ui-kit/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2014-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

export function hasAncestorWithClass(element: HTMLElement, className: string): boolean {
if (element && element.classList.contains(className)) {
return true;
}
if (element.parentElement) {
return hasAncestorWithClass(element.parentElement as HTMLElement, className);
}
return false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
</@template_cmd>
</a>
</@template_cmd>
<button class="navigation-controls--btn navigation-controls--btn_menu ui-kit_mobile-only" id="menu-toggle" type="button">Toggle table of content</button>
<button class="navigation-controls--btn navigation-controls--btn_menu ui-kit_mobile-only" id="menu-toggle"
type="button">Toggle table of content
</button>
<div class="navigation-controls--break ui-kit_mobile-only"></div>
<div class="library-version">
<#-- This can be handled by the versioning plugin -->
Expand All @@ -17,11 +19,20 @@
<div class="navigation-controls">
<@source_set_selector.display/>
<#if homepageLink?has_content>
<a class="navigation-controls--btn navigation-controls--btn_homepage" id="homepage-link" href="${homepageLink}"></a>
<a class="navigation-controls--btn navigation-controls--btn_homepage" id="homepage-link"
href="${homepageLink}"></a>
</#if>
<button class="navigation-controls--btn navigation-controls--btn_theme" id="theme-toggle-button" type="button">Switch theme</button>
<button class="navigation-controls--btn navigation-controls--btn_filter ui-kit_mobile-only" id="menu-toggle" type="button">Toggle source set</button>
<div class="navigation-controls--btn navigation-controls--btn_search" id="searchBar" role="button">Search in API</div>
<button class="navigation-controls--btn navigation-controls--btn_theme" id="theme-toggle-button"
type="button">Switch theme
</button>
<#if sourceSets?has_content>
<button class="navigation-controls--btn navigation-controls--btn_filter ui-kit_mobile-only"
id="platform-tags-toggle" type="button">Toggle source set
</button>
</#if>
<div class="navigation-controls--btn navigation-controls--btn_search" id="searchBar" role="button">Search in
API
</div>
</div>
</nav>
</#macro>
Loading

0 comments on commit 1184fbf

Please sign in to comment.