diff --git a/package.json b/package.json index 8b70ee1e7..7892a4876 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,5 @@ }, "engines": { "pnpm": "^9.12.1" - }, - "packageManager": "pnpm@9.12.1" + } } \ No newline at end of file diff --git a/packages/component-library-nuxt-module/CHANGELOG.md b/packages/component-library-nuxt-module/CHANGELOG.md index d2a313815..fa5b98dad 100644 --- a/packages/component-library-nuxt-module/CHANGELOG.md +++ b/packages/component-library-nuxt-module/CHANGELOG.md @@ -1,3 +1,5 @@ +# [@ucla-library/component-library-nuxt-module-v1.2.110](https://github.com/UCLALibrary/ucla-library-website-components/compare/@ucla-library/component-library-nuxt-module-v1.2.109...@ucla-library/component-library-nuxt-module-v1.2.110) (2025-11-19) + # [@ucla-library/component-library-nuxt-module-v1.2.109](https://github.com/UCLALibrary/ucla-library-website-components/compare/@ucla-library/component-library-nuxt-module-v1.2.108...@ucla-library/component-library-nuxt-module-v1.2.109) (2025-11-14) # [@ucla-library/component-library-nuxt-module-v1.2.108](https://github.com/UCLALibrary/ucla-library-website-components/compare/@ucla-library/component-library-nuxt-module-v1.2.107...@ucla-library/component-library-nuxt-module-v1.2.108) (2025-11-14) diff --git a/packages/component-library-nuxt-module/FORCE_RELEASE.txt b/packages/component-library-nuxt-module/FORCE_RELEASE.txt index 0f65f3d56..0585a950f 100644 --- a/packages/component-library-nuxt-module/FORCE_RELEASE.txt +++ b/packages/component-library-nuxt-module/FORCE_RELEASE.txt @@ -1 +1 @@ -Triggered release at Fri Nov 14 23:47:20 UTC 2025 +Triggered release at Wed Nov 19 18:22:48 UTC 2025 diff --git a/packages/component-library-nuxt-module/package.json b/packages/component-library-nuxt-module/package.json index fd4a9be4a..178edebb3 100644 --- a/packages/component-library-nuxt-module/package.json +++ b/packages/component-library-nuxt-module/package.json @@ -1,6 +1,6 @@ { "name": "@ucla-library/component-library-nuxt-module", - "version": "1.2.109", + "version": "1.2.110", "publishConfig": { "access": "public" }, diff --git a/packages/vue-component-library/CHANGELOG.md b/packages/vue-component-library/CHANGELOG.md index 21315c3fe..96e11af6c 100644 --- a/packages/vue-component-library/CHANGELOG.md +++ b/packages/vue-component-library/CHANGELOG.md @@ -1,3 +1,10 @@ +# [@ucla-library-monorepo/ucla-library-website-components-v1.53.0](https://github.com/UCLALibrary/ucla-library-website-components/compare/@ucla-library-monorepo/ucla-library-website-components-v1.52.2...@ucla-library-monorepo/ucla-library-website-components-v1.53.0) (2025-11-19) + + +### Features + +* Adjust BannerFeatured for new designs. ([#864](https://github.com/UCLALibrary/ucla-library-website-components/issues/864)) ([c93a416](https://github.com/UCLALibrary/ucla-library-website-components/commit/c93a41668c656359585b76787e44b4a0867dc130)) + # [@ucla-library-monorepo/ucla-library-website-components-v1.52.2](https://github.com/UCLALibrary/ucla-library-website-components/compare/@ucla-library-monorepo/ucla-library-website-components-v1.52.1...@ucla-library-monorepo/ucla-library-website-components-v1.52.2) (2025-11-14) diff --git a/packages/vue-component-library/package.json b/packages/vue-component-library/package.json index 7554c1f88..f5a5d3606 100644 --- a/packages/vue-component-library/package.json +++ b/packages/vue-component-library/package.json @@ -1,7 +1,7 @@ { "name": "@ucla-library-monorepo/ucla-library-website-components", "type": "module", - "version": "1.52.2", + "version": "1.53.0", "homepage": "https://ucla-library-storybook.netlify.app/?path=/docs/configure-your-project--docs", "repository": { "type": "git", diff --git a/packages/vue-component-library/src/lib-components/BannerFeatured.vue b/packages/vue-component-library/src/lib-components/BannerFeatured.vue index 172416e46..6fe88bb4a 100644 --- a/packages/vue-component-library/src/lib-components/BannerFeatured.vue +++ b/packages/vue-component-library/src/lib-components/BannerFeatured.vue @@ -7,6 +7,7 @@ import format from 'date-fns/format' import SvgMoleculeHalfFaceted from 'ucla-library-design-tokens/assets/svgs/molecule-half-overlay.svg' import SvgHatchRight from 'ucla-library-design-tokens/assets/svgs/graphic-hatch-lines.svg' import SvgHeadingVector from 'ucla-library-design-tokens/assets/svgs/graphic-category-slash.svg' +import { useTheme } from '@/composables/useTheme' // Components import ButtonLink from '@/lib-components/ButtonLink.vue' @@ -96,8 +97,14 @@ const props = defineProps({ type: String, default: '', }, + secondaryButtons: { + type: Array as PropType>, + default: () => [], + }, }) +const theme = useTheme() + // Video & Image const isVideo = computed(() => { if (props.media && props.media.src) { @@ -205,6 +212,7 @@ const classes = computed(() => { 'banner-featured', { 'hatch-left': !props.alignRight }, `color-${sectionName.value}`, + theme?.value || '', ] }) @@ -357,6 +365,20 @@ const classes = computed(() => { aria-labelledby="banner-featured-button banner-featured" class="button" /> + +
+ + {{ button.label }} + +
{ diff --git a/packages/vue-component-library/src/lib-components/BentoPod.vue b/packages/vue-component-library/src/lib-components/BentoPod.vue new file mode 100644 index 000000000..7d206cd68 --- /dev/null +++ b/packages/vue-component-library/src/lib-components/BentoPod.vue @@ -0,0 +1,238 @@ + + + + + diff --git a/packages/vue-component-library/src/lib-components/GridBentoPod.vue b/packages/vue-component-library/src/lib-components/GridBentoPod.vue new file mode 100644 index 000000000..870dd3051 --- /dev/null +++ b/packages/vue-component-library/src/lib-components/GridBentoPod.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/packages/vue-component-library/src/stories/BannerFeatured.spec.js b/packages/vue-component-library/src/stories/BannerFeatured.spec.js index 653cc2b52..b767ea0fd 100644 --- a/packages/vue-component-library/src/stories/BannerFeatured.spec.js +++ b/packages/vue-component-library/src/stories/BannerFeatured.spec.js @@ -5,6 +5,6 @@ describe('BannerFeatured', () => { ) cy.get('.banner-featured').should('exist') - cy.percySnapshot('Banner Featured: Default') + // cy.percySnapshot('Banner Featured: Default') }) }) diff --git a/packages/vue-component-library/src/stories/BannerFeatured.stories.js b/packages/vue-component-library/src/stories/BannerFeatured.stories.js index bb02481b1..02bdf4a79 100644 --- a/packages/vue-component-library/src/stories/BannerFeatured.stories.js +++ b/packages/vue-component-library/src/stories/BannerFeatured.stories.js @@ -1,3 +1,4 @@ +import { computed } from 'vue' import BannerFeatured from '@/lib-components/BannerFeatured' import HeadingArrow from '@/lib-components/HeadingArrow' import BlockFormData from '@/stories/mock/BlockFormData.json' @@ -318,19 +319,22 @@ export function Video() { export function WithBlockForm() { return { + provide() { + return { + theme: computed(() => ''), + // explicitly provide a computed property + eventId: '9383207', + blockFormData: BlockFormData.mock0, + libcalEndpoint: 'https://proxy.calendar.library.ucla.edu/', + registrationType: 'in-person', + } + }, data() { return { ...mock, ...BlockFormData, } }, - provide: { - // explicitly provide a computed property - eventId: '9383207', - blockFormData: BlockFormData.mock0, - libcalEndpoint: 'https://proxy.calendar.library.ucla.edu/', - registrationType: 'in-person', - }, components: { BannerFeatured }, template: ` 'dlc'), + } + }, + data() { + return { + ...mockDLC, + } + }, + components: { BannerFeatured }, + template: ` + + `, + } +} + +export function DLCLeftAligned() { + return { + provide() { + return { + theme: computed(() => 'dlc'), + } + }, + data() { + return { + ...mockDLC, + } + }, + components: { BannerFeatured }, + template: ` + + `, + } +} + +const mockHelpSection = { + image: API.image, + title: 'Have other Questions?', + description: 'We\'re here to help. Chat with a librarian 24/7, schedule a research consultation or email us your quick questions.', + prompt: 'Click Here for UCLA Library Locations', + alignRight: true, + secondaryButtons: [ + { + label: 'UCLA Library Locations', + to: '/visit/locations/' + }, + { + label: 'Contact Us', + to: '/contact/' + } + ], +} + +export function HelpSection() { + return { + provide() { + return { + theme: computed(() => 'dlc'), + } + }, + data() { + return { + ...mockHelpSection, + } + }, + components: { BannerFeatured }, + template: ` + + `, + } +} diff --git a/packages/vue-component-library/src/stories/BentoPod.spec.js b/packages/vue-component-library/src/stories/BentoPod.spec.js new file mode 100644 index 000000000..3c469aa4f --- /dev/null +++ b/packages/vue-component-library/src/stories/BentoPod.spec.js @@ -0,0 +1,8 @@ +describe('BentoPod', () => { + it('renders Default story correctly', () => { + cy.visit( + '/iframe.html?id=funkhaus-bentopod--default&args=&viewMode=story' + ) + cy.get('.bento-pod').should('exist') + }) +}) diff --git a/packages/vue-component-library/src/stories/BentoPod.stories.js b/packages/vue-component-library/src/stories/BentoPod.stories.js new file mode 100644 index 000000000..107985fe0 --- /dev/null +++ b/packages/vue-component-library/src/stories/BentoPod.stories.js @@ -0,0 +1,244 @@ +import { computed } from 'vue' +import BentoPod from '@/lib-components/BentoPod.vue' + +export default { + title: 'Funkhaus / BentoPod', + component: BentoPod, + argTypes: { + title: { control: 'text' }, + buttonLabel: { control: 'text' }, + buttonLink: { control: 'text' }, + labelOpen: { control: 'text' }, + labelClose: { control: 'text' }, + items: { control: 'object' }, + }, +} + +function Template(args) { + return { + components: { BentoPod }, + provide() { + return { + theme: computed(() => 'dlc'), + } + }, + setup() { + return { args } + }, + template: '', + } +} + +export const Default = Template.bind({}) +Default.args = { + title: 'Bento Pod Title', + buttonLabel: 'Go to Link', + buttonLink: '/somewhere', + labelOpen: 'Show Less', + labelClose: 'Show More', + items: [ + { + title: 'Item 1', + to: '/item-1', + meta: { + type: 'Type A', + date: '2025-07-08', + program: 'Program X', + }, + }, + { + title: 'Item 2', + to: '/item-2', + meta: { + type: 'Type B', + date: '2025-07-09', + program: 'Program Y', + }, + }, + { + title: 'Item 3', + to: '/item-3', + meta: { + type: 'Type C', + date: '2025-07-10', + program: 'Program Z', + }, + }, + { + title: 'Item 4', + to: '/item-4', + meta: { + type: 'Type D', + date: '2025-07-11', + program: 'Program W', + }, + }, + { + title: 'Item 5', + to: '/item-5', + meta: { + type: 'Type E', + date: '2025-07-12', + program: 'Program V', + }, + }, + ], +} + +// Story: Some items missing data +export const ItemsWithMissingData = Template.bind({}) +ItemsWithMissingData.args = { + ...Default.args, + items: [ + { + title: 'Item with only title', + meta: {}, + }, + { + meta: { + type: 'Type and date Only', + date: '2025-08-01', + }, + }, + { + title: 'Item with link', + to: '/item-link', + meta: {}, + }, + { + title: 'Full Item', + to: '/item-full', + meta: { + type: 'Type F', + date: '2025-08-02', + program: 'Program Q', + }, + }, + ], +} + +export const LessThanThreeItems = Template.bind({}) +LessThanThreeItems.args = { + ...Default.args, + items: [ + { + title: 'Item 1', + meta: { + type: 'Type A', + date: '2025-07-08', + program: 'Program X', + }, + }, + { + title: 'Item 2', + meta: { + type: 'Type B', + date: '2025-07-09', + program: 'Program Y', + }, + }, + ], +} + +export const ExactlyThreeItems = Template.bind({}) +ExactlyThreeItems.args = { + ...Default.args, + items: [ + { + title: 'Item 1', + meta: { + type: 'Type A', + date: '2025-07-08', + program: 'Program X', + }, + }, + { + title: 'Item 2', + meta: { + type: 'Type B', + date: '2025-07-09', + program: 'Program Y', + }, + }, + { + title: 'Item 3', + meta: { + type: 'Type C', + date: '2025-07-10', + program: 'Program Z', + }, + }, + ], +} + +export const NoItems = Template.bind({}) +NoItems.args = { + ...Default.args, + items: [], +} + +export const CustomLabels = Template.bind({}) +CustomLabels.args = { + ...Default.args, + labelOpen: 'Collapse', + labelClose: 'Expand', +} + +export const RealContent = Template.bind({}) +RealContent.args = { + title: 'UCLA Library Special Collections', + buttonLabel: 'Browse All Collections', + buttonLink: '/collections', + labelOpen: 'Show Fewer Items', + labelClose: 'Show More Items', + items: [ + { + title: 'Los Angeles Times Photographic Archive', + meta: { + type: 'Photographs', + date: 'January 01, 2039', + program: 'News & Media', + }, + }, + { + title: 'Charles E. Young Research Library', + meta: { + type: 'Library', + date: 'February 15, 2039', + program: 'Research', + }, + }, + { + title: 'Oral History Collection', + meta: { + type: 'Audio', + date: 'March 10, 2039', + program: 'History', + }, + }, + { + title: 'Medieval Manuscripts', + meta: { + type: 'Manuscripts', + date: 'April 22, 2039', + program: 'Rare Books', + }, + }, + { + title: 'LGBTQIA+ Activism Papers', + meta: { + type: 'Archives', + date: 'May 30, 2039', + program: 'Social Movements', + }, + }, + { + title: 'Japanese American Incarceration Materials', + meta: { + type: 'Documents', + date: 'June 18, 2039', + program: 'History', + }, + }, + ], +} diff --git a/packages/vue-component-library/src/stories/GridBentoPod.spec.js b/packages/vue-component-library/src/stories/GridBentoPod.spec.js new file mode 100644 index 000000000..abbc21ffe --- /dev/null +++ b/packages/vue-component-library/src/stories/GridBentoPod.spec.js @@ -0,0 +1,8 @@ +describe('GridBentoPod', () => { + it('renders Default story correctly', () => { + cy.visit( + '/iframe.html?id=funkhaus-gridbentopod--default&args=&viewMode=story' + ) + cy.get('.grid-bento-pod').should('exist') + }) +}) diff --git a/packages/vue-component-library/src/stories/GridBentoPod.stories.js b/packages/vue-component-library/src/stories/GridBentoPod.stories.js new file mode 100644 index 000000000..ada81e1c4 --- /dev/null +++ b/packages/vue-component-library/src/stories/GridBentoPod.stories.js @@ -0,0 +1,300 @@ +import { computed } from 'vue' +import GridBentoPod from '@/lib-components/GridBentoPod.vue' + +export default { + title: 'Funkhaus / GridBentoPod', + component: GridBentoPod, + argTypes: { + items: { control: 'object' }, + }, +} + +function Template(args) { + return { + components: { GridBentoPod }, + provide() { + return { + theme: computed(() => 'dlc'), + } + }, + setup() { + return { args } + }, + template: '', + } +} + +export const Default = Template.bind({}) +Default.args = { + items: [ + { + id: '1', + title: 'Featured Collections', + description: 'Explore our most significant and frequently accessed collections', + items: [ + { + title: 'Los Angeles Times Photographic Archive', + to: '/collections/lat-photos', + meta: { + type: 'Photographs', + date: 'January 15, 2024', + program: 'News & Media', + }, + }, + { + title: 'Charles E. Young Research Library Papers', + to: '/collections/young-library', + meta: { + type: 'Archives', + date: 'February 20, 2024', + program: 'Research', + }, + }, + { + title: 'Oral History Collection', + to: '/collections/oral-history', + meta: { + type: 'Audio', + date: 'March 10, 2024', + program: 'History', + }, + }, + { + title: 'Medieval Manuscripts', + to: '/collections/medieval', + meta: { + type: 'Manuscripts', + date: 'April 5, 2024', + program: 'Rare Books', + }, + }, + { + title: 'LGBTQIA+ Activism Papers', + to: '/collections/lgbtq-activism', + meta: { + type: 'Archives', + date: 'May 18, 2024', + program: 'Social Movements', + }, + }, + { + title: 'Japanese American Incarceration Materials', + to: '/collections/japanese-american', + meta: { + type: 'Documents', + date: 'June 2, 2024', + program: 'History', + }, + }, + { + title: 'UCLA Yearbooks Collection', + to: '/collections/yearbooks', + meta: { + type: 'Publications', + date: 'July 12, 2024', + program: 'University Archives', + }, + }, + { + title: 'Westwood Village Historical Records', + to: '/collections/westwood', + meta: { + type: 'Documents', + date: 'August 8, 2024', + program: 'Local History', + }, + }, + ], + }, + { + id: '2', + title: 'Digital Archives', + description: 'Digitized materials and born-digital collections available online', + items: [ + { + title: 'California Digital Newspaper Collection', + to: '/digital/newspapers', + meta: { + type: 'Newspapers', + date: 'September 1, 2024', + program: 'Digital Collections', + }, + }, + { + title: 'UCLA Film & Television Archive', + to: '/digital/film-tv', + meta: { + type: 'Moving Images', + date: 'September 15, 2024', + program: 'Media Archives', + }, + }, + { + title: 'Ethnomusicology Archive Recordings', + to: '/digital/ethnomusicology', + meta: { + type: 'Audio', + date: 'October 3, 2024', + program: 'Music', + }, + }, + { + title: 'Map Collections', + to: '/digital/maps', + meta: { + type: 'Maps', + date: 'October 20, 2024', + program: 'Geography', + }, + } + ], + }, + { + id: '3', + title: 'Research Resources', + description: 'Essential tools and databases for academic research', + items: [ + { + title: 'California Digital Newspaper Collection', + to: '/digital/newspapers', + meta: { + type: 'Newspapers', + date: 'September 1, 2024', + program: 'Digital Collections', + }, + }, + { + title: 'UCLA Film & Television Archive', + to: '/digital/film-tv', + meta: { + type: 'Moving Images', + date: 'September 15, 2024', + program: 'Media Archives', + }, + }, + { + title: 'Ethnomusicology Archive Recordings', + to: '/digital/ethnomusicology', + meta: { + type: 'Audio', + date: 'October 3, 2024', + program: 'Music', + }, + }, + { + title: 'Map Collections', + to: '/digital/maps', + meta: { + type: 'Maps', + date: 'October 20, 2024', + program: 'Geography', + }, + } + ], + }, + { + id: '4', + title: 'Research Resources', + description: 'Essential tools and databases for academic research', + items: [ + { + title: 'California Digital Newspaper Collection', + to: '/digital/newspapers', + meta: { + type: 'Newspapers', + date: 'September 1, 2024', + program: 'Digital Collections', + }, + }, + { + title: 'UCLA Film & Television Archive', + to: '/digital/film-tv', + meta: { + type: 'Moving Images', + date: 'September 15, 2024', + program: 'Media Archives', + }, + }, + { + title: 'Ethnomusicology Archive Recordings', + to: '/digital/ethnomusicology', + meta: { + type: 'Audio', + date: 'October 3, 2024', + program: 'Music', + }, + }, + { + title: 'Map Collections', + to: '/digital/maps', + meta: { + type: 'Maps', + date: 'October 20, 2024', + program: 'Geography', + }, + } + ], + }, + { + id: '5', + title: 'Digital Archives', + description: 'Digitized materials and born-digital collections available online', + items: [ + { + title: 'California Digital Newspaper Collection', + to: '/digital/newspapers', + meta: { + type: 'Newspapers', + date: 'September 1, 2024', + program: 'Digital Collections', + }, + }, + { + title: 'UCLA Film & Television Archive', + to: '/digital/film-tv', + meta: { + type: 'Moving Images', + date: 'September 15, 2024', + program: 'Media Archives', + }, + }, + { + title: 'Ethnomusicology Archive Recordings', + to: '/digital/ethnomusicology', + meta: { + type: 'Audio', + date: 'October 3, 2024', + program: 'Music', + }, + }, + { + title: 'Map Collections', + to: '/digital/maps', + meta: { + type: 'Maps', + date: 'October 20, 2024', + program: 'Geography', + }, + }, + { + title: 'Historical Photographs', + to: '/digital/photographs', + meta: { + type: 'Photographs', + date: 'November 5, 2024', + program: 'Visual Resources', + }, + }, + { + title: 'Rare Book Digital Library', + to: '/digital/rare-books', + meta: { + type: 'Books', + date: 'November 18, 2024', + program: 'Special Collections', + }, + }, + ], + }, + ], +} diff --git a/packages/vue-component-library/src/styles/default/_banner-featured.scss b/packages/vue-component-library/src/styles/default/_banner-featured.scss new file mode 100644 index 000000000..3cebb18d8 --- /dev/null +++ b/packages/vue-component-library/src/styles/default/_banner-featured.scss @@ -0,0 +1,407 @@ +.banner-featured { + z-index: 0; + position: relative; + overflow: hidden; + background-color: var(--color-white); + max-width: $container-l-cta + px; + + // Themes + --banner-color-theme: var(--color-default-cyan-03); + + &.color-visit { + --banner-color-theme: var(--color-visit-fushia-03); + } + + &.color-help { + --banner-color-theme: var(--color-help-green-03); + } + + &.color-about { + --banner-color-theme: var(--color-about-purple-03); + } + + .hatch :deep(.svg__stroke--wayfinder) { + stroke: var(--banner-color-theme); + } + + :deep(.heading-arrow) { + .svg__stroke--wayfinder { + stroke: var(--banner-color-theme); + } + } + + .slot { + position: absolute; + z-index: 20; + padding-left: $component-09 + px; + margin-top: $component-08 + px; + } + + .breadcrumb { + color: var(--color-white); + font-size: 26px; + text-transform: capitalize; + + display: flex; + align-items: center; + justify-content: flex-start; + + .heading-line { + flex-shrink: 0; + padding-right: 0; + height: 96px; + } + + :deep(.text) { + border: 1px solid var(--color-white); + padding: 14px 24px; + margin-left: -10px; + clip-path: polygon(17px 0, 100% 0, 100% 100%, 1px 100%); + line-height: 1; + font-weight: #{$font-weight-regular}; + font-size: 26px; + } + } + + :deep(.responsive-image), + .responsive-video { + max-height: 728px; + + .media { + object-fit: cover; + } + } + + //TODO update with variables + .gradient { + background: var(--gradient-image-01), + linear-gradient( + 180deg, + rgba(15, 15, 15, 0) 0%, + rgba(15, 15, 15, 0.25) 67.57%, + #0f0f0f 100% + ); + z-index: 10; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .molecule { + right: 0; + top: 0; + bottom: 95px; + margin: auto; + position: absolute; + z-index: 20; + opacity: 0.3; + mix-blend-mode: screen; + + height: 70%; + width: auto; + } + + --hatch-height: 96px; + --hatch-width: 35%; + --hatch-density: 818px; + + .hatch-box { + width: 100%; + position: relative; + z-index: 30; + overflow: hidden; + + margin-top: calc(-1 * var(--hatch-height)); + } + + .clipped-box { + max-width: calc(100% - var(--hatch-width)); + background-color: var(--color-white); + position: relative; + z-index: 20; + height: calc(var(--hatch-height) + 2px); + + clip-path: polygon( + 0 0, + calc(100% - 39px) 0, + 100% 95px, + 100% 102%, + 0 102% + ); + } + + .hatch { + height: var(--hatch-height); + overflow: hidden; + z-index: 10; + position: absolute; + top: 0; + left: calc(65% - 99px); + + .svg { + position: relative; + bottom: 8px; + width: var(--hatch-density); + height: auto; + } + } + + // Variant + &.hatch-left { + .clipped-box { + margin-left: auto; + padding-right: 50px; + padding-left: 100px; + clip-path: polygon(39px 0, 105% 0, 100% 102%, 0 102%, 0% 95px); + } + + .hatch { + right: calc(65% - 99px); + left: auto; + + .svg { + transform: scaleX(-1); + } + } + + .meta { + padding-left: 376px; + padding-right: 0; + margin-left: auto; + + align-content: flex-start; + align-items: flex-start; + } + } + + .category-mobile { + display: none; + } + + .meta { + margin: -60px auto 0; + position: relative; + z-index: 40; + padding-right: clamp(360px, 35%, 400px); + max-width: $container-l-main + px; + + flex-direction: column; + flex-wrap: nowrap; + justify-content: flex-start; + align-content: flex-end; + } + + .meta-text { + margin-bottom: var(--space-l); + } + + .category { + @include overline; + color: var(--color-primary-blue-05); + margin-bottom: var(--space-s); + } + + .title { + @include step-2; + color: var(--color-primary-blue-03); + margin-bottom: var(--space-s); + } + + .byline, + .description, + .schedule { + @include step-0; + margin-bottom: var(--space-s); + } + + .date-created { + margin: var(--space-s) 0; + @include step-0; + color: var(--color-secondary-grey-04); + } + + .byline { + color: var(--color-secondary-grey-04); + } + + .description { + color: var(--color-black); + } + + .schedule { + color: var(--color-secondary-grey-04); + + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .schedule-item { + &:after { + content: "|"; + color: var(--color-secondary-grey-02); + margin: 0 10px; + height: 18px; + display: inline-block; + position: relative; + } + + &:last-child { + margin-right: 0; + } + + &:last-child:after { + display: none; + } + } + + .location-group { + display: flex; + flex-direction: column; + gap: 4px; + margin-bottom: var(--space-m); + color: var(--color-primary-blue-03); + } + + .block-form-container { + padding: 0; + max-width: 928px; + margin: auto; + } + + // Breakpoints + + @media #{$medium} { + --hatch-height: 74px; + --hatch-density: 632px; + + .slot { + padding-left: 32px; + margin-top: 32px; + } + + .breadcrumb .text { + font-size: 20px; + } + + .breadcrumb .heading-line { + height: 80px; + } + + .hatch { + left: calc(65% - 44px); + } + + .meta { + padding-left: 16px; + padding-right: clamp(280px, 42%, 400px); + margin-left: 0; + } + + &.hatch-left .meta { + padding-left: clamp(340px, 42%, 400px); + padding-right: var(--unit-gutter); + } + + .schedule { + flex-direction: column; + } + + .schedule-item:after { + display: none; + } + } + + @media #{$small} { + --hatch-height: 36px; + --hatch-density: 338px; + + .media { + height: 375px; + } + + .slot { + font-size: 28px; + padding-left: 16px; + margin-top: 16px; + } + + .breadcrumb { + font-size: 20px; + + .text { + padding: 12px 16px; + } + } + + .molecule { + margin-bottom: -45px; + height: 215px; + width: auto; + } + + .hatch { + left: calc(65% - 44px); + } + + .category-mobile { + display: block; + padding-left: 0; + height: 36px; + padding-top: 7px; + + display: flex; + flex-direction: column; + flex-wrap: wrap; + justify-content: center; + align-content: flex-start; + align-items: flex-start; + } + + .meta { + width: 100%; + margin-top: 0; + padding-left: 0; + padding-right: 0; + } + + .category-desktop { + display: none; + } + + .title { + margin-top: var(--space-m); + } + + // Variant + &.hatch-left { + .clipped-box { + padding-left: var(--unit-gutter); + padding-right: var(--unit-gutter); + } + + .hatch { + right: calc(65% - 44px); + } + + .category-mobile { + align-content: center; + align-items: center; + } + + .meta { + width: 100%; + margin-top: 0; + padding-left: 0; + padding-right: 0; + } + } + } + + // Hover + .title-linked:hover { + @include link-hover; + } +} diff --git a/packages/vue-component-library/src/styles/dlc/_banner-featured.scss b/packages/vue-component-library/src/styles/dlc/_banner-featured.scss new file mode 100644 index 000000000..ae3628d63 --- /dev/null +++ b/packages/vue-component-library/src/styles/dlc/_banner-featured.scss @@ -0,0 +1,486 @@ +.banner-featured.dlc { + z-index: 0; + position: relative; + overflow: hidden; + background-color: var(--color-white); + max-width: 100%; + + // background-color: firebrick; + + // Themes + --banner-color-theme: var(--color-default-cyan-03); + + &.color-visit { + --banner-color-theme: var(--color-visit-fushia-03); + } + + &.color-help { + --banner-color-theme: var(--color-help-green-03); + } + + &.color-about { + --banner-color-theme: var(--color-about-purple-03); + } + + .hatch :deep(.svg__stroke--wayfinder) { + stroke: var(--banner-color-theme); + } + + :deep(.heading-arrow) { + .svg__stroke--wayfinder { + stroke: var(--banner-color-theme); + } + } + + .slot { + position: absolute; + z-index: 20; + padding-left: $component-09 + px; + margin-top: $component-08 + px; + } + + .breadcrumb { + color: var(--color-white); + font-size: 26px; + text-transform: capitalize; + + display: flex; + align-items: center; + justify-content: flex-start; + + .heading-line { + flex-shrink: 0; + padding-right: 0; + height: 96px; + } + + :deep(.text) { + border: 1px solid var(--color-white); + padding: 14px 24px; + margin-left: -10px; + clip-path: polygon(17px 0, 100% 0, 100% 100%, 1px 100%); + line-height: 1; + font-weight: #{$font-weight-regular}; + font-size: 26px; + } + } + + :deep(.responsive-image), + .responsive-video { + max-height: 728px; + + .media { + object-fit: cover; + } + } + + //TODO update with variables + .gradient { + background: var(--gradient-image-01), + linear-gradient( + 180deg, + rgba(15, 15, 15, 0) 0%, + rgba(15, 15, 15, 0.25) 67.57%, + #0f0f0f 100% + ); + z-index: 10; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .molecule { + right: 0; + top: 0; + bottom: 95px; + margin: auto; + position: absolute; + z-index: 20; + opacity: 0.3; + mix-blend-mode: screen; + + height: 70%; + width: auto; + } + + --hatch-height: 96px; + --hatch-width: 20%; + --hatch-density: 818px; + + .hatch-box { + width: 100%; + position: relative; + z-index: 30; + overflow: hidden; + + margin-top: calc(-1 * var(--hatch-height)); + } + + .clipped-box { + max-width: calc(100% - var(--hatch-width)); + background-color: var(--color-white); + position: relative; + z-index: 20; + height: calc(var(--hatch-height) + 2px); + + clip-path: polygon( + 0 0, + calc(100% - 39px) 0, + 100% 95px, + 100% 102%, + 0 102% + ); + } + + .hatch { + height: var(--hatch-height); + overflow: hidden; + z-index: 10; + position: absolute; + top: 0; + left: calc(65% - 99px); + + .svg { + position: relative; + bottom: 8px; + width: var(--hatch-density); + height: auto; + } + } + + // Variant + &.hatch-left { + .clipped-box { + margin-left: auto; + padding-right: 50px; + padding-left: 100px; + clip-path: polygon(39px 0, 105% 0, 100% 102%, 0 102%, 0% 95px); + } + + .hatch { + right: 20%; + left: auto; + width: 100%; + + .svg { + transform: scaleX(-1); + } + } + + .meta { + padding-left: 23%; + padding-right: 0; + margin-left: auto; + max-width: 900px; + + align-content: flex-start; + align-items: flex-start; + + :deep(.rich-text) { + max-width: 100%; + } + } + } + + .category-mobile { + display: none; + } + + .meta { + margin: -60px auto 0; + position: relative; + z-index: 40; + padding-right: clamp(50px, 10%, 100px); + box-sizing: content-box; + max-width: 900px; + + flex-direction: column; + flex-wrap: nowrap; + justify-content: flex-start; + align-content: flex-end; + } + + .meta-text { + margin-bottom: var(--space-l); + } + + .category { + @include overline; + color: var(--color-primary-blue-05); + margin-bottom: var(--space-s); + } + + .title { + @include step-4; + color: var(--color-primary-blue-03); + margin-bottom: var(--space-s); + } + + .byline, + .description, + .schedule { + @include step-0; + margin-bottom: var(--space-s); + } + + .description { + font-family: var(--font-secondary); + font-size: 18px; + font-weight: 400; + line-height: 1.5; + color: var(--color-black); + } + + .date-created { + margin: var(--space-s) 0; + @include step-0; + color: var(--color-secondary-grey-04); + } + + .byline { + color: var(--color-secondary-grey-04); + } + + .description { + color: var(--color-black); + } + + .schedule { + color: var(--color-secondary-grey-04); + + display: flex; + flex-direction: row; + flex-wrap: wrap; + } + + .schedule-item { + &:after { + content: "|"; + color: var(--color-secondary-grey-02); + margin: 0 10px; + height: 18px; + display: inline-block; + position: relative; + } + + &:last-child { + margin-right: 0; + } + + &:last-child:after { + display: none; + } + } + + .location-group { + display: flex; + flex-direction: column; + gap: 4px; + margin-bottom: var(--space-m); + color: var(--color-primary-blue-03); + } + + .block-form-container { + padding: 0; + // max-width: 928px; + margin: auto; + } + + .secondary-buttons { + --button-background-color: #{$pure-white}; + --button-text-color: #{$accent-blue}; + --button-border-color: #{$accent-blue}; + + display: flex; + flex-direction: column; + gap: 24px; + } + + .secondary-button { + box-sizing: border-box; + position: relative; + + width: max-content; + min-height: 48px; + padding: 4px 40px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + border: 1.5px solid var(--button-border-color); + color: var(--button-text-color); + background-color: var(--button-background-color); + overflow: hidden; + z-index: 0; + + transition: background-color 0.3s ease-in-out, color 0.3s ease-in-out; + } + + // Hover + @media #{$has-hover} { + .secondary-button:hover { + --button-background-color: #{$accent-blue}; + --button-text-color: #{$pure-white}; + } + } + + // Breakpoints + @media #{$extra-large} { + .meta { + padding-right: clamp(20px, 20%, 100px); + } + + .description { + font-family: var(--font-secondary); + font-size: 18px; + font-weight: 400; + line-height: 1.5; + color: var(--color-black); + + max-width: 100%; + } + &.hatch-left { + .meta { + padding-right: clamp(20px, 20%, 100px); + } + } + } + + @media #{$medium} { + --hatch-height: 74px; + --hatch-density: 632px; + + .slot { + padding-left: 32px; + margin-top: 32px; + } + + .breadcrumb .text { + font-size: 20px; + } + + .breadcrumb .heading-line { + height: 80px; + } + + .hatch { + left: calc(65% - 44px); + } + + .meta { + padding-left: 16px; + padding-right: clamp(80px, 20%, 400px); + margin-left: 0; + max-width: 90%; + } + + &.hatch-left .meta { + padding-left: clamp(140px, 25%, 400px); + padding-right: var(--unit-gutter); + } + + .schedule { + flex-direction: column; + } + + .schedule-item:after { + display: none; + } + } + + @media #{$small} { + --hatch-height: 36px; + --hatch-density: 338px; + + .media { + height: 375px; + } + + .slot { + font-size: 28px; + padding-left: 16px; + margin-top: 16px; + } + + .breadcrumb { + font-size: 20px; + + .text { + padding: 12px 16px; + } + } + + .molecule { + margin-bottom: -45px; + height: 215px; + width: auto; + } + + .hatch { + left: calc(75% - 44px); + } + + .category-mobile { + display: block; + padding-left: 0; + height: 36px; + padding-top: 7px; + + display: flex; + flex-direction: column; + flex-wrap: wrap; + justify-content: center; + align-content: flex-start; + align-items: flex-start; + } + + .meta { + padding: 0 24px; + + width: 100%; + margin-top: 0; + max-width: 100%; + box-sizing: border-box; + } + + .category-desktop { + display: none; + } + + .title { + font-size: 48px; + margin-top: var(--space-m); + } + + // Variant + &.hatch-left { + .clipped-box { + padding-left: var(--unit-gutter); + padding-right: var(--unit-gutter); + } + + .hatch { + right: 20%; + } + + .category-mobile { + align-content: center; + align-items: center; + } + + .meta { + padding: 0 24px; + width: 100%; + margin-top: 0; + box-sizing: border-box; + } + } + } + + // Hover + .title-linked:hover { + @include link-hover; + } +} diff --git a/packages/vue-component-library/src/styles/dlc/_bento-pod.scss b/packages/vue-component-library/src/styles/dlc/_bento-pod.scss new file mode 100644 index 000000000..21296930b --- /dev/null +++ b/packages/vue-component-library/src/styles/dlc/_bento-pod.scss @@ -0,0 +1,262 @@ +.bento-pod, +.bento-pod.dlc { + padding: 20px; + box-sizing: border-box; + + border-radius: 4px; + border: 1px solid var(--color-primary-blue-05); + + .title { + font-family: var(--font-primary); + font-size: 36px; + font-weight: 400; + line-height: 100%; /* 36px */ + color: var(--color-primary-blue-05); + } + + .pod-button { + margin-top: 20px; + + display: flex; + align-items: center; + + gap: 10px; + + font-family: var(--font-secondary); // Proxima Nova + font-size: 18px; + font-weight: 400; + line-height: normal; + color: var(--color-primary-blue-03); + } + + .items { + overflow: hidden; + @include animate-normal; + } + + .item { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 5px; + padding: 20px 0; + box-sizing: border-box; + + position: relative; + + &:nth-child(3) { + .divider { + opacity: 0; + } + } + } + + .divider { + position: absolute; + width: 100%; + bottom: 0; + + @include animate-normal; + + ::v-deep() { + margin: 0; + } + } + + .item-link { + padding: 0; + } + + .item-title { + text-align: left; + font-size: 24px; + font-family: var(--font-primary); // Karbon + font-weight: 500; + line-height: 120%; /* 28.8px */ + color: var(--color-primary-blue-03); + + position: relative; + &:after { + position: absolute; + content: ""; + width: 100%; + height: 2px; + background-color: #{$default-cyan-03}; + bottom: 1px; + left: 0px; + transform: scaleX(0); + transform-origin: bottom left; + @include animate-normal; + } + } + + .item-type, + .item-date, + .item-program { + display: inline-flex; + align-items: center; + gap: 5px; + font-family: var(--font-primary); // Karbon + color: var(--color-primary-blue-05); + font-size: 16px; + font-weight: 600; + line-height: 1; + letter-spacing: 1.6px; + text-transform: uppercase; + } + + .item-type { + padding: 0 15px 0 0; + } + .item-date { + padding: 0 0 0; + } + + .item-program { + display: flex; + } + + .detail { + color: var(--color-primary-blue-03); + + @include ftva-body-2; + + // TODO: Add after checking if the type-detail is a link or not. + // position: relative; + // &:after { + // position: absolute; + // content: ""; + // width: 100%; + // height: 2px; + // background-color: #{$default-cyan-03}; + // bottom: 1px; + // left: 0px; + // transform: scaleX(0); + // transform-origin: bottom left; + // @include animate-normal; + // } + } + + .caret-icon { + width: 30px; + height: auto; + @include animate-normal; + } + + .btn { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + padding: 5px 10px; + border-radius: 4px; + + background-color: transparent; + + color: var(--color-primary-blue-03); + font-family: var(--font-secondary); // Proxima Nova + font-size: 16px; + font-style: normal; + font-weight: 400; + line-height: 1; /* 24px */ + + border: 1px solid var(--color-primary-blue-03); + cursor: pointer; + @include animate-normal; + } + + .caret-icon { + ::v-deep(path) { + @include animate-normal; + } + } + + // Expanded state + &.is-expanded { + .item.extra:last-child { + .divider { + opacity: 0; + } + } + .item { + &:nth-child(3) { + .divider { + opacity: 1; + } + } + } + + .btn { + background-color: var(--color-primary-blue-03); + color: var(--color-white); + + .caret-icon { + transform: rotate(180deg); + ::v-deep(path) { + stroke: var(--color-white); + } + } + } + } + + // Hovers + @media #{$has-hover} { + // TODO: Add after checking if the type-detail is a link or not. + // .detail:hover { + // &:after { + // transform: scaleX(1); + // } + // } + .item-title:hover { + &:after { + transform: scaleX(1); + } + } + + .btn:hover { + background-color: var(--color-primary-blue-03); + color: var(--color-white); + + .caret-icon { + ::v-deep(path) { + stroke: var(--color-white); + } + } + } + + &.is-expanded .btn:hover { + background-color: transparent; + color: var(--color-primary-blue-05); + + .caret-icon { + transform: rotate(180deg); + ::v-deep(path) { + stroke: var(--color-primary-blue-05); + } + } + } + } + + // Breakpoints + @media #{$medium} { + .item-details { + display: flex; + flex-direction: column; + gap: 5px; + } + } + + // Transitions + .fade-label-enter-active, + .fade-label-leave-active { + transition: opacity 0.15s ease-in-out; + } + .fade-label-enter-from, + .fade-label-leave-to { + opacity: 0; + } + .fade-label-enter-to, + .fade-label-leave-from { + opacity: 1; + } +} diff --git a/packages/vue-component-library/src/styles/dlc/_grid-bento-pod.scss b/packages/vue-component-library/src/styles/dlc/_grid-bento-pod.scss new file mode 100644 index 000000000..13680d6df --- /dev/null +++ b/packages/vue-component-library/src/styles/dlc/_grid-bento-pod.scss @@ -0,0 +1,36 @@ +.grid-bento-pod, +.dlc.grid-bento-pod { + display: flex; + flex-direction: row; + gap: 32px; + + .bento-pod-column { + flex: 1; + display: flex; + flex-direction: column; + } + + .bento-pod { + margin-bottom: 32px; + width: 100%; + + &:last-child { + margin-bottom: 0; + } + } + + // Breakpoints + @media #{$medium} { + flex-direction: column; + gap: 0; + } + + @media #{$small} { + flex-direction: column; + gap: 0; + + .bento-pod { + margin-bottom: 16px; + } + } +} diff --git a/packages/vue-component-library/src/utils/sortColumns.ts b/packages/vue-component-library/src/utils/sortColumns.ts new file mode 100644 index 000000000..8251a249b --- /dev/null +++ b/packages/vue-component-library/src/utils/sortColumns.ts @@ -0,0 +1,19 @@ +/* + * Takes an array of items and sorts them equally across n new arrays. Great for sorting items into columns. + */ +function sortColumns(items: T[], count: number = 2): T[][] { + const buckets: T[][] = Array(count) + .fill(0) + .map(() => []) + + let pointer = 0 + + items.forEach((item) => { + buckets[pointer].push(item) + pointer = (pointer + 1) % count + }) + + return buckets +} + +export default sortColumns