diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..72e9aa42 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +Dockerfile +.dockerignore +node_modules +npm-debug.log +README.md +.next +.git \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index efb82d5b..17a11a14 100644 --- a/.eslintrc +++ b/.eslintrc @@ -24,7 +24,8 @@ "@typescript-eslint/array-type": [1, { "default": "array-simple" }], "@typescript-eslint/no-unused-vars": 0, "no-console": "warn", - "@typescript-eslint/explicit-module-boundary-types": "off" + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/ban-ts-comment": "off" }, "overrides": [ { diff --git a/.github/workflows/azure-static-web-apps-happy-river-0aceb3600.yml b/.github/workflows/azure-static-web-apps-happy-river-0aceb3600.yml deleted file mode 100644 index 058ae799..00000000 --- a/.github/workflows/azure-static-web-apps-happy-river-0aceb3600.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Azure Static Web Apps CI/CD - -on: - push: - branches: - - main - pull_request: - types: [opened, synchronize, reopened, closed] - -jobs: - build_and_deploy_job: - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed') - runs-on: ubuntu-latest - name: Build and Deploy Job - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - name: Build And Deploy - id: builddeploy - uses: Azure/static-web-apps-deploy@v1 - with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_HAPPY_RIVER_0ACEB3600 }} - repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) - action: "upload" - ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### - # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "/" # App source code path - api_location: "" # Api source code path - optional - output_location: "" # Built app content directory - optional - ###### End of Repository/Build Configurations ###### - - close_pull_request_job: - if: github.event_name == 'pull_request' && github.event.action == 'closed' - runs-on: ubuntu-latest - name: Close Pull Request Job - steps: - - name: Close Pull Request - id: closepullrequest - uses: Azure/static-web-apps-deploy@v1 - with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_HAPPY_RIVER_0ACEB3600 }} - action: "close" diff --git a/.github/workflows/container-app.yml b/.github/workflows/container-app.yml new file mode 100644 index 00000000..07108641 --- /dev/null +++ b/.github/workflows/container-app.yml @@ -0,0 +1,65 @@ +name: Container App Deployment + +on: + push: + branches: + - feat/next-13 + +permissions: + id-token: write + contents: read + packages: write + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build_and_deploy_job: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + - name: Build and push Docker image + id: push + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} +# - name: Log in to Azure +# uses: azure/login@v2 +# with: +# client-id: ${{ secrets.AZURE_CLIENT_ID }} +# tenant-id: ${{ secrets.AZURE_TENANT_ID }} +# subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} +# auth-type: IDENTITY +# enable-AzPSSession: true +# - name: Build and deploy Container App +# uses: azure/container-apps-deploy-action@v1 +# with: +# imageToDeploy: ghcr.io/openddd/dddmelbourne-website-2024:feat-next-13 +# containerAppName: website-ghcr +# resourceGroup: dddmelb-2024 +# targetPort: 3000 +# ingress: external \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..12a09719 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,69 @@ +FROM node:18-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ +RUN \ + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ + else echo "Lockfile not found." && exit 1; \ + fi + + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry during the build. +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN \ + if [ -f yarn.lock ]; then yarn run build; \ + elif [ -f package-lock.json ]; then npm run build; \ + elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \ + else echo "Lockfile not found." && exit 1; \ + fi + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV production +# Uncomment the following line in case you want to disable telemetry during runtime. +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT 3000 +# set hostname to localhost +ENV HOSTNAME "0.0.0.0" + +# server.js is created by next build from the standalone output +# https://nextjs.org/docs/pages/api-reference/next-config-js/output +CMD ["node", "server.js"] \ No newline at end of file diff --git a/README.md b/README.md index 0d5b88a1..e6f98b15 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ -[![Build status](https://dev.azure.com/dddwa/DDD%20Perth%20Website/_apis/build/status/dddwa.dddperth-website?branchName=main)](https://dev.azure.com/dddwa/DDD%20Perth%20Website/_build/latest?definitionId=4) +# DDD Melbourne Website -# DDD Perth Website - -The DDD Perth website is deployed to https://dddperth.com and is built using [Next.js](https://github.com/zeit/next.js/). +The DDD Melbourne website is deployed to https://dddmelbourne.com and is built using [Next.js](https://github.com/zeit/next.js/). ## Getting started @@ -20,6 +18,21 @@ The DDD Perth website is deployed to https://dddperth.com and is built using [Ne - Grab the `.next` directory and deploy to the destination - Run `npm` in the deploy folder and deploy all files from there alongside the `.next` directory (the web.config file is targeted towards Azure Web Apps) +## Special Note for current deployment + +We are now running the site on to Azure Container Apps (see `.github/workflows/container-app.yml`) + +Currently there is no automatic deployemnt of new Docker image once it has been updated, as the full setup of the Azure credentials is a WIP. To deploy a new image: + +1. Grab the new image SHA (find it in the completed Action under the Build and Push Docker image, where it says `#22 naming to ghcr.io/*******:sha-b5602ed done`) +2. Go to your Azure Portal > Container Apps > and into the right container +3. Go to Application > Containers +4. Click "Edit and Deploy" +5. In the Containers table, click on the desired container and in the sidebar that pops up, change teh "Image and tag" to have the correct SHA at the end +6. Click Save and then Create + +After this, it should deploy the new image to the container. + ## Code organisation - `/` - Usual array of .json and other config files for a JavaScript / TypeScript project @@ -71,4 +84,3 @@ We use Azure DevOps for CI / CD. This is controlled via [.devops/azure-pipelines ## Contributing So you’re thinking about contributing to the project? You are awesome! It’s **massively** appreciated. Before getting started, please take the time to review the [contribution guidelines](CONTRIBUTING.MD) before sending that epic pull request / bug report. - diff --git a/components/ActionBar/ActionBar.tsx b/components/ActionBar/ActionBar.tsx index 66e2a41b..97e77acb 100644 --- a/components/ActionBar/ActionBar.tsx +++ b/components/ActionBar/ActionBar.tsx @@ -1,5 +1,4 @@ import React from 'react' -import Link from 'next/link' import { ButtonAnchor } from 'components/global/Button/Button' import { StyledActionBarContainer } from './ActionBar.styled' import getConferenceActions from 'config/actions' @@ -15,20 +14,16 @@ export const ActionBar = (): JSX.Element => { diff --git a/components/Agenda/Agenda.tsx b/components/Agenda/Agenda.tsx index 3b89b633..f4e1392e 100644 --- a/components/Agenda/Agenda.tsx +++ b/components/Agenda/Agenda.tsx @@ -96,7 +96,7 @@ export const Agenda = ({ sessions, ...props }: AgendaProps) => { {props.render(sessions, nextSessionGroup, onSelectHandler)} - + × diff --git a/components/Agenda/SessionDetails.styled.tsx b/components/Agenda/SessionDetails.styled.tsx index 60c02187..d5531bb7 100644 --- a/components/Agenda/SessionDetails.styled.tsx +++ b/components/Agenda/SessionDetails.styled.tsx @@ -1,22 +1,20 @@ -import { DialogContent, DialogOverlay } from '@reach/dialog' import { breakpoint, breakpointMax } from 'components/utils/styles/breakpoints' import { calcRem } from 'components/utils/styles/calcRem' import styled from '@emotion/styled' -import { zIndex } from 'components/utils/styles/zindex' +import ReactModal from 'react-modal' -export const StyledDialogOverlay = styled(DialogOverlay)({ +export const StyledDialogOverlay = styled(ReactModal)({ position: 'fixed', top: 0, right: 0, bottom: 0, left: 0, overflow: 'auto', - zIndex: zIndex.agendaOverlay, background: `hsla(0, 0%, 0%, 0.33)`, }) StyledDialogOverlay.displayName = 'StyledDialogOverlay' -export const StyledDialogContent = styled(DialogContent)({ +export const StyledDialogContent = styled('div')({ position: 'relative', width: '90vw', padding: calcRem(15), @@ -43,6 +41,7 @@ export const StyledCloseButton = styled('button')(({ theme }) => ({ fontSize: calcRem(30), fontWeight: theme.weights.bold, lineHeight: 1, + cursor: 'pointer', '&:focus, &:hover': { color: '#808080', diff --git a/components/Agenda/SessionDetails.tsx b/components/Agenda/SessionDetails.tsx index c80b48e6..3b8aaf8a 100644 --- a/components/Agenda/SessionDetails.tsx +++ b/components/Agenda/SessionDetails.tsx @@ -29,6 +29,10 @@ export const SessionDetails = ({ hideLevelAndFormat = false, showBio, }: SessionDetailsProps) => { + if (!session) { + return
Uh Oh
+ } + return ( {session.Title} diff --git a/components/Feedback/FeedbackFetch.ts b/components/Feedback/FeedbackFetch.ts index 254c8810..61b842f3 100644 --- a/components/Feedback/FeedbackFetch.ts +++ b/components/Feedback/FeedbackFetch.ts @@ -1,5 +1,3 @@ -import { logEvent, logException } from 'components/global/analytics' - interface PostFeedbackParams { formName: string feedbackUrl: string @@ -7,12 +5,7 @@ interface PostFeedbackParams { deviceId: string } -export async function postFeedback({ - formName, - feedbackUrl, - values, - deviceId, -}: PostFeedbackParams): Promise { +export async function postFeedback({ feedbackUrl, values, deviceId }: PostFeedbackParams): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { const response = await fetch(feedbackUrl, { @@ -22,14 +15,8 @@ export async function postFeedback({ }) if (!response.ok) { - logException( - `Error submitting ${formName}`, - new Error(`Got ${response.status} ${response.statusText} when posting ${formName}.`), - { deviceId }, - ) reject() } else { - logEvent('feedback', 'submit', { deviceId }) resolve() } }) diff --git a/components/TestingControl/TestingControl.tsx b/components/TestingControl/TestingControl.tsx index 92daad89..61a1033a 100644 --- a/components/TestingControl/TestingControl.tsx +++ b/components/TestingControl/TestingControl.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import From2024 from 'config/2024' +import Conference from 'config/conference' import SponsorData from 'config/sponsors' import { TicketPurchasingOptions } from 'config/types' import { Button } from 'components/global/Button/Button' @@ -85,7 +85,7 @@ export const TestingControl = (): JSX.Element => { > Tickets sold out - (conference.Sponsors = From2024.Sponsors)}> + (conference.Sponsors = Conference.Sponsors)}> Add sponsors diff --git a/components/Voting/VotingFilters.styled.tsx b/components/Voting/VotingFilters.styled.tsx deleted file mode 100644 index 0a9d8aa2..00000000 --- a/components/Voting/VotingFilters.styled.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { calcRem } from 'components/utils/styles/calcRem' -import styled from '@emotion/styled' - -export const StyledTagCloudList = styled('ul')({ - display: 'flex', - flexWrap: 'wrap', - padding: 0, - margin: 0, - listStyleType: 'none', -}) - -export const StyledTagCloudInput = styled('input')(({ theme }) => ({ - position: 'absolute', - clip: 'rect(0, 0, 0, 0)', - - '&:checked': { - '& + label': { - background: theme.colors.tertiary, - color: '#fff', - }, - }, - - '&:focus': { - '& + label': { - borderColor: theme.colors.tertiary, - }, - }, -})) - -export const StyledTagCloudLabel = styled('label')(({ theme }) => ({ - display: 'block', - padding: calcRem(5), - margin: calcRem(2), - border: '2px solid transparent', - cursor: 'pointer', - fontSize: calcRem(14), - - '&:active': { - backgroundColor: theme.colors.tertiary, - color: '#fff', - }, -})) diff --git a/components/Voting/VotingFilters.tsx b/components/Voting/VotingFilters.tsx deleted file mode 100644 index 1579ac74..00000000 --- a/components/Voting/VotingFilters.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { useRef } from 'react' -import { logEvent } from 'components/global/analytics' -import { StyledTagCloudInput, StyledTagCloudLabel, StyledTagCloudList } from './VotingFilters.styled' - -interface VotingFiltersProps { - tags: string[] - levels: string[] - onTagFilter: (tags: string[]) => void - onLevelsFilter: (levels: string[]) => void -} - -export const VotingFilters = ({ tags, levels, onTagFilter, onLevelsFilter }: VotingFiltersProps) => { - const tagCloudRef = useRef(null) - const filterCloudRef = useRef(null) - - return ( -
-

- Filter by tag: -

-
- - {tags.map((tag) => ( -
  • - { - const filteredTags = Array.from( - tagCloudRef.current.querySelectorAll('input:checked'), - ).map((input) => input.value) - - if (filteredTags.length > 0) { - logEvent('voting', 'tagFilter', { filter: filteredTags.join(',') }) - } - - onTagFilter(filteredTags) - }} - /> - {tag} -
  • - ))} -
    -
    -

    - Filter by level: -

    -
    - - {levels.map((level) => ( -
  • - { - const filteredTags = Array.from( - filterCloudRef.current.querySelectorAll('input:checked'), - ).map((input) => input.value) - - if (filteredTags.length > 0) { - logEvent('voting', 'levelFilter', { filter: filteredTags.join(',') }) - } - - onLevelsFilter(filteredTags) - }} - /> - {level} -
  • - ))} -
    -
    -
    - ) -} diff --git a/components/Voting/landing.styled.tsx b/components/Voting/landing.styled.tsx index 50400130..62137d61 100644 --- a/components/Voting/landing.styled.tsx +++ b/components/Voting/landing.styled.tsx @@ -2,7 +2,6 @@ import styled from '@emotion/styled' import { Button } from 'components/global/Button/Button' import { Text } from 'components/global/text' import { calcRem } from 'components/utils/styles/calcRem' -import { DialogContent } from '@reach/dialog' import { breakpointMax } from '../utils/styles/breakpoints' export const StyledLandingContainer = styled('div')(() => ({ @@ -54,7 +53,7 @@ export const StyledFormRow = styled('div')({ marginBottom: calcRem(30), }) -export const StyledDialogContent = styled(DialogContent)({ +export const StyledDialogContent = styled('div')({ [breakpointMax('sm')]: { width: '100%', }, diff --git a/components/actionButton.tsx b/components/actionButton.tsx index 7081aecc..f74ec8ec 100644 --- a/components/actionButton.tsx +++ b/components/actionButton.tsx @@ -1,4 +1,3 @@ -import Link from 'next/link' import React from 'react' import { Action } from 'config/types' import { ButtonAnchor } from 'components/global/Button/Button' @@ -8,8 +7,8 @@ interface ActionButtonProps { } export const ActionButton = ({ action }: ActionButtonProps) => ( - - {action.Title} - + + {action.Title} + ) ActionButton.displayName = 'ActionButton' diff --git a/components/currentAgenda.tsx b/components/currentAgenda.tsx index 4ba1e12b..0df20e0f 100644 --- a/components/currentAgenda.tsx +++ b/components/currentAgenda.tsx @@ -15,6 +15,7 @@ import { AgendaProvider } from 'components/Agenda/AgendaContext' import { AgendaSession } from 'components/Agenda/AgendaSession' import { AgendaTime } from 'components/Agenda/AgendaTime' import { set } from 'date-fns' +import { StyledAgendaPresenter } from './Agenda/AgendaSession.styled' interface CurrentAgendaProps { date: Date @@ -117,19 +118,16 @@ export const CurrentAgenda = ({ - {/* (*/} - {/* Keynote: {presenters}*/} - {/* )}*/} - {/* fullWidth*/} - {/* isKeynote*/} - {/* alwaysShowRoom*/} - {/*/>*/} - - Key Note TBD - + ( + Keynote: {presenters} + )} + fullWidth + isKeynote + alwaysShowRoom + /> @@ -139,10 +137,10 @@ export const CurrentAgenda = ({ - + - + @@ -154,7 +152,7 @@ export const CurrentAgenda = ({ - + @@ -201,7 +199,7 @@ export const CurrentAgenda = ({ - + @@ -214,7 +212,7 @@ export const CurrentAgenda = ({ - + @@ -229,19 +227,16 @@ export const CurrentAgenda = ({ - {/* (*/} - {/* Locknote: {presenters}*/} - {/* )}*/} - {/* fullWidth*/} - {/* isKeynote*/} - {/* alwaysShowRoom*/} - {/*/>*/} - - Close Note TBD - + ( + Locknote: {presenters} + )} + fullWidth + isKeynote + alwaysShowRoom + /> diff --git a/components/global/Alert/Alert.styled.tsx b/components/global/Alert/Alert.styled.tsx index 6606db87..f54603da 100644 --- a/components/global/Alert/Alert.styled.tsx +++ b/components/global/Alert/Alert.styled.tsx @@ -1,49 +1,16 @@ import styled from '@emotion/styled' -import Alert from '@reach/alert' -import { calcRem } from 'components/utils/styles/calcRem' -import { DDDTheme } from 'components/utils/styles/theme' +import { calcRem } from '../../utils/styles/calcRem' export type Kind = 'info' | 'success' | 'error' | 'warning' -interface StyledAlertProps { - kind: Kind -} - -function stylesFromKind(kind: StyledAlertProps['kind'], theme: DDDTheme) { - switch (kind) { - case 'error': - return { - backgroundColor: theme.colors.alerts.error.background, - borderColor: theme.colors.alerts.error.border, - color: theme.colors.alerts.error.color, - } - case 'success': - return { - backgroundColor: theme.colors.alerts.success.background, - borderColor: theme.colors.alerts.success.border, - color: theme.colors.alerts.success.color, - } - case 'warning': - return { - backgroundColor: theme.colors.alerts.warning.background, - borderColor: theme.colors.alerts.warning.border, - color: theme.colors.alerts.warning.color, - } - default: - return { - backgroundColor: theme.colors.alerts.info.background, - borderColor: theme.colors.alerts.info.border, - color: theme.colors.alerts.info.color, - } - } -} - -export const StyledAlert = styled(Alert, { - shouldForwardProp: (prop) => prop !== 'kind', -})(({ kind, theme }) => ({ +export const StyledAlert = styled('div')({ + position: 'fixed', + bottom: 0, + right: 0, + overflow: 'auto', + margin: calcRem(15), padding: calcRem(15), - margin: calcRem(0, 0, 20), - border: '1px solid transparent', - borderRadius: calcRem(4), - ...stylesFromKind(kind, theme), -})) + background: `hsla(0, 0%, 0%, 0.33)`, + color: 'white', +}) +StyledAlert.displayName = 'StyledAlert' diff --git a/components/global/Alert/Alert.tsx b/components/global/Alert/Alert.tsx index 97036e8d..a98cceb5 100644 --- a/components/global/Alert/Alert.tsx +++ b/components/global/Alert/Alert.tsx @@ -7,4 +7,6 @@ interface AlertProps { type?: 'assertive' | 'polite' } -export const Alert = (props: AlertProps) => +export const Alert = (props: AlertProps) => { + return {props.children} +} diff --git a/components/global/Button/Button.styled.ts b/components/global/Button/Button.styled.ts index dbe8349f..32d275c0 100644 --- a/components/global/Button/Button.styled.ts +++ b/components/global/Button/Button.styled.ts @@ -4,6 +4,7 @@ import { calcRem } from 'components/utils/styles/calcRem' import { DDDTheme } from 'components/utils/styles/theme' import { conditionalStyles } from 'components/utils/styles/conditionalStyles' import { ButtonKinds, Size } from './Button' +import Link from 'next/link' function shouldStyledButtonForwardProps(prop: string) { return !['size', 'kind'].includes(prop) @@ -63,7 +64,7 @@ interface StyledButtonAnchorProps { size?: Size } -export const StyledButtonAnchor = styled('a', { +export const StyledButtonAnchor = styled(Link, { shouldForwardProp: shouldStyledButtonForwardProps, })(({ theme, kind, size }) => ({ display: 'inline-flex', diff --git a/components/global/Button/Button.tsx b/components/global/Button/Button.tsx index 0d0b2949..f8f66e96 100644 --- a/components/global/Button/Button.tsx +++ b/components/global/Button/Button.tsx @@ -13,7 +13,8 @@ export interface ButtonProps export const Button = (props: ButtonProps) => { const Component = props.kind !== 'link' ? StyledButton : StyledLinkButton return ( - + // @ts-ignore + {props.children} ) @@ -25,8 +26,8 @@ interface ButtonAnchorProps size?: Size } -export const ButtonAnchor = ({ children, kind = 'secondary', size = 'normal', ...props }: ButtonAnchorProps) => ( - +export const ButtonAnchor = ({ children, kind = 'secondary', size = 'normal', href, ...props }: ButtonAnchorProps) => ( + {children} ) diff --git a/components/global/Footer/socialLinks.tsx b/components/global/Footer/socialLinks.tsx index 1834da6a..6acef94d 100644 --- a/components/global/Footer/socialLinks.tsx +++ b/components/global/Footer/socialLinks.tsx @@ -3,7 +3,7 @@ import { Socials } from 'config/types' import { StyledSocialLinks, StyledSocialLink } from './Footer.styled' import { FacebookIcon } from 'components/global/Icons/Facebook' import { InstagramIcon } from 'components/global/Icons/Instagram' -import { TwitterIcon } from 'components/global/Icons/Twitter' +import { BlueskyIcon } from 'components/global/Icons/Bluesky' import { LinkedinIcon } from 'components/global/Icons/Linkedin' import { FlickrIcon } from 'components/global/Icons/Flickr' import { MediumIcon } from 'components/global/Icons/Medium' @@ -18,11 +18,15 @@ interface SocialLinksArgs { export const SocialLinks = ({ socials }: SocialLinksArgs) => ( - {socials.Twitter.Name && ( + {socials.Bluesky?.Name && (
  • - - - Twitter, opens in new window + + + Blueksy, opens in new window
  • )} @@ -34,27 +38,27 @@ export const SocialLinks = ({ socials }: SocialLinksArgs) => ( )} - {socials.Instagram && ( + {socials.Linkedin && (
  • - - Instagram, opens in new window + + LinkedIn, will open in a new window
  • )} - {socials.Linkedin && ( + {socials.Instagram && (
  • - - LinkedIn, will open in a new window + + Instagram, opens in new window
  • )} diff --git a/components/global/Header/Header.styled.tsx b/components/global/Header/Header.styled.tsx index 6dbf43bc..c7b19e8d 100644 --- a/components/global/Header/Header.styled.tsx +++ b/components/global/Header/Header.styled.tsx @@ -2,6 +2,7 @@ import styled from '@emotion/styled' import { calcRem } from 'components/utils/styles/calcRem' import { breakpoint } from 'components/utils/styles/breakpoints' import { zIndex } from 'components/utils/styles/zindex' +import Link from 'next/link' export const StyledHeader = styled('header')(({ theme }) => ({ position: 'sticky', @@ -15,7 +16,7 @@ export const StyledHeader = styled('header')(({ theme }) => ({ zIndex: zIndex.stickyHeader, })) -export const StyledAnchor = styled('a')({ +export const StyledAnchor = styled(Link)({ display: 'flex', margin: 0, marginRight: 'auto', diff --git a/components/global/Header/Header.tsx b/components/global/Header/Header.tsx index 0305e49f..cc8722d2 100644 --- a/components/global/Header/Header.tsx +++ b/components/global/Header/Header.tsx @@ -1,6 +1,5 @@ import React from 'react' import { StyledHeader, StyledAnchor } from './Header.styled' -import Link from 'next/link' import { DDDLogo } from 'components/global/Icons/DDDLogo' import { HeaderSocials } from './components/HeaderSocials' import { NavToggle } from 'components/global/Nav/components/NavToggle' @@ -12,11 +11,9 @@ export const Header = (): JSX.Element => { return ( - - - - - + + + ) diff --git a/components/global/Header/components/HeaderSocials.tsx b/components/global/Header/components/HeaderSocials.tsx index dff25f37..d60fc601 100644 --- a/components/global/Header/components/HeaderSocials.tsx +++ b/components/global/Header/components/HeaderSocials.tsx @@ -2,7 +2,7 @@ import React from 'react' import { StyledSocialList, StyledSafeLink } from './HeaderSocials.styled' import { FacebookIcon } from 'components/global/Icons/Facebook' import { InstagramIcon } from 'components/global/Icons/Instagram' -import { TwitterIcon } from 'components/global/Icons/Twitter' +import { BlueskyIcon } from 'components/global/Icons/Bluesky' import { LinkedinIcon } from 'components/global/Icons/Linkedin' import { RedBubbleIcon } from 'components/global/Icons/RedBubble' import { useConfig } from 'Context/Config' @@ -22,23 +22,15 @@ export const HeaderSocials = (): JSX.Element => { )} - {socials.Instagram && ( + {socials.Bluesky?.Name && (
  • - - Instagram, opens in new window - -
  • - )} - {socials.Twitter && ( -
  • - - - Twitter, opens in new window + + Bluesky, opens in new window
  • )} @@ -54,6 +46,18 @@ export const HeaderSocials = (): JSX.Element => { )} + {socials.Instagram && ( +
  • + + + Instagram, opens in new window + +
  • + )} {socials.RedBubble && (
  • diff --git a/components/global/Icons/Bluesky.tsx b/components/global/Icons/Bluesky.tsx new file mode 100644 index 00000000..aca137ee --- /dev/null +++ b/components/global/Icons/Bluesky.tsx @@ -0,0 +1,12 @@ +import React from 'react' + +interface BlueskyIconProps { + title?: string +} + +export const BlueskyIcon = ({ title = 'Bluesky icon' }: BlueskyIconProps) => ( + + {title} + + +) diff --git a/components/global/Nav/Nav.styled.tsx b/components/global/Nav/Nav.styled.tsx index d4dd6762..a391ac0d 100644 --- a/components/global/Nav/Nav.styled.tsx +++ b/components/global/Nav/Nav.styled.tsx @@ -3,6 +3,7 @@ import styled from '@emotion/styled' import { zIndex } from 'components/utils/styles/zindex' import { breakpoint } from 'components/utils/styles/breakpoints' import { NavStatus } from './Nav' +import Link from 'next/link' interface StyleNavProps { status: NavStatus @@ -33,10 +34,10 @@ export const StyledNavList = styled('ul')(({ theme }) => ({ StyledNavList.displayName = 'StyledNavList' interface StyledNavLinkProps { - active?: boolean + active?: string } -export const StyledNavLink = styled('a')(({ theme, active }) => ({ +export const StyledNavLink = styled(Link)(({ theme, active }) => ({ display: 'flex', alignItems: 'center', padding: calcRem(theme.metrics.lg, theme.metrics.lg), diff --git a/components/global/Nav/Nav.tsx b/components/global/Nav/Nav.tsx index bb374628..c35c7585 100644 --- a/components/global/Nav/Nav.tsx +++ b/components/global/Nav/Nav.tsx @@ -1,6 +1,5 @@ import React from 'react' import { useRouter } from 'next/router' -import Link from 'next/link' import { MenuItem } from 'config/types' import { StyledNav, StyledNavLink, StyledNavList } from './Nav.styled' import { useNavigationState, useNavigationDispatch } from './Nav.context' @@ -94,8 +93,10 @@ export const Nav = ({ menu }: NavProps) => { } if (expanded) { - document.addEventListener('click', documentClickHandler) - document.addEventListener('touchstart', documentClickHandler) + window.setTimeout(() => { + document.addEventListener('click', documentClickHandler) + document.addEventListener('touchstart', documentClickHandler) + }, 0) } return () => { @@ -112,13 +113,17 @@ export const Nav = ({ menu }: NavProps) => { {menu.map((item) => (
  • {item.href.indexOf('http') !== -1 ? ( - + {item.name} ) : ( - - {item.name} - + + {item.name} + )}
  • ))} diff --git a/components/global/Nav/components/NavToggle.tsx b/components/global/Nav/components/NavToggle.tsx index 6925a47b..8d584542 100644 --- a/components/global/Nav/components/NavToggle.tsx +++ b/components/global/Nav/components/NavToggle.tsx @@ -3,11 +3,11 @@ import { StyledToggle } from './NavToggle.styled' import { useNavigationState, useNavigationDispatch } from '../Nav.context' export const NavToggle = () => { - const { id, expanded } = useNavigationState() + const { expanded } = useNavigationState() const dispatch = useNavigationDispatch() return ( - dispatch('toggle')} aria-controls={id}> + dispatch('toggle')} aria-controls="nav-id">