feat: one breadcrumb, same place and style on every inner page

- Plugin: vc_breadcrumb_trail()/vc_breadcrumb_html(); tours, region, city
  and tag pages show Home / (Region) / Page in the banner instead of the
  generic 'Tour & Travel' label; the tour page uses the same helper
- Theme: blog list shows Home / Blog; blog post title, breadcrumb and
  meta move into the banner like the other pages
- Shared style: title's colour (white in photo banners, black on About),
  softer links, current page bold and shortened if long - also on phones
- Plugin 1.9.6, theme 1.0.16

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-29 21:32:09 +03:30
parent 023b998694
commit 466ea0ac5f
14 changed files with 148 additions and 69 deletions

View File

@@ -266,6 +266,17 @@ class VC_Display {
. '.vc-fullwidth .site-content,.vc-fullwidth .ast-container,'
. '.vc-fullwidth .entry-content,.vc-fullwidth .site-main>article'
. '{overflow:visible!important;}',
// Breadcrumb — one style on every page (the theme's design pages use
// the same rules): takes the colour of the title it sits above,
// links softer, current page bold and shortened if long.
'.vc-app.vc-app .crumbs{color:inherit;}',
'.vc-app.vc-app .crumbs__list{color:inherit;font-size:.8125rem;font-weight:500;}',
'.vc-app.vc-app .crumbs__list a{opacity:.75;}',
'.vc-app.vc-app .crumbs__list a:hover{opacity:1;}',
'.vc-app.vc-app .crumbs__list [aria-current]{max-width:min(40ch,60vw);overflow:hidden;font-weight:700;text-overflow:ellipsis;white-space:nowrap;}',
'.vc-app.vc-app .hero__content>.crumbs{margin-block-end:calc(var(--sp-1) * -1);}',
// In a banner the title is white, so the breadcrumb is too.
'.vc-app.vc-app .hero .crumbs{color:var(--c-white);}',
// FAQ question buttons must stay flat — Astra gives <button> a shadow.
'.vc-app.vc-app .acc__q{box-shadow:none!important;}',
// Astra colours every heading on the element itself (h1–h6 and

View File

@@ -617,6 +617,64 @@ function vc_icon( $name, $extra_class = '' ) {
return '<svg class="' . esc_attr( $class ) . '" aria-hidden="true"><use href="#' . esc_attr( $name ) . '"></use></svg>';
}
/**
* Breadcrumb trail for the current Viator view: list of [label, url] links
* (Home first); the current page itself is not included.
* tours archive Home
* region / city Home › Region (for a city)
* tag / category Home › Tours
* single tour Home › Region › City (its canonical city)
* other pages Home
*/
function vc_breadcrumb_trail() {
$trail = array( array( __( 'Home', 'viator-collector' ), home_url( '/' ) ) );
$city = null;
if ( is_tax( 'viator_destination' ) ) {
$term = get_queried_object();
if ( $term instanceof WP_Term && $term->parent ) {
$city = $term; // its parent (region) is added below
}
} elseif ( is_tax( array( 'viator_tag', 'viator_category' ) ) ) {
$trail[] = array( __( 'Tours', 'viator-collector' ), get_post_type_archive_link( 'viator_tour' ) );
} elseif ( is_singular( 'viator_tour' ) ) {
$post_id = get_queried_object_id();
$city_slug = class_exists( 'VC_Routing' ) ? VC_Routing::product_city( $post_id ) : '';
$city = $city_slug ? get_term_by( 'slug', $city_slug, 'viator_destination' ) : null;
if ( ! $city ) {
$terms = get_the_terms( $post_id, 'viator_destination' );
$city = ( $terms && ! is_wp_error( $terms ) ) ? $terms[0] : null;
}
}
if ( $city instanceof WP_Term ) {
if ( $city->parent ) {
$region = get_term( $city->parent, 'viator_destination' );
if ( $region instanceof WP_Term && ! is_wp_error( get_term_link( $region ) ) ) {
$trail[] = array( $region->name, get_term_link( $region ) );
}
}
// On a city archive the city is the current page, not a link.
if ( is_singular( 'viator_tour' ) && ! is_wp_error( get_term_link( $city ) ) ) {
$trail[] = array( $city->name, get_term_link( $city ) );
}
}
return apply_filters( 'vc_breadcrumb_trail', $trail );
}
/**
* Breadcrumb markup shared by every page (the theme's design pages print the
* same structure): links, then the current page in bold.
*/
function vc_breadcrumb_html( array $trail, $current, $extra_class = '' ) {
$out = '<nav class="crumbs' . ( $extra_class ? ' ' . esc_attr( $extra_class ) : '' ) . '" aria-label="' . esc_attr__( 'Breadcrumb', 'viator-collector' ) . '"><ol class="crumbs__list">';
foreach ( $trail as $item ) {
$out .= '<li><a href="' . esc_url( $item[1] ) . '">' . esc_html( $item[0] ) . '</a></li>';
}
return $out . '<li aria-current="page">' . esc_html( $current ) . '</li></ol></nav>';
}
/**
* Rotating ring badge (the circular "BOOK NOW ·" anchor in the design).
*