Evolving Web: Hands-On With Drupal 10: Olivero, a New Theme With a Meaningful Name

Image removed.

It was high time we said goodbye to Bartik. Having been Drupal’s default front-end theme for over a decade (from Drupal 7 to 9.4,) Bartik was quite the veteran. And although it served users well for many years, the theme didn’t get any major updates after 2011. Its age began to show: aside from an increasingly dated look, Bartik didn’t evolve to work well with new functionality such as Layout Builder.

Bartik got its figurative cannon salute in 2022. It was retired and replaced with Olivero: a modern and accessible theme for the future. 

The idea for Olivero was conceived in a hotel lobby at DrupalCon Seattle, 2019. It grew into the Drupal 9 theme initiative, with considerable support from Dries and key contributors. Over several years, the Olivero Team worked to build a cutting-edge theme based on five design principles:

  • Simple: a clutter-free environment that’s easy to navigate and use
  • Modern: support for the latest browser features and interaction modes
  • Flexible: gives multiple options to Drupal front-end developers
  • Focused: includes eye-catching, meaningful design elements
  • Accessible: WCAG Level AA compliant from the ground up

Olivero was initially introduced as an experiment in Drupal 9.1. It’s now the default front-end theme in Drupal 9 and Drupal 10. (Bartik is deprecated in Drupal 9.5 and unavailable in Drupal 10.)

[Quote]

"It looks amazing, and it’s also by far the most accessible theme that we’ve ever shipped in the history of Drupal."

– Dries Buytaert, DrupalCon Portland 2022’s Driesnote

Image removed.

Drupal 10’s default theme is clean, modern, and accessible. 

Rachel Olivero’s Legacy of Championing Accessibility 

The Olivero theme was named in memory of Rachel Olivero, who passed away in 2019. Rachel was an accessibility advocate and a valued member of the Drupal community. As a person who was blind, transgender, and a lesbian, Rachel had a deep understanding of the importance of inclusivity and a passion for making technology better for everyone. 

"We chose the name Olivero not just because we have made accessibility a top priority, but also because we aspire to develop this new theme in our community in a manner that is consistent with the qualities that Rachel Olivero embodied, including patience, generosity, and inclusivity."

– The Olivero Team

A Rundown of the Olivero Theme’s Best Features

Modern Colour Palette 

Olivero uses a vivid blue as its base colour for a bright, professional look that gives a subtle nod to Drupal’s branding. Neutral grays provide visual balance. The palette provides both dark and light shades, as well as secondary colours, to enable an accessible, high-contrast design. 

Image removed.

A clean, accessible colour palette gives Drupal 10’s default theme a modern look and feel. 

Simple Forms and Buttons

Content editors will be delighted with the simple elegance of text fields, checkboxes, radio buttons, and submit buttons in Drupal 10’s default theme. 

Web accessibility is clearly at the forefront of the design. Forms are simple for users to fill out thanks to their uniform look and clear labels. Buttons are high-contrast and have easily-perceivable focus modes that work well for keyboard users. 

Image removed.

Forms are clear and clutter-free in Olivero. 

Accessible Typography

Olivero makes content more readable and scannable thanks to a base font-size of 18px for body copy. Other text elements are scaled accordingly and typography is adjusted for mobile devices. The Olivero team gave particular focus to maintaining consistency throughout line-height and spacing. 

Olivero also perfectly displays right-to-left languages including Urdu, Arabic, and Hebrew. This is critical for supporting Drupal’s multilingual capabilities. 

Image removed.

Typography is scaled to provide a responsive, accessible, and consistent experience for users. 

Intuitive Headers and Menus

The header in Olivero can collapse into a hamburger menu as the user scrolls down the page. This means users have easy access to the navigation links regardless of where they are on the page. Olivero also supports secondary dropdown menus in Drupal – something that wasn’t possible with Bartik.

There are multiple versions of the header to choose from. All of them are designed to seamlessly incorporate any type of logo. 

Image removed.

An animated, sticky hamburger menu makes navigation easier for users. 

Eye-Catching Messages 

Olivero uses brightly coloured icons to convey the purpose of different types of messages. Error, alert, and success messages are displayed in boxes with plenty of padding to ensure they’re noticeable and easily readable. 

Image removed.

