Skip to content

Commit 3e4d3b7

Browse files
committed
Create modal component, add local FA icons.
1 parent b95093a commit 3e4d3b7

File tree

10 files changed

+90
-100
lines changed

10 files changed

+90
-100
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@astrojs/sitemap": "^3.3.0",
1919
"@astrojs/tailwind": "^5.1.4",
2020
"@fontsource-variable/inter": "^5.1.1",
21+
"@fortawesome/fontawesome-free": "^6.7.2",
2122
"@tailwindcss/typography": "^0.5.16",
2223
"@types/react": "^19.1.0",
2324
"@types/react-dom": "^19.1.1",

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/BaseHead.astro

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,3 @@ const { title, description, image = "/social-card.png" } = Astro.props;
5454
is:inline
5555
data-domain="ep2025.europython.eu"
5656
src="https://plausible.io/js/script.js"></script>
57-
58-
<script
59-
is:inline
60-
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/js/all.min.js"
61-
crossorigin="anonymous"></script>

src/components/Modal.astro

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
import Button from '@ui/Button.astro';
3+
const { id = 'modal', open = false } = Astro.props;
4+
---
5+
6+
<div
7+
id={id}
8+
class={`fixed inset-0 z-50 flex items-center justify-center transition-opacity duration-300 ${
9+
open ? 'opacity-100 visible bg-black/50' : 'opacity-0 invisible'
10+
}`}
11+
data-modal-wrapper
12+
>
13+
<div
14+
class="relative bg-white dark:bg-gray-800 p-6 lg:rounded-2xl lg:shadow-xl lg:max-w-4xl lg:mx-4 h-full lg:h-[80vh] w-full lg:w-[70vw] max-h-full overflow-y-auto"
15+
>
16+
<Button
17+
id="search-close"
18+
clear
19+
icon="close"
20+
iconSize="fa-xl"
21+
data-close-modal
22+
class="w-[3em] h-[3em] absolute top-4 right-4 text-primary hover:text-black "
23+
/>
24+
<slot />
25+
</div>
26+
</div>
27+
28+
<script is:inline>
29+
document.addEventListener('DOMContentLoaded', () => {
30+
document.querySelectorAll('[data-open-modal]').forEach(button => {
31+
button.addEventListener('click', () => {
32+
const modal = document.getElementById(button.dataset.openModal);
33+
modal?.classList.remove('opacity-0', 'invisible');
34+
modal?.classList.add('opacity-100', 'visible');
35+
});
36+
});
37+
38+
document.querySelectorAll('[data-close-modal]').forEach(button => {
39+
button.addEventListener('click', () => {
40+
const modal = button.closest('[data-modal-wrapper]');
41+
modal?.classList.remove('opacity-100', 'visible');
42+
modal?.classList.add('opacity-0', 'invisible');
43+
});
44+
});
45+
});
46+
</script>

src/components/Search.astro

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
11
---
22
import SearchComponent from "astro-pagefind/components/Search";
33
import Button from "@ui/Button.astro";
4+
import Modal from "@components/Modal.astro";
45
56
---
67

7-
<div class="search-wrapper hidden" style="display: none;">
8-
9-
<div class="search-header flex items-center justify-between z-40 h-0 md:h-[85px] m-auto ">
10-
<h2 class="text-black text-4xl ml-10 top-[46px] md:top-[85px]">Search<h2/>
11-
<Button
12-
id="search-close"
13-
clear
14-
icon="close"
15-
iconSize="fa-xl"
16-
class="w-[3em] h-[3em] top-[46px] md:top-[85px]"
17-
/>
18-
</div>
19-
<div class="modal__overlay"></div>
208

9+
<Modal id="modal-search">
10+
<h2 class="text-xl font-bold mb-2 py-2">Search</h2>
2111
<SearchComponent
2212
id="search"
2313
className="pagefind-ui"
@@ -28,21 +18,24 @@ import Button from "@ui/Button.astro";
2818
},
2919
}}
3020
/>
21+
</div>
3122
</div>
23+
</Modal>
24+
3225

