@codecademy/brand 5.2.0-alpha.f811da96e.0 → 5.3.0-alpha.50a688319.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,7 @@
1
- $appbar-gutter: 8px;
2
- $appbar-tab-width: 48px;
1
+ @use "~@codecademy/gamut-styles/utils";
2
+
3
+ $appbar-gutter: utils.px-rem(8px);
4
+ $appbar-tab-width: utils.px-rem(48px);
3
5
  $appbar-z: 14;
4
6
 
5
7
  .wrapper {
@@ -0,0 +1,6 @@
1
+ import type { UpcomingWorkshopNavItem } from '../../../../GlobalHeader/types';
2
+ type AppHeaderWorkshopCardProps = {
3
+ workshop: UpcomingWorkshopNavItem;
4
+ };
5
+ export declare const AppHeaderWorkshopCard: React.FC<AppHeaderWorkshopCardProps>;
6
+ export {};
@@ -0,0 +1,135 @@
1
+ import _styled from "@emotion/styled/base";
2
+ import { Anchor, Box, Card, FlexBox, Text } from '@codecademy/gamut';
3
+ import { CalendarIcon, OptimizationClockIcon } from '@codecademy/gamut-icons';
4
+ import { GridDense } from '@codecademy/gamut-patterns';
5
+ import { useGlobalHeaderItemClick } from '../../../../GlobalHeader/context';
6
+ import { Divider } from '../../../../InstructorCard';
7
+ import { useAppHeaderDropdownContext } from '../../AppHeaderDropdownProvider';
8
+ import { useAppHeaderSectionContext } from '../../AppHeaderSection/AppHeaderSectionContext';
9
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
10
+ const StyledCard = /*#__PURE__*/_styled(Card, {
11
+ target: "e1aahqt50",
12
+ label: "StyledCard"
13
+ })("&:hover{color:", ({
14
+ theme
15
+ }) => theme.colors.primary, ";border-color:", ({
16
+ theme
17
+ }) => theme.colors.primary, ";}" + (process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9BcHBIZWFkZXIvQXBwSGVhZGVyRWxlbWVudHMvQXBwSGVhZGVyTGl2ZUNvdXJzZXNEcm9wZG93bi9BcHBIZWFkZXJXb3Jrc2hvcENhcmQvaW5kZXgudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVcrQiIsImZpbGUiOiIuLi8uLi8uLi8uLi8uLi9zcmMvQXBwSGVhZGVyL0FwcEhlYWRlckVsZW1lbnRzL0FwcEhlYWRlckxpdmVDb3Vyc2VzRHJvcGRvd24vQXBwSGVhZGVyV29ya3Nob3BDYXJkL2luZGV4LnRzeCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFuY2hvciwgQm94LCBDYXJkLCBGbGV4Qm94LCBUZXh0IH0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQnO1xuaW1wb3J0IHsgQ2FsZW5kYXJJY29uLCBPcHRpbWl6YXRpb25DbG9ja0ljb24gfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1pY29ucyc7XG5pbXBvcnQgeyBHcmlkRGVuc2UgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1wYXR0ZXJucyc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5cbmltcG9ydCB7IHVzZUdsb2JhbEhlYWRlckl0ZW1DbGljayB9IGZyb20gJy4uLy4uLy4uLy4uL0dsb2JhbEhlYWRlci9jb250ZXh0JztcbmltcG9ydCB0eXBlIHsgVXBjb21pbmdXb3Jrc2hvcE5hdkl0ZW0gfSBmcm9tICcuLi8uLi8uLi8uLi9HbG9iYWxIZWFkZXIvdHlwZXMnO1xuaW1wb3J0IHsgRGl2aWRlciB9IGZyb20gJy4uLy4uLy4uLy4uL0luc3RydWN0b3JDYXJkJztcbmltcG9ydCB7IHVzZUFwcEhlYWRlckRyb3Bkb3duQ29udGV4dCB9IGZyb20gJy4uLy4uL0FwcEhlYWRlckRyb3Bkb3duUHJvdmlkZXInO1xuaW1wb3J0IHsgdXNlQXBwSGVhZGVyU2VjdGlvbkNvbnRleHQgfSBmcm9tICcuLi8uLi9BcHBIZWFkZXJTZWN0aW9uL0FwcEhlYWRlclNlY3Rpb25Db250ZXh0JztcblxuY29uc3QgU3R5bGVkQ2FyZCA9IHN0eWxlZChDYXJkKWBcbiAgJjpob3ZlciB7XG4gICAgY29sb3I6ICR7KHsgdGhlbWUgfSkgPT4gdGhlbWUuY29sb3JzLnByaW1hcnl9O1xuICAgIGJvcmRlci1jb2xvcjogJHsoeyB0aGVtZSB9KSA9PiB0aGVtZS5jb2xvcnMucHJpbWFyeX07XG4gIH1cbmA7XG5cbnR5cGUgSW5mb1Jvd1Byb3BzID0ge1xuICBpY29uOiBSZWFjdC5SZWFjdE5vZGU7XG4gIGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGU7XG59O1xuXG5jb25zdCBJbmZvUm93OiBSZWFjdC5GQzxJbmZvUm93UHJvcHM+ID0gKHsgaWNvbiwgY2hpbGRyZW4gfSkgPT4gKFxuICA8RmxleEJveCBhbGlnbkl0ZW1zPVwiY2VudGVyXCIgZ2FwPXs4fT5cbiAgICB7aWNvbn1cbiAgICA8VGV4dCBmb250U2l6ZT17MTR9IGxpbmVIZWlnaHQ9XCJiYXNlXCIgY29sb3I9XCJ0ZXh0XCI+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9UZXh0PlxuICA8L0ZsZXhCb3g+XG4pO1xuXG50eXBlIEFwcEhlYWRlcldvcmtzaG9wQ2FyZFByb3BzID0ge1xuICB3b3Jrc2hvcDogVXBjb21pbmdXb3Jrc2hvcE5hdkl0ZW07XG59O1xuXG5leHBvcnQgY29uc3QgQXBwSGVhZGVyV29ya3Nob3BDYXJkOiBSZWFjdC5GQzxBcHBIZWFkZXJXb3Jrc2hvcENhcmRQcm9wcz4gPSAoe1xuICB3b3Jrc2hvcCxcbn0pID0+IHtcbiAgY29uc3QgeyBnbG9iYWxIZWFkZXJJdGVtQ2xpY2sgfSA9IHVzZUdsb2JhbEhlYWRlckl0ZW1DbGljaygpO1xuICBjb25zdCB7IGhhbmRsZUNsb3NlIH0gPSB1c2VBcHBIZWFkZXJEcm9wZG93bkNvbnRleHQoKTtcbiAgY29uc3QgeyB0YWJJbmRleCB9ID0gdXNlQXBwSGVhZGVyU2VjdGlvbkNvbnRleHQoKTtcblxuICBjb25zdCBsaW5rSXRlbSA9IHtcbiAgICB0eXBlOiAnbGluaycgYXMgY29uc3QsXG4gICAgaWQ6IHdvcmtzaG9wLmlkLFxuICAgIGhyZWY6IHdvcmtzaG9wLmhyZWYsXG4gICAgdGV4dDogd29ya3Nob3AudGl0bGUsXG4gICAgdHJhY2tpbmdUYXJnZXQ6IHdvcmtzaG9wLnRyYWNraW5nVGFyZ2V0LFxuICB9O1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPEFuY2hvclxuICAgICAgICBocmVmPXt3b3Jrc2hvcC5ocmVmfVxuICAgICAgICB2YXJpYW50PVwiaW50ZXJmYWNlXCJcbiAgICAgICAgZGlzcGxheT1cImJsb2NrXCJcbiAgICAgICAgdGFiSW5kZXg9e3RhYkluZGV4fVxuICAgICAgICBvbkNsaWNrPXsoZXZlbnQ6IFJlYWN0Lk1vdXNlRXZlbnQ8SFRNTEFuY2hvckVsZW1lbnQsIE1vdXNlRXZlbnQ+KSA9PiB7XG4gICAgICAgICAgZ2xvYmFsSGVhZGVySXRlbUNsaWNrKGV2ZW50LCBsaW5rSXRlbSk7XG4gICAgICAgICAgaGFuZGxlQ2xvc2UoKTtcbiAgICAgICAgfX1cbiAgICAgID5cbiAgICAgICAgPFN0eWxlZENhcmRcbiAgICAgICAgICBib3JkZXJSYWRpdXM9XCJsZ1wiXG4gICAgICAgICAgYm9yZGVyPXsxfVxuICAgICAgICAgIGJvcmRlckNvbG9yPVwiYm9yZGVyLXRlcnRpYXJ5XCJcbiAgICAgICAgICBkaXNwbGF5PVwiZmxleFwiXG4gICAgICAgICAgYWxpZ25JdGVtcz1cImZsZXgtc3RhcnRcIlxuICAgICAgICAgIGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIlxuICAgICAgICAgIHB4PXsxNn1cbiAgICAgICAgICBweT17MjR9XG4gICAgICAgICAgbWluSGVpZ2h0PXsyMTl9XG4gICAgICAgICAgaGVpZ2h0PVwiMTAwJVwiXG4gICAgICAgID5cbiAgICAgICAgICA8VGV4dFxuICAgICAgICAgICAgdmFyaWFudD1cInAtbGFyZ2VcIlxuICAgICAgICAgICAgZm9udFdlaWdodD17NzAwfVxuICAgICAgICAgICAgYXM9XCJoM1wiXG4gICAgICAgICAgICB3aWR0aD1cIjEwMCVcIlxuICAgICAgICAgICAgdHJ1bmNhdGU9XCJlbGxpcHNpc1wiXG4gICAgICAgICAgICB0cnVuY2F0ZUxpbmVzPXsyfVxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt3b3Jrc2hvcC50aXRsZX1cbiAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgPEJveCB3aWR0aD1cIjEwMCVcIj5cbiAgICAgICAgICAgIDxHcmlkRGVuc2UgaGVpZ2h0PXs0fSAvPlxuICAgICAgICAgIDwvQm94PlxuICAgICAgICAgIDxGbGV4Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIiBnYXA9ezR9IHdpZHRoPVwiMTAwJVwiPlxuICAgICAgICAgICAgPFRleHQgZm9udFNpemU9ezE0fSBmb250V2VpZ2h0PVwiYm9sZFwiIGxpbmVIZWlnaHQ9XCJiYXNlXCI+XG4gICAgICAgICAgICAgIHt3b3Jrc2hvcC5pbnN0cnVjdG9yTmFtZX1cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgIDxUZXh0XG4gICAgICAgICAgICAgIGZvbnRTaXplPXsxNH1cbiAgICAgICAgICAgICAgbGluZUhlaWdodD1cImJhc2VcIlxuICAgICAgICAgICAgICBjb2xvcj1cInRleHQtc2Vjb25kYXJ5XCJcbiAgICAgICAgICAgICAgdHJ1bmNhdGU9XCJlbGxpcHNpc1wiXG4gICAgICAgICAgICAgIHRydW5jYXRlTGluZXM9ezF9XG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt3b3Jrc2hvcC5pbnN0cnVjdG9yVGl0bGV9XG4gICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgPC9GbGV4Qm94PlxuICAgICAgICAgIDxGbGV4Qm94XG4gICAgICAgICAgICBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCJcbiAgICAgICAgICAgIGFsaWduU2VsZj1cInN0cmV0Y2hcIlxuICAgICAgICAgICAgd2lkdGg9XCIxMDAlXCJcbiAgICAgICAgICAgIG10PXs0fVxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt3b3Jrc2hvcC5uZXh0Q29ob3J0U3RhcnREYXRlID8gKFxuICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgIDxEaXZpZGVyIC8+XG4gICAgICAgICAgICAgICAgPEluZm9Sb3cgaWNvbj17PENhbGVuZGFySWNvbiBzaXplPXsxNn0gYXJpYS1oaWRkZW4gLz59PlxuICAgICAgICAgICAgICAgICAgTmV4dCBjb2hvcnQ6IG9ueycgJ31cbiAgICAgICAgICAgICAgICAgIDxUZXh0IGFzPVwic3BhblwiIGZvbnRXZWlnaHQ9XCJib2xkXCI+XG4gICAgICAgICAgICAgICAgICAgIHt3b3Jrc2hvcC5uZXh0Q29ob3J0U3RhcnREYXRlfVxuICAgICAgICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgICAgICAgIDwvSW5mb1Jvdz5cbiAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApIDogbnVsbH1cbiAgICAgICAgICAgIHt3b3Jrc2hvcC5kdXJhdGlvbkxhYmVsID8gKFxuICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgIDxEaXZpZGVyIC8+XG4gICAgICAgICAgICAgICAgPEluZm9Sb3cgaWNvbj17PE9wdGltaXphdGlvbkNsb2NrSWNvbiBzaXplPXsxNn0gYXJpYS1oaWRkZW4gLz59PlxuICAgICAgICAgICAgICAgICAgPFRleHQgYXM9XCJzcGFuXCIgZm9udFdlaWdodD1cImJvbGRcIj5cbiAgICAgICAgICAgICAgICAgICAge3dvcmtzaG9wLmR1cmF0aW9uTGFiZWx9XG4gICAgICAgICAgICAgICAgICA8L1RleHQ+eycgJ31cbiAgICAgICAgICAgICAgICAgIGxvbmdcbiAgICAgICAgICAgICAgICA8L0luZm9Sb3c+XG4gICAgICAgICAgICAgIDwvPlxuICAgICAgICAgICAgKSA6IG51bGx9XG4gICAgICAgICAgPC9GbGV4Qm94PlxuICAgICAgICA8L1N0eWxlZENhcmQ+XG4gICAgICA8L0FuY2hvcj5cbiAgICA8L2xpPlxuICApO1xufTtcbiJdfQ== */"));
18
+ const InfoRow = ({
19
+ icon,
20
+ children
21
+ }) => /*#__PURE__*/_jsxs(FlexBox, {
22
+ alignItems: "center",
23
+ gap: 8,
24
+ children: [icon, /*#__PURE__*/_jsx(Text, {
25
+ fontSize: 14,
26
+ lineHeight: "base",
27
+ color: "text",
28
+ children: children
29
+ })]
30
+ });
31
+ export const AppHeaderWorkshopCard = ({
32
+ workshop
33
+ }) => {
34
+ const {
35
+ globalHeaderItemClick
36
+ } = useGlobalHeaderItemClick();
37
+ const {
38
+ handleClose
39
+ } = useAppHeaderDropdownContext();
40
+ const {
41
+ tabIndex
42
+ } = useAppHeaderSectionContext();
43
+ const linkItem = {
44
+ type: 'link',
45
+ id: workshop.id,
46
+ href: workshop.href,
47
+ text: workshop.title,
48
+ trackingTarget: workshop.trackingTarget
49
+ };
50
+ return /*#__PURE__*/_jsx("li", {
51
+ children: /*#__PURE__*/_jsx(Anchor, {
52
+ href: workshop.href,
53
+ variant: "interface",
54
+ display: "block",
55
+ tabIndex: tabIndex,
56
+ onClick: event => {
57
+ globalHeaderItemClick(event, linkItem);
58
+ handleClose();
59
+ },
60
+ children: /*#__PURE__*/_jsxs(StyledCard, {
61
+ borderRadius: "lg",
62
+ border: 1,
63
+ borderColor: "border-tertiary",
64
+ display: "flex",
65
+ alignItems: "flex-start",
66
+ flexDirection: "column",
67
+ px: 16,
68
+ py: 24,
69
+ minHeight: 219,
70
+ height: "100%",
71
+ children: [/*#__PURE__*/_jsx(Text, {
72
+ variant: "p-large",
73
+ fontWeight: 700,
74
+ as: "h3",
75
+ width: "100%",
76
+ truncate: "ellipsis",
77
+ truncateLines: 2,
78
+ children: workshop.title
79
+ }), /*#__PURE__*/_jsx(Box, {
80
+ width: "100%",
81
+ children: /*#__PURE__*/_jsx(GridDense, {
82
+ height: 4
83
+ })
84
+ }), /*#__PURE__*/_jsxs(FlexBox, {
85
+ flexDirection: "column",
86
+ gap: 4,
87
+ width: "100%",
88
+ children: [/*#__PURE__*/_jsx(Text, {
89
+ fontSize: 14,
90
+ fontWeight: "bold",
91
+ lineHeight: "base",
92
+ children: workshop.instructorName
93
+ }), /*#__PURE__*/_jsx(Text, {
94
+ fontSize: 14,
95
+ lineHeight: "base",
96
+ color: "text-secondary",
97
+ truncate: "ellipsis",
98
+ truncateLines: 1,
99
+ children: workshop.instructorTitle
100
+ })]
101
+ }), /*#__PURE__*/_jsxs(FlexBox, {
102
+ flexDirection: "column",
103
+ alignSelf: "stretch",
104
+ width: "100%",
105
+ mt: 4,
106
+ children: [workshop.nextCohortStartDate ? /*#__PURE__*/_jsxs(_Fragment, {
107
+ children: [/*#__PURE__*/_jsx(Divider, {}), /*#__PURE__*/_jsxs(InfoRow, {
108
+ icon: /*#__PURE__*/_jsx(CalendarIcon, {
109
+ size: 16,
110
+ "aria-hidden": true
111
+ }),
112
+ children: ["Next cohort: on", ' ', /*#__PURE__*/_jsx(Text, {
113
+ as: "span",
114
+ fontWeight: "bold",
115
+ children: workshop.nextCohortStartDate
116
+ })]
117
+ })]
118
+ }) : null, workshop.durationLabel ? /*#__PURE__*/_jsxs(_Fragment, {
119
+ children: [/*#__PURE__*/_jsx(Divider, {}), /*#__PURE__*/_jsxs(InfoRow, {
120
+ icon: /*#__PURE__*/_jsx(OptimizationClockIcon, {
121
+ size: 16,
122
+ "aria-hidden": true
123
+ }),
124
+ children: [/*#__PURE__*/_jsx(Text, {
125
+ as: "span",
126
+ fontWeight: "bold",
127
+ children: workshop.durationLabel
128
+ }), ' ', "long"]
129
+ })]
130
+ }) : null]
131
+ })]
132
+ })
133
+ })
134
+ });
135
+ };
@@ -3,5 +3,6 @@ type PanelProps = {
3
3
  tabIndex?: number;
4
4
  };
5
5
  export declare const BootcampsPanel: React.FC<PanelProps>;
6
+ export declare const WorkshopsPanel: React.FC<PanelProps>;
6
7
  export declare const CoachingPanel: React.FC<PanelProps>;
7
8
  export {};
@@ -1,9 +1,11 @@
1
- import { Anchor, Box } from '@codecademy/gamut';
1
+ import { Anchor, Box, GridBox, Text } from '@codecademy/gamut';
2
2
  import React from 'react';
3
- import { useGlobalHeaderItemClick } from '../../../GlobalHeader/context';
3
+ import { useGlobalHeaderDynamicDataContext, useGlobalHeaderItemClick } from '../../../GlobalHeader/context';
4
4
  import { useAppHeaderSectionContext } from '../AppHeaderSection/AppHeaderSectionContext';
5
5
  import { PanelLayout } from '../AppHeaderSection/PanelLayout';
6
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
+ import { SkillTile } from '../AppHeaderSkillTile';
7
+ import { AppHeaderWorkshopCard } from './AppHeaderWorkshopCard';
8
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
7
9
  const makeCta = (id, href, text, trackingTarget) => ({
8
10
  id,
9
11
  href,
@@ -18,17 +20,22 @@ export const BootcampsPanel = () => {
18
20
  const {
19
21
  globalHeaderItemClick
20
22
  } = useGlobalHeaderItemClick();
23
+ const {
24
+ globalHeaderDynamicData
25
+ } = useGlobalHeaderDynamicDataContext();
21
26
  const privateBootcampFormUrl = 'https://forms.office.com/r/qqjDwRmkqA';
27
+ const upcomingBootcamps = globalHeaderDynamicData?.liveCoursesDropdown?.upcomingBootcamps ?? [];
22
28
  const description = /*#__PURE__*/_jsxs(Box, {
23
29
  mb: 8,
24
- children: ["Join live virtual bootcamps that span multiple weeks and help you build real-world, in-demand skills. Led by experts, each bootcamp includes instructor support, community, and comes with Codecademy Pro access.", /*#__PURE__*/_jsx("br", {}), "Looking for a private bootcamp?", ' ', /*#__PURE__*/_jsx(Anchor, {
30
+ children: ["Join live virtual bootcamps that span multiple weeks and help you build real-world, in-demand skills. Led by experts, each bootcamp includes instructor support, community, professional mentorship\u2014and comes with Codecademy Pro access.", /*#__PURE__*/_jsx("br", {}), "Looking for a private bootcamp?", ' ', /*#__PURE__*/_jsx(Anchor, {
25
31
  tabIndex: tabIndex,
26
32
  href: privateBootcampFormUrl,
27
33
  onClick: event => globalHeaderItemClick(event, {
28
34
  type: 'link',
29
35
  href: privateBootcampFormUrl,
30
36
  text: 'Get in touch',
31
- id: 'private-bootcamp-contact'
37
+ id: 'private-bootcamp-contact',
38
+ trackingTarget: 'topnav_live_courses_private_bootcamp_contact'
32
39
  }),
33
40
  children: "Get in touch"
34
41
  })]
@@ -36,7 +43,69 @@ export const BootcampsPanel = () => {
36
43
  return /*#__PURE__*/_jsx(PanelLayout, {
37
44
  heading: "Bootcamps",
38
45
  description: description,
39
- linkItem: makeCta('bootcamps', '/bootcamps', 'Explore Bootcamps', 'topnav_live_courses_bootcamps')
46
+ linkItem: makeCta('bootcamps', '/bootcamps', 'Explore all Bootcamps', 'topnav_live_courses_bootcamps'),
47
+ children: upcomingBootcamps.length > 0 && /*#__PURE__*/_jsxs(_Fragment, {
48
+ children: [/*#__PURE__*/_jsx(Text, {
49
+ variant: "p-large",
50
+ fontWeight: 700,
51
+ as: "h3",
52
+ children: "Upcoming bootcamps"
53
+ }), /*#__PURE__*/_jsx(GridBox, {
54
+ gridTemplateColumns: {
55
+ _: '1fr',
56
+ xs: '1fr 1fr'
57
+ },
58
+ gap: 8,
59
+ pl: 0,
60
+ as: "ul",
61
+ listStyle: "none",
62
+ mb: 24,
63
+ children: upcomingBootcamps.map(bootcamp => /*#__PURE__*/_jsx("li", {
64
+ children: /*#__PURE__*/_jsx(SkillTile, {
65
+ item: {
66
+ ...bootcamp,
67
+ type: 'link'
68
+ }
69
+ })
70
+ }, bootcamp.id))
71
+ })]
72
+ })
73
+ });
74
+ };
75
+ export const WorkshopsPanel = () => {
76
+ const {
77
+ globalHeaderDynamicData
78
+ } = useGlobalHeaderDynamicDataContext();
79
+ const upcomingWorkshops = globalHeaderDynamicData?.liveCoursesDropdown?.upcomingWorkshops ?? [];
80
+ const description = /*#__PURE__*/_jsx(Box, {
81
+ mb: 8,
82
+ children: "Join live, interactive workshops designed to build practical skills in a short time. Led by experts, each session includes hands-on learning, real-time guidance, and community interaction to help you apply what you learn instantly."
83
+ });
84
+ return /*#__PURE__*/_jsx(PanelLayout, {
85
+ heading: "Workshops",
86
+ description: description,
87
+ linkItem: makeCta('workshops', '/bootcamps#upcoming-workshops', 'Explore Workshops', 'topnav_live_courses_workshops'),
88
+ children: upcomingWorkshops.length > 0 && /*#__PURE__*/_jsxs(_Fragment, {
89
+ children: [/*#__PURE__*/_jsx(Text, {
90
+ variant: "p-large",
91
+ fontWeight: 700,
92
+ as: "h3",
93
+ children: "Upcoming workshops"
94
+ }), /*#__PURE__*/_jsx(GridBox, {
95
+ gridTemplateColumns: {
96
+ _: '1fr',
97
+ xs: '1fr 1fr'
98
+ },
99
+ gap: 24,
100
+ pl: 0,
101
+ as: "ul",
102
+ listStyle: "none",
103
+ mb: 24,
104
+ children: upcomingWorkshops.map(workshop => /*#__PURE__*/_jsx(AppHeaderWorkshopCard, {
105
+ workshop: workshop
106
+ }, workshop.id))
107
+ })]
108
+ })
40
109
  });
41
110
  };
42
111
  export const CoachingPanel = () => {
@@ -1,5 +1,5 @@
1
- import { CertificateIcon, ObjectiveIcon } from '@codecademy/gamut-icons';
2
- import { BootcampsPanel, CoachingPanel } from './NavPanels';
1
+ import { BadgeIcon, CertificateIcon, ObjectiveIcon } from '@codecademy/gamut-icons';
2
+ import { BootcampsPanel, CoachingPanel, WorkshopsPanel } from './NavPanels';
3
3
  export const LIVE_COURSES_NAV_SECTIONS = [{
4
4
  item: {
5
5
  icon: CertificateIcon,
@@ -9,6 +9,15 @@ export const LIVE_COURSES_NAV_SECTIONS = [{
9
9
  trackingTarget: 'topnav_live_courses_tab_bootcamps'
10
10
  },
11
11
  panel: BootcampsPanel
12
+ }, {
13
+ item: {
14
+ icon: BadgeIcon,
15
+ text: 'Workshops',
16
+ id: 'workshops',
17
+ type: 'live-courses-dropdown',
18
+ trackingTarget: 'topnav_live_courses_tab_workshops'
19
+ },
20
+ panel: WorkshopsPanel
12
21
  }, {
13
22
  item: {
14
23
  icon: ObjectiveIcon,
@@ -98,6 +98,26 @@ export type PromotedPath = {
98
98
  difficulty: CourseDifficulty | null;
99
99
  durationHours: number | null;
100
100
  };
101
+ export type UpcomingLiveCoursesNavItem = {
102
+ id: string;
103
+ href: string;
104
+ text: string;
105
+ trackingTarget: string;
106
+ };
107
+ export type UpcomingWorkshopNavItem = {
108
+ id: string;
109
+ href: string;
110
+ trackingTarget: string;
111
+ title: string;
112
+ instructorName: string;
113
+ instructorTitle: string;
114
+ nextCohortStartDate?: string;
115
+ durationLabel?: string;
116
+ };
117
+ export type LiveCoursesDropdownData = {
118
+ upcomingBootcamps: UpcomingLiveCoursesNavItem[];
119
+ upcomingWorkshops: UpcomingWorkshopNavItem[];
120
+ };
101
121
  export type GlobalHeaderDynamicData = {
102
122
  catalogDropdown: {
103
123
  banner: {
@@ -116,5 +136,6 @@ export type GlobalHeaderDynamicData = {
116
136
  totalCertificationPathCount: number;
117
137
  };
118
138
  };
139
+ liveCoursesDropdown: LiveCoursesDropdownData;
119
140
  };
120
141
  export {};
@@ -1,3 +1,5 @@
1
+ @use "~@codecademy/gamut-styles/utils";
2
+
1
3
  $c-offset: 169;
2
4
  $inner-offset: 287;
3
5
  $outer-offset: 361;
@@ -74,11 +76,11 @@ $animation-duration: 3s;
74
76
 
75
77
  .fullPage {
76
78
  width: 100%;
77
- height: calc(100vh - 4rem);
79
+ height: viewport-height(-(utils.$height-header));
78
80
  }
79
81
 
80
82
  .loading {
81
- width: 120px;
83
+ width: utils.px-rem(120px);
82
84
  }
83
85
 
84
86
  .underline {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codecademy/brand",
3
- "version": "5.2.0-alpha.f811da96e.0",
3
+ "version": "5.3.0-alpha.50a688319.0",
4
4
  "description": "Brand component library for Codecademy",
5
5
  "license": "MIT",
6
6
  "repository": "git@github.com:codecademy-engineering/mono.git",