diff --git a/assets/js/before-after-slider.js b/assets/js/before-after-slider.js index 8162b4c9..51b492ac 100644 --- a/assets/js/before-after-slider.js +++ b/assets/js/before-after-slider.js @@ -1,21 +1,13 @@ document.addEventListener("DOMContentLoaded", function () { - const toggleSwitch = document.getElementById("view-toggle"); - const slider = document.getElementById("slider"); - const container = document.querySelector(".ba-slider"); - const beforeText = document.getElementById("before-text"); - const afterText = document.getElementById("after-text"); - - // Initialize the state - const initializeState = () => { - slider.value = 0; // Start with "After" at 0% - container.style.setProperty("--position", "0%"); - beforeText.classList.add("text-muted"); - afterText.classList.remove("text-muted"); - toggleSwitch.setAttribute("aria-checked", "true"); - }; + // Get all instances of the toggle switch, sliders, and containers + const toggleSwitches = document.querySelectorAll(".toggle-input"); + const sliders = document.querySelectorAll(".slider"); + const containers = document.querySelectorAll(".ba-slider"); + const beforeTexts = document.querySelectorAll(".before-text"); + const afterTexts = document.querySelectorAll(".after-text"); // Function to animate the slider - const animateSlider = (start, end, duration = 350) => { + const animateSlider = (slider, container, start, end, duration = 350) => { const stepTime = 10; // Step interval in ms const steps = duration / stepTime; const stepValue = (end - start) / steps; @@ -36,33 +28,91 @@ document.addEventListener("DOMContentLoaded", function () { }, stepTime); }; - // Function to handle slider position when toggling - const handleToggle = () => { + // Function to update the toggle switch based on slider position + const updateToggleFromSlider = ( + container, + slider, + toggleSwitch, + beforeText, + afterText + ) => { + const position = + parseFloat(container.style.getPropertyValue("--position")) || 0; + + if (position === 0 && !toggleSwitch.checked) { + toggleSwitch.checked = true; + afterText.classList.remove("text-muted"); + beforeText.classList.add("text-muted"); + toggleSwitch.setAttribute("aria-checked", "true"); + } else if (position === 100 && toggleSwitch.checked) { + toggleSwitch.checked = false; + afterText.classList.add("text-muted"); + beforeText.classList.remove("text-muted"); + toggleSwitch.setAttribute("aria-checked", "false"); + } + }; + + // Function to handle toggle switch logic + const handleToggle = ( + toggleSwitch, + slider, + container, + beforeText, + afterText + ) => { const isChecked = toggleSwitch.checked; if (isChecked) { // Show "After" view - animateSlider(parseFloat(slider.value), 0); // Animate to 0% (After) + animateSlider(slider, container, parseFloat(slider.value), 0); // Animate to 0% (After) beforeText.classList.add("text-muted"); afterText.classList.remove("text-muted"); toggleSwitch.setAttribute("aria-checked", "true"); } else { // Show "Before" view - animateSlider(parseFloat(slider.value), 100); // Animate to 100% (Before) + animateSlider(slider, container, parseFloat(slider.value), 100); // Animate to 100% (Before) afterText.classList.add("text-muted"); beforeText.classList.remove("text-muted"); toggleSwitch.setAttribute("aria-checked", "false"); } }; - // Initialize the state on page load - initializeState(); + // Initialize the state for each slider instance + toggleSwitches.forEach((toggleSwitch, index) => { + const slider = sliders[index]; + const container = containers[index]; + const beforeText = beforeTexts[index]; + const afterText = afterTexts[index]; - // Add event listener for the switch toggle - toggleSwitch.addEventListener("change", handleToggle); + if (slider && container && beforeText && afterText) { + // Initialize slider position + container.style.setProperty("--position", "0%"); + slider.value = 0; + beforeText.classList.add("text-muted"); + afterText.classList.remove("text-muted"); + toggleSwitch.setAttribute("aria-checked", "true"); + + // Add event listener for the switch toggle + toggleSwitch.addEventListener("change", () => { + handleToggle(toggleSwitch, slider, container, beforeText, afterText); + }); - // Add slider logic (if manual adjustment is still needed) - slider.addEventListener("input", (e) => { - container.style.setProperty("--position", `${e.target.value}%`); + // Add event listener for manual slider input + slider.addEventListener("input", () => { + const value = parseFloat(slider.value); + container.style.setProperty("--position", `${value}%`); + updateToggleFromSlider( + container, + slider, + toggleSwitch, + beforeText, + afterText + ); + }); + } else { + console.error( + "One or more elements (slider, container, beforeText, afterText) are missing." + ); + } }); }); diff --git a/assets/scss/_custom.scss b/assets/scss/_custom.scss index 68063507..cc4db61a 100644 --- a/assets/scss/_custom.scss +++ b/assets/scss/_custom.scss @@ -1854,13 +1854,12 @@ details[open] summary svg { .image-container { max-width: 100%; max-height: 90vh; - aspect-ratio: 1/1; + aspect-ratio: auto; } .slider-image { & figure { width: 100%; - height: 100%; padding-block: 0; } @@ -1897,10 +1896,10 @@ details[open] summary svg { .slider-line { position: absolute; inset: 0; - width: 0.15rem; + width: 0.1rem; height: 100%; - opacity: 0.4; - background-color: $black; + opacity: 0.3; + background-color: $gray-500; left: var(--position); transform: translateX(-50%); pointer-events: none; @@ -1909,9 +1908,9 @@ details[open] summary svg { .slider-button { position: absolute; background-color: $white; - color: $black; + color: $gray-500; padding: 0.5rem; - border-radius: 100vw; + border-radius: 0; display: grid; place-items: center; top: 50%; diff --git a/config.toml b/config.toml index 2ebbab02..251784a5 100644 --- a/config.toml +++ b/config.toml @@ -84,10 +84,6 @@ pluralizeListTitles = false name = "github" url = "https://github.com/uradotdesign" - [[params.social]] - name = "x-twitter" - url = "https://twitter.com/uradotdesign" - [[params.social]] name = "instagram" url = "https://instagram.com/uradotdesign" diff --git a/content/de/imprint.md b/content/de/imprint.md index 271dd9c8..b4f408c6 100644 --- a/content/de/imprint.md +++ b/content/de/imprint.md @@ -7,11 +7,13 @@ text = "#FFFFFF" Ura Design wird betrieben von (Impressum nach § 5 TMG, ebenso verantwortlich für den Inhalt nach § 55 Abs. 2 RStV): -Elio Qoshi +Elio Qoshi\ +Ura Design e.K.\ c/o Cultivation Space\ Aufgang 4\ Gottschedstraße 4\ -13357 Berlin\ +13357 Berlin, Deutschland + Steuernummer: 34/481/01445\ USt.-IDNr: DE357155567 diff --git a/content/de/work/qubesos.md b/content/de/work/qubesos.md new file mode 100644 index 00000000..1b4d7ae0 --- /dev/null +++ b/content/de/work/qubesos.md @@ -0,0 +1,104 @@ ++++ +layout = "work/single" +featured = true +theme = "light" +background = "#FFFFFF" +accent = "#005F9C" +text = "#212529" +title = "Qubes OS Usability Audit" +summary = "Qubes OS is renowned for its security, but its complex interface can be a major hurdle for new users. This project aimed to untangle that complexity while preserving the advanced protections that make it one of the most secure systems available." +date = "2025-01-08 12:00:00 +0200" +images = ["img/work/qubesos.webp", "qubesos"] +tags = [] +categories = ["Accessibility", "UX Research", "Illustrations"] +[links] + "Qubes OS Website" = "https://www.qubes-os.org/" ++++ + +{{< figure class="with-js on-light" src="/img/work/qubesos-logo.svg" alt="QubesOS logo" >}} +{{< figure class="with-js on-dark" src="/img/work/qubesos-logo-dark.svg" alt="QubesOS logo" >}} +{{< figure class="no-js" src="/img/work/qubesos-logo.webp" alt="QubesOS logo" >}} + +## Qubes OS Mission + +Qubes OS is a security-focused operating system that uses virtualization to isolate tasks and applications in separate environments called ‘qubes’. This means that if one qube is compromised, the rest of the system stays secure. Think of it like a digital fortress, where each room is locked and independently secured. + +{{< figure src="/img/work/qubesos-cover.webp" alt="QubesOS cover image" >}} + +## Our Approach and Objectives + +Qubes OS is known for its strong security but faces significant usability challenges. Technical users often bypass the user interface in favor of the command line, limiting its appeal to non-technical users. + +We identified journalists as a key user group who need strong security but lack the technical expertise to navigate Qubes OS. For instance, a journalist investigating government corruption may need a secure system to protect sensitive communications but could struggle with the platform’s complexity. + +To address these challenges, we focused on improving critical aspects of the user experience: accessibility, visual consistency, clear communication, and intuitive interface design. Our goal was to lower the learning curve and make Qubes OS accessible to a broader range of users without compromising its core strengths. + +## Creating an accessible color system + +We adopted the [Tailwind CSS](https://tailwindcss.com/docs/customizing-colors) color system, an open-source framework with a diverse palette. This system improves readability, accessibility, and creates a more cohesive, visually appealing UI with improved WCAG 2.2 compliance. + +Each qube is identified by a color to help users differentiate them. The previous color scheme lacked sufficient contrast, making text hard to read. We updated the qube window colors using the Tailwind palette to improve readability and color contrast across Windows. + +{{< ba-slider + before_light="/img/work/qubesos-window-before.webp" + before_dark="/img/work/qubesos-window-before.webp" + before_nojs="/img/work/qubesos-window-before.webp" + after_light="/img/work/qubesos-window-after.webp" + after_dark="/img/work/qubesos-window-after.webp" + after_nojs="/img/work/qubesos-window-after.webp" +>}} + +## Building a consistent icon set + +We reviewed the existing Qubes icons, analyzing their usage to understand how they functioned across the platform. This informed our proposal for a new icon set, sourced mostly from lucide.dev under an MIT license, featuring outlined designs with customizable stroke widths. + +{{< ba-slider + before_light="/img/work/qubesos-icons-before.webp" + before_dark="/img/work/qubesos-icons-before-dark.webp" + before_nojs="/img/work/qubesos-icons-before-dark.webp" + after_light="/img/work/qubesos-icons-after.webp" + after_dark="/img/work/qubesos-icons-after-dark.webp" + after_nojs="/img/work/qubesos-icons-after-dark.webp" +>}} + +While most icons were sourced from Lucide, we redesigned those for specific qube types, as the previous icons didn't align well with pixel grids. The redesign incorporated the updated qube colors and gave the icons a more modern look. + +{{< ba-slider + before_light="/img/work/qubesos-qubeicons-before.svg" + before_dark="/img/work/qubesos-qubeicons-before.svg" + before_nojs="/img/work/qubesos-qubeicons-before.webp" + after_light="/img/work/qubesos-qubeicons-after.svg" + after_dark="/img/work/qubesos-qubeicons-after.svg" + after_nojs="/img/work/qubesos-qubeicons-after.webp" +>}} + +## Rewriting UX copy + +To improve clarity and accessibility, we conducted a copy audit of the Global Configuration settings. We focused on making the text **necessary**, **clear**, **concise**, and **useful**, ensuring it provided essential, actionable information for users. Based on these criteria, we proposed updated text to replace the old content. + +## Bringing it all together + +For the final step, we took all these elements; the new color system, icon set, and updated text to redesign the global configurations page. + +We chose screens from the global configuration settings that showcased the different design patterns that exist across all the screens. This way when the redesign is implemented they have all the different ux patterns documented so they can be applied across the different screens. + +{{< ba-slider + before_light="/img/work/qubesos-general-settings-before.svg" + before_dark="/img/work/qubesos-general-settings-before.svg" + before_nojs="/img/work/qubesos-general-settings-before.webp" + after_light="/img/work/qubesos-general-settings-after.svg" + after_dark="/img/work/qubesos-general-settings-after.svg" + after_nojs="/img/work/qubesos-general-settings-after.webp" +>}} + +## How we helped + +**Improved Accessibility**: The introduction of the Tailwind color system and the update of qube window colors have improved the clarity of text and ensured compliance with WCAG 2.2 standards, making the interface more usable. + +**Visual Consistency**: A refreshed logo has resolved inconsistencies in branding across platforms, reinforcing Qubes OS's visual identity. + +**Enhanced Iconography**: The redesigned icon set creates a unified, modern look while improving functionality, making navigation and interaction more intuitive for users. + +**Clearer UX Copy**: The audit of the Global Configuration settings copy has led to clearer, more concise text, improving user comprehension and facilitating smoother interactions. + +**Unified UI/UX Design**: The redesign of the global configuration pages, incorporating new colors, icons, and updated text, has resulted in a cohesive and visually appealing user experience. \ No newline at end of file diff --git a/content/en/imprint.md b/content/en/imprint.md index 9127170e..9054c7f4 100644 --- a/content/en/imprint.md +++ b/content/en/imprint.md @@ -7,11 +7,13 @@ text = "#FFFFFF" Ura Design is operated by (Impressum nach § 5 TMG, ebenso verantwortlich für den Inhalt nach § 55 Abs. 2 RStV): -Elio Qoshi +Elio Qoshi\ +Ura Design e.K.\ c/o Cultivation Space\ Aufgang 4\ Gottschedstraße 4\ -13357 Berlin\ +13357 Berlin, Germany + Tax ID: 34/481/01445\ VAT: DE357155567 diff --git a/content/en/work/qubesos.md b/content/en/work/qubesos.md new file mode 100644 index 00000000..1b4d7ae0 --- /dev/null +++ b/content/en/work/qubesos.md @@ -0,0 +1,104 @@ ++++ +layout = "work/single" +featured = true +theme = "light" +background = "#FFFFFF" +accent = "#005F9C" +text = "#212529" +title = "Qubes OS Usability Audit" +summary = "Qubes OS is renowned for its security, but its complex interface can be a major hurdle for new users. This project aimed to untangle that complexity while preserving the advanced protections that make it one of the most secure systems available." +date = "2025-01-08 12:00:00 +0200" +images = ["img/work/qubesos.webp", "qubesos"] +tags = [] +categories = ["Accessibility", "UX Research", "Illustrations"] +[links] + "Qubes OS Website" = "https://www.qubes-os.org/" ++++ + +{{< figure class="with-js on-light" src="/img/work/qubesos-logo.svg" alt="QubesOS logo" >}} +{{< figure class="with-js on-dark" src="/img/work/qubesos-logo-dark.svg" alt="QubesOS logo" >}} +{{< figure class="no-js" src="/img/work/qubesos-logo.webp" alt="QubesOS logo" >}} + +## Qubes OS Mission + +Qubes OS is a security-focused operating system that uses virtualization to isolate tasks and applications in separate environments called ‘qubes’. This means that if one qube is compromised, the rest of the system stays secure. Think of it like a digital fortress, where each room is locked and independently secured. + +{{< figure src="/img/work/qubesos-cover.webp" alt="QubesOS cover image" >}} + +## Our Approach and Objectives + +Qubes OS is known for its strong security but faces significant usability challenges. Technical users often bypass the user interface in favor of the command line, limiting its appeal to non-technical users. + +We identified journalists as a key user group who need strong security but lack the technical expertise to navigate Qubes OS. For instance, a journalist investigating government corruption may need a secure system to protect sensitive communications but could struggle with the platform’s complexity. + +To address these challenges, we focused on improving critical aspects of the user experience: accessibility, visual consistency, clear communication, and intuitive interface design. Our goal was to lower the learning curve and make Qubes OS accessible to a broader range of users without compromising its core strengths. + +## Creating an accessible color system + +We adopted the [Tailwind CSS](https://tailwindcss.com/docs/customizing-colors) color system, an open-source framework with a diverse palette. This system improves readability, accessibility, and creates a more cohesive, visually appealing UI with improved WCAG 2.2 compliance. + +Each qube is identified by a color to help users differentiate them. The previous color scheme lacked sufficient contrast, making text hard to read. We updated the qube window colors using the Tailwind palette to improve readability and color contrast across Windows. + +{{< ba-slider + before_light="/img/work/qubesos-window-before.webp" + before_dark="/img/work/qubesos-window-before.webp" + before_nojs="/img/work/qubesos-window-before.webp" + after_light="/img/work/qubesos-window-after.webp" + after_dark="/img/work/qubesos-window-after.webp" + after_nojs="/img/work/qubesos-window-after.webp" +>}} + +## Building a consistent icon set + +We reviewed the existing Qubes icons, analyzing their usage to understand how they functioned across the platform. This informed our proposal for a new icon set, sourced mostly from lucide.dev under an MIT license, featuring outlined designs with customizable stroke widths. + +{{< ba-slider + before_light="/img/work/qubesos-icons-before.webp" + before_dark="/img/work/qubesos-icons-before-dark.webp" + before_nojs="/img/work/qubesos-icons-before-dark.webp" + after_light="/img/work/qubesos-icons-after.webp" + after_dark="/img/work/qubesos-icons-after-dark.webp" + after_nojs="/img/work/qubesos-icons-after-dark.webp" +>}} + +While most icons were sourced from Lucide, we redesigned those for specific qube types, as the previous icons didn't align well with pixel grids. The redesign incorporated the updated qube colors and gave the icons a more modern look. + +{{< ba-slider + before_light="/img/work/qubesos-qubeicons-before.svg" + before_dark="/img/work/qubesos-qubeicons-before.svg" + before_nojs="/img/work/qubesos-qubeicons-before.webp" + after_light="/img/work/qubesos-qubeicons-after.svg" + after_dark="/img/work/qubesos-qubeicons-after.svg" + after_nojs="/img/work/qubesos-qubeicons-after.webp" +>}} + +## Rewriting UX copy + +To improve clarity and accessibility, we conducted a copy audit of the Global Configuration settings. We focused on making the text **necessary**, **clear**, **concise**, and **useful**, ensuring it provided essential, actionable information for users. Based on these criteria, we proposed updated text to replace the old content. + +## Bringing it all together + +For the final step, we took all these elements; the new color system, icon set, and updated text to redesign the global configurations page. + +We chose screens from the global configuration settings that showcased the different design patterns that exist across all the screens. This way when the redesign is implemented they have all the different ux patterns documented so they can be applied across the different screens. + +{{< ba-slider + before_light="/img/work/qubesos-general-settings-before.svg" + before_dark="/img/work/qubesos-general-settings-before.svg" + before_nojs="/img/work/qubesos-general-settings-before.webp" + after_light="/img/work/qubesos-general-settings-after.svg" + after_dark="/img/work/qubesos-general-settings-after.svg" + after_nojs="/img/work/qubesos-general-settings-after.webp" +>}} + +## How we helped + +**Improved Accessibility**: The introduction of the Tailwind color system and the update of qube window colors have improved the clarity of text and ensured compliance with WCAG 2.2 standards, making the interface more usable. + +**Visual Consistency**: A refreshed logo has resolved inconsistencies in branding across platforms, reinforcing Qubes OS's visual identity. + +**Enhanced Iconography**: The redesigned icon set creates a unified, modern look while improving functionality, making navigation and interaction more intuitive for users. + +**Clearer UX Copy**: The audit of the Global Configuration settings copy has led to clearer, more concise text, improving user comprehension and facilitating smoother interactions. + +**Unified UI/UX Design**: The redesign of the global configuration pages, incorporating new colors, icons, and updated text, has resulted in a cohesive and visually appealing user experience. \ No newline at end of file diff --git a/i18n/de.toml b/i18n/de.toml index 638240e2..3931bf20 100644 --- a/i18n/de.toml +++ b/i18n/de.toml @@ -123,7 +123,7 @@ other = "Sign up now and start making a difference" [faq] other = "Frequently Asked Questions" [whatTest] -other = "What Does It Mean to Be a Tester?" +other = "What does it mean to be a tester?" [whatDescription] other = "As a tester, you’ll play a crucial role in improving open-source projects. Here’s what you can expect." @@ -133,9 +133,9 @@ other = "Kontakt aufnehmen" [contactTeam] other = "Hast Du eine Herausforderung für uns? Setze Dich mit unserem Team in Verbindung, um zu sehen, wie wir helfen können." [preferCall] -other = "Möchtest Du lieber ein persönliches Gespräch?" +other = "Was unsere Kunden über uns sagen" [scheduleCall] -other = "Einen Anruf vereinbaren" +other = "Lesen Sie Erfahrungsberichte" [helpProject] other = "Können wir Dir bei Deinem Projekt helfen?" [contactUs] @@ -147,7 +147,7 @@ other = "Wir sind auf" [letsTalk] other = "Lass uns reden" [getInvolved] -other = "Werde Aktiv" +other = "Mach mit" [researchPanel] other = "Forschungspanel" diff --git a/i18n/en.toml b/i18n/en.toml index 3ceaef52..2719b29f 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -124,7 +124,7 @@ other = "Sign up now and start making a difference" [faq] other = "Frequently Asked Questions" [whatTest] -other = "What Does It Mean to Be a Tester?" +other = "What does it mean to be a tester?" [whatDescription] other = "As a tester, you’ll play a crucial role in improving open-source projects. Here’s what you can expect." @@ -134,9 +134,9 @@ other = "Get in touch" [contactTeam] other = "Have a challenge? Get in touch with our team to discuss how we can help." [preferCall] -other = "Prefer to talk over a call?" +other = "What our clients say about us" [scheduleCall] -other = "Schedule a call" +other = "Read testimonials" [helpProject] other = "Can we help on your project?" [contactUs] diff --git a/layouts/_default/contact.html b/layouts/_default/contact.html index 5e3449d9..827807d0 100644 --- a/layouts/_default/contact.html +++ b/layouts/_default/contact.html @@ -14,10 +14,12 @@ - +