Как да създадете компонент на времевата линия с React

Тези дни работя върху нова страница за моя уебсайт. Исках да имам времева линия, за да покажа някои от моите професионални постижения през годините.

Направих го по няколко причини:

  1. Бъдещото ми аз ще погледна назад един ден и ще каже: „Леле… Спомням си деня, когато го направих! Колко щастлив бях да постигна тази цел! ”Нашият успех е пътуване, а не дестинация и искам да запиша всяка цел, която постигам по пътя
  2. Може да привлече повече клиенти (ще видим как става това )
  3. Според мен това е различен вид портфолио. Уникално портфолио, може би?

Независимо от това ... Нека сега изградим нещо!

На снимката по-горе можете да видите какво ще изградим днес, използвайки React! Преди да започнем да разбием стъпките, които трябва да предприемем:

  1. Създайте данните, които ще ни трябват
  2. Създайте компонента TimelineItem - всеки отделен запис на времевата линия
  3. Създайте контейнер на Timeline - той ще вземе данните и ще ги предаде на TimelineItems
  4. Стил всичко

Създайте данните

Преди да преминем към действително създаване на компонентите React, трябва да знаем как точно ще изглеждат данните, за да можем да планираме структурата на DOM.

За това приложение за Timeline ще ни трябва масив от обекти. Ще наречем този масив: timelineData.

Нека да видим как може да изглежда:

[
    {
        текст: „Написах първата си публикация в блога някога в Medium“,
        дата: „03 март 2017 г.“,
        категория: {
            таг: „среден“,
            цвят: '# 018f69'
        }
        връзка: {
            URL адрес:
                "Https://medium.com/@popflorin1705/javascript-coding-challenge-1-6d9c712963d2"
            текст: „Прочетете повече“
        }
    }
    {
        // Друг обект с данни
    }
];

Свойствата са доста прости, нали? Използвах подобни данни на тези, които имам на страницата си с времева линия, така че можем да кажем, че това е готово за производство!

След това ще изградим компонента TimelineItem. Това ще използва данните от обекта по-горе:

Компонентът TimelineItem

const TimelineItem = ({данни}) => (
    
        
                             {Data.category.tag}                          <Време> {data.date}             

{data.text}             {data.link && (                 <а                     HREF = {data.link.url}                     насочите = "_ празно"                     rel = "noopener noreferrer"                 >                     {Data.link.text}                              )}                            );

Имаме следните тагове:

  1. .timeline-елемент div - използва се като обвивка. Този div ще има половината от ширината на родителската му ширина (50%) и всеки друг. Div div-елемент div ще бъде поставен от дясната страна, използвайки: nth-child (нечетен) селектор
  2. .timeline-item-content div - друга обвивка (повече за това защо се нуждаем от това в секцията за стайлинг)
  3. .tang span - този маркер ще има персонализиран цвят на фона в зависимост от категорията
  4. часа / датата и текста
  5. връзка - ще трябва да проверим това, за да видим дали е предоставена връзка, защото може да не винаги искаме да имаме такава
  6. .circle span - този маркер ще се използва за поставяне на кръг в средната линия / лента

Забележка: Всичко ще има много по-голям смисъл, когато стигнем до CSS / стилизиращата част, но преди това нека създадем компонента Timeline:

Контейнерът на Timeline

Този компонент основно ще картографира масива и за всеки обект ще създаде компонент на TimelineItem. Добавяме и малка проверка, за да се уверим, че има поне един елемент в масива:

импортиране на времева линияData от '_path_to_file_';
const Timeline = () =>
    timelineData.length> 0 && (
        
            {timelineData.map ((данни, idx) => (                              ))}              );

Както бе споменато по-горе, timelineData е масив от обекти, съдържащ цялата необходима информация. В моя случай аз запазих този масив във файл и го импортирах тук, но можете да го вземете от собствената си база данни или от крайна точка на API, зависи от вас.