3326
<script>
3427
document.addEventListener("DOMContentLoaded", function () {
35-
const searchWrapper = document.querySelector(".search-wrapper") as HTMLElement | null;
3628
const searchContainer = document.querySelector(".pagefind-ui") as HTMLElement | null;
3729
const searchInput = searchContainer?.querySelector("input") as HTMLInputElement | null;
38-
const closeButton = document.querySelector("#search-close") as HTMLElement | null;
3930
const searchButton = document.getElementById("searchButton") as HTMLElement | null;
31+
const openModal = document.querySelector('[data-open-modal="modal-search"]') as HTMLElement;
32+
const closeButton = document.querySelector('#search-close') as HTMLElement | null;
4033

4134
let selectedIndex = -1;
4235

4336
function openSearch() {
44-
if (searchWrapper) {
45-
searchWrapper.style.display = "block";
37+
console.log("open");
38+
openModal.click();
4639
if (searchInput) {
4740
searchInput.value = "Tips";
4841
const inputEvent = new Event("input", { bubbles: true });
@@ -53,15 +46,11 @@ document.addEventListener("DOMContentLoaded", function () {
5346
}, 100);
5447
searchInput.focus();
5548
}
56-
}
5749
}
5850

59-
function closeSearch() {
60-
if (searchWrapper) {
61-
searchWrapper.style.display = "none";
62-
selectedIndex = -1;
63-
}
64-
}
51+
function closeSearch() {
52+
closeButton?.click();
53+
}
6554

6655
function updateSelection() {
6756
const results = searchContainer?.querySelectorAll(".pagefind-ui__result");
@@ -99,7 +88,7 @@ document.addEventListener("DOMContentLoaded", function () {
9988
});
10089
}
10190

102-
if (searchButton && searchWrapper) {
91+
if (searchButton) {
10392
searchButton.addEventListener("click", openSearch);
10493
}
10594

src/components/header/header-actions.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const IS_LIVE = false;
2424
<button
2525
id="searchButton"
2626
class="mx-6 md:mx-2"
27-
data-open-modal
27+
data-open-modal="modal-search"
2828
aria-label="Search"
2929
aria-keyshortcuts="Control+K"
3030
>

src/components/ui/Button.astro

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
import Icon from "@ui/Icon.astro";
33
4+
// Destructure known props, rest goes into `restProps`
45
const {
56
url,
67
id,
@@ -14,38 +15,39 @@ const {
1415
iconSvg = false,
1516
iconRight = true,
1617
iconSize = "",
17-
title="",
18+
title = "",
19+
...restProps // all data-*, aria-* and custom attributes
1820
} = Astro.props;
1921
2022
const resolvedIsExternal = isExternal ?? url?.startsWith("http");
2123
2224
const baseClasses = "font-bold text-lg px-4 py-4 rounded-lg inline-flex items-center justify-center leading-4 transition-colors duration-200 not-prose border hover:text-black";
2325
const primaryClasses = "bg-button text-text-inverted hover:bg-button-hover border-transparent";
2426
const secondaryClasses = "bg-primary text-white hover:bg-primary-hover border-transparent";
25-
const clearClasses = "bg-transparent text-primary hover:bg-transparent hover:text-primary-active border-transparent"
27+
const clearClasses = "bg-transparent text-primary hover:bg-transparent hover:text-primary-active border-transparent";
2628
const outlineClasses = "border-gray-500 text-gray-700 hover:bg-gray-100 hover:bg-button-hover";
2729
const disabledClasses = "opacity-50 pointer-events-none";
2830
const iconClasses = "mx-2 ";
29-
const idName = id;
30-
const slotContent = await Astro.slots.render('default')
31-
3231
32+
const idName = id;
33+
const slotContent = await Astro.slots.render('default');
3334
---
3435

3536
{url ? (
3637
<a
3738
id={idName}
3839
href={disabled ? undefined : url}
3940
title={title}
40-
aria-label={title ? title : slotContent }
41+
aria-label={title ? title : slotContent}
4142
class={`${baseClasses}
4243
${clear ? clearClasses : outline ? outlineClasses : secondary ? secondaryClasses : primaryClasses}
4344
${disabled ? disabledClasses : ""}
4445
${className}`}
4546
aria-disabled={disabled}
4647
{...(resolvedIsExternal ? { target: "_blank", rel: "noopener noreferrer" } : {})}
48+
{...restProps}
4749
>
48-
{!iconRight && icon && <Icon name={icon} svg={iconSvg} size={iconSize} class={iconClasses} />}
50+
{!iconRight && icon && <Icon name={icon} svg={iconSvg} size={iconSize} class={iconClasses} />}
4951
<slot />
5052
{iconRight && icon && <Icon name={icon} svg={iconSvg} size={iconSize} class={iconClasses} />}
5153
{resolvedIsExternal && <Icon name="external-link" svg={iconSvg} size={iconSize} class={iconClasses} />}
@@ -54,15 +56,16 @@ const slotContent = await Astro.slots.render('default')
5456
<button
5557
id={idName}
5658
title={title}
57-
aria-label={title ? title : slotContent }
59+
aria-label={title ? title : slotContent}
5860
class={`${baseClasses}
5961
${clear ? clearClasses : outline ? outlineClasses : secondary ? secondaryClasses : primaryClasses}
6062
${disabled ? disabledClasses : ""}
6163
${className}`}
6264
disabled={disabled}
6365
aria-disabled={disabled}
66+
{...restProps}
6467
>
65-
{!iconRight && icon && <Icon name={icon} svg={iconSvg} size={iconSize} class={iconClasses} />}
68+
{!iconRight && icon && <Icon name={icon} svg={iconSvg} size={iconSize} class={iconClasses} />}
6669
<slot />
6770
{iconRight && icon && <Icon name={icon} svg={iconSvg} size={iconSize} class={iconClasses} />}
6871
</button>

src/layouts/Layout.astro

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import Header from "@components/Header.astro";
44
import Footer from "@components/Footer.astro";
55
import Search from "@components/Search.astro";
66
7+
78
import "@src/styles/global.css";
89
import "@src/styles/search.css";
910
import "@fontsource-variable/inter";
11+
import "@fortawesome/fontawesome-free/css/all.min.css";
12+
1013
1114
export interface Props {
1215
title: string;

src/pages/index.astro

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ deadlines = deadlines
2020
title="EuroPython 2025 | July 14th-20th 2025 | Prague, Czech Republic & Remote"
2121
description="EuroPython is the largest Python conference in Europe. We are looking forward to seeing you in Prague, Czech Republic & Remote from July 14th-20th 2025."
2222
>
23-
2423
<Hero />
2524
<Updates />
2625
<Keynoters />

src/styles/search.css

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
#search {
2-
padding: 85px 10px 10px 10px;
2+
padding: 10px;
33
position: relative;
4-
max-height: 80vh;
54
width: 100%;
65
max-width: 48rem;
76
margin: auto;
8-
background: #f5e5d6;
9-
border-radius: 0.5rem;
10-
box-shadow: 0 8px 24px -2px rgba(0, 0, 0, 0.4);
117
overflow: auto;
128
transition: background ease-out 0.2s;
139
z-index: 2;
14-
overflow: auto;
15-
height: 100%;
16-
17-
border-bottom: 1px solid #e1e3e6;
18-
border-bottom-color: rgb(225, 227, 230);
1910
}
2011

2112
.pagefind-ui__search-input {
@@ -25,17 +16,17 @@
2516
padding-inline-end: 0.5rem;
2617
background-color: #fff;
2718
font-size: 16px;
28-
color: #5f3d1b;
19+
color: #000000;
2920
}
3021

3122
.pagefind-ui__result.selected {
32-
background-color: #f5f5f5;
23+
background-color: #f8f8f8;
3324
background-image: linear-gradient(to right, #3684b6 7px, transparent 5px);
3425
-webkit-transform: translate3d(0, 0, 0);
3526
transform: translate3d(0, 0, 0);
3627
}
3728
.pagefind-ui__result:hover {
38-
background-color: #f5f5f5;
29+
background-color: #f8f8f8;
3930
}
4031
.pagefind-ui__message {
4132
margin: 1em;
@@ -59,13 +50,11 @@
5950
--pagefind-ui-border: #d8d8d8;
6051
--pagefind-ui-border-width: 2px;
6152
--pagefind-ui-border-radius: 0.5rem;
62-
/*width: 50%;*/
6353
}
6454
.pagefind-ui .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
6555
z-index: 9999;
6656
position: relative;
6757
overflow: auto;
68-
height: 100%;
6958
}
7059
.pagefind-ui__result {
7160
padding: 0 2em 1em !important;
@@ -76,47 +65,3 @@
7665
.pagefind-ui .pagefind-ui__result-excerpt {
7766
color: var(--pagefind-ui-text);
7867
}
79-
80-
.search-header {
81-
max-width: 48rem;
82-
margin: auto;
83-
}
84-
.search-header h2 {
85-
position: relative;
86-
left: -12px;
87-
z-index: 100;
88-
}
89-
.modal__overlay {
90-
z-index: 1;
91-
position: absolute;
92-
top: 0;
93-
left: 0;
94-
width: 100%;
95-
height: 100%;
96-
}
97-
98-
.search-wrapper {
99-
width: 100%;
100-
height: 100%;
101-
position: fixed;
102-
display: block;
103-
top: 0;
104-
bottom: 0;
105-
left: 0;
106-
right: 0;
107-
z-index: 500;
108-
box-sizing: border-box;
109-
display: none;
110-
transition: opacity ease-out 0.2s;
111-
background: rgba(116, 116, 116, 0.9);
112-
z-index: 100;
113-
}
114-
115-
#search-close {
116-
position: relative;
117-
left: -12px;
118-
margin: 0;
119-
border: 0;
120-
transition: opacity ease-out 0.2s;
121-
z-index: 10;
122-
}

0 commit comments

Comments
 (0)