section h-full
This commit is contained in:
@@ -14,7 +14,7 @@ const { lang, socialMediaLinks } = Astro.props
|
|||||||
const t = useTranslations(lang)
|
const t = useTranslations(lang)
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer id="contacts" class="flex flex-col items-center gap-4 text-center md:gap-6">
|
<footer id="contacts" class="flex w-full flex-col items-center gap-4 text-center md:gap-6">
|
||||||
<iframe
|
<iframe
|
||||||
transition:persist
|
transition:persist
|
||||||
src=`https://yandex.ru/map-widget/v1/?um=constructor%3A069b17526dc83cbf87c488f13ae089eb3af0f8f74af57e1be82e183434693562&source=constructor&scroll=false&lang=${lang}`
|
src=`https://yandex.ru/map-widget/v1/?um=constructor%3A069b17526dc83cbf87c488f13ae089eb3af0f8f74af57e1be82e183434693562&source=constructor&scroll=false&lang=${lang}`
|
||||||
|
|||||||
@@ -9,15 +9,18 @@ export const GymGallery: React.FC<GymGalleryProps> = ({ images }) => {
|
|||||||
return (
|
return (
|
||||||
<MediaSwiper
|
<MediaSwiper
|
||||||
breakpoints={{
|
breakpoints={{
|
||||||
[TW_SCREENS.MD]: {
|
[TW_SCREENS.SM]: {
|
||||||
slidesPerView: 2,
|
slidesPerView: 2,
|
||||||
},
|
},
|
||||||
[TW_SCREENS.LG]: {
|
[TW_SCREENS.MD]: {
|
||||||
slidesPerView: 3,
|
slidesPerView: 3,
|
||||||
},
|
},
|
||||||
|
[TW_SCREENS.LG]: {
|
||||||
|
slidesPerView: 4,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
images={images}
|
images={images}
|
||||||
imageClassName="aspect-3/4 max-w-[50vh] md:max-w-none mx-auto lg:max-h-[calc(90vh-144px)]"
|
imageClassName="aspect-3/4 max-w-[50vh] sm:max-w-[33vh] lg:max-w-[45vh] mx-auto"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const repeatedTexts =
|
|||||||
texts.length < 10 ? Array.from({ length: 10 / texts.length }, () => texts).flat() : texts
|
texts.length < 10 ? Array.from({ length: 10 / texts.length }, () => texts).flat() : texts
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex h-full w-max animate-marquee items-center gap-10 text-5xl font-bold uppercase">
|
<div class="flex h-full w-max animate-marquee items-center gap-10 text-5xl font-bold uppercase bg-brand">
|
||||||
{
|
{
|
||||||
repeatedTexts.map((text) => (
|
repeatedTexts.map((text) => (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const { title, description, className, id } = Astro.props
|
|||||||
<section
|
<section
|
||||||
id={id}
|
id={id}
|
||||||
class={cn(
|
class={cn(
|
||||||
'overflow-hidden w-full flex flex-col gap-5 py-16 px-5 md:px-10 lg:p-24 md:gap-12',
|
'overflow-hidden w-full flex flex-col gap-5 py-16 px-5 md:px-10 lg:p-24 md:gap-12 h-full justify-center',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ export const CoachCard: React.FC<CoachCardProps> = ({ data, slug }) => {
|
|||||||
const coachPageLink = `/coaches/${slug}`
|
const coachPageLink = `/coaches/${slug}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative aspect-3/4 h-full max-w-[262px] overflow-hidden rounded-3xl text-white md:max-w-[320px] lg:max-w-[400px]">
|
<div className="relative mx-auto aspect-3/4 max-w-[45vh] overflow-hidden rounded-3xl text-white">
|
||||||
<img
|
<img
|
||||||
{...cover}
|
{...cover}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
className="h-full w-full object-cover object-top mix-blend-luminosity"
|
className="w-full object-cover object-top mix-blend-luminosity"
|
||||||
alt={coverAlt}
|
alt={coverAlt}
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -2,17 +2,30 @@ import type { CollectionEntry } from 'astro:content'
|
|||||||
import { SimpleSwiper } from '../swiper/SimpleSwiper'
|
import { SimpleSwiper } from '../swiper/SimpleSwiper'
|
||||||
import { SwiperSlide } from 'swiper/react'
|
import { SwiperSlide } from 'swiper/react'
|
||||||
import { CoachCard } from './CoachCard'
|
import { CoachCard } from './CoachCard'
|
||||||
|
import { isAboveBreakpoint } from '@/libs/breakpoint'
|
||||||
|
import { TW_SCREENS } from '@/constants/images'
|
||||||
|
|
||||||
type CoachesProps = {
|
type CoachesProps = {
|
||||||
coaches: CollectionEntry<'coaches'>[]
|
coaches: CollectionEntry<'coaches'>[]
|
||||||
lang?: string
|
lang?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isXs = isAboveBreakpoint('XS')
|
||||||
|
|
||||||
export const Coaches: React.FC<CoachesProps> = ({ coaches, lang }) => {
|
export const Coaches: React.FC<CoachesProps> = ({ coaches, lang }) => {
|
||||||
return (
|
return (
|
||||||
<SimpleSwiper>
|
<SimpleSwiper
|
||||||
|
slidesPerView={1}
|
||||||
|
freeMode={isXs}
|
||||||
|
pagination={{ type: 'fraction', enabled: !isXs }}
|
||||||
|
breakpoints={{
|
||||||
|
[TW_SCREENS.XS]: {
|
||||||
|
slidesPerView: 'auto',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
{coaches.map((coach, index) => (
|
{coaches.map((coach, index) => (
|
||||||
<SwiperSlide className="!h-auto" style={{ width: 'auto' }} key={index}>
|
<SwiperSlide key={index} className="w-full xs:!w-auto">
|
||||||
<CoachCard {...coach} lang={lang} />
|
<CoachCard {...coach} lang={lang} />
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const MediaSwiper = React.forwardRef<SwiperRef, MediaSwiperProps>(
|
|||||||
loop={true}
|
loop={true}
|
||||||
watchSlidesProgress={true}
|
watchSlidesProgress={true}
|
||||||
style={{ overflow: 'hidden' }}
|
style={{ overflow: 'hidden' }}
|
||||||
className={cn('h-full w-full', className)}
|
className={cn('w-full rounded-3xl', className)}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
{images.map((image, index) => (
|
{images.map((image, index) => (
|
||||||
@@ -38,7 +38,7 @@ export const MediaSwiper = React.forwardRef<SwiperRef, MediaSwiperProps>(
|
|||||||
decoding="async"
|
decoding="async"
|
||||||
fetchPriority={index === 0 ? 'high' : 'auto'}
|
fetchPriority={index === 0 ? 'high' : 'auto'}
|
||||||
className={cn(
|
className={cn(
|
||||||
'aspect-video h-full w-full rounded-3xl object-cover object-center',
|
'aspect-video w-full rounded-3xl object-cover object-center',
|
||||||
imageClassName
|
imageClassName
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'swiper/css/pagination'
|
|||||||
import 'swiper/css/thumbs'
|
import 'swiper/css/thumbs'
|
||||||
import 'swiper/css/free-mode'
|
import 'swiper/css/free-mode'
|
||||||
import { MediaSwiper, type MediaSwiperProps } from './MediaSwiper'
|
import { MediaSwiper, type MediaSwiperProps } from './MediaSwiper'
|
||||||
|
import { TW_SCREENS } from '@/constants/images'
|
||||||
|
|
||||||
type MediaSwiperPropsWithThumbs = MediaSwiperProps & {
|
type MediaSwiperPropsWithThumbs = MediaSwiperProps & {
|
||||||
thumbs: ImportAttributes[]
|
thumbs: ImportAttributes[]
|
||||||
@@ -29,7 +30,12 @@ export const MediaSwiperWithThumbs: React.FC<MediaSwiperPropsWithThumbs> = ({
|
|||||||
/>
|
/>
|
||||||
<Swiper
|
<Swiper
|
||||||
onSwiper={setThumbsSwiper}
|
onSwiper={setThumbsSwiper}
|
||||||
spaceBetween={12}
|
spaceBetween={8}
|
||||||
|
breakpoints={{
|
||||||
|
[TW_SCREENS.MD]: {
|
||||||
|
spaceBetween: 12,
|
||||||
|
},
|
||||||
|
}}
|
||||||
slidesPerView={4}
|
slidesPerView={4}
|
||||||
freeMode={true}
|
freeMode={true}
|
||||||
watchSlidesProgress={true}
|
watchSlidesProgress={true}
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
.simple-swiper {
|
.simple-swiper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
/* height: 100%; */
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-wrapper {
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-pagination-fraction {
|
.swiper-pagination-fraction {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const ui = {
|
|||||||
'coaches.subtitle': 'Вашему вниманию! Представляем наш тренерский состав',
|
'coaches.subtitle': 'Вашему вниманию! Представляем наш тренерский состав',
|
||||||
'coaches.link': 'Подробнее',
|
'coaches.link': 'Подробнее',
|
||||||
// Slider Section
|
// Slider Section
|
||||||
'slider.title': 'НАШ <span class="text-brand">ТРЕНАЖЕРНЫЙ ЗАЛ</span>',
|
'slider.title': 'НАШ <span class="text-brand">ЗАЛ</span>',
|
||||||
'slider.subtitle': 'Современное оборудование в просторном зале',
|
'slider.subtitle': 'Современное оборудование в просторном зале',
|
||||||
// Services Section
|
// Services Section
|
||||||
'services.title': 'НАШИ <span class="text-brand">УСЛУГИ</span>',
|
'services.title': 'НАШИ <span class="text-brand">УСЛУГИ</span>',
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ const [thumbs, optimizedGallery] = galleryWithCover
|
|||||||
<Header />
|
<Header />
|
||||||
{
|
{
|
||||||
optimizedGallery && (
|
optimizedGallery && (
|
||||||
<Section className="mt-[var(--header-height)] md:mt-0">
|
<Section className="mt-[var(--header-height)] md:mt-0 overflow-auto h-auto">
|
||||||
<div class="grid w-full grid-cols-1 place-items-start gap-8 lg:grid-cols-2">
|
<div class="grid w-full grid-cols-1 place-items-start gap-8 lg:grid-cols-2">
|
||||||
<MediaSwiperWithThumbs
|
<MediaSwiperWithThumbs
|
||||||
client:only="react"
|
client:only="react"
|
||||||
images={optimizedGallery}
|
images={optimizedGallery}
|
||||||
thumbs={thumbs}
|
thumbs={thumbs}
|
||||||
imageClassName="aspect-3/4 max-w-[50vh] lg:w-auto object-top mx-auto lg:max-h-[70vh]"
|
imageClassName="aspect-3/4 max-w-[35vh] lg:w-auto object-top mx-auto lg:max-h-[70vh]"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-1 flex-col gap-8">
|
<div class="flex flex-1 flex-col gap-8">
|
||||||
<h1 class="font-bold lg:text-nowrap">{data.name}</h1>
|
<h1 class="font-bold lg:text-nowrap">{data.name}</h1>
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const t = useTranslations(lang)
|
|||||||
|
|
||||||
{
|
{
|
||||||
services && (
|
services && (
|
||||||
<Section id="services" title={t('services.title')}>
|
<Section id="services" title={t('services.title')} className="h-auto">
|
||||||
<Services client:visible services={services} />
|
<Services client:visible services={services} />
|
||||||
</Section>
|
</Section>
|
||||||
)
|
)
|
||||||
@@ -97,7 +97,7 @@ const t = useTranslations(lang)
|
|||||||
|
|
||||||
{
|
{
|
||||||
optimizedReviews && (
|
optimizedReviews && (
|
||||||
<Section id="reviews" title={t('reviews.title')}>
|
<Section id="reviews" title={t('reviews.title')} className="h-auto">
|
||||||
<Reviews client:only="react" reviews={optimizedReviews} lang={lang} />
|
<Reviews client:only="react" reviews={optimizedReviews} lang={lang} />
|
||||||
</Section>
|
</Section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--header-height: 6rem;
|
--header-height: 4rem;
|
||||||
--marquee-height: 105px;
|
--marquee-height: 105px;
|
||||||
--swiper-theme-color: rgba(198, 15, 211, 1) !important;
|
--swiper-theme-color: rgba(198, 15, 211, 1) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
import { TW_WIDTHS } from './src/constants/images';
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
screens: {
|
||||||
|
xs: `${TW_WIDTHS.XS}px`,
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
bg: {
|
bg: {
|
||||||
main: 'rgba(19, 21, 20, 1)',
|
main: 'rgba(19, 21, 20, 1)',
|
||||||
|
|||||||
Reference in New Issue
Block a user