Skip to content
Snippets Groups Projects
Commit 7902d7df authored by Jennifer Dust's avatar Jennifer Dust
Browse files

Issue #3374468 by jldust: Component: Search Bar

parent 439a64ac
No related branches found
Tags 5.2.0-alpha4
No related merge requests found
$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
name: Search bar
status: experimental
description: Search bar component for the global header.
props:
type: object
properties:
form_action:
title: Form Action
type: string
form_children:
title: Form Children
type: string
libraryOverrides:
dependencies:
- core/drupal
- core/once
.c-search-bar {
align-items: center;
position: relative;
}
@media (min-width: 992px) {
.c-search-bar {
display: inline-flex;
flex-direction: row-reverse;
gap: 16px;
}
}
.c-search-bar__content form {
position: relative;
}
@media (max-width: 991.98px) {
.c-search-bar__content form {
display: inline-flex;
gap: 16px;
padding: 32px;
}
.c-search-bar__content form > .js-form-item {
width: -webkit-fill-available;
}
}
.c-search-bar__content[aria-hidden=true] form {
width: 0px;
opacity: 0;
overflow: hidden;
transition: opacity 300ms ease-in-out, width 300ms ease-in-out;
}
@media (max-width: 991.98px) {
.c-search-bar__content[aria-hidden=true] form {
width: 100%;
opacity: 1;
overflow: visible;
}
}
.c-search-bar__content[aria-hidden=false] form {
width: 100%;
opacity: 1;
transition: opacity 300ms ease-in-out, width 300ms ease-in-out;
}
@media (min-width: 992px) {
.c-search-bar__content[aria-hidden=false] form {
width: 160px;
}
}
@media (min-width: 1200px) {
.c-search-bar__content[aria-hidden=false] form {
width: 220px;
}
}
@media (min-width: 1440px) {
.c-search-bar__content[aria-hidden=false] form {
width: 300px;
}
}
.c-search-bar__content .form-actions {
margin: 0;
width: -moz-fit-content;
width: fit-content;
}
@media (min-width: 992px) {
.c-search-bar__content .form-actions {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
}
.c-search-bar__content .form-actions input[type=submit] {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22%23000000%22%3E%3Cpath%20d%3D%22M9.516%2014.016q1.875%200%203.188-1.313t1.313-3.188-1.313-3.188-3.188-1.313-3.188%201.313-1.313%203.188%201.313%203.188%203.188%201.313zM15.516%2014.016l4.969%204.969-1.5%201.5-4.969-4.969v-0.797l-0.281-0.281q-1.781%201.547-4.219%201.547-2.719%200-4.617-1.875t-1.898-4.594%201.898-4.617%204.617-1.898%204.594%201.898%201.875%204.617q0%200.984-0.469%202.227t-1.078%201.992l0.281%200.281h0.797z%22%2F%3E%3C%2Fsvg%3E%20");
background-position: center;
background-repeat: no-repeat;
background-size: 32px;
border: none;
border-radius: 32px;
cursor: pointer;
margin-left: 0;
text-indent: -9999px;
width: 48px;
}
.c-search-bar__content .form-actions input[type=submit]:hover {
box-shadow: none;
}
@media (min-width: 992px) {
.c-search-bar__content .form-actions input[type=submit] {
background-color: transparent;
border-radius: 0;
margin-left: 8px;
padding: 0px;
}
}
.c-search-bar__content .form-element--api-search {
background: transparent;
border-radius: 2px;
box-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.25) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.25) inset;
color: #000000;
width: 100%;
padding-right: 3.375rem;
}
@media (max-width: 991.98px) {
.c-search-bar__content .form-element--api-search {
height: 48px;
padding-right: 12px;
}
}
.c-search-bar__content input[type=search]::-webkit-search-cancel-button {
display: none;
}
.c-search-bar__button {
align-items: center;
background: transparent;
border: none;
cursor: pointer;
transition: all 300ms ease-in-out;
}
@media (max-width: 991.98px) {
.c-search-bar__button {
display: none;
}
}
.c-search-bar__button:hover, .c-search-bar__button[aria-expanded=true] {
transition: all 300ms ease-in-out;
}
.c-search-bar__button[aria-expanded=true] .c-search-bar__button-icon svg.close {
display: block;
}
.c-search-bar__button[aria-expanded=true] .c-search-bar__button-icon svg.open {
display: none;
}
.c-search-bar__button[aria-expanded=false] .c-search-bar__button-icon svg.close {
display: none;
}
.c-search-bar__button[aria-expanded=false] .c-search-bar__button-icon svg.open {
display: block;
}
\ No newline at end of file
!function(){var t,e;t=Drupal,e=once,t.behaviors.barSearch={attach(d,t){e("searchbar",".c-search-bar__button",d).forEach(a=>{const r=window.matchMedia("(max-width: 1023px)"),n=document.getElementById(a.getAttribute("aria-controls")),c=n.querySelectorAll("input");function i(t){"Escape"!=t.key&&"Esc"!=t.key||(d.removeEventListener("keydown",i,!0),a.setAttribute("aria-expanded","false"),r.matches||n.setAttribute("aria-hidden","true"),c.forEach(t=>{t.setAttribute("tabindex",-1)}),a.querySelector(".c-search-bar__button-text").textContent="Expand Search",a.focus())}r.matches&&n.setAttribute("aria-hidden",!1),a.addEventListener("click",()=>{const e="true"===a.getAttribute("aria-expanded");a.setAttribute("aria-expanded",!e),r.matches||n.setAttribute("aria-hidden",e),c.forEach(t=>{e?t.setAttribute("tabindex",-1):t.setAttribute("tabindex",0)}),a.querySelector(".c-search-bar__button-text").textContent=e?"Expand Search":"Close Search",e||d.addEventListener("keydown",i,!0)})})}}}();
\ No newline at end of file
<div class='c-search-bar'>
<button class='c-search-bar__button' aria-expanded='false' aria-controls='search-bar' aria-label='toggle searchbar'>
<span class='c-search-bar__button-icon' aria-hidden='true' focusable='false'>
<svg class='open' xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewbox='0 0 32 32' fill='none'>
<path d='M12.6667 4C14.9652 4 17.1696 4.91309 18.7949 6.53841C20.4202 8.16372 21.3333 10.3681 21.3333 12.6667C21.3333 14.8133 20.5467 16.7867 19.2533 18.3067L19.6133 18.6667H20.6667L27.3333 25.3333L25.3333 27.3333L18.6667 20.6667V19.6133L18.3067 19.2533C16.7341 20.5957 14.7343 21.3332 12.6667 21.3333C10.3681 21.3333 8.16372 20.4202 6.53841 18.7949C4.91309 17.1696 4 14.9652 4 12.6667C4 10.3681 4.91309 8.16372 6.53841 6.53841C8.16372 4.91309 10.3681 4 12.6667 4ZM12.6667 6.66667C9.33333 6.66667 6.66667 9.33333 6.66667 12.6667C6.66667 16 9.33333 18.6667 12.6667 18.6667C16 18.6667 18.6667 16 18.6667 12.6667C18.6667 9.33333 16 6.66667 12.6667 6.66667Z' fill='black'/>
</svg>
<svg class='close' xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewbox='0 0 32 32' fill='none'>
<path d='M25.3333 8.54699L23.4533 6.66699L16 14.1203L8.54663 6.66699L6.66663 8.54699L14.12 16.0003L6.66663 23.4537L8.54663 25.3337L16 17.8803L23.4533 25.3337L25.3333 23.4537L17.88 16.0003L25.3333 8.54699Z' fill='black'/>
</svg>
</span>
<span class='c-search-bar__button-text visually-hidden'>
{{ button_text|default('Expand Search') }}
</span>
</button>
<div class='c-search-bar__content' id='search-bar' aria-hidden='true'>
{{content}}
</div>
</div>
((Drupal, once) => {
Drupal.behaviors.barSearch = {
attach(context, _settings) {
// Search bar Expand/Collapse functionality
once('searchbar', '.c-search-bar__button', context).forEach(
(searchToggle) => {
// Mobile Media Query
const isMobile = window.matchMedia('(max-width: 1023px)');
const searchContent = document.getElementById(
searchToggle.getAttribute('aria-controls')
);
const inputFields = searchContent.querySelectorAll('input');
// If on mobile always display search content
if (isMobile.matches) {
searchContent.setAttribute('aria-hidden', false);
}
searchToggle.addEventListener('click', () => {
const isExpanded =
searchToggle.getAttribute('aria-expanded') === 'true';
searchToggle.setAttribute('aria-expanded', !isExpanded);
if (!isMobile.matches) {
searchContent.setAttribute('aria-hidden', isExpanded);
}
// For each inputField set tabindex to -1
inputFields.forEach((inputField) => {
if (isExpanded) {
inputField.setAttribute('tabindex', -1);
} else {
inputField.setAttribute('tabindex', 0);
}
});
searchToggle.querySelector(
'.c-search-bar__button-text'
).textContent = !isExpanded ? 'Close Search' : 'Expand Search';
if (!isExpanded) {
context.addEventListener('keydown', closeSearch, true);
}
});
// Listen for escape key to close search
function closeSearch(e) {
if (e.key == 'Escape' || e.key == 'Esc') {
context.removeEventListener('keydown', closeSearch, true);
searchToggle.setAttribute('aria-expanded', 'false');
if (!isMobile.matches) {
searchContent.setAttribute('aria-hidden', 'true');
}
// For each inputField set tabindex to -1
inputFields.forEach((inputField) => {
inputField.setAttribute('tabindex', -1);
});
searchToggle.querySelector(
'.c-search-bar__button-text'
).textContent = 'Expand Search';
// Set focus for keyboard users
searchToggle.focus();
}
}
}
);
},
};
})(Drupal, once);
@use '../../../libraries/partials/partials' as *;
.c-search-bar {
align-items: center;
position: relative;
@include bp-min(lg-tablet) {
display: inline-flex;
flex-direction: row-reverse;
gap: 16px;
}
}
.c-search-bar__content {
form {
position: relative;
@include bp-max(lg-tablet) {
display: inline-flex;
gap: 16px;
padding: 32px;
> .js-form-item {
width: -webkit-fill-available;
}
}
}
&[aria-hidden='true'] form {
inline-size: 0px;
opacity: 0;
overflow: hidden;
transition: opacity 300ms ease-in-out, width 300ms ease-in-out;
// Account for screen resize, JS handles aria-hidden
@include bp-max(lg-tablet) {
inline-size: 100%;
opacity: 1;
overflow: visible;
}
}
&[aria-hidden='false'] form {
inline-size: 100%;
opacity: 1;
transition: opacity 300ms ease-in-out, width 300ms ease-in-out;
@include bp-min(lg-tablet) {
inline-size: 160px;
}
@include bp-min(desktop) {
inline-size: 220px;
}
@include bp-min(lg-desktop) {
inline-size: 300px;
}
}
.form-actions {
margin: 0;
width: fit-content;
@include bp-min(lg-tablet) {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
input[type='submit'] {
background-image: svg-load('icon-search.svg', fill= '#000000');
background-position: center;
background-repeat: no-repeat;
background-size: 32px;
border: none;
border-radius: 32px;
cursor: pointer;
margin-left: 0;
text-indent: -9999px;
width: 48px;
&:hover {
box-shadow: none;
}
@include bp-min(lg-tablet) {
background-color: transparent;
border-radius: 0;
margin-left: 8px;
padding: 0px;
}
}
}
.form-element--api-search {
background: transparent;
border-radius: 2px;
box-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.25) inset,
0px -1px 0px 0px rgba(255, 255, 255, 0.25) inset;
color: #000000;
inline-size: 100%;
padding-right: rem(54px);
@include bp-max(lg-tablet) {
height: 48px;
padding-right: 12px;
}
}
// Hide default input clear
input[type='search']::-webkit-search-cancel-button {
display: none;
}
}
// Search Toggle button
.c-search-bar__button {
align-items: center;
background: transparent;
border: none;
cursor: pointer;
transition: all 300ms ease-in-out;
// Hide on mobile screens
@include bp-max(lg-tablet) {
display: none;
}
&:hover,
&[aria-expanded='true'] {
transition: all 300ms ease-in-out;
}
// Togggle button is closed, change icon
&[aria-expanded='true'] .c-search-bar__button-icon {
svg.close {
display: block;
}
svg.open {
display: none;
}
}
// Togggle button is open, change icon
&[aria-expanded='false'] .c-search-bar__button-icon {
svg.close {
display: none;
}
svg.open {
display: block;
}
}
}
{#
/**
* @file
* Theme override to display a block.
*
* Available variables:
* - plugin_id: The ID of the block implementation.
* - label: The configured label of the block if visible.
* - configuration: A list of the block's configuration values.
* - label: The configured label for the block.
* - label_display: The display settings for the label.
* - provider: The module or other provider that provided this block plugin.
* - Block plugin specific settings will also be stored here.
* - in_preview: Whether the plugin is being rendered in preview mode.
* - content: The content of this block.
* - attributes: array of HTML attributes populated by modules, intended to
* be added to the main container tag of this template.
* - id: A valid HTML ID and guaranteed unique.
* - title_attributes: Same as attributes, except applied to the main title
* tag that appears in the template.
* - title_prefix: Additional output populated by modules, intended to be
* displayed in front of the main title tag that appears in the template.
* - title_suffix: Additional output populated by modules, intended to be
* displayed after the main title tag that appears in the template.
*
* @see template_preprocess_block()
*/
#}
<div{{attributes}}>
{{ title_prefix }}
{% if label %}
<h2{{title_attributes}}>{{ label }}</h2>
{% endif %}
{{ title_suffix }}
{% block content %}
{% embed 'prototype:search-bar' with {
content: content,
} only %}{% endembed %}
{% endblock %}
</div>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment