mirror of
https://gitlab.unicamp.br/infimecc_drupal11_modules/site_users.git
synced 2026-05-04 06:50:40 -03:00
Adiciona bloco MicrositeHeaderBlock e regiões ao tema do microsite
- Novo bloco MicrositeHeaderBlock (site_users_microsite): exibe foto circular (220×280px), nome (h1), biografia e contatos (telefone, e-mail). Título oculto por padrão; biografia renderizada via ->processed com |raw no template. - Remove UserInfoBlock e seu template (não estava em uso). - Adiciona regiões Top Bar e Navigation ao tema; menu.html.twig para gerar classes .menu__item/.menu__link compatíveis com o CSS. - CSS: estilos das novas regiões e do bloco de cabeçalho. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,24 @@
|
||||
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function site_users_microsite_theme(): array {
|
||||
return [
|
||||
'microsite_header_block' => [
|
||||
'variables' => [
|
||||
'photo_url' => NULL,
|
||||
'photo_alt' => '',
|
||||
'name' => NULL,
|
||||
'bio' => NULL,
|
||||
'phone' => NULL,
|
||||
'email' => NULL,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_page().
|
||||
*
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\site_users_microsite\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Bloco de cabeçalho do microsite com informações do usuário.
|
||||
*
|
||||
* Exibe foto (circular), nome, biografia e
|
||||
* informações de contato (telefone, e-mail).
|
||||
*
|
||||
* @Block(
|
||||
* id = "site_users_microsite_header",
|
||||
* admin_label = @Translation("Microsite — cabeçalho do usuário"),
|
||||
* category = @Translation("Site Users")
|
||||
* )
|
||||
*/
|
||||
class MicrositeHeaderBlock extends BlockBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
public function __construct(
|
||||
array $configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
protected RouteMatchInterface $routeMatch,
|
||||
protected EntityTypeManagerInterface $entityTypeManager,
|
||||
) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
}
|
||||
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('current_route_match'),
|
||||
$container->get('entity_type.manager'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration(): array {
|
||||
return ['label_display' => '0'] + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build(): array {
|
||||
$user = $this->getUser();
|
||||
if (!$user instanceof UserInterface) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
'#theme' => 'microsite_header_block',
|
||||
'#photo_url' => $this->getPhotoUrl($user),
|
||||
'#photo_alt' => $this->getPhotoAlt($user),
|
||||
'#name' => $this->getFieldValue($user, 'field_user_name') ?: $user->getDisplayName(),
|
||||
'#bio' => $this->getProcessedValue($user, 'field_user_bio'),
|
||||
'#phone' => $this->getFieldValue($user, 'field_user_phone'),
|
||||
'#email' => $user->getEmail(),
|
||||
'#cache' => [
|
||||
'tags' => $user->getCacheTags(),
|
||||
'contexts' => ['route'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna o usuário da rota atual.
|
||||
*/
|
||||
protected function getUser(): ?UserInterface {
|
||||
$user = $this->routeMatch->getParameter('user');
|
||||
if ($user instanceof UserInterface) {
|
||||
return $user;
|
||||
}
|
||||
if (is_numeric($user)) {
|
||||
return $this->entityTypeManager->getStorage('user')->load($user);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna a URL absoluta da foto padrão do usuário.
|
||||
*/
|
||||
protected function getPhotoUrl(UserInterface $user): ?string {
|
||||
if (!function_exists('site_users_get_default_photo')) {
|
||||
return NULL;
|
||||
}
|
||||
$media = site_users_get_default_photo($user);
|
||||
if (!$media) {
|
||||
return NULL;
|
||||
}
|
||||
$source_field = $media->getSource()->getConfiguration()['source_field'];
|
||||
if (!$media->hasField($source_field) || $media->get($source_field)->isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
$file = $media->get($source_field)->entity;
|
||||
if (!$file) {
|
||||
return NULL;
|
||||
}
|
||||
return \Drupal::service('file_url_generator')->generateAbsoluteString($file->getFileUri());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna o texto alternativo da foto padrão.
|
||||
*/
|
||||
protected function getPhotoAlt(UserInterface $user): string {
|
||||
if (!function_exists('site_users_get_default_photo')) {
|
||||
return '';
|
||||
}
|
||||
$media = site_users_get_default_photo($user);
|
||||
return $media ? $media->label() : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna o valor de texto de um campo do usuário.
|
||||
*/
|
||||
protected function getFieldValue(UserInterface $user, string $field_name): ?string {
|
||||
if ($user->hasField($field_name) && !$user->get($field_name)->isEmpty()) {
|
||||
return $user->get($field_name)->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna o valor processado (HTML filtrado) de um campo text_long.
|
||||
*
|
||||
* Usa ->processed, que aplica o formato de texto configurado e retorna um
|
||||
* objeto Markup — o Twig renderiza como HTML sem escape adicional.
|
||||
*/
|
||||
protected function getProcessedValue(UserInterface $user, string $field_name): ?string {
|
||||
if ($user->hasField($field_name) && !$user->get($field_name)->isEmpty()) {
|
||||
return $user->get($field_name)->processed;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags(): array {
|
||||
$user = $this->getUser();
|
||||
if ($user instanceof UserInterface) {
|
||||
return Cache::mergeTags(parent::getCacheTags(), $user->getCacheTags());
|
||||
}
|
||||
return parent::getCacheTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheContexts(): array {
|
||||
return Cache::mergeContexts(parent::getCacheContexts(), ['route']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Template do bloco de cabeçalho do microsite.
|
||||
*
|
||||
* Variáveis:
|
||||
* - photo_url: URL absoluta da foto padrão (string|null).
|
||||
* - photo_alt: Texto alternativo da foto (string).
|
||||
* - name: Nome completo do usuário (string).
|
||||
* - roles: Array de rótulos das roles do usuário (string[]).
|
||||
* - bio: Biografia (string|null).
|
||||
* - phone: Telefone (string|null).
|
||||
* - email: E-mail (string|null).
|
||||
*/
|
||||
#}
|
||||
<div class="msite-header-block">
|
||||
|
||||
<div class="msite-header-block__photo-wrap">
|
||||
{% if photo_url %}
|
||||
<img
|
||||
class="msite-header-block__photo"
|
||||
src="{{ photo_url }}"
|
||||
alt="{{ photo_alt }}"
|
||||
/>
|
||||
{% else %}
|
||||
<div class="msite-header-block__photo msite-header-block__photo--initials" aria-hidden="true">
|
||||
{{ name|first|upper }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="msite-header-block__info">
|
||||
|
||||
<h1 class="msite-header-block__name">{{ name }}</h1>
|
||||
|
||||
{% if bio %}
|
||||
<div class="msite-header-block__bio">{{ bio|raw }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if phone or email %}
|
||||
<ul class="msite-header-block__contact">
|
||||
{% if phone %}
|
||||
<li class="msite-header-block__contact-item">
|
||||
<span class="msite-header-block__contact-label">{{ 'Telefone'|t }}:</span>
|
||||
<a href="tel:{{ phone }}">{{ phone }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if email %}
|
||||
<li class="msite-header-block__contact-item">
|
||||
<span class="msite-header-block__contact-label">{{ 'E-mail'|t }}:</span>
|
||||
<a href="mailto:{{ email }}">{{ email }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -32,13 +32,7 @@ function site_users_theme($existing, $type, $theme, $path) {
|
||||
'template' => 'user--restricted',
|
||||
'base hook' => 'user',
|
||||
],
|
||||
'site_users_info_block' => [
|
||||
'template' => 'site-user-info-block',
|
||||
'variables' => [
|
||||
'user_info' => [],
|
||||
'user' => NULL,
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\site_users\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Bloco com informações básicas do usuário.
|
||||
*
|
||||
* Exibe automaticamente as informações do usuário da rota /user/{id}.
|
||||
*
|
||||
* @Block(
|
||||
* id = "site_users_info_block",
|
||||
* admin_label = @Translation("User Information"),
|
||||
* category = @Translation("Site Users")
|
||||
* )
|
||||
*/
|
||||
class UserInfoBlock extends BlockBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The current route match.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteMatchInterface
|
||||
*/
|
||||
protected $routeMatch;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new UserInfoBlock instance.
|
||||
*
|
||||
* @param array $configuration
|
||||
* The plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definition.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The current route match.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(
|
||||
array $configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
RouteMatchInterface $route_match,
|
||||
EntityTypeManagerInterface $entity_type_manager
|
||||
) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->routeMatch = $route_match;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('current_route_match'),
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
$user = $this->getUserFromContext();
|
||||
|
||||
if (!$user instanceof UserInterface) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Obter foto padrão.
|
||||
$default_photo = NULL;
|
||||
$default_photo_url = NULL;
|
||||
if (function_exists('site_users_get_default_photo')) {
|
||||
$default_photo = site_users_get_default_photo($user);
|
||||
if ($default_photo) {
|
||||
// Usar o source field do media (forma padrão do Drupal).
|
||||
$source_field = $default_photo->getSource()->getConfiguration()['source_field'];
|
||||
if ($default_photo->hasField($source_field) && !$default_photo->get($source_field)->isEmpty()) {
|
||||
$file = $default_photo->get($source_field)->entity;
|
||||
if ($file) {
|
||||
$default_photo_url = \Drupal::service('file_url_generator')->generateAbsoluteString($file->getFileUri());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Coletar informações do usuário.
|
||||
$user_info = [
|
||||
'uid' => $user->id(),
|
||||
'username' => $user->getDisplayName(),
|
||||
'name' => $this->getFieldValue($user, 'field_user_name'),
|
||||
'phone' => $this->getFieldValue($user, 'field_user_phone'),
|
||||
'bio' => $this->getFieldValue($user, 'field_user_bio'),
|
||||
'social_links' => $this->getSocialLinks($user),
|
||||
'photo_url' => $default_photo_url,
|
||||
'photo_alt' => $default_photo ? $default_photo->label() : '',
|
||||
];
|
||||
|
||||
return [
|
||||
'#theme' => 'site_users_info_block',
|
||||
'#user_info' => $user_info,
|
||||
'#user' => $user,
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'site_users/user-info-block',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtém o usuário da rota atual.
|
||||
*
|
||||
* @return \Drupal\user\UserInterface|null
|
||||
* O usuário ou NULL se não estiver em uma página de usuário.
|
||||
*/
|
||||
protected function getUserFromContext(): ?UserInterface {
|
||||
// Obter da rota /user/{user}.
|
||||
$user = $this->routeMatch->getParameter('user');
|
||||
|
||||
if ($user instanceof UserInterface) {
|
||||
return $user;
|
||||
}
|
||||
|
||||
// Se for apenas o ID, carregar o usuário.
|
||||
if (is_numeric($user)) {
|
||||
return $this->entityTypeManager->getStorage('user')->load($user);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the social network links of a user.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* The user entity.
|
||||
*
|
||||
* @return array
|
||||
* Array of items with 'network' and 'url' keys.
|
||||
*/
|
||||
protected function getSocialLinks(UserInterface $user): array {
|
||||
$links = [];
|
||||
|
||||
if (!$user->hasField('field_user_social_links') || $user->get('field_user_social_links')->isEmpty()) {
|
||||
return $links;
|
||||
}
|
||||
|
||||
foreach ($user->get('field_user_social_links') as $item) {
|
||||
if (!$item->isEmpty()) {
|
||||
$links[] = [
|
||||
'network' => $item->network,
|
||||
'url' => $item->url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtém o valor de um campo do usuário.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* O usuário.
|
||||
* @param string $field_name
|
||||
* O nome do campo.
|
||||
*
|
||||
* @return string|null
|
||||
* O valor do campo ou NULL.
|
||||
*/
|
||||
protected function getFieldValue(UserInterface $user, string $field_name): ?string {
|
||||
if ($user->hasField($field_name) && !$user->get($field_name)->isEmpty()) {
|
||||
return $user->get($field_name)->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags() {
|
||||
$tags = parent::getCacheTags();
|
||||
|
||||
$user = $this->getUserFromContext();
|
||||
if ($user instanceof UserInterface) {
|
||||
$tags = Cache::mergeTags($tags, $user->getCacheTags());
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheContexts() {
|
||||
return Cache::mergeContexts(parent::getCacheContexts(), ['route', 'user']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
{#
|
||||
/**
|
||||
* @file
|
||||
* Template for the user information block.
|
||||
*
|
||||
* Available variables:
|
||||
* - user_info: Array with user information:
|
||||
* - uid: User ID
|
||||
* - username: Display name
|
||||
* - name: Full name
|
||||
* - phone: Phone number
|
||||
* - bio: Biography
|
||||
* - social_links: Array of social links, each with 'network' and 'url' keys
|
||||
* - photo_url: Default photo URL
|
||||
* - photo_alt: Photo alternative text
|
||||
* - user: User entity.
|
||||
*/
|
||||
#}
|
||||
<div class="site-user-info-block">
|
||||
<div class="site-user-info-block__photo">
|
||||
{% if user_info.photo_url %}
|
||||
<img src="{{ user_info.photo_url }}" alt="{{ user_info.photo_alt }}" class="site-user-info-block__image" />
|
||||
{% else %}
|
||||
<div class="site-user-info-block__no-photo">
|
||||
<span class="site-user-info-block__initials">
|
||||
{{ user_info.name ? user_info.name|first|upper : user_info.username|first|upper }}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="site-user-info-block__details">
|
||||
<h2 class="site-user-info-block__name">
|
||||
{{ user_info.name ?: user_info.username }}
|
||||
</h2>
|
||||
|
||||
{% if user_info.phone %}
|
||||
<div class="site-user-info-block__phone">
|
||||
<span class="site-user-info-block__label">{{ 'Phone:'|t }}</span>
|
||||
<a href="tel:{{ user_info.phone }}">{{ user_info.phone }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user_info.bio %}
|
||||
<div class="site-user-info-block__bio">
|
||||
{{ user_info.bio }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user_info.social_links %}
|
||||
<div class="site-user-info-block__social-links">
|
||||
{% for link in user_info.social_links %}
|
||||
<a href="{{ link.url }}"
|
||||
class="social-link social-link--{{ link.network }}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
{{ link.network }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,6 +154,105 @@ body.microsite {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Microsite Header Block --------------------------------------------------- */
|
||||
/*
|
||||
* Bloco .msite-header-block: foto circular, nome (h1), meta (roles +
|
||||
* departamento), biografia e lista de contatos.
|
||||
* Assume fundo escuro herdado do .microsite-header.
|
||||
*/
|
||||
|
||||
.msite-header-block {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 1.75rem;
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1.5rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* --- Foto ----------------------------------------------------------------- */
|
||||
|
||||
.msite-header-block__photo-wrap {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.msite-header-block__photo {
|
||||
display: block;
|
||||
width: 220px;
|
||||
height: 280px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
border: 3px solid rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
/* Fallback de iniciais quando não há foto */
|
||||
.msite-header-block__photo--initials {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
font-size: 4rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* --- Informações ---------------------------------------------------------- */
|
||||
|
||||
.msite-header-block__info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.msite-header-block__name {
|
||||
margin: 0 0 0.3rem;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.msite-header-block__meta {
|
||||
margin: 0 0 0.75rem;
|
||||
font-size: 0.95rem;
|
||||
font-style: italic;
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
|
||||
.msite-header-block__bio {
|
||||
margin-bottom: 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
/* --- Contatos ------------------------------------------------------------- */
|
||||
|
||||
.msite-header-block__contact {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.3rem 1.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.msite-header-block__contact-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.msite-header-block__contact a {
|
||||
color: hsl(202, 79%, 70%);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.msite-header-block__contact a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Top Bar ------------------------------------------------------------------ */
|
||||
/*
|
||||
* Barra estreita no topo da página, antes do header.
|
||||
|
||||
Reference in New Issue
Block a user