CSS

Забележка: по-голямата част от опаковките ще бъдат контейнери за флешбокс, защото можем да си играем по-лесно с тяхното позициониране.

Да започнем с CSS .timeline-контейнер:

.timeline-container {
    дисплей: гъвкав;
    гъвкава посока: колона;
    позиция: относителна;
    марж: 40px 0;
}
.timeline-container :: след {
    цвят на фона: # e17b77;
    съдържание: '';
    позиция: абсолютна;
    вляво: изчислено (50% - 2px);
    ширина: 4px;
    височина: 100%;
}

Използваме селектора :: after, за да създадем тази червена линия / лента в средата на контейнера .timeline. С помощта на функцията calc () можем да позиционираме линията точно по средата, като извадим половината от нейния размер (2px) от 50%. Трябва да направим това, защото по подразбиране лявото свойство го позиционира според левия ръб на елемент, а не по средата.

Сега, да преминем към опаковката на.

По-долу можете да видите пример как те са позиционирани в родителя си (контейнера .timeline). За демонстрационни цели добавих рамка, за да подчертая тези опаковки:

Както можете да видите, всяка друга обвивка отива надясно, а вътрешната обвивка (съдържанието на .timeline-item) заема по-малко място - място, дадено от p маркера, който е вътре в нея (предимно).

Нека видим CSS за това:

.timeline-item {
    дисплей: гъвкав;
    обосновка-съдържание: flex-end;
    подложка-дясна: 30px;
    позиция: относителна;
    марж: 10px 0;
    ширина: 50%;
}
.timeline-item: nth-дете (нечетно) {
    подравняване: самостоятелен флекс;
    обосновка-съдържание: флекс-старт;
    подложка-ляво: 30px;
    подложка-дясно: 0;
}

Ключът към това е, че използваме селектора: nth-child (нечетен) и задаваме свойството на подравняване-self към flex-end, което означава: „Отидете надясно колкото можете“!

Тъй като тези опаковки са с 50% ширина, можете да видите, че два от тях заемат цялата ширина. Отсега нататък всеки път, когато искаме да стилизираме различно нещо в дясната страна, ще трябва да използваме този подход.

На следващо място, опаковката на .timeline-item-content:

.timeline-item-content {
    кутия-сянка: 0 0 5px rgba (0, 0, 0, 0.3);
    граница-радиус: 5px;
    цвят на фона: #fff;
    дисплей: гъвкав;
    гъвкава посока: колона;
    подравняване-елементи: flex-end;
    подплънки: 15px;
    позиция: относителна;
    ширина: 400px;
    максимална ширина: 70%;
    подравняване на текст: дясно;
}
.timeline-item-content :: след {
    съдържание: '';
    цвят на фона: #fff;
    кутия-сянка: 1px -1px 1px rgba (0, 0, 0, 0.2);
    позиция: абсолютна;
    вдясно: -7.5px;
    отгоре: изчислено (50% - 7,5 пиксела);
    трансформация: завъртане (45deg);
    ширина: 15px;
    височина: 15px;
}
.timeline-item: nth-дете (нечетно) .timeline-item-content {
    подравняване на текст: вляво;
    подравняване-елементи: flex-start;
}
.timeline-item: nth-дете (нечетно) .timeline-item-content :: след {
    вдясно: авто;
    вляво: -7.5px;
    кутия-сянка: -1px 1px 1px rgba (0, 0, 0, 0.2);
}

Ние имаме няколко неща:

  1. Тази обвивка има фиксирана ширина и също максимална ширина. Това е така, защото искаме той да има някои граници, което означава, че ако има само няколко думи, искаме полето да е с ширина поне 400px, но ако има много текст, не трябва да заема цялото пространство (50% от опаковката на .timeline-елемент), но текстът трябва да премине към следващия ред -> това е причината да използваме тази втора обвивка: .timeline-item-content
  2. Свойствата за подравняване на текст и подравняване се използват за избутване на вътрешните елементи наляво или надясно, в зависимост от родителя
  3. Малката стрелка, която сочи към средната линия, се дава от стиловете, приложени на селектора :: след. По същество това е кутия с приложена върху нея кутия-сянка, която е завъртяна на 45 градуса
  4. Както бе споменато по-горе, ние оформяме дясната страна, като избираме родителя със селектора: nth-child (нечетен)