Olivero has an eye-catching design for messages.

Useful Sidebar 

Olivero features a sidebar that floats next to the primary content. This is a great place to display things like related content and social buttons. 

Improvements for Developers

Taking a lead from Claro, the new default admin UI, Olivero has implemented PostCSS to reduce maintenance overhead. It uses CSS Grid to help developers build complex layouts more easily. And for added flexibility, Olivero uses CSS custom properties to enable front-end developers to customize the theme on a block-by-block basis.

 

Planning to migrate to Drupal 10?

//--> //-->

+ more awesome articles by Evolving Web

Golems GABB: Illustration with Shapes

Illustration with Shapes Editor Tue, 03/07/2023 - 17:12

We are so interested in who you are. Are you a designer? We can suppose it as you are interested in this topic. However, it can be assumed that you are not. Basically, you may not even be related to design, and the last time you drew was in school. Did we guess? Whoever you are, we've written this blog for you!

Specbee: How to Efficiently Fetch Drupal Reference Entities in Custom Modules

How to Efficiently Fetch Drupal Reference Entities in Custom Modules Jigish Chauhan 07 Mar, 2023 Subscribe to our Newsletter Now Subscribe Leave this field blank

Fetching Drupal entities and fields in custom modules is a critical part of building complex Drupal applications that require custom functionality. By understanding how to access and manipulate entities and fields programmatically, developers can create powerful and flexible modules that can handle a wide range of data-driven tasks. 

In this article, we will share tips and easy methods on fetching reference entity fields using entity API that will help you simplify your custom module development process.

Image removed.

Getting Back to Basics

What are Entities?

Entities are the most core part of Drupal and it is important to understand what they are and how they work. They are objects that represent anything from users and nodes to taxonomy terms. Each entity has their own properties and can be customized or extended to fit the needs of a website.

What are Fields?

Fields make it easy to manage complex content structures. They are used to collect and display a variety of data like text, images, date and more which can be associated with an entity. For example, a content node can have multiple fields like a title, summary, body, image etc.

What are Nodes?

A node is a basic unit of content in Drupal. It can be a blog post, a product, a news article or an event. Each node has its own properties and can be organized into different types (or content types). A node can be used to create, edit, delete or categorize content.

Drupal Entity Reference Fields

Entity reference fields provide relationships between entities in Drupal. It stores references to another entity (a node, user, taxonomy, etc.). An example of a relationship would be:

  • A taxonomy term associated with a content type or user account.
  • A parent content that references a child content element.

It is commonly used in views and adding view relationships makes it quite easy to use reference fields. But the problem arises when fetching values of the reference fields in your custom module and custom theme.

The common method used to get a referenced entity is very long, so I will take you through a shorter solution.

For example, let's say we have a node object with a reference taxonomy field named field_specbee_term.

How it is usually done:

Method 1:

// $id = Node ID // $field = 'field_specbee_term'; // field name for term reference field $node = Drupal\node\Entity\Node::load($id); // To get first value from multivalue field used first() method. $reference_item = $node->get($field)->first(); // \Drupal\Core\Entity\Plugin\DataType\EntityReference. $entity_reference = $reference_item->get('entity'); // \Drupal\Core\Entity\Plugin\DataType\EntityAdapter. $entity_adapter = $entity_reference->getTarget(); // \Drupal\Core\Entity\EntityInterface. $referenced_entity = $entity_adapter->getValue();

Here, $referenced_entity is the referenced entity object.

Now alternatively, instead of using the above tedious method 1, here is an easier way of doing it.

Method 2:

$referenced_entity = $node->field_specbee_term->entity;

However, if you want to fetch all the values from the multivalue field, Method 2 will not work.

For loading the entire list of reference entities as objects will use the below method which is a type of array.

$referenced_entities = $node->get('field_specbee_term')->referencedEntities();

This method can be used for image reference as well. 

Let’s see an example of how we can get an image URL from a node with a specific image style.

// $fid = File ID $file = Drupal\file\Entity\File::load($fid); // Alternatively you can use direct node field. $file = $node->field_image->entity; $image_uri = $file->getFileUri(); // Get origin image URI. $style = ImageStyle::load('thumbnail'); // Load image style "thumbnail". $uri = $style->buildUri($image_uri); // Get URI. $url = $style->buildUrl($image_uri); // Get URL.

