aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site/static/css/timeline
diff options
context:
space:
mode:
Diffstat (limited to 'pydis_site/static/css/timeline')
-rw-r--r--pydis_site/static/css/timeline/timeline.css432
1 files changed, 432 insertions, 0 deletions
diff --git a/pydis_site/static/css/timeline/timeline.css b/pydis_site/static/css/timeline/timeline.css
new file mode 100644
index 00000000..7f6c4160
--- /dev/null
+++ b/pydis_site/static/css/timeline/timeline.css
@@ -0,0 +1,432 @@
+/* Adapted from https://codyhouse.co/gem/vertical-timeline/ with significant
+ * modifications.
+ * */
+
+:root {
+ --side-spacing: 0;
+ --background-color: rgb(232, 239, 245);
+ --accent: hsl(205, 26%, 84%);
+
+ --timeline-line-color: hsl(205, 38%, 89%);
+ --timeline-line-width: 4px;
+ --timeline-line-half-width: calc(var(--timeline-line-width) / 2);
+
+ --content-background-color: white;
+ --content-padding: 1.25rem;
+
+ --icon-width: 60px;
+ --icon-half-width: calc(var(--icon-width) / 2);
+ --icon-border-width: 4px;
+ --icon-border-color: white;
+ --icon-color: white;
+ --icon-image-width: 40px;
+ --icon-size: 1.5rem;
+ --icon-side-spacing: 1.5rem;
+
+ --date-color: hsl(0, 0%, 48%);
+ --arrow-size: 7px;
+}
+
+[data-theme="dark"] {
+ --background-color: #2C2F33;
+ --content-background-color: #23272A;
+ --accent: hsl(0, 0%, 34%);
+ --timeline-line-color: var(--accent);
+
+ --icon-border-color: hsl(0, 0%, 50%);
+}
+
+@media (max-width: 1023px) {
+ :root {
+ --side-spacing: 1.25rem;
+ --icon-side-spacing: var(--side-spacing);
+ --icon-width: 40px;
+ --icon-image-width: 30px;
+ --icon-size: 1.1rem;
+ }
+}
+
+/* Use a tighter margin and smaller icon dimensions on the most narrow screens.
+ * */
+@media (max-width: 600px) {
+ :root {
+ --side-spacing: .75rem;
+ --icon-side-spacing: .5rem;
+ --timeline-line-width: 3px;
+ --icon-width: 30px;
+ --icon-border-width: 3px;
+ --icon-image-width: 24px;
+ --icon-size: .9rem;
+ }
+}
+
+/* Containers */
+.timeline {
+ overflow: hidden;
+ padding: 3rem 0;
+ background-color: var(--background-color);
+}
+
+.timeline .container {
+ position: relative;
+ padding: 1rem var(--side-spacing);
+}
+
+/* The line that goes through all the icons */
+.timeline .container::before {
+ content: '';
+ position: absolute;
+
+ height: 100%;
+ width: var(--timeline-line-width);
+ background-color: var(--timeline-line-color);
+ z-index: 1;
+}
+
+@media (min-width: 1023px) {
+ .timeline .container::before {
+ left: calc(50% - var(--timeline-line-half-width));
+ }
+}
+
+@media (max-width: 1023px) {
+ .timeline .container::before {
+ margin-left: calc(var(--icon-half-width) - var(--timeline-line-half-width));
+ }
+}
+
+/* Each timeline item */
+.timeline-item {
+ display: flex;
+ align-items: flex-start;
+ margin-bottom: 2.5rem;
+}
+
+/* Arrow indicator on the top left/right of each content box */
+.timeline-content::before {
+ content: '';
+ position: absolute;
+ border: solid var(--arrow-size) transparent;
+ border-right-color: var(--accent);
+ height: 0;
+}
+
+@media (max-width: 1023px) {
+ .timeline-content::before {
+ margin-left: calc(0px - var(--content-padding) - 14px);
+ margin-top: calc(0px - var(--arrow-size) / 2);
+ }
+}
+
+@media (max-width: 600px) {
+ .timeline-content::before {
+ margin-top: calc(0px - var(--icon-half-width) + var(--arrow-size));
+ }
+}
+
+@media (min-width: 1023px) {
+ .timeline-content::before {
+ right: 100%;
+ margin-top: var(--arrow-size);
+ }
+ .timeline-item:nth-child(odd) .timeline-content::before {
+ border-left-color: var(--accent);
+ border-right-color: transparent;
+ left: 100%;
+ right: unset;
+ }
+}
+
+/* Visual container of the timeline item */
+.timeline-content.box {
+ padding: var(--content-padding);
+ box-shadow: var(--accent) 0px 3px 0px 0px;
+ background-color: var(--content-background-color);
+ flex-grow: 1;
+}
+
+@media (min-width: 1023px) {
+ .timeline-item:nth-child(odd) {
+ flex-direction: row-reverse;
+ }
+ /* On desktop, the content boxes are anchored with respect to the vertical
+ * center of the screen, set using `left`/`right` properties depending on
+ * even and odd children of timeline items.
+ * */
+ .timeline-content.box {
+ width: 45%;
+ flex-grow: 0;
+
+ position: relative;
+
+ --content-position: calc(50% + var(--icon-border-width) + var(--icon-half-width));
+
+ left: var(--content-position);
+ margin-left: var(--icon-side-spacing);
+ }
+ .timeline-item:nth-child(odd) .timeline-content.box {
+ left: unset;
+ right: var(--content-position);
+ margin-right: var(--icon-side-spacing);
+ }
+}
+
+@media (max-width: 1023px) {
+ .timeline-content.box {
+ margin-left: calc(var(--icon-side-spacing) + var(--arrow-size));
+ }
+}
+
+/* The icon and date components are grouped together in a flexbox to ensure
+ * there are center-aligned vertically on both desktop and mobile screens. This
+ * also makes it easy to both have dates' horizontal position follow that of
+ * the icon, and reverse their ordering for alternate timeline items on
+ * desktop.
+ * */
+.timeline-icon-date {
+ z-index: 4;
+ display: flex;
+ align-items: baseline;
+}
+
+@media (min-width: 1023px) {
+ .timeline-icon-date {
+ order: 1;
+
+ /* Arbitrary container width to prevent wrapping of the date text */
+ width: 50%;
+ align-items: center;
+ gap: var(--icon-side-spacing);
+
+ position: absolute;
+ left: calc(50% - var(--icon-half-width));
+ }
+
+ .timeline-item:nth-child(even) .timeline-icon-date {
+ flex-direction: row-reverse;
+ left: unset;
+ right: calc(50% - var(--icon-half-width));
+ }
+}
+
+/* Icon */
+.timeline-icon {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-shrink: 0;
+
+ border-radius: 50%;
+ height: var(--icon-width);
+ width: var(--icon-width);
+ /* The border does not actually use the border property because this border
+ * needs to cover the bottom box-shadow, which is easier if the border is
+ * implemented as a box-shadow.
+ * */
+ box-shadow: 0 0 0 var(--icon-border-width) var(--icon-border-color),
+ inset 0 2px 0 rgba(0,0,0,.08),
+ 0 3px 0 4px rgba(0,0,0,.05);
+ margin-top: var(--icon-border-width);
+
+ /* Font Awesome icon size and color */
+ color: var(--icon-color);
+ font-size: var(--icon-size);
+}
+
+/* Icons that use a custom image */
+.timeline-icon img {
+ width: var(--icon-image-width);
+ height: var(--icon-image-width);
+}
+
+/* Icons that use the pydis logo */
+.timeline-icon img.pydis {
+ /* Visually centering the pydis logo requires a margin adjustment here
+ * due to the right and bottom box shadow on the logo which is not very
+ * visible on the page.
+ *
+ * XXX: Hardcoded; Unresponsive to actual image dimensions.
+ * */
+ margin-top: 1px;
+ margin-left: 1px;
+}
+
+.timeline-date {
+ font-size: .9rem;
+ color: var(--date-color);
+}
+
+@media (min-width: 1023px) {
+ .timeline-item:nth-child(even) .timeline-date {
+ left: auto;
+ right: 50%;
+ text-align: right;
+ }
+}
+
+@media (max-width: 1023px) {
+ .timeline-date {
+ position: absolute;
+ /* On mobile, place the date at the top of the text box left-aligned
+ * with the other text in the box. When margin-left is zero, the date
+ * is left-aligned to the left of the icon (right of box-shadow).
+ * */
+ margin-left: calc(var(--icon-width) + var(--icon-side-spacing)
+ + var(--arrow-size) + var(--content-padding));
+ margin-top: .75rem;
+ }
+
+ .timeline-content.content h3 {
+ /* Make space for the date text */
+ margin-top: 1.25rem;
+ }
+}
+
+/* Icon background colors */
+.pastel-red {
+ background-color: #ff7878 !important;
+}
+[data-theme="dark"] .pastel-red {
+ background-color: #a44848 !important;
+}
+.pastel-orange {
+ background-color: #ffbf76 !important;
+}
+[data-theme="dark"] .pastel-orange {
+ background-color: #967147 !important;
+}
+.pastel-green {
+ background-color: #8bd6a7 !important;
+}
+[data-theme="dark"] .pastel-green {
+ background-color: #649f7a !important;
+}
+.pastel-blue {
+ background-color: #8edbec !important;
+}
+[data-theme="dark"] .pastel-blue {
+ background-color: #3d7986 !important;
+}
+.pastel-purple {
+ background-color: #cbb1ff !important;
+}
+[data-theme="dark"] .pastel-purple {
+ background-color: #8775ad !important;
+}
+.pastel-pink {
+ background-color: #f6acff !important;
+}
+[data-theme="dark"] .pastel-pink {
+ background-color: #79507e !important;
+}
+.pastel-lime {
+ background-color: #b6df3a !important;
+}
+[data-theme="dark"] .pastel-lime {
+ background-color: #7c9a21 !important;
+}
+.pastel-dark-blue {
+ /* Works well for both themes */
+ background-color: #576297 !important;
+}
+
+img, video, svg {
+ max-width: 100%
+}
+
+/* Bounce-in and bounce-out animations, desktop-only */
+@media (min-width: 1023px) {
+ .timeline-icon--hidden, .timeline-content--hidden, .timeline-date--hidden {
+ visibility: hidden;
+ }
+ .timeline-icon--bounce-in {
+ animation: icon-bounce 0.6s;
+ }
+ .timeline-content--bounce-in,
+ .timeline-date--bounce-in {
+ animation: item-bounce-left 0.6s;
+ }
+ .timeline-item:nth-child(even) .timeline-content--bounce-in,
+ .timeline-item:nth-child(even) .timeline-date--bounce-in {
+ animation-name: item-bounce-right;
+ }
+ .timeline-icon--bounce-out {
+ animation: icon-bounce-out 0.6s;
+ }
+ .timeline-content--bounce-out,
+ .timeline-date--bounce-out {
+ animation: item-bounce-out 0.6s;
+ }
+}
+
+@keyframes icon-bounce {
+ 0% {
+ opacity: 0;
+ transform: scale(0.5);
+ }
+ 60% {
+ opacity: 1;
+ transform: scale(1.2);
+ }
+ 100% {
+ transform: scale(1);
+ }
+}
+
+@keyframes item-bounce-left {
+ 0% {
+ opacity: 0;
+ transform: translateX(-100px)
+ }
+ 60% {
+ opacity: 1;
+ transform: translateX(20px)
+ }
+ 100% {
+ transform: translateX(0)
+ }
+}
+
+@keyframes item-bounce-right {
+ 0% {
+ opacity: 0;
+ transform: translateX(100px)
+ }
+ 60% {
+ opacity: 1;
+ transform: translateX(-20px)
+ }
+ 100% {
+ transform: translateX(0)
+ }
+}
+
+@keyframes icon-bounce-out {
+ 0% {
+ opacity: 1;
+ transform: scale(1);
+ }
+
+ 60% {
+ transform: scale(1.2);
+ }
+
+ 100% {
+ opacity: 0;
+ transform: scale(0.5);
+ }
+}
+
+@keyframes item-bounce-out {
+ 0% {
+ opacity: 1;
+ transform: translateX(0);
+ }
+ 60% {
+ transform: translateX(20px);
+ }
+ 100% {
+ opacity: 0;
+ transform: translateX(-100px);
+ }
+}