След това, всички вътрешни елементи:

.timeline-item-content .tag {
    цвят: #fff;
    размер на шрифта: 12px;
    шрифт: удебелен шрифт;
    отгоре: 5px;
    вляво: 5px;
    разстояние между букви: 1px;
    подплънки: 5px;
    позиция: абсолютна;
    преобразуване на текст: главни букви;
}
.timeline-item: nth-дете (нечетно) .timeline-item-content .tag {
    вляво: автоматично;
    вдясно: 5px;
}
.timeline-item-content time {
    цвят: # 777;
    размер на шрифта: 12px;
    шрифт: удебелен шрифт;
}
.timeline-item-content p {
    размер на шрифта: 16px;
    линия височина: 24px;
    марж: 15px 0;
    максимална ширина: 250px;
}
.timeline-item-content a {
    размер на шрифта: 14px;
    шрифт: удебелен шрифт;
}
.timeline-item-content a :: след {
    съдържание: „►“;
    размер на шрифта: 12px;
}
.timeline-item-content .circle {
    цвят на фона: #fff;
    граница: 3px твърд # e17b77;
    граница-радиус: 50%;
    позиция: абсолютна;
    отгоре: изчислено (50% - 10px);
    вдясно: -40px;
    ширина: 20px;
    височина: 20px;
    z-индекс: 100;
}
.timeline-item: nth-дете (нечетно) .timeline-item-content .circle {
    вдясно: авто;
    вляво: -40px;
}

Малко неща, които трябва да отбележите тук:

  1. Както може би се досещате,.
  2. Искаме да добавим малко каре след маркер, за да подчертаем, че това е връзка
  3. Създаваме .circle и го позиционираме отгоре на средната линия / лента директно пред стрелката

Почти сме приключили! Единственото, което остава да направите, е да добавите CSS, за да направите всичко отзивчиво във всички размери на екрана:

само @media екран и (максимална ширина: 1023px) {
    .timeline-item-content {
        максимална ширина: 100%;
    }
}
@media само екран и (максимална ширина: 767px) {
    .timeline-т-съдържание,
    .timeline-item: nth-дете (нечетно) .timeline-item-content {
        подплънки: 15px 10px;
        подравняване на текст: център;
        подравняване-елементи: център;
    }
    .timeline-item-content .tag {
        ширина: изчисление (100% - 10px);
        подравняване на текст: център;
    }
    .timeline-item-content time {
        марж-отгоре: 20px;
    }
    .timeline-item-content a {
        декорация на текст: подчертаване;
    }
    .timeline-item-content a :: след {
        дисплей: няма;
    }
}

Имаме две медийни заявки:

При малки размери на екрана на лаптоп - max-width: 1023px - искаме да позволим на .timeline-item-content да премине по цялата ширина на родителския му екран, защото екранът е по-малък и в противен случай ще изглежда стиснат

  1. На телефоните - макс. Ширина: 767px
  • настройте.
  • центрирайте целия текст и го натиснете надолу само отгоре
  • премахнете карето на линка и добавете подчертаване - изглежда по-добре на мобилни устройства

Aaaand ... Свършихме!

заключение

Както споменах, този компонент е на страницата ми Timeline. Вижте го, за да го видите в действие!

Ако има нещо, което не сте разбрали от тази статия, уверете се, че се свържете с мен и ще се радвам да отговоря на вашите въпроси!

Честито кодиране!

Първоначално публикуван на www.florin-pop.com.