Now let’s understand how to retrieve any field values and which method is preferred for different scenarios.

// $id = Node ID $node = Node::load($id); $node->get(FIELDNAME)->value; // ALL VALUES - WON'T WORK IN REFERENCE FIELDS $node->get(FIELDNAME)->getValue(); // ALL VALUES $node->get(FIELDNAME)->getString(); // ALL VALUES

1. value :

This will return the actual value of the field but it will not work for any referenced field. 

2. getValue() :

When you need to get values of a field, whether it is a single-value or multi-value field, you can use this method. It will return an array of field values. 

3. getString() :

This method will return the value of a single-value field, and if it is a multi-valued field it will return comma-separated values.

Note: Sometimes when using getString(), if there is no value present, it will throw an error. This can be tackled by using the hasvalue() function before using the getString() function.

Final Thoughts

Fetching Drupal reference entities is an essential skill for Drupal developers. With the Entity API, you can easily load and manipulate entities and their fields, making your custom module development process more efficient and streamlined. However, if you need expert assistance with Drupal development, our team of experienced developers is here to help. Contact us today to learn more about our Drupal development services and how we can help you build powerful Drupal websites and applications that meet your unique needs.

Author: Jigish Chauhan

Meet Jigish Chauhan, Technical Architect, who’s fond of photography. He dreams of traveling to the playground of Europe, Switzerland, and loves to embrace the nature around him.

Email Address Subscribe Leave this field blank Drupal Drupal Module Drupal Development Drupal Planet

Leave us a Comment

 

Recent Blogs

Image Image removed.

How to Efficiently Fetch Drupal Reference Entities in Custom Modules

Image Image removed.

Finding Balance - Santhosh Kumar's Parallel Worlds

Image Image removed.

Migrate to Drupal 9 (or 10) Without Losing Your Hard-Earned SEO Ranking

Want to extract the maximum out of Drupal? TALK TO US

Featured Case Studies

Image removed.Image removed.

Upgrading the web presence of IEEE Information Theory Society, the most trusted voice for advanced technology

Explore
Image removed.Image removed.

A Drupal powered multi-site, multi-lingual platform to enable a unified user experience at SEMI

Explore
Image removed.Image removed.

Great Southern Homes, one of the fastest growing home builders in the US, sees greater results with Drupal

Explore
View all Case Studies

ComputerMinds.co.uk: Drupal 10 upgrade: Custom code upgrades

Image removed.

This one is entirely on us, we wrote the custom code, which makes us responsible for maintaining it.

The upgrade status module gives us a nice report of each custom project and what changes it thinks are required to bring the code up to date to work with Drupal 10.

We really don't have a lot of custom module code, and the code that we do have is very simple, standard Drupal 8/9/10 stuff, so there are a couple of calls to taxonomy_term_load_multiple_by_name to remove, and an accessCheck to add to an entity query, but other than that our custom module code looked fine.

Our custom theme however, is a different story: we have some usages of jQuery once to remove, and we have a lot of custom Twig PHP classes that are extending deprecated classes. Nothing show-stopping, but a few things to do worth covering in more detail.

jQuery once

The jQuery once plugin has gone from core in Drupal 10, so we need to upgrade our javascript that is using it to use the vanilla javascript alternative that ships in Drupal 9: the once plugin. This is simple enough, we can rewrite code like this:

(function($) { Drupal.behaviors.smoothScroll = { attach: function (context, settings) { $('a[href*="#"]:not([href="#"])').once('smoothscroll').click(function() { if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { var target = $(this.hash); target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); if (target.length) { var offset_height = target.offset().top; $('html, body').stop().animate({ scrollTop: offset_height , }, 1000); return false; } } }); } }; })(jQuery);

Into code like this:

(function($, Drupal, once) { Drupal.behaviors.smoothScroll = { attach: function (context, settings) { var elements = once('smoothscroll', 'a[href*="#"]:not([href="#"])', context); $(elements).click(function() { if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { var target = $(this.hash); target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); if (target.length) { var offset_height = target.offset().top; $('html, body').stop().animate({ scrollTop: offset_height , }, 1000); return false; } } }); } }; })(jQuery, Drupal, once);

And then we need to tweak the definition of our library in the corresponding .libraries.yml file to remove the dependency on core/jquery.once and add one on core/once.

Twig changes

As mentioned previously the site was originally built in Drupal 8, which meant using Twig version 1, so there are plenty of deprecations to take care of to get the codebase ready for Drupal 10.

This is largely because we have a slightly strange setup in that we're using an early version of Emulsify to build our theme. Most importantly for this article it means that our theme contains quite a few twig functions like this:

<?php /** * @file * Add "getUniqueId" function for Pattern Lab. * * Brings the useful Drupal Html::getUniqueId function in. */ use Drupal\Component\Utility\Html; /** * Create the function we want to be able to call. * * Our function will be passed $context and then any other values provided. */ $function = new Twig_SimpleFunction('getUniqueId', function ($context, $string) { if (is_string($string)) { // Must cover the Drupal context AND the PatternLab context. if (class_exists('Drupal')) { return Html::getUniqueId($string); } else { return $string; } } else { return $string; } }, ['needs_context' => TRUE, 'is_safe' => ['html']]);

This can trivially become (changing the base class that is extended):

<?php /** * @file * Add "getUniqueId" function for Pattern Lab. * * Brings the useful Drupal Html::getUniqueId function in. */ use Drupal\Component\Utility\Html; /** * Create the function we want to be able to call. * * Our function will be passed $context and then any other values provided. */ $function = new \Twig\TwigFunction('getUniqueId', function ($context, $string) { if (is_string($string)) { // Must cover the Drupal context AND the PatternLab context. if (class_exists('Drupal')) { return Html::getUniqueId($string); } else { return $string; } } else { return $string; } }, ['needs_context' => TRUE, 'is_safe' => ['html']]);

The codebase has around 20 usages of deprecated Twig classes, however the task looks simple enough and there's nothing particularly tricky to do here, simply tweak the classes used per the deprecation messages in the older classes. There are automated tools that'll make these changes for you, but to be honest, there aren't that many changes to make and I'm keen to get eyes on the codebase more generally and get a feel for what we have in it!

All done

So that's it for Custom code and theme. We had actually been pretty good at:

  • Not writing custom code unless we had to.
  • If we did write custom code, not using already deprecated code.
  • Going back periodically and remediating new deprecations.

Which then makes these changes pretty straightforward. 

Aside: I'll just note that we have a lot jQuery style JavaScript in our codebase....mostly because we've been around for a while and learned JavaScript with jQuery, so it's just too easy for us to still write with jQuery everywhere. However, we know that we need to get to a place where we don't need jQuery and we'll get there, but we'll need to do some internal training on that and then go back through our code and re-write it without jQuery. Maybe I'll write an article about that too one day!

Salsa Digital Drupal-Related Articles: BenefitMe — coding NZ’s Social Security Act (Rules as Code)

Image removed.Overview  Digital Aotearoa Collective’s  challenge The Digital Aotearoa Collective (formerly GovZero Aotearoa) wanted to use Rules as Code (RaC) to code NZ’s Social Security Act. This was an important project for the collective, which aims to address injustice and improve wellbeing in Aotearoa New Zealand. Digital Aotearoa Collective’s transformation Salsa donated NZ$20,000 and three team members (for a total of 24 hours a week for 11 months) to help build the first iteration of BenefitMe . Working with other key members, we started with rules analysis, before splitting into two teams: one focused on service design and building the frontend, and one focused on the OpenFisca rules coding.  In the last 6 weeks of the project, Salsa also contributed additional Drupal resources.

Salsa Digital Drupal-Related Articles: The CivicTheme 1.4 release

Image removed.What’s in the CivicTheme 1.4 release? The recent CivicTheme 1.4 release includes a major review of all components and over 100 bug fixes. Some of the bigger changes include: New Event content type  Standardisation across all CivicTheme cards New support for external links  Updates to filters for automated lists Automatically generated component pages for visual regression testing New documentation The release of CivicTheme on drupal.org New Event content type The new Event content type provides event-specific fields. For example, time and date, and location (with the ability to embed a map URL or add in an address). Event cards can then link to this content.  Standardisation across all CivicTheme cards CivicTheme boasts an extensive range of different cards.