├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── labeler.yml └── workflows │ ├── changesets.yml │ ├── chromatic.yml │ ├── ci.yml │ ├── deploy-storybook.yml │ ├── labeler.yml │ ├── project.yml │ ├── snyk.yml │ └── yarn-lock.yml ├── .gitignore ├── .husky └── pre-commit ├── .nvmrc ├── .prettierignore ├── .storybook ├── main.js ├── manager.js ├── preview-head.html ├── preview.tsx ├── preview │ ├── FocusManagerDecorator.tsx │ ├── ThemeProviderDecorator.tsx │ ├── backgrounds.ts │ └── viewport.ts └── theme.ts ├── .vscode └── extensions.json ├── .yarn └── releases │ ├── yarn-1.22.18.cjs │ └── yarn-1.22.19.cjs ├── .yarnrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets └── logo.png ├── docs ├── CHANGELOG_v0-v3.md ├── README.md ├── components.stories.mdx ├── contributing │ ├── overview.stories.mdx │ └── stories.stories.mdx ├── development-kitchen.stories.mdx ├── eslint-plugins.stories.mdx ├── foundations.stories.mdx ├── release-notes │ ├── v3.stories.mdx │ ├── v4.stories.mdx │ └── v5.stories.mdx ├── rfcs │ ├── header-component-api.md │ ├── images │ │ └── header-component-api │ │ │ ├── editorial-header.png │ │ │ ├── header.png │ │ │ ├── masthead-link.png │ │ │ ├── masthead-links.png │ │ │ ├── masthead-menu.png │ │ │ ├── masthead-switch-item.png │ │ │ ├── masthead-switch.png │ │ │ ├── masthead.png │ │ │ ├── navigation-expanded.png │ │ │ ├── navigation-primary-link.png │ │ │ ├── navigation-primary-links.png │ │ │ ├── navigation-secondary-link.png │ │ │ ├── navigation-secondary-links-group.png │ │ │ ├── navigation-secondary-links-supplemental-link.png │ │ │ ├── navigation-secondary-links.png │ │ │ ├── subnav-link.png │ │ │ ├── subnav.png │ │ │ ├── support-buttons.png │ │ │ └── support-thank-you.png │ └── no-unusable-components-line-in-the-sand.md └── source.stories.mdx ├── jest.config.js ├── nx.json ├── package.json ├── packages └── @guardian │ ├── eslint-plugin-source-foundations │ ├── .eslintrc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── README.stories.mdx │ ├── jest.config.js │ ├── jest.e2e.setup.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── rules │ │ │ ├── no-star-imports-or-exports.test.ts │ │ │ ├── no-star-imports-or-exports.ts │ │ │ ├── valid-import-path.test.ts │ │ │ └── valid-import-path.ts │ └── tsconfig.json │ ├── eslint-plugin-source-react-components │ ├── .eslintrc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── README.stories.mdx │ ├── jest.config.js │ ├── jest.e2e.setup.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── rules │ │ │ ├── valid-import-path.test.ts │ │ │ └── valid-import-path.ts │ └── tsconfig.json │ ├── source-foundations │ ├── .yarnrc │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── jest.e2e.setup.js │ ├── lib │ │ └── jest-matchers │ │ │ ├── index.ts │ │ │ └── toBeValidCSS.ts │ ├── package.json │ ├── rollup.config.js │ └── src │ │ ├── accessibility │ │ ├── accessibility.test.ts │ │ ├── description-id.stories.mdx │ │ ├── description-id.ts │ │ ├── focus-halo.stories.mdx │ │ ├── focus-halo.ts │ │ ├── focus-style-manager.stories.mdx │ │ ├── focus-style-manager.ts │ │ ├── generate-source-id.stories.mdx │ │ ├── generate-source-id.ts │ │ ├── visually-hidden.stories.mdx │ │ └── visually-hidden.ts │ │ ├── animation │ │ └── transitions.ts │ │ ├── breakpoints │ │ └── breakpoints.ts │ │ ├── colour │ │ ├── palette.stories.mdx │ │ ├── palette.tsx │ │ └── storybookColorPalette.tsx │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── mq │ │ ├── mq.stories.mdx │ │ ├── mq.test.ts │ │ └── mq.ts │ │ ├── size │ │ ├── size.stories.mdx │ │ └── size.ts │ │ ├── space │ │ ├── space.stories.mdx │ │ ├── space.test.ts │ │ └── space.ts │ │ ├── typography │ │ ├── api.ts │ │ ├── data.ts │ │ ├── font-styles.ts │ │ ├── index.ts │ │ ├── obj │ │ │ ├── index.ts │ │ │ └── typography.obj.test.ts │ │ ├── storybookTypographyRenderers.tsx │ │ ├── types.ts │ │ ├── typography.stories.mdx │ │ └── typography.test.ts │ │ └── utils │ │ ├── px-to-rem.test.ts │ │ ├── px-to-rem.ts │ │ ├── resets.stories.mdx │ │ ├── resets.test.ts │ │ ├── resets.ts │ │ ├── supports-queries.ts │ │ └── svg-background-image.ts │ ├── source-react-components-development-kitchen │ ├── .github │ │ └── pull_request_template.md │ ├── .yarnrc │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── jest.e2e.setup.js │ ├── package.json │ ├── rollup.config.js │ └── src │ │ ├── divider │ │ ├── Divider.stories.tsx │ │ ├── Divider.tsx │ │ ├── README.md │ │ └── styles.ts │ │ ├── editorial-button │ │ ├── EditorialButton.stories.tsx │ │ ├── EditorialButton.tsx │ │ ├── EditorialLinkButton.stories.tsx │ │ ├── EditorialLinkButton.tsx │ │ ├── README.md │ │ ├── styles.ts │ │ └── types.ts │ │ ├── expanding-wrapper │ │ ├── ExpandingWrapper.stories.tsx │ │ ├── ExpandingWrapper.tsx │ │ ├── README.md │ │ ├── styles.ts │ │ ├── theme.ts │ │ └── types.ts │ │ ├── footer-with-contents │ │ ├── FooterLinks.stories.tsx │ │ ├── FooterLinks.tsx │ │ ├── FooterWithContents.stories.tsx │ │ ├── FooterWithContents.tsx │ │ ├── README.md │ │ ├── footerLinksStyles.ts │ │ └── footerWithContentsStyles.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── lines │ │ ├── DashedLines.tsx │ │ ├── DottedLines.tsx │ │ ├── Lines.stories.tsx │ │ ├── Lines.tsx │ │ ├── README.md │ │ ├── SquigglyLines.tsx │ │ └── StraightLines.tsx │ │ ├── logo │ │ ├── Logo.stories.tsx │ │ ├── Logo.tsx │ │ └── README.md │ │ ├── numeric-input │ │ ├── InputExtension.tsx │ │ ├── NumericInput.stories.tsx │ │ ├── NumericInput.tsx │ │ ├── README.md │ │ ├── inputExtensionStyles.ts │ │ ├── numericInputStyles.ts │ │ └── sharedStyles.ts │ │ ├── quote-icon │ │ ├── QuoteIcon.stories.tsx │ │ ├── QuoteIcon.tsx │ │ └── README.md │ │ ├── star-rating │ │ ├── README.md │ │ ├── StarRating.stories.tsx │ │ └── StarRating.tsx │ │ ├── summary │ │ ├── ErrorSummary.stories.tsx │ │ ├── ErrorSummary.tsx │ │ ├── InfoSummary.stories.tsx │ │ ├── InfoSummary.tsx │ │ ├── README.md │ │ ├── SuccessSummary.stories.tsx │ │ ├── SuccessSummary.tsx │ │ ├── styles.ts │ │ └── types.ts │ │ ├── toggle-switch-apps │ │ ├── README.md │ │ ├── ToggleSwitchApps.stories.tsx │ │ ├── ToggleSwitchApps.tsx │ │ └── styles.ts │ │ └── toggle-switch │ │ ├── README.md │ │ ├── ToggleSwitch.stories.tsx │ │ ├── ToggleSwitch.tsx │ │ └── styles.ts │ └── source-react-components │ ├── .yarnrc │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── jest.e2e.setup.js │ ├── package.json │ ├── rollup.config.js │ ├── scripts │ ├── README.md │ ├── create-icons │ │ ├── create-icon-component.ts │ │ ├── create-readme.ts │ │ ├── get-svgs-from-figma.ts │ │ └── index.ts │ └── vendor │ │ └── icons │ │ └── README.md │ ├── src │ ├── @types │ │ ├── Icons.ts │ │ ├── Props.ts │ │ ├── Theme.ts │ │ └── ThemeName.ts │ ├── accordion │ │ ├── Accordion.stories.tsx │ │ ├── Accordion.tsx │ │ ├── AccordionRow.tsx │ │ ├── AccordionRowNoJS.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── brand │ │ ├── SvgGuardianBestWebsiteLogo.stories.tsx │ │ ├── SvgGuardianBestWebsiteLogo.tsx │ │ ├── SvgGuardianLiveLogo.stories.tsx │ │ ├── SvgGuardianLiveLogo.tsx │ │ ├── SvgGuardianLogo.stories.tsx │ │ ├── SvgGuardianLogo.tsx │ │ ├── SvgRoundel.tsx │ │ ├── SvgRoundelBrand.stories.tsx │ │ ├── SvgRoundelBrand.tsx │ │ ├── SvgRoundelBrandInverse.stories.tsx │ │ ├── SvgRoundelBrandInverse.tsx │ │ ├── SvgRoundelDefault.stories.tsx │ │ ├── SvgRoundelDefault.tsx │ │ ├── SvgRoundelInverse.stories.tsx │ │ ├── SvgRoundelInverse.tsx │ │ └── favicons │ │ │ ├── 114x114-roundel.png │ │ │ ├── 114x114.png │ │ │ ├── 120x120.png │ │ │ ├── 144x144.png │ │ │ ├── 152x152-roundel.png │ │ │ ├── 152x152.png │ │ │ ├── 32x32-dev.ico │ │ │ ├── 32x32.ico │ │ │ ├── 57x57.png │ │ │ └── 72x72.png │ ├── button │ │ ├── Button.stories.tsx │ │ ├── Button.tsx │ │ ├── LinkButton.stories.tsx │ │ ├── LinkButton.tsx │ │ ├── shared.tsx │ │ ├── styles.ts │ │ ├── theme-reader-revenue.ts │ │ ├── theme.ts │ │ └── types.ts │ ├── checkbox │ │ ├── Checkbox.stories.tsx │ │ ├── Checkbox.tsx │ │ ├── CheckboxGroup.stories.tsx │ │ ├── CheckboxGroup.tsx │ │ ├── LabelText.tsx │ │ ├── SupportingText.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── choice-card │ │ ├── ChoiceCard.stories.tsx │ │ ├── ChoiceCard.tsx │ │ ├── ChoiceCardGroup.stories.tsx │ │ ├── ChoiceCardGroup.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── columns │ │ ├── Column.tsx │ │ ├── Columns.stories.tsx │ │ ├── Columns.tsx │ │ └── styles.ts │ ├── container │ │ ├── Container.stories.tsx │ │ ├── Container.tsx │ │ └── styles.ts │ ├── deprecated-exports.ts │ ├── footer │ │ ├── BackToTop.stories.tsx │ │ ├── BackToTop.tsx │ │ ├── Footer.stories.tsx │ │ ├── Footer.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── hide │ │ ├── Hide.stories.tsx │ │ └── Hide.tsx │ ├── icons │ │ ├── Icons.stories.tsx │ │ ├── SvgSpinner.tsx │ │ └── labels.ts │ ├── index.test.ts │ ├── index.ts │ ├── inline │ │ ├── Inline.stories.tsx │ │ ├── Inline.tsx │ │ ├── styles.ts │ │ └── types.ts │ ├── label │ │ ├── Label.stories.tsx │ │ ├── Label.tsx │ │ ├── Legend.stories.tsx │ │ ├── Legend.tsx │ │ ├── SupportingText.tsx │ │ ├── Text.tsx │ │ ├── styles.ts │ │ ├── theme.ts │ │ └── types.ts │ ├── link │ │ ├── ButtonLink.stories.tsx │ │ ├── ButtonLink.tsx │ │ ├── Link.stories.tsx │ │ ├── Link.tsx │ │ ├── shared.tsx │ │ ├── styles.ts │ │ ├── theme.ts │ │ └── types.ts │ ├── radio │ │ ├── Radio.stories.tsx │ │ ├── Radio.tsx │ │ ├── RadioGroup.stories.tsx │ │ ├── RadioGroup.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── select │ │ ├── Option.tsx │ │ ├── Select.stories.tsx │ │ ├── Select.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── stack │ │ ├── Stack.stories.tsx │ │ ├── Stack.tsx │ │ └── styles.ts │ ├── text-area │ │ ├── TextArea.stories.tsx │ │ ├── TextArea.tsx │ │ └── styles.ts │ ├── text-input │ │ ├── TextInput.stories.tsx │ │ ├── TextInput.tsx │ │ ├── styles.ts │ │ └── theme.ts │ ├── tiles │ │ ├── Tiles.stories.tsx │ │ ├── Tiles.tsx │ │ ├── styles.ts │ │ └── types.ts │ └── user-feedback │ │ ├── InlineError.stories.tsx │ │ ├── InlineError.tsx │ │ ├── InlineSuccess.stories.tsx │ │ ├── InlineSuccess.tsx │ │ ├── styles.ts │ │ ├── theme.ts │ │ └── types.ts │ └── vendor │ └── icons │ ├── README.md │ ├── SvgAlertPhone.tsx │ ├── SvgAlertRound.tsx │ ├── SvgAlertTriangle.tsx │ ├── SvgAppleBrand.tsx │ ├── SvgArrowContract.tsx │ ├── SvgArrowDownStraight.tsx │ ├── SvgArrowExpand.tsx │ ├── SvgArrowLeftStraight.tsx │ ├── SvgArrowOutdent.tsx │ ├── SvgArrowPopOut.tsx │ ├── SvgArrowRightStraight.tsx │ ├── SvgArrowScroll.tsx │ ├── SvgArrowUpAndDownSmall.tsx │ ├── SvgArrowUpStraight.tsx │ ├── SvgArrowUpStraightSmall.tsx │ ├── SvgAsterisk.tsx │ ├── SvgAudio.tsx │ ├── SvgAudioMute.tsx │ ├── SvgBookMark.tsx │ ├── SvgBookMarkCross.tsx │ ├── SvgCalendar.tsx │ ├── SvgCamera.tsx │ ├── SvgCheckmark.tsx │ ├── SvgChevronDownDouble.tsx │ ├── SvgChevronDownSingle.tsx │ ├── SvgChevronDownSingleXsmall.tsx │ ├── SvgChevronLeftDouble.tsx │ ├── SvgChevronLeftSingle.tsx │ ├── SvgChevronRightDouble.tsx │ ├── SvgChevronRightSingle.tsx │ ├── SvgChevronUpDouble.tsx │ ├── SvgChevronUpSingle.tsx │ ├── SvgClock.tsx │ ├── SvgClockBaselineSmall.tsx │ ├── SvgCreditCard.tsx │ ├── SvgCross.tsx │ ├── SvgCrossRound.tsx │ ├── SvgCrossedOutCloud.tsx │ ├── SvgCrosswords.tsx │ ├── SvgDirectDebit.tsx │ ├── SvgDirectDebitWide.tsx │ ├── SvgDocument.tsx │ ├── SvgDownload.tsx │ ├── SvgDragHandle.tsx │ ├── SvgEdit.tsx │ ├── SvgEllipsis.tsx │ ├── SvgEnvelope.tsx │ ├── SvgExclamation.tsx │ ├── SvgExternal.tsx │ ├── SvgEye.tsx │ ├── SvgEyeStrike.tsx │ ├── SvgFacebook.tsx │ ├── SvgFacebookBrand.tsx │ ├── SvgFacebookMessenger.tsx │ ├── SvgFilter.tsx │ ├── SvgGift.tsx │ ├── SvgGlobe.tsx │ ├── SvgGoogleBrand.tsx │ ├── SvgGps.tsx │ ├── SvgHandPointed.tsx │ ├── SvgHouse.tsx │ ├── SvgHouseCross.tsx │ ├── SvgHousePlus.tsx │ ├── SvgHouseSetting.tsx │ ├── SvgIndent.tsx │ ├── SvgInfoRound.tsx │ ├── SvgLinkedIn.tsx │ ├── SvgLocationMarker.tsx │ ├── SvgMagnifyingGlass.tsx │ ├── SvgMagnifyingGlassMinus.tsx │ ├── SvgMagnifyingGlassPlus.tsx │ ├── SvgMagnifyingGlassSadFace.tsx │ ├── SvgMediaControlsBack.tsx │ ├── SvgMediaControlsForward.tsx │ ├── SvgMediaControlsPause.tsx │ ├── SvgMediaControlsPlay.tsx │ ├── SvgMediaControlsStop.tsx │ ├── SvgMenu.tsx │ ├── SvgMinus.tsx │ ├── SvgMoon.tsx │ ├── SvgNewsletter.tsx │ ├── SvgNotificationsOff.tsx │ ├── SvgNotificationsOn.tsx │ ├── SvgPadlock.tsx │ ├── SvgPartyOfThree.tsx │ ├── SvgPayPalBrand.tsx │ ├── SvgPerson.tsx │ ├── SvgPersonCross.tsx │ ├── SvgPersonPlus.tsx │ ├── SvgPersonRound.tsx │ ├── SvgPersonTick.tsx │ ├── SvgPhone.tsx │ ├── SvgPinned.tsx │ ├── SvgPinterest.tsx │ ├── SvgPlus.tsx │ ├── SvgQuote.tsx │ ├── SvgReload.tsx │ ├── SvgSettings.tsx │ ├── SvgShare.tsx │ ├── SvgShareCallout.tsx │ ├── SvgSpeechBubble.tsx │ ├── SvgSpeechBubbleCross.tsx │ ├── SvgSpeechBubblePlus.tsx │ ├── SvgStar.tsx │ ├── SvgStarOutline.tsx │ ├── SvgTextLarge.tsx │ ├── SvgTextSize.tsx │ ├── SvgTextSmall.tsx │ ├── SvgTickRound.tsx │ ├── SvgTwitter.tsx │ ├── SvgUpload.tsx │ ├── SvgVideo.tsx │ └── SvgWhatsApp.tsx ├── scripts ├── README.md └── paths.ts ├── stylelint.config.js ├── tsconfig.json └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "main", 8 | "updateInternalDependencies": "patch", 9 | "ignore": [], 10 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 11 | "onlyUpdatePeerDependentsWhenOutOfRange": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # based on https://github.com/guardian/configs/blob/main/.editorconfig 2 | 3 | ; top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | # Tabs for accessibility reasons: 8 | # - https://alexandersandberg.com/tabs-for-accessibility 9 | # - https://twitter.com/Rich_Harris/status/1541761871585464323 10 | # If it messes up your github previews, you can choose your favourite tab width: 11 | # - https://github.com/settings/appearance 12 | indent_style = tab 13 | end_of_line = lf 14 | charset = utf-8 15 | trim_trailing_whitespace = true 16 | insert_final_newline = true 17 | 18 | # Because `yml` 19 | [*.{yml,yaml}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @guardian/client-side-infra 2 | 3 | /packages/@guardian/source-react-components-development-kitchen/src/components/button @guardian/dotcom-platform 4 | /packages/@guardian/source-react-components-development-kitchen/src/components/footer-with-contents @guardian/conversions-developers 5 | /packages/@guardian/source-react-components-development-kitchen/src/components/lines @guardian/dotcom-platform 6 | /packages/@guardian/source-react-components-development-kitchen/src/components/logo @guardian/dotcom-platform 7 | /packages/@guardian/source-react-components-development-kitchen/src/components/numeric-input @guardian/conversions-developers 8 | /packages/@guardian/source-react-components-development-kitchen/src/components/quote-icon @guardian/dotcom-platform 9 | /packages/@guardian/source-react-components-development-kitchen/src/components/star-rating @guardian/dotcom-platform 10 | /packages/@guardian/source-react-components-development-kitchen/src/components/summary @guardian/identity 11 | /packages/@guardian/source-react-components-development-kitchen/src/components/toggle-switch @guardian/mss-admins 12 | /packages/@guardian/source-react-components-development-kitchen/src/components/expanding-wrapper @guardian/editorial-experience 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: 'npm' # See documentation for possible values 9 | directory: '/' # Location of package manifests 10 | schedule: 11 | interval: 'monthly' 12 | day: 'monday' 13 | time: '06:00' 14 | open-pull-requests-limit: 1 15 | # Minimise the number of chromatic runs. 16 | # We've enabled 'Require branches to be up to date before merging', 17 | # so you won't be able to merge a dependabot PR unless you rebase manually anyway. 18 | rebase-strategy: 'disabled' 19 | - package-ecosystem: 'github-actions' 20 | directory: '/' 21 | schedule: 22 | interval: 'monthly' 23 | day: 'monday' 24 | time: '06:00' 25 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/marketplace/actions/labeler 2 | 3 | foundations: 4 | - 'packages/@guardian/source-foundations/**/*' 5 | react-components: 6 | - 'packages/@guardian/source-react-components/**/*' 7 | kitchen: 8 | - 'packages/@guardian/source-react-components-development-kitchen/**/*' 9 | -------------------------------------------------------------------------------- /.github/workflows/changesets.yml: -------------------------------------------------------------------------------- 1 | name: Manage Changesets 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | changesets-version: 10 | name: Manage Changesets Pull Request 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repo 14 | uses: actions/checkout@v3 15 | with: 16 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 17 | fetch-depth: 0 18 | 19 | - uses: guardian/actions-setup-node@v2.4.1 20 | with: 21 | cache: 'yarn' 22 | 23 | - name: Install Dependencies 24 | run: yarn install --frozen-lockfile 25 | 26 | - name: Create Release Pull Request or Publish to npm 27 | id: changesets 28 | uses: changesets/action@v1 29 | with: 30 | publish: yarn release 31 | title: 'Release package updates' 32 | commit: 'Bump package versions' 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | -------------------------------------------------------------------------------- /.github/workflows/chromatic.yml: -------------------------------------------------------------------------------- 1 | name: Chromatic 2 | on: 3 | push: 4 | jobs: 5 | upload-storybook: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v3 9 | with: 10 | fetch-depth: 0 11 | - uses: guardian/actions-setup-node@v2.4.1 12 | with: 13 | cache: 'yarn' 14 | - run: yarn install --frozen-lockfile 15 | - uses: chromaui/action@v1 16 | with: 17 | projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} 18 | token: ${{ secrets.GITHUB_TOKEN }} 19 | buildScriptName: 'build:storybook' 20 | exitOnceUploaded: true 21 | onlyChanged: '!(main)' # only turbosnap on non-main branches 22 | -------------------------------------------------------------------------------- /.github/workflows/deploy-storybook.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Storybook to GitHub Pages 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: guardian/actions-setup-node@v2.4.1 12 | with: 13 | cache: 'yarn' 14 | - name: build 15 | run: | 16 | yarn install --frozen-lockfile 17 | yarn build:storybook 18 | - name: deploy 19 | run: yarn storybook-to-ghpages --ci 20 | env: 21 | GH_TOKEN: ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: 'Pull Request Labeler' 2 | on: 3 | - pull_request_target 4 | 5 | jobs: 6 | label-pr: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/labeler@v4 10 | with: 11 | repo-token: '${{ secrets.GITHUB_TOKEN }}' 12 | sync-labels: true # remove redundant labels after a change 13 | -------------------------------------------------------------------------------- /.github/workflows/project.yml: -------------------------------------------------------------------------------- 1 | name: Add new issues to CSTI project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@v0.3.0 14 | with: 15 | # You can target a repository in a different organization 16 | # to the issue 17 | project-url: https://github.com/orgs/guardian/projects/61 18 | # uses a PAT from @sndrs 19 | github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} 20 | -------------------------------------------------------------------------------- /.github/workflows/snyk.yml: -------------------------------------------------------------------------------- 1 | # This action runs snyk monitor on every push to main 2 | name: Snyk 3 | 4 | on: 5 | push: 6 | branches: 7 | - main 8 | workflow_dispatch: 9 | 10 | jobs: 11 | security: 12 | uses: guardian/.github/.github/workflows/sbt-node-snyk.yml@main 13 | with: 14 | DEBUG: true 15 | ORG: guardian-csti 16 | SKIP_NODE: false 17 | secrets: 18 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/yarn-lock.yml: -------------------------------------------------------------------------------- 1 | name: Yarn Lock Changes 2 | on: [pull_request] 3 | 4 | jobs: 5 | yarn_lock_changes: 6 | runs-on: ubuntu-latest 7 | # Permission overwrite is required for Dependabot PRs 8 | permissions: 9 | pull-requests: write 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v3 13 | - name: Yarn Lock Changes 14 | # Please use `main` as version before the stable release will be published as `v1`. 15 | uses: Simek/yarn-lock-changes@main 16 | with: 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | collapsibleThreshold: 150 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | dist 4 | .cache 5 | .DS_Store 6 | *.tgz 7 | package-lock.json 8 | .idea/ 9 | .vscode/settings.json 10 | coverage/ 11 | .eslintcache 12 | .vscode/ 13 | 14 | # scripts/eslint-integration-test 15 | scripts/eslint-integration-test/integration-test-content.ts 16 | 17 | # Environment 18 | .env 19 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 16.15.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .yarn 2 | dist 3 | node_modules 4 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | import { theme } from './theme'; 3 | 4 | addons.setConfig({ 5 | theme, 6 | }); 7 | -------------------------------------------------------------------------------- /.storybook/preview.tsx: -------------------------------------------------------------------------------- 1 | import { ThemeProviderDecorator } from './preview/ThemeProviderDecorator'; 2 | import { FocusManagerDecorator } from './preview/FocusManagerDecorator'; 3 | import { viewport } from './preview/viewport'; 4 | import { backgrounds } from './preview/backgrounds'; 5 | 6 | export const parameters = { 7 | viewport, 8 | backgrounds, 9 | actions: { argTypesRegex: '^on[A-Z].*' }, 10 | controls: { 11 | matchers: { 12 | color: /(background|color)$/i, 13 | date: /Date$/, 14 | }, 15 | }, 16 | options: { 17 | storySort: { 18 | order: [ 19 | 'Source', 20 | 'Foundations', 21 | 'Components', 22 | 'Development Kitchen', 23 | 'Packages', 24 | ], 25 | method: 'alphabetical', 26 | }, 27 | }, 28 | }; 29 | 30 | export const decorators = [FocusManagerDecorator, ThemeProviderDecorator]; 31 | -------------------------------------------------------------------------------- /.storybook/preview/FocusManagerDecorator.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { FocusStyleManager } from '@guardian/source-foundations'; 3 | 4 | export const FocusManagerDecorator = (storyFn) => { 5 | useEffect(() => { 6 | FocusStyleManager.onlyShowFocusOnTabs(); 7 | }); 8 | 9 | return <>{storyFn()}; 10 | }; 11 | -------------------------------------------------------------------------------- /.storybook/preview/ThemeProviderDecorator.tsx: -------------------------------------------------------------------------------- 1 | import { ThemeProvider } from '@emotion/react'; 2 | 3 | export const ThemeProviderDecorator = (storyFn, context) => { 4 | const theme = context.parameters.theme; 5 | return theme ? ( 6 | {storyFn()} 7 | ) : ( 8 | <>{storyFn()} 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /.storybook/preview/backgrounds.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | 3 | export const backgrounds = { 4 | default: 'background.primary', 5 | values: [ 6 | { 7 | name: 'background.primary', 8 | value: palette.neutral[100], 9 | }, 10 | { 11 | name: 'background.secondary', 12 | value: palette.neutral[97], 13 | }, 14 | { 15 | name: 'background.inverse', 16 | value: palette.neutral[10], 17 | }, 18 | { 19 | name: 'brandBackground.primary', 20 | value: palette.brand[400], 21 | }, 22 | { 23 | name: 'brandAltBackground.primary', 24 | value: palette.brandAlt[400], 25 | }, 26 | ], 27 | }; 28 | -------------------------------------------------------------------------------- /.storybook/theme.ts: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming'; 2 | 3 | export const theme = create({ 4 | base: 'light', 5 | brandTitle: '@guardian/source', 6 | brandUrl: 'https://www.npmjs.com/package/@guardian/source', 7 | brandImage: 8 | 'https://raw.githubusercontent.com/guardian/source/main/assets/logo.png', 9 | }); 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "editorconfig.editorconfig", 4 | "esbenp.prettier-vscode", 5 | "styled-components.vscode-styled-components", 6 | "stylelint.vscode-stylelint", 7 | "stkb.rewrap", 8 | "naumovs.color-highlight" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | lastUpdateCheck 1633433443971 6 | yarn-path ".yarn/releases/yarn-1.22.19.cjs" 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please read the [Contributing](https://guardian.github.io/source/?path=/story/contributing-overview--page) page in Storybook. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Source 2 | 3 | > A component library for the Guardian's [Source Design System](https://theguardian.design). 4 | 5 | **Source packages have moved to https://github.com/guardian/csnx in [#252](https://github.com/guardian/csnx/pull/252)**. 6 | 7 | The last versions to be published from here were: 8 | 9 | - @guardian/source-foundations@7.0.1 10 | - @guardian/source-react-components@9.1.0 11 | - @guardian/source-react-components-development-kitchen@7.0.0 12 | - @guardian/eslint-plugin-source-foundations@7.0.0 13 | - @guardian/eslint-plugin-source-react-components@9.0.0 14 | 15 | https://github.com/guardian/source/releases 16 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/assets/logo.png -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Docs 2 | 3 | Please see our [Storybook docs](https://guardian.github.io/source) 4 | -------------------------------------------------------------------------------- /docs/components.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | import ReadMe from '../packages/@guardian/source-react-components/README.md'; 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/development-kitchen.stories.mdx: -------------------------------------------------------------------------------- 1 | import ReadMe from '../packages/@guardian/source-react-components-development-kitchen/README.md'; 2 | import { Meta } from '@storybook/addon-docs'; 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/eslint-plugins.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # ESLint plugins 9 | 10 | The foundations and components packages have accompanying ESLint plugins which contain Source-specific linting rules that are highly recommended for your project. 11 | 12 | They can also work as codemods to help migrate your project to the next version of Source, using ESLint’s `--fix` option (beginning with v4): 13 | 14 | - [@guardian/eslint-plugin-source-foundations](https://guardian.github.io/source/?path=/story/packages-eslint-plugin-source-foundations) 15 | - [@guardian/eslint-plugin-source-react-components](https://guardian.github.io/source/?path=/story/packages-eslint-plugin-source-react-components) 16 | -------------------------------------------------------------------------------- /docs/foundations.stories.mdx: -------------------------------------------------------------------------------- 1 | import ReadMe from '../packages/@guardian/source-foundations/README.md'; 2 | import { Meta } from '@storybook/addon-docs'; 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/editorial-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/editorial-header.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/header.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/masthead-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/masthead-link.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/masthead-links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/masthead-links.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/masthead-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/masthead-menu.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/masthead-switch-item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/masthead-switch-item.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/masthead-switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/masthead-switch.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/masthead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/masthead.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-expanded.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-primary-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-primary-link.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-primary-links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-primary-links.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-secondary-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-secondary-link.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-secondary-links-group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-secondary-links-group.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-secondary-links-supplemental-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-secondary-links-supplemental-link.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/navigation-secondary-links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/navigation-secondary-links.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/subnav-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/subnav-link.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/subnav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/subnav.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/support-buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/support-buttons.png -------------------------------------------------------------------------------- /docs/rfcs/images/header-component-api/support-thank-you.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/docs/rfcs/images/header-component-api/support-thank-you.png -------------------------------------------------------------------------------- /docs/source.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # Source 9 | 10 | Our library for the web lives in the [Source repository](https://github.com/guardian/source). It consists of three packages: 11 | 12 | 1. [@guardian/source-foundations](https://guardian.github.io/source/?path=/story/foundations--page) – the foundations for our design system. 13 | 1. [@guardian/source-react-components](https://guardian.github.io/source/?path=/story/components--page) – a set of robust, accessible React components implemented using the foundations. 14 | 1. [@guardian/source-react-components-development-kitchen](https://guardian.github.io/source/?path=/story/development-kitchen--page) – an experimental set of React components for development and testing. 15 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | testPathIgnorePatterns: ['/node_modules', '/dist'], 6 | }; 7 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@nrwl/workspace/presets/npm.json", 3 | "npmScope": "guardian", 4 | "tasksRunnerOptions": { 5 | "default": { 6 | "runner": "@nrwl/nx-cloud", 7 | "options": { 8 | "cacheableOperations": ["build", "test", "e2e"], 9 | "accessToken": "YjlhZjRmOWQtNWQwNy00YzUyLTk0YzItZWY1NTk3OGExMDQ4fHJlYWQtd3JpdGU=" 10 | } 11 | } 12 | }, 13 | "targetDependencies": { 14 | "build": [ 15 | { 16 | "target": "build", 17 | "projects": "dependencies" 18 | } 19 | ], 20 | "test": [ 21 | { 22 | "target": "build", 23 | "projects": "dependencies" 24 | } 25 | ], 26 | "e2e": [ 27 | { 28 | "target": "build", 29 | "projects": "self" 30 | }, 31 | { 32 | "target": "build", 33 | "projects": "dependencies" 34 | } 35 | ] 36 | }, 37 | "affected": { 38 | "defaultBase": "main" 39 | }, 40 | "pluginsConfig": { 41 | "@nrwl/js": { 42 | "analyzeSourceFiles": false 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "settings": { 4 | "import/resolver": { 5 | "typescript": { 6 | "alwaysTryTypes": true 7 | } 8 | } 9 | }, 10 | "env": { 11 | "jest": true, 12 | "browser": true, 13 | "node": true 14 | }, 15 | "parserOptions": { 16 | "sourceType": "module", 17 | "ecmaVersion": 2020, 18 | "ecmaFeatures": { 19 | "modules": true 20 | }, 21 | "project": "./tsconfig.json" 22 | }, 23 | "extends": ["@guardian/eslint-config"], 24 | "ignorePatterns": ["dist", "coverage"], 25 | "overrides": [ 26 | { 27 | "files": ["**/*.ts", "**/*.tsx"], 28 | "extends": ["@guardian/eslint-config-typescript"] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @guardian/eslint-plugin-source-foundations 2 | 3 | ## 8.0.0 4 | 5 | ### Major Changes 6 | 7 | - aa4c2caa: Bump @guardian/libs to `^9.0.0` 8 | 9 | ## 7.0.0 10 | 11 | ### Major Changes 12 | 13 | - Updated `peerDependencies` [905c5148] 14 | - @guardian/source-foundations@7.0.0 15 | 16 | ## 6.0.1 17 | 18 | ### Patch Changes 19 | 20 | - 40e41a43: **No changes**: Patch bump to fix deploy to npm due to the major version already having been published and deleted 21 | 22 | ## 6.0.0 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [3823490a] 27 | - @guardian/source-foundations@6.0.0 28 | 29 | ## 5.0.1 30 | 31 | ### Patch Changes 32 | 33 | - 5c23c1d1: Remove `console.log` from `valid-foundations-import-path` rule 34 | 35 | ## 5.0.0 36 | 37 | ### Patch Changes 38 | 39 | - Updated dependencies [b87baf5c] 40 | - Updated dependencies [1e129d0b] 41 | - Updated dependencies [8bd1adce] 42 | - Updated dependencies [51f8737e] 43 | - Updated dependencies [f6865ac5] 44 | - Updated dependencies [34ec716d] 45 | - @guardian/source-foundations@5.0.0 46 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/README.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | import ReadMe from './README.md'; 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; 5 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/jest.e2e.setup.js: -------------------------------------------------------------------------------- 1 | // Mock `src/index` with whatever `package.json` points at. 2 | // This means we can run `src/index.test.ts` against `dist` instead. 3 | 4 | const dist = require('.'); 5 | 6 | jest.mock('./src/index', () => dist); 7 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/rollup.config.js: -------------------------------------------------------------------------------- 1 | import ts from 'rollup-plugin-ts'; 2 | import pkg from './package.json'; 3 | 4 | const bundle = (config) => ({ 5 | ...config, 6 | input: 'src/index.ts', 7 | }); 8 | 9 | // eslint-disable-next-line import/no-default-export -- it's what rollup wants 10 | export default [ 11 | bundle({ 12 | plugins: [ts()], 13 | output: [ 14 | { 15 | file: pkg.main, 16 | format: 'cjs', 17 | sourcemap: true, 18 | }, 19 | { 20 | file: pkg.module, 21 | format: 'es', 22 | sourcemap: true, 23 | }, 24 | ], 25 | }), 26 | ]; 27 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import * as pkgExports from './index'; 2 | 3 | it('Should have exactly these exports', () => { 4 | expect(Object.keys(pkgExports).sort()).toEqual(['configs', 'rules']); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/src/index.ts: -------------------------------------------------------------------------------- 1 | import { noStarImportsOrExports } from './rules/no-star-imports-or-exports'; 2 | import { validFoundationsImportPath } from './rules/valid-import-path'; 3 | 4 | export const rules = { 5 | 'valid-foundations-import-path': validFoundationsImportPath, 6 | 'no-star-imports-or-exports': noStarImportsOrExports, 7 | }; 8 | 9 | export const configs = { 10 | recommended: { 11 | plugins: ['@guardian/source-foundations', 'import'], 12 | 13 | rules: { 14 | '@guardian/source-foundations/valid-foundations-import-path': 'error', 15 | '@guardian/source-foundations/no-star-imports-or-exports': 'error', 16 | 'import/no-duplicates': 'error', 17 | }, 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-foundations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs" 6 | }, 7 | "exclude": ["src/rules/*.test.ts", "dist"], 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "settings": { 4 | "import/resolver": { 5 | "typescript": { 6 | "alwaysTryTypes": true 7 | } 8 | } 9 | }, 10 | "env": { 11 | "jest": true, 12 | "browser": true, 13 | "node": true 14 | }, 15 | "parserOptions": { 16 | "sourceType": "module", 17 | "ecmaVersion": 2020, 18 | "ecmaFeatures": { 19 | "modules": true 20 | }, 21 | "project": "./tsconfig.json" 22 | }, 23 | "extends": ["@guardian/eslint-config"], 24 | "ignorePatterns": ["dist", "coverage"], 25 | "overrides": [ 26 | { 27 | "files": ["**/*.ts", "**/*.tsx"], 28 | "extends": ["@guardian/eslint-config-typescript"] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/README.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | import ReadMe from './README.md'; 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; 5 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/jest.e2e.setup.js: -------------------------------------------------------------------------------- 1 | // Mock `src/index` with whatever `package.json` points at. 2 | // This means we can run `src/index.test.ts` against `dist` instead. 3 | 4 | const dist = require('.'); 5 | 6 | jest.mock('./src/index', () => dist); 7 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/rollup.config.js: -------------------------------------------------------------------------------- 1 | import ts from 'rollup-plugin-ts'; 2 | import pkg from './package.json'; 3 | 4 | const bundle = (config) => ({ 5 | ...config, 6 | input: 'src/index.ts', 7 | }); 8 | 9 | // eslint-disable-next-line import/no-default-export -- it's what rollup wants 10 | export default [ 11 | bundle({ 12 | plugins: [ts()], 13 | output: [ 14 | { 15 | file: pkg.main, 16 | format: 'cjs', 17 | sourcemap: true, 18 | }, 19 | { 20 | file: pkg.module, 21 | format: 'es', 22 | sourcemap: true, 23 | }, 24 | ], 25 | }), 26 | ]; 27 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import * as pkgExports from './index'; 2 | 3 | it('Should have exactly these exports', () => { 4 | expect(Object.keys(pkgExports).sort()).toEqual(['configs', 'rules']); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/src/index.ts: -------------------------------------------------------------------------------- 1 | import { validImportPath } from './rules/valid-import-path'; 2 | 3 | export const rules = { 4 | 'valid-import-path': validImportPath, 5 | }; 6 | 7 | export const configs = { 8 | recommended: { 9 | plugins: ['@guardian/source-react-components'], 10 | 11 | rules: { 12 | '@guardian/source-react-components/valid-import-path': 'error', 13 | }, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/@guardian/eslint-plugin-source-react-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "module": "commonjs" 6 | }, 7 | "exclude": ["src/rules/*.test.ts", "dist"], 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix source-foundations-v 2 | version-git-message "@guardian/source-foundations v%s" 3 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | setupFilesAfterEnv: ['./lib/jest-matchers/index.ts'], 6 | }; 7 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/jest.e2e.setup.js: -------------------------------------------------------------------------------- 1 | // Mock `src/index` with whatever `package.json` points at. 2 | // This means we can run `src/index.test.ts` against `dist` instead. 3 | 4 | const dist = require('.'); 5 | 6 | jest.mock('./src/index', () => dist); 7 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/lib/jest-matchers/index.ts: -------------------------------------------------------------------------------- 1 | // Registers our custom jest matchers before running tests. 2 | 3 | // Register the toBeValidCSS matcher 4 | require('./toBeValidCSS'); 5 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@guardian/source-foundations", 3 | "version": "7.0.1", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/guardian/source.git" 7 | }, 8 | "license": "Apache-2.0", 9 | "sideEffects": false, 10 | "main": "dist/cjs/index.js", 11 | "module": "dist/esm/index.js", 12 | "files": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "build": "rollup -c", 17 | "clean": "rm -rf dist", 18 | "e2e": "jest src/index.test.ts --setupFilesAfterEnv=./jest.e2e.setup.js", 19 | "test": "jest --coverage" 20 | }, 21 | "dependencies": { 22 | "mini-svg-data-uri": "^1.3.3" 23 | }, 24 | "devDependencies": { 25 | "jest": "^27.2.3", 26 | "lightningcss": "^1.16.0", 27 | "rollup": "^2.75.4", 28 | "rollup-plugin-ts": "^2.0.7", 29 | "ts-jest": "^27.0.5" 30 | }, 31 | "publishConfig": { 32 | "access": "public" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/rollup.config.js: -------------------------------------------------------------------------------- 1 | import ts from 'rollup-plugin-ts'; 2 | import pkg from './package.json'; 3 | 4 | const bundle = (config) => ({ 5 | ...config, 6 | input: 'src/index.ts', 7 | external: (id) => !/^[./]/.test(id), 8 | }); 9 | 10 | // eslint-disable-next-line import/no-default-export -- it's what rollup wants 11 | export default [ 12 | bundle({ 13 | plugins: [ts({ tsconfig: '../../../tsconfig.json' })], 14 | output: [ 15 | { 16 | dir: pkg.main.replace('/index.js', ''), 17 | format: 'cjs', 18 | sourcemap: true, 19 | preserveModules: true, 20 | }, 21 | { 22 | dir: pkg.module.replace('/index.js', ''), 23 | format: 'es', 24 | sourcemap: true, 25 | preserveModules: true, 26 | }, 27 | ], 28 | }), 29 | ]; 30 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/accessibility.test.ts: -------------------------------------------------------------------------------- 1 | import { focusHalo, focusHaloSpaced } from './focus-halo'; 2 | import { visuallyHidden } from './visually-hidden'; 3 | 4 | test('focusHalo should be a valid CSS fragment', () => { 5 | expect(focusHalo).toBeValidCSS({ isFragment: true }); 6 | }); 7 | 8 | test('focusHaloSpaced should be a valid CSS fragment', () => { 9 | expect(focusHaloSpaced).toBeValidCSS({ isFragment: true }); 10 | }); 11 | 12 | test('visuallyHidden should be a valid CSS fragment', () => { 13 | expect(visuallyHidden).toBeValidCSS({ isFragment: true }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/description-id.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # `descriptionId` 9 | 10 | A function that takes the ID of an element and generates a new ID. This should be set as the ID of an element that describes the first element. The generated ID should also be passed to the `aria-describedby` attribute on the first element. 11 | 12 | ```tsx 13 | import { descriptionId } from '@guardian/source-foundations'; 14 | 15 | const Form = () => { 16 | const id = 'first_name'; 17 | return ( 18 |
19 | 20 |

21 |

22 | ); 23 | }; 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/description-id.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-foundations-descriptionid--page) 3 | * 4 | * Takes the ID of an element and generates a new ID. This should be set as the ID of an element that describes the first element. The generated ID should also be passed to the `aria-describedby` attribute on the first element. 5 | * 6 | * @param {string} id - ID of an element 7 | * @returns {string} ID of an element that describes the first element 8 | * 9 | * @example 10 | *
11 | * 12 | *

13 | *

14 | */ 15 | export const descriptionId = (id: string): string => `${id}_description`; 16 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/focus-halo.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | import { focusHalo } from './focus-halo'; 4 | 5 | 9 | 10 | # `focusHalo` 11 | 12 | Providing a clear focus state (the blue halo effect around active elements) is essential to support keyboard navigation. 13 | 14 | Apply the `focusHalo` style to custom interactive elements: 15 | 16 | ```tsx 17 | import { focusHalo } from '@guardian/source-foundations'; 18 | 19 | const customButtonStyles = css` 20 | ${focusHalo}; 21 | `; 22 | ``` 23 | 24 | # `focusHaloSpaced` 25 | 26 | The blue halo effect with additional spacing between the element and the halo for better visibility of halo on blue-coloured elements. 27 | 28 | Apply the `focusHaloSpaced` style to custom interactive elements: 29 | 30 | ```tsx 31 | import { focusHaloSpaced } from '@guardian/source-foundations'; 32 | 33 | const customButtonStyles = css` 34 | ${focusHaloSpaced}; 35 | `; 36 | ``` 37 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/focus-halo.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '../colour/palette'; 2 | 3 | /** 4 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-foundations-focushalo--page) 5 | * 6 | * CSS rules that provide a clear visual focus state to support keyboard navigation. 7 | */ 8 | export const focusHalo = ` 9 | outline: 0; 10 | html:not(.src-focus-disabled) & { 11 | box-shadow: 0 0 0 5px ${palette.focus[400]}; 12 | } 13 | `; 14 | 15 | export const focusHaloSpaced = ` 16 | outline: 0; 17 | html:not(.src-focus-disabled) & { 18 | outline: 5px solid ${palette.focus[400]}; 19 | outline-offset: 3px; 20 | } 21 | `; 22 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/focus-style-manager.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | import { FocusStyleManager } from './focus-style-manager'; 3 | 4 | 8 | 9 | # `FocusStyleManager` 10 | 11 | While providing a clear focus state is essential to support keyboard navigation, it is less important for mouse users. 12 | 13 | Source provides a utility that manages the appearance of focus styles. When enabled, focus styles will be hidden while the user interacts using the mouse. They will appear when the tab key is pressed to begin keyboard navigation. 14 | 15 | You should explictly enable this feature in your app: 16 | 17 | ```tsx 18 | import { FocusStyleManager } from '@guardian/source-foundations'; 19 | 20 | FocusStyleManager.onlyShowFocusOnTabs(); 21 | ``` 22 | 23 | ## API 24 | 25 | ### FocusStyleManager.isActive() 26 | 27 | Returns whether the FocusStyleManager is currently running. 28 | 29 | ### FocusStyleManager.onlyShowFocusOnTabs() 30 | 31 | Enable behavior which hides focus styles during mouse interaction. 32 | 33 | ### FocusStyleManager.alwaysShowFocus() 34 | 35 | Stop this behavior (focus styles are always visible). 36 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/generate-source-id.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # `generateSourceId` 9 | 10 | A function that generates a unique ID for an element of the form `src-component-X` where `X` is a number. 11 | 12 | ```tsx 13 | import { generateSourceId } from '@guardian/source-foundations'; 14 | 15 | const Form = () => { 16 | const id = generateSourceId(); 17 | return ( 18 |
19 | 20 |
21 | ); 22 | }; 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/generate-source-id.ts: -------------------------------------------------------------------------------- 1 | let sourceIdIndex = 0; 2 | 3 | export const generateSourceId = (): string => 4 | `src-component-${sourceIdIndex++}`; 5 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/accessibility/visually-hidden.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # `visuallyHidden` 9 | 10 | Some elements should be presented only to screen reader users e.g. restyled checkboxes and button labels that provide more contextual information to the user. 11 | 12 | Apply the `visuallyHidden` CSS rules to elements that need to be hidden from sighted users but displayed to screen reader users: 13 | 14 | ```tsx 15 | import { visuallyHidden } from '@guardian/source-foundations'; 16 | 17 | const label = css` 18 | ${visuallyHidden}; 19 | `; 20 | ``` 21 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/animation/transitions.ts: -------------------------------------------------------------------------------- 1 | const transitions = { 2 | short: '.2s cubic-bezier(.64, .57, .67, 1.53)', 3 | medium: '.3s ease-in-out', 4 | long: '.65s ease-in-out', 5 | }; 6 | 7 | export { transitions }; 8 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/breakpoints/breakpoints.ts: -------------------------------------------------------------------------------- 1 | export type Breakpoint = 2 | | 'mobile' 3 | | 'mobileMedium' 4 | | 'mobileLandscape' 5 | | 'phablet' 6 | | 'tablet' 7 | | 'desktop' 8 | | 'leftCol' 9 | | 'wide'; 10 | 11 | /** 12 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-foundations-media-queries--page) • 13 | * [Design System](https://theguardian.design/2a1e5182b/p/41be19-grids) 14 | */ 15 | export const breakpoints = { 16 | mobile: 320, 17 | mobileMedium: 375, 18 | mobileLandscape: 480, 19 | phablet: 660, 20 | tablet: 740, 21 | desktop: 980, 22 | leftCol: 1140, 23 | wide: 1300, 24 | } as const; 25 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/mq/mq.test.ts: -------------------------------------------------------------------------------- 1 | import type { Breakpoint } from '../breakpoints/breakpoints'; 2 | import { breakpoints } from '../breakpoints/breakpoints'; 3 | import { between, from, until } from './mq'; 4 | 5 | it('from should return a min-width media query', () => { 6 | const min: Breakpoint = 'mobile'; 7 | 8 | expect(from[min]).toBe(`@media (min-width: ${`${breakpoints[min]}px`})`); 9 | }); 10 | 11 | it('until should return a max-width media query', () => { 12 | const max: Breakpoint = 'wide'; 13 | 14 | expect(until[max]).toBe(`@media (max-width: ${`${breakpoints[max] - 1}px`})`); 15 | }); 16 | 17 | it('between should return a media query with min- and max-width', () => { 18 | const min: Breakpoint = 'tablet'; 19 | const max: Breakpoint = 'desktop'; 20 | 21 | expect(between[min].and[max]).toBe( 22 | `@media (min-width: ${`${breakpoints[min]}px`}) and (max-width: ${`${ 23 | breakpoints[max] - 1 24 | }px`})`, 25 | ); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/space/space.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # Space 9 | 10 | Space units create visual rhythm and balance 11 | 12 | ## Example 13 | 14 | ```tsx 15 | import { space } from '@guardian/source-foundations'; 16 | 17 | const container = css` 18 | margin: ${space[1]}px; 19 | `; 20 | 21 | /* 22 | .class-name { 23 | margin: 4px; 24 | } 25 | */ 26 | ``` 27 | 28 | ## Space scale 29 | 30 | The following units can be applied to margin or padding properties, vertically 31 | or horizontally. 32 | 33 | - `space[1]` -> 4px 34 | - `space[2]` -> 8px 35 | - `space[3]` -> 12px 36 | - `space[4]` -> 16px 37 | - `space[5]` -> 20px 38 | - `space[6]` -> 24px 39 | - `space[9]` -> 36px 40 | - `space[12]` -> 48px 41 | - `space[24]` -> 96px 42 | 43 | The same scale is also available as rems: 44 | 45 | - `remSpace[1]` -> 0.25rem 46 | - `remSpace[2]` -> 0.5rem 47 | - `remSpace[3]` -> 0.75rem 48 | - `remSpace[4]` -> 1rem 49 | - `remSpace[5]` -> 1.25rem 50 | - `remSpace[6]` -> 1.5rem 51 | - `remSpace[9]` -> 2.25rem 52 | - `remSpace[12]` -> 3rem 53 | - `remSpace[24]` -> 6rem 54 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/space/space.test.ts: -------------------------------------------------------------------------------- 1 | import { remSpace, space } from './space'; 2 | 3 | it('should provide a rem equivalent of the pixel space', () => 4 | expect(remSpace[2]).toBe(`${space[2] / 16}rem`)); 5 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/typography/obj/index.ts: -------------------------------------------------------------------------------- 1 | import { body, headline, textSans, titlepiece } from '../api'; 2 | import { 3 | bodySizes, 4 | fonts, 5 | fontWeights, 6 | headlineSizes, 7 | lineHeights, 8 | remBodySizes, 9 | remHeadlineSizes, 10 | remTextSansSizes, 11 | remTitlepieceSizes, 12 | textSansSizes, 13 | titlepieceSizes, 14 | } from '../data'; 15 | 16 | export { 17 | titlepiece, 18 | headline, 19 | body, 20 | textSans, 21 | titlepieceSizes, 22 | headlineSizes, 23 | bodySizes, 24 | textSansSizes, 25 | remTitlepieceSizes, 26 | remHeadlineSizes, 27 | remBodySizes, 28 | remTextSansSizes, 29 | fonts, 30 | fontWeights, 31 | lineHeights, 32 | }; 33 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/utils/px-to-rem.test.ts: -------------------------------------------------------------------------------- 1 | import { pxToRem, rootPixelFontSize } from './px-to-rem'; 2 | 3 | it('should calculate a rem equivalent of a pixel value', () => { 4 | const value = 17; 5 | const result = pxToRem(value); 6 | expect(result).toBe(value / rootPixelFontSize); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/utils/px-to-rem.ts: -------------------------------------------------------------------------------- 1 | export const rootPixelFontSize = 16; 2 | export const pxToRem = (px: number): number => px / rootPixelFontSize; 3 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/utils/resets.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs'; 2 | 3 | 7 | 8 | # CSS reset 9 | 10 | Source provides an optional CSS reset that sets some sensible default CSS rules. The intention is to provide a base for a consistent environment across projects and browsers. 11 | 12 | In a future major version, consuming the reset will become mandatory for consumers of Source. 13 | 14 | We recommend adopting this reset today. 15 | 16 | ## Example 17 | 18 | ```tsx 19 | import { resets } from '@guardian/source-foundations'; 20 | 21 | const document = () => ( 22 | 23 | 24 | 25 | 26 | {/* … */} 27 | 28 | ); 29 | ``` 30 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/utils/resets.test.ts: -------------------------------------------------------------------------------- 1 | import { resets } from './resets'; 2 | 3 | test('resets.defaults should be valid CSS', () => { 4 | expect(resets.defaults).toBeValidCSS(); 5 | }); 6 | 7 | test('resets.fieldset should be a valid CSS fragment', () => { 8 | expect(resets.fieldset).toBeValidCSS({ isFragment: true }); 9 | }); 10 | 11 | test('resets.input should be an invalid CSS fragment', () => { 12 | // We add a test here so we don't forget to add/update a test 13 | // when this is converted to CSS in the future. 14 | expect(resets.input).not.toBeValidCSS({ isFragment: true }); 15 | }); 16 | 17 | test('resets.legend should be a valid CSS fragment', () => { 18 | expect(resets.legend).toBeValidCSS({ isFragment: true }); 19 | }); 20 | 21 | test('resets.resetCSS should be valid CSS', () => { 22 | expect(resets.resetCSS).toBeValidCSS(); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/utils/supports-queries.ts: -------------------------------------------------------------------------------- 1 | export const appearance = 2 | '(appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none)'; 3 | -------------------------------------------------------------------------------- /packages/@guardian/source-foundations/src/utils/svg-background-image.ts: -------------------------------------------------------------------------------- 1 | import svgToTinyDataUri from 'mini-svg-data-uri'; 2 | 3 | export const svgBackgroundImage = (svg: string): string => { 4 | return `url("${svgToTinyDataUri(svg.replace(/\s\s+/g, ' '))}")`; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## What does this change? 2 | 3 | - 4 | 5 | ## Checklist 6 | 7 | - [ ] This change captured in a [a story](https://storybook.js.org/docs/react/writing-stories/introduction) 8 | - [ ] A designer seen this change 9 | 10 | 11 | 12 | ## Screenshots 13 | 14 | ### Before 15 | 16 | ### After 17 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix kitchen-v 2 | version-git-message "@guardian/source-react-components-development-kitchen v%s" 3 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | }; 6 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/jest.e2e.setup.js: -------------------------------------------------------------------------------- 1 | // Mock `src/index` with whatever `package.json` points at. 2 | // This means we can run `src/index.test.ts` against `dist` instead. 3 | 4 | const dist = require('.'); 5 | 6 | jest.mock('./src/index', () => dist); 7 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@guardian/source-react-components-development-kitchen", 3 | "version": "7.0.0", 4 | "license": "Apache-2.0", 5 | "sideEffects": false, 6 | "main": "dist/cjs/index.js", 7 | "module": "dist/esm/index.js", 8 | "files": [ 9 | "dist" 10 | ], 11 | "scripts": { 12 | "build": "rollup -c", 13 | "clean": "rm -rf dist", 14 | "test": "jest --coverage", 15 | "e2e": "jest src/index.test.ts --setupFilesAfterEnv=./jest.e2e.setup.js" 16 | }, 17 | "devDependencies": { 18 | "mini-svg-data-uri": "^1.3.3", 19 | "npm-run-all": "^4.1.5", 20 | "rollup": "^2.75.4", 21 | "rollup-plugin-ts": "^2.0.7", 22 | "tslib": "^2.4.0", 23 | "web-vitals": "^2.0.0" 24 | }, 25 | "peerDependencies": { 26 | "@emotion/react": "^11.0.0", 27 | "@guardian/libs": "^9.0.0", 28 | "@guardian/source-foundations": "^7.0.0", 29 | "@guardian/source-react-components": "^9.0.0", 30 | "react": "^17.0.1" 31 | }, 32 | "publishConfig": { 33 | "access": "public" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/rollup.config.js: -------------------------------------------------------------------------------- 1 | import ts from 'rollup-plugin-ts'; 2 | import pkg from './package.json'; 3 | 4 | const bundle = (config) => ({ 5 | ...config, 6 | input: 'src/index.ts', 7 | external: (id) => !/^[./]/.test(id), 8 | }); 9 | 10 | // eslint-disable-next-line import/no-default-export -- it's what rollup wants 11 | export default [ 12 | bundle({ 13 | plugins: [ts({ tsconfig: '../../../tsconfig.json' })], 14 | output: [ 15 | { 16 | dir: pkg.main.replace('/index.js', ''), 17 | format: 'cjs', 18 | sourcemap: true, 19 | preserveModules: true, 20 | }, 21 | { 22 | dir: pkg.module.replace('/index.js', ''), 23 | format: 'es', 24 | sourcemap: true, 25 | preserveModules: true, 26 | }, 27 | ], 28 | }), 29 | ]; 30 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/divider/README.md: -------------------------------------------------------------------------------- 1 | # `Divider` 2 | 3 | Inserts a line on the page acting as a section break dividing content 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-divider--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/divider/styles.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | 3 | export const fullStyles = css` 4 | margin-left: -10px; 5 | width: calc(100% + 20px); 6 | `; 7 | export const partialStyles = css` 8 | margin-left: -10px; 9 | width: 160px; 10 | `; 11 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/editorial-button/README.md: -------------------------------------------------------------------------------- 1 | # EditorialButton 2 | 3 | This is the editorial version of the core `Button` coomponent. This editorial version 4 | requires the `format` prop and uses that to override `Button` styles based on 5 | `format.theme` 6 | 7 | Also exported is `EditorialLinkButton` which, like in core, offers a href version of the buttom 8 | 9 | ## Install 10 | 11 | ```sh 12 | $ yarn add @guardian/source-react-components-development-kitchen 13 | ``` 14 | 15 | or 16 | 17 | ```sh 18 | $ npm i @guardian/source-react-components-development-kitchen 19 | ``` 20 | 21 | ## Use 22 | 23 | ### API 24 | 25 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-editorial-button--playground) 26 | 27 | ### How to use 28 | 29 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design/2a1e5182b/p/435225-button). 30 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/editorial-button/types.ts: -------------------------------------------------------------------------------- 1 | import type { ArticleFormat } from '@guardian/libs'; 2 | 3 | export interface SharedEditorialButtonProps { 4 | /** 5 | * A format object denoting the style of the button using the enums 6 | * available from [@guardian/libs](https://github.com/guardian/libs/blob/main/src/format.ts). 7 | * 8 | * For example: 9 | * 10 | * ```ts 11 | * { 12 | * display: Display.Standard, 13 | * design: Design.Article, 14 | * theme: Pillar.News, 15 | * } 16 | * ``` 17 | */ 18 | format?: ArticleFormat; 19 | } 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/expanding-wrapper/README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | The Expanding Wrapper wraps around any children, and collapses the block so it takes up less space on screen. The children can be expanded via a 'Show More' button, and collapsed again via a 'Show Less' Button. Additional content can be rendered inline with the show/hide button. 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | #### `ExpandingWrapper` 22 | 23 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-expanding-wrapper--playground) 24 | 25 | ### How to use 26 | 27 | For context and visual guides relating to usage see the [Source Design System website](https://www.theguardian.design/2a1e5182b/p/108ed3-user-feedback/b/3803b4/t/08c895). 28 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/expanding-wrapper/theme.ts: -------------------------------------------------------------------------------- 1 | import type { Theme as EmotionTheme } from '@emotion/react'; 2 | import { palette } from '@guardian/source-foundations'; 3 | 4 | export const expandingWrapperThemeDefault = { 5 | expander: { 6 | border: palette.neutral[86], 7 | expandBackground: palette.neutral[7], 8 | expandText: palette.neutral[100], 9 | collapseBackground: palette.neutral[100], 10 | collapseText: palette.neutral[7], 11 | }, 12 | }; 13 | export const expandingWrapperDarkTheme = { 14 | expander: { 15 | border: palette.neutral[60], 16 | expandBackground: palette.neutral[86], 17 | expandText: palette.neutral[7], 18 | collapseBackground: palette.neutral[10], 19 | collapseText: palette.neutral[86], 20 | }, 21 | }; 22 | 23 | export interface Theme extends EmotionTheme { 24 | expander?: typeof expandingWrapperThemeDefault.expander; 25 | } 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/expanding-wrapper/types.ts: -------------------------------------------------------------------------------- 1 | import type { ReactElement } from 'react'; 2 | 3 | export interface ExpandingWrapperProps { 4 | children: ReactElement; 5 | name: string; 6 | disableTabbingWhenCollapsed?: boolean; 7 | renderExtra?: () => ReactElement; 8 | expandCallback?: (expanded: boolean) => void; 9 | } 10 | 11 | export type TabbableElementType = 12 | | HTMLInputElement 13 | | HTMLTextAreaElement 14 | | HTMLSelectElement 15 | | HTMLButtonElement 16 | | HTMLAnchorElement; 17 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/footer-with-contents/FooterLinks.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { FooterLinksProps } from './FooterLinks'; 3 | import { defaultGuardianLinks, FooterLinks } from './FooterLinks'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components-development-kitchen/FooterLinks', 7 | component: FooterLinks, 8 | parameters: { 9 | layout: 'fullscreen', 10 | }, 11 | }; 12 | 13 | const Template: Story = (args: FooterLinksProps) => ( 14 | 15 | ); 16 | 17 | // ***************************************************************************** 18 | 19 | export const DefaultFooterLinks = Template.bind({}); 20 | 21 | // ***************************************************************************** 22 | 23 | export const FooterLinksInColumns = Template.bind({}); 24 | FooterLinksInColumns.args = { 25 | links: [ 26 | ...defaultGuardianLinks, 27 | { 28 | href: '/', 29 | text: 'About us', 30 | }, 31 | ], 32 | }; 33 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/footer-with-contents/FooterWithContents.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import { 3 | DefaultFooterLinks, 4 | FooterLinksInColumns, 5 | } from './FooterLinks.stories'; 6 | import type { FooterWithContentsProps } from './FooterWithContents'; 7 | import { FooterWithContents } from './FooterWithContents'; 8 | 9 | export default { 10 | title: 11 | 'Packages/source-react-components-development-kitchen/FooterWithContents', 12 | component: FooterWithContents, 13 | parameters: { 14 | layout: 'fullscreen', 15 | }, 16 | }; 17 | 18 | const Template: Story = ( 19 | args: FooterWithContentsProps, 20 | ) => ; 21 | 22 | // ***************************************************************************** 23 | 24 | export const DefaultFooterWithContents = Template.bind({}); 25 | DefaultFooterWithContents.args = { 26 | children: , 27 | }; 28 | 29 | // ***************************************************************************** 30 | 31 | export const FooterWithColumnLinks = Template.bind({}); 32 | FooterWithColumnLinks.args = { 33 | children: , 34 | }; 35 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/footer-with-contents/README.md: -------------------------------------------------------------------------------- 1 | # `Footer With Contents` 2 | 3 | A footer component that can have content added inside of it, and a footer links component to be used to display links within the footer. 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-divider--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/footer-with-contents/footerWithContentsStyles.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | import { 3 | brand, 4 | from, 5 | neutral, 6 | space, 7 | textSans, 8 | } from '@guardian/source-foundations'; 9 | 10 | export const footer = css` 11 | background-color: ${brand[400]}; 12 | color: ${neutral[100]}; 13 | padding-bottom: ${space[1]}px; 14 | ${textSans.medium()}; 15 | `; 16 | 17 | export const contentWrapperStyles = css` 18 | display: flex; 19 | position: relative; 20 | `; 21 | 22 | export const copyrightStyles = css` 23 | display: block; 24 | ${textSans.xxsmall()}; 25 | padding-top: ${space[6]}px; 26 | padding-bottom: 18px; 27 | ${from.tablet} { 28 | padding-top: ${space[3]}px; 29 | } 30 | `; 31 | 32 | export const backToTopStyles = css` 33 | background-color: ${brand[400]}; 34 | padding: 0 ${space[2]}px; 35 | position: absolute; 36 | bottom: -21px; 37 | right: ${space[3]}px; 38 | ${from.tablet} { 39 | padding: 0 5px; 40 | right: 0; 41 | } 42 | `; 43 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import * as pkgExports from './index'; 2 | 3 | // this makes sure no type exports have been removed 4 | // it won't catch that new ones have been added, but can anyone? 5 | export type { 6 | EditorialButtonProps, 7 | EditorialLinkButtonProps, 8 | ExpandingWrapperProps, 9 | FooterLinksProps, 10 | FooterWithContentsProps, 11 | LineCount, 12 | LinesProps, 13 | LogoProps, 14 | NumericInput, 15 | NumericInputProps, 16 | HeadlineSize, 17 | QuoteIconProps, 18 | StarRatingProps, 19 | ToggleSwitchProps, 20 | ToggleSwitchAppsProps, 21 | } from './index'; 22 | 23 | it('Should have exactly these exports', () => { 24 | expect(Object.keys(pkgExports).sort()).toEqual([ 25 | 'DashedLines', 26 | 'Divider', 27 | 'DottedLines', 28 | 'EditorialButton', 29 | 'EditorialLinkButton', 30 | 'ErrorSummary', 31 | 'ExpandingWrapper', 32 | 'FooterLinks', 33 | 'FooterWithContents', 34 | 'InfoSummary', 35 | 'Lines', 36 | 'Logo', 37 | 'NumericInput', 38 | 'QuoteIcon', 39 | 'SquigglyLines', 40 | 'StarRating', 41 | 'StraightLines', 42 | 'SuccessSummary', 43 | 'ToggleSwitch', 44 | 'ToggleSwitchApps', 45 | 'defaultGuardianLinks', 46 | ]); 47 | }); 48 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/lines/README.md: -------------------------------------------------------------------------------- 1 | # Lines 2 | 3 | 📣 For more context and visual guides relating to lines usage, visit the [Source Design System website](https://www.theguardian.design) 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-lines--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://www.theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/logo/README.md: -------------------------------------------------------------------------------- 1 | # QuoteIcon 2 | 3 | The Guardian logo appears in the header on most editorial pages 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-logo--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/numeric-input/InputExtension.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | inputExtension, 3 | inputPrefix, 4 | inputSuffix, 5 | } from './inputExtensionStyles'; 6 | import type { InputTheme } from './NumericInput'; 7 | import { errorInput, successInput } from './sharedStyles'; 8 | 9 | type InputExtensionProps = { 10 | children: string; 11 | type: 'prefix' | 'suffix'; 12 | error?: string; 13 | success?: string; 14 | }; 15 | 16 | export const InputExtension = ({ 17 | children, 18 | type, 19 | error, 20 | success, 21 | }: InputExtensionProps) => { 22 | const style = type === 'prefix' ? inputPrefix : inputSuffix; 23 | 24 | return ( 25 | 36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/numeric-input/README.md: -------------------------------------------------------------------------------- 1 | # `Numeric Input` 2 | 3 | A component for taking numeric input such as currency. Can display a prefix and/or suffix to add visual context for the user. 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-numericinput--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/numeric-input/inputExtensionStyles.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | import { space } from '@guardian/source-foundations'; 3 | import { textInputThemeDefault } from '@guardian/source-react-components'; 4 | import { inputBase } from './sharedStyles'; 5 | 6 | export const inputExtension = (input = textInputThemeDefault.textInput) => css` 7 | ${inputBase(input)} 8 | display: inline-flex; 9 | align-items: center; 10 | `; 11 | 12 | export const inputPrefix = css` 13 | padding-right: ${space[1]}px; 14 | border-right: none; 15 | `; 16 | 17 | export const inputSuffix = css` 18 | padding-left: ${space[1]}px; 19 | border-left: none; 20 | `; 21 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/quote-icon/README.md: -------------------------------------------------------------------------------- 1 | # QuoteIcon 2 | 3 | The Guardian quote icon is used in kickers, headlines, drop caps and pull quotes to denote quoted text. 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-quote-icon--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/star-rating/README.md: -------------------------------------------------------------------------------- 1 | # StarRating 2 | 3 | Displays a rating, 1-5, using star SVGs. See the accompanying stories for visual examples. 4 | 5 | 📣 For more context and visual guides relating to `StarRating` usage, visit the [Source Design System website](https://www.theguardian.design). 6 | 7 | ## Install 8 | 9 | ```sh 10 | $ yarn add @guardian/source-react-components-development-kitchen 11 | ``` 12 | 13 | or 14 | 15 | ```sh 16 | $ npm i @guardian/source-react-components-development-kitchen 17 | ``` 18 | 19 | ## Use 20 | 21 | ### API 22 | 23 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-star-rating--playground) 24 | 25 | ### How to use 26 | 27 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 28 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/summary/ErrorSummary.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { error as errorColors } from '@guardian/source-foundations'; 3 | import { SvgAlertTriangle } from '@guardian/source-react-components'; 4 | import { 5 | contextStyles, 6 | iconStyles, 7 | messageStyles, 8 | messageWrapperStyles, 9 | wrapperStyles, 10 | } from './styles'; 11 | import type { SummaryProps } from './types'; 12 | 13 | export interface ErrorSummaryProps extends SummaryProps { 14 | /** 15 | * The error report link URL 16 | */ 17 | errorReportUrl?: string; 18 | } 19 | 20 | export const ErrorSummary = ({ 21 | message, 22 | errorReportUrl, 23 | context, 24 | cssOverrides, 25 | ...props 26 | }: ErrorSummaryProps): EmotionJSX.Element => ( 27 |
28 |
29 | 30 |
31 |
32 |
{message}
33 | {errorReportUrl && ( 34 | 35 | Report this error 36 | 37 | )} 38 | {context &&
{context}
} 39 |
40 |
41 | ); 42 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/summary/InfoSummary.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { brand as brandColors, text } from '@guardian/source-foundations'; 3 | import { SvgInfo } from '@guardian/source-react-components'; 4 | import { 5 | contextStyles, 6 | iconStyles, 7 | messageStyles, 8 | messageWrapperStyles, 9 | wrapperStyles, 10 | } from './styles'; 11 | import type { SummaryProps } from './types'; 12 | 13 | export type InfoSummaryProps = SummaryProps; 14 | 15 | export const InfoSummary = ({ 16 | message, 17 | context, 18 | cssOverrides, 19 | ...props 20 | }: InfoSummaryProps): EmotionJSX.Element => ( 21 |
22 |
23 | 24 |
25 |
26 |
{message}
27 | {context &&
{context}
} 28 |
29 |
30 | ); 31 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/summary/README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | Summary messages appear at the top of a group of content to summarise any actions that the user has taken or errors that have occurred. 4 | 5 | There are three components available, `ErrorSummary`, `SuccessSummary`, and `InfoSummary`. 6 | 7 | ## Install 8 | 9 | ```sh 10 | $ yarn add @guardian/source-react-components-development-kitchen 11 | ``` 12 | 13 | or 14 | 15 | ```sh 16 | $ npm i @guardian/source-react-components-development-kitchen 17 | ``` 18 | 19 | ## Use 20 | 21 | ### API 22 | 23 | #### `ErrorSummary` 24 | 25 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-error-summary--playground) 26 | 27 | #### `Success Summary` 28 | 29 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-success-summary--playground) 30 | 31 | #### `Info Summary` 32 | 33 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-info-summary--playground) 34 | 35 | ### How to use 36 | 37 | For context and visual guides relating to usage see the [Source Design System website](https://www.theguardian.design/2a1e5182b/p/108ed3-user-feedback/b/3803b4/t/08c895). 38 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/summary/SuccessSummary.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { success as successColors } from '@guardian/source-foundations'; 3 | import { SvgTickRound } from '@guardian/source-react-components'; 4 | import { 5 | contextStyles, 6 | iconStyles, 7 | messageStyles, 8 | messageWrapperStyles, 9 | wrapperStyles, 10 | } from './styles'; 11 | import type { SummaryProps } from './types'; 12 | 13 | export type SuccessSummaryProps = SummaryProps; 14 | 15 | export const SuccessSummary = ({ 16 | message, 17 | context, 18 | cssOverrides, 19 | ...props 20 | }: SuccessSummaryProps): EmotionJSX.Element => ( 21 |
22 |
23 | 24 |
25 |
26 |
{message}
27 | {context &&
{context}
} 28 |
29 |
30 | ); 31 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/summary/styles.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | import { css } from '@emotion/react'; 3 | import { size, space, textSans } from '@guardian/source-foundations'; 4 | 5 | export const wrapperStyles = (color: string): SerializedStyles => css` 6 | border: 4px solid ${color}; 7 | padding: ${space[1]}px; 8 | 9 | display: flex; 10 | `; 11 | 12 | export const iconStyles = (color: string): SerializedStyles => css` 13 | display: flex; 14 | flex: 0 1 auto; 15 | margin-top: 1px; 16 | svg { 17 | fill: ${color}; 18 | height: ${size.xsmall}px; 19 | width: ${size.xsmall}px; 20 | } 21 | `; 22 | 23 | export const messageStyles = ( 24 | color: string, 25 | isBold = true, 26 | ): SerializedStyles => css` 27 | ${textSans.medium({ 28 | fontWeight: isBold ? 'bold' : 'regular', 29 | lineHeight: 'loose', 30 | })} 31 | color: ${color}; 32 | `; 33 | 34 | export const messageWrapperStyles = css` 35 | margin-left: ${space[1]}px; 36 | `; 37 | 38 | export const contextStyles = css` 39 | ${textSans.medium()} 40 | `; 41 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/summary/types.ts: -------------------------------------------------------------------------------- 1 | import type { Props } from '@guardian/source-react-components'; 2 | 3 | export interface SummaryProps extends Props { 4 | /** 5 | * The main message of the component 6 | * e.g. the main error message, success message etc. 7 | */ 8 | message: React.ReactNode; 9 | /** 10 | * Optional context information about the message 11 | */ 12 | context?: React.ReactNode; 13 | } 14 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/toggle-switch-apps/README.md: -------------------------------------------------------------------------------- 1 | # ToggleSwitchApps 2 | 3 | Displays an on/off switch for use in apps web views. See the accompanying stories for visual examples. 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-toggle-switch-apps--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components-development-kitchen/src/toggle-switch/README.md: -------------------------------------------------------------------------------- 1 | # ToggleSwitch 2 | 3 | Displays an on/off switch for web. See the accompanying stories for visual examples. 4 | 5 | ## Install 6 | 7 | ```sh 8 | $ yarn add @guardian/source-react-components-development-kitchen 9 | ``` 10 | 11 | or 12 | 13 | ```sh 14 | $ npm i @guardian/source-react-components-development-kitchen 15 | ``` 16 | 17 | ## Use 18 | 19 | ### API 20 | 21 | See [storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-development-kitchen-toggle-switch--playground) 22 | 23 | ### How to use 24 | 25 | For context and visual guides relating to usage see the [Source Design System website](https://theguardian.design). 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix source-react-components-v 2 | version-git-message "@guardian/source-react-components v%s" 3 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | }; 6 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/jest.e2e.setup.js: -------------------------------------------------------------------------------- 1 | // Mock `src/index` with whatever `package.json` points at. 2 | // This means we can run `src/index.test.ts` against `dist` instead. 3 | 4 | const dist = require('.'); 5 | 6 | jest.mock('./src/index', () => dist); 7 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@guardian/source-react-components", 3 | "version": "9.1.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/guardian/source.git" 7 | }, 8 | "license": "Apache-2.0", 9 | "sideEffects": false, 10 | "main": "dist/cjs/src/index.js", 11 | "module": "dist/esm/src/index.js", 12 | "files": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "build": "rollup -c", 17 | "clean": "rm -rf dist", 18 | "create-icons": "ts-node scripts/create-icons", 19 | "e2e": "jest src/index.test.ts --setupFilesAfterEnv=./jest.e2e.setup.js", 20 | "test": "jest --coverage" 21 | }, 22 | "devDependencies": { 23 | "@rollup/plugin-node-resolve": "^13.3.0", 24 | "@svgr/babel-preset": "^6.3.1", 25 | "@svgr/core": "^6.3.1", 26 | "@svgr/plugin-jsx": "^6.3.1", 27 | "@svgr/plugin-prettier": "^6.3.1", 28 | "@svgr/plugin-svgo": "^6.3.1", 29 | "@types/mkdirp": "^1.0.2", 30 | "@types/svgo": "^2.6.3", 31 | "axios": "^0.27.2", 32 | "mkdirp": "^1.0.4", 33 | "rollup": "^2.77.2", 34 | "rollup-plugin-ts": "^2.0.7", 35 | "ts-node": "^10.7.0" 36 | }, 37 | "peerDependencies": { 38 | "@emotion/react": "^11.0.0", 39 | "@guardian/source-foundations": "^7.0.0", 40 | "react": "^17.0.1" 41 | }, 42 | "publishConfig": { 43 | "access": "public" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from '@rollup/plugin-node-resolve'; 2 | import ts from 'rollup-plugin-ts'; 3 | import pkg from './package.json'; 4 | 5 | const external = ['@guardian/source-foundations', 'react', /@emotion\/react/]; 6 | 7 | // eslint-disable-next-line import/no-default-export -- it's what rollup wants 8 | export default [ 9 | { 10 | input: 'src/index.ts', 11 | output: [ 12 | { 13 | dir: pkg.main.replace('/src/index.js', ''), 14 | format: 'cjs', 15 | sourcemap: true, 16 | preserveModules: true, 17 | }, 18 | { 19 | dir: pkg.module.replace('/src/index.js', ''), 20 | format: 'es', 21 | sourcemap: true, 22 | preserveModules: true, 23 | }, 24 | ], 25 | external, 26 | plugins: [ 27 | nodeResolve({ extensions: ['.ts', '.tsx', '.mjs', '.jsx', '.js'] }), 28 | ts({ tsconfig: '../../../tsconfig.json' }), 29 | ], 30 | }, 31 | ]; 32 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/scripts/README.md: -------------------------------------------------------------------------------- 1 | # `@guardian/source-react-components` scripts 2 | 3 | ## `create-icons` 4 | 5 | Pulls the SVG source of icons from Figma and generates react components from them using [SVGR](https://github.com/gregberge/svgr). 6 | 7 | Run the script using the following command: 8 | 9 | ```sh 10 | yarn workspace @guardian/source-react-components create-icons 11 | ``` 12 | 13 | It requires a Personal Access Token (PAT) to authenticate against the Figma API. 14 | 15 | 1. [Create a token](https://www.figma.com/developers/api#access-tokens) 16 | 2. Create an environment variable called `FIGMA_TOKEN`, using the token as the value. 17 | 18 | _Note:_ The script does not run as part of the build process to ensure we don't inadvertently pick up changes to icons as part of an unrelated change. 19 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/scripts/create-icons/create-readme.ts: -------------------------------------------------------------------------------- 1 | import { ICON_FILE } from './get-svgs-from-figma'; 2 | 3 | export const createReadme = () => `# Icons 4 | 5 | **The contents of this directory are created automatically. Any edits will be 6 | overwritten sooner or later.** 7 | 8 | The SVGs for these icons are automatically pulled in from the [source design file in 9 | Figma](https://www.figma.com/file/${ICON_FILE}/%E2%97%90-Icons?node-id=55%3A2) 10 | using the create-icons script via the Figma API: 11 | 12 | \`\`\`sh 13 | yarn workspace @guardian/source-react-components create-icons 14 | \`\`\` 15 | `; 16 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/scripts/vendor/icons/README.md: -------------------------------------------------------------------------------- 1 | # Icons 2 | 3 | **The contents of this directory are created automatically. Any edits will be 4 | overwritten sooner or later.** 5 | 6 | The SVGs for these icons are automatically pulled in from the [source design file in 7 | Figma](https://www.figma.com/file/Ai7AELHC6KCz38qKZkvuHo/%E2%97%90-Icons?node-id=55%3A2) 8 | using the fetch-icons script via the Figma API: 9 | 10 | ```sh 11 | yarn workspace @guardian/source-react-components create-icons 12 | ``` 13 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/@types/Icons.ts: -------------------------------------------------------------------------------- 1 | export type IconSize = 'xsmall' | 'small' | 'medium'; 2 | 3 | export interface IconProps { 4 | size?: IconSize; 5 | isAnnouncedByScreenReader?: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/@types/Props.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | 3 | export interface Props { 4 | className?: string; 5 | /** 6 | * Override component styles by passing in the result of [emotion's `css` function/prop](https://emotion.sh/docs/introduction). 7 | */ 8 | cssOverrides?: SerializedStyles | SerializedStyles[]; 9 | } 10 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/@types/ThemeName.ts: -------------------------------------------------------------------------------- 1 | export type ThemeName = 'default' | 'brand' | 'brandAlt'; 2 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/accordion/Accordion.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { AccordionProps } from './Accordion'; 3 | import { Accordion } from './Accordion'; 4 | import { AccordionRow } from './AccordionRow'; 5 | 6 | export default { 7 | title: 'Packages/source-react-components/Accordion', 8 | component: Accordion, 9 | subcomponents: { AccordionRow }, 10 | args: { 11 | hideToggleLabel: false, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: AccordionProps) => ( 16 | 17 | 18 | Present your card to a newsagent each time you collect the paper. The 19 | newsagent will scan your card and will be reimbursed for each transaction 20 | automatically. 21 | 22 | 23 | Simply give your preferred store / retailer the barcode printed on your 24 | subscription letter. 25 | 26 | 27 | ); 28 | 29 | export const WithCTALabelsDefaultTheme = Template.bind({}); 30 | 31 | // ***************************************************************************** 32 | 33 | export const WithoutCTALabelsDefaultTheme = Template.bind({}); 34 | WithoutCTALabelsDefaultTheme.args = { 35 | hideToggleLabel: true, 36 | }; 37 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/accordion/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | 3 | export const accordionThemeDefault = { 4 | accordion: { 5 | textPrimary: palette.neutral[7], 6 | borderPrimary: palette.neutral[60], 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgGuardianBestWebsiteLogo.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgGuardianBestWebsiteLogoProps } from './SvgGuardianBestWebsiteLogo'; 3 | import { SvgGuardianBestWebsiteLogo } from './SvgGuardianBestWebsiteLogo'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgGuardianBestWebsiteLogo', 7 | component: SvgGuardianBestWebsiteLogo, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgGuardianBestWebsiteLogoProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgGuardianLiveLogo.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgGuardianLiveLogoProps } from './SvgGuardianLiveLogo'; 3 | import { SvgGuardianLiveLogo } from './SvgGuardianLiveLogo'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgGuardianLiveLogo', 7 | component: SvgGuardianLiveLogo, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgGuardianLiveLogoProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgGuardianLogo.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgGuardianLogoProps } from './SvgGuardianLogo'; 3 | import { SvgGuardianLogo } from './SvgGuardianLogo'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgGuardianLogo', 7 | component: SvgGuardianLogo, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgGuardianLogoProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelBrand.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgRoundelBrandProps } from './SvgRoundelBrand'; 3 | import { SvgRoundelBrand } from './SvgRoundelBrand'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgRoundelBrand', 7 | component: SvgRoundelBrand, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgRoundelBrandProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelBrand.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { brand } from '@guardian/source-foundations'; 3 | import { SvgRoundel } from './SvgRoundel'; 4 | 5 | export type SvgRoundelBrandProps = { 6 | /** 7 | * The width the SVG will display at (height is automatically adjusted 8 | * to maintain the correct aspect ratio). 9 | */ 10 | width?: number; 11 | }; 12 | 13 | /** 14 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-svgroundelbrand--playground) • 15 | * [Design System](https://theguardian.design/2a1e5182b/p/8909e0-assets/t/37168b) • 16 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/brand/SvgRoundelBrand.tsx) • 17 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components) 18 | */ 19 | export const SvgRoundelBrand = ( 20 | args: SvgRoundelBrandProps, 21 | ): EmotionJSX.Element => { 22 | return ( 23 | 24 | ); 25 | }; 26 | SvgRoundelBrand.args = { 27 | width: 300, 28 | }; 29 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelBrandInverse.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgRoundelBrandInverseProps } from './SvgRoundelBrandInverse'; 3 | import { SvgRoundelBrandInverse } from './SvgRoundelBrandInverse'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgRoundelBrandInverse', 7 | component: SvgRoundelBrandInverse, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgRoundelBrandInverseProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelBrandInverse.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { brand } from '@guardian/source-foundations'; 3 | import { SvgRoundel } from './SvgRoundel'; 4 | 5 | export type SvgRoundelBrandInverseProps = { 6 | /** 7 | * The width the SVG will display at (height is automatically adjusted 8 | * to maintain the correct aspect ratio). 9 | */ 10 | width?: number; 11 | }; 12 | 13 | /** 14 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-svgroundelbrandinverse--playground) • 15 | * [Design System](https://theguardian.design/2a1e5182b/p/8909e0-assets/t/37168b) • 16 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/brand/SvgRoundelBrandInverse.tsx) • 17 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components) 18 | */ 19 | export const SvgRoundelBrandInverse = ( 20 | args: SvgRoundelBrandInverseProps, 21 | ): EmotionJSX.Element => { 22 | return ( 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelDefault.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgRoundelDefaultProps } from './SvgRoundelDefault'; 3 | import { SvgRoundelDefault } from './SvgRoundelDefault'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgRoundelDefault', 7 | component: SvgRoundelDefault, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgRoundelDefaultProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelDefault.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { neutral } from '@guardian/source-foundations'; 3 | import { SvgRoundel } from './SvgRoundel'; 4 | 5 | export type SvgRoundelDefaultProps = { 6 | /** 7 | * The width the SVG will display at (height is automatically adjusted 8 | * to maintain the correct aspect ratio). 9 | */ 10 | width?: number; 11 | }; 12 | 13 | /** 14 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-svgroundeldefault--playground) • 15 | * [Design System](https://theguardian.design/2a1e5182b/p/8909e0-assets/t/37168b) • 16 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/brand/SvgRoundelDefault.tsx) • 17 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components) 18 | */ 19 | export const SvgRoundelDefault = ( 20 | args: SvgRoundelDefaultProps, 21 | ): EmotionJSX.Element => { 22 | return ( 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelInverse.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import type { SvgRoundelInverseProps } from './SvgRoundelInverse'; 3 | import { SvgRoundelInverse } from './SvgRoundelInverse'; 4 | 5 | export default { 6 | title: 'Packages/source-react-components/SvgRoundelInverse', 7 | component: SvgRoundelInverse, 8 | argTypes: { 9 | width: { 10 | control: { type: 'range', min: 10, max: 600 }, 11 | }, 12 | }, 13 | }; 14 | 15 | const Template: Story = (args: SvgRoundelInverseProps) => ( 16 | 17 | ); 18 | 19 | export const Default = Template.bind({}); 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/SvgRoundelInverse.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { neutral } from '@guardian/source-foundations'; 3 | import { SvgRoundel } from './SvgRoundel'; 4 | 5 | export type SvgRoundelInverseProps = { 6 | /** 7 | * The width the SVG will display at (height is automatically adjusted 8 | * to maintain the correct aspect ratio). 9 | */ 10 | width?: number; 11 | }; 12 | 13 | /** 14 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-svgroundelinverse--playground) • 15 | * [Design System](https://theguardian.design/2a1e5182b/p/8909e0-assets/t/37168b) • 16 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/brand/SvgRoundelInverse.tsx) • 17 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components) 18 | */ 19 | export const SvgRoundelInverse = ( 20 | args: SvgRoundelInverseProps, 21 | ): EmotionJSX.Element => { 22 | return ( 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/114x114-roundel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/114x114-roundel.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/114x114.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/120x120.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/144x144.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/152x152-roundel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/152x152-roundel.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/152x152.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/32x32-dev.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/32x32-dev.ico -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/32x32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/32x32.ico -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/57x57.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/brand/favicons/72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guardian/source/d84c25d67ed51545994f53986eb4487d35c1aab4/packages/@guardian/source-react-components/src/brand/favicons/72x72.png -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/checkbox/LabelText.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import type { ReactNode } from 'react'; 3 | import type { Theme } from '../@types/Theme'; 4 | import { labelText, labelTextWithSupportingText } from './styles'; 5 | 6 | export const LabelText = ({ 7 | hasSupportingText, 8 | children, 9 | }: { 10 | hasSupportingText?: boolean; 11 | children: ReactNode; 12 | }): EmotionJSX.Element => { 13 | return ( 14 |
[ 16 | labelText(theme.checkbox), 17 | hasSupportingText ? labelTextWithSupportingText : '', 18 | ]} 19 | > 20 | {children} 21 |
22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/checkbox/SupportingText.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import type { ReactNode } from 'react'; 3 | import type { Theme } from '../@types/Theme'; 4 | import { supportingText } from './styles'; 5 | 6 | export const SupportingText = ({ 7 | children, 8 | }: { 9 | children: ReactNode; 10 | }): EmotionJSX.Element => { 11 | return ( 12 |
supportingText(theme.checkbox)}>{children}
13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/checkbox/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | import { labelThemeBrand, labelThemeDefault } from '../label/theme'; 3 | import { 4 | userFeedbackThemeBrand, 5 | userFeedbackThemeDefault, 6 | } from '../user-feedback/theme'; 7 | 8 | export const checkboxThemeDefault = { 9 | checkbox: { 10 | border: palette.neutral[46], 11 | borderHover: palette.brand[500], 12 | borderChecked: palette.brand[500], 13 | borderError: palette.error[400], 14 | backgroundChecked: palette.brand[500], 15 | textLabel: palette.neutral[7], 16 | textLabelSupporting: palette.neutral[46], 17 | textIndeterminate: palette.neutral[46], 18 | }, 19 | ...userFeedbackThemeDefault, 20 | ...labelThemeDefault, 21 | }; 22 | 23 | export const checkboxThemeBrand = { 24 | checkbox: { 25 | border: palette.brand[800], 26 | borderHover: palette.neutral[100], 27 | borderChecked: palette.neutral[100], 28 | borderError: palette.error[500], 29 | backgroundChecked: palette.neutral[100], 30 | textLabel: palette.neutral[100], 31 | textLabelSupporting: palette.brand[800], 32 | textIndeterminate: palette.brand[800], 33 | }, 34 | ...userFeedbackThemeBrand, 35 | ...labelThemeBrand, 36 | }; 37 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/choice-card/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | import { userFeedbackThemeDefault } from '../user-feedback/theme'; 3 | 4 | export const choiceCardThemeDefault = { 5 | choiceCard: { 6 | textLabel: palette.neutral[46], 7 | textLabelSupporting: palette.neutral[46], 8 | textGroupLabel: palette.neutral[7], 9 | textGroupLabelSupporting: palette.neutral[46], 10 | border: palette.neutral[46], 11 | textChecked: palette.brand[400], 12 | backgroundChecked: '#E3F6FF', 13 | backgroundTick: palette.brand[500], 14 | borderChecked: palette.brand[500], 15 | textHover: palette.brand[400], 16 | borderHover: palette.brand[500], 17 | textError: palette.error[400], 18 | borderError: palette.error[400], 19 | }, 20 | ...userFeedbackThemeDefault, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/footer/BackToTop.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import { BackToTop } from './BackToTop'; 3 | 4 | export default { 5 | component: BackToTop, 6 | title: 'Packages/source-react-components/BackToTop', 7 | }; 8 | 9 | const Template: Story = () => BackToTop; 10 | 11 | export const Default = Template.bind({}); 12 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/footer/BackToTop.tsx: -------------------------------------------------------------------------------- 1 | import { SvgChevronUpSingle } from '../../vendor/icons/SvgChevronUpSingle'; 2 | import type { Theme } from '../@types/Theme'; 3 | import { backToTop, backToTopIcon } from './styles'; 4 | 5 | export const BackToTop = ( 6 | backToTop(theme.footer)}> 7 | Back to top 8 |
backToTopIcon(theme.footer)}> 9 | 10 |
11 |
12 | ); 13 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/footer/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | 3 | export const footerThemeBrand = { 4 | footer: { 5 | border: palette.brand[600], 6 | background: palette.brand[400], 7 | text: palette.neutral[100], 8 | anchor: palette.neutral[100], 9 | anchorHover: palette.brandAlt[400], 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/inline/Inline.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import type { HTMLAttributes } from 'react'; 3 | import type { Props } from '../@types/Props'; 4 | import { inline, inlineSpace } from './styles'; 5 | import type { InlineSpace } from './types'; 6 | 7 | export interface InlineProps extends HTMLAttributes, Props { 8 | /** 9 | * [Units of space](https://www.theguardian.design/2a1e5182b/p/449bd5-space) between inline items (one unit is 4px). 10 | */ 11 | space?: InlineSpace; 12 | } 13 | 14 | /** 15 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-inline) • 16 | * [Design System](https://theguardian.design/2a1e5182b/p/99f3c1-inline) • 17 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/inline/Inline.tsx) • 18 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components) 19 | * 20 | * `Inline` components will be laid out one next to the other. 21 | */ 22 | export const Inline = ({ 23 | cssOverrides, 24 | children, 25 | space, 26 | ...props 27 | }: InlineProps): EmotionJSX.Element => { 28 | return ( 29 |
33 | {children} 34 |
35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/inline/styles.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | import { css } from '@emotion/react'; 3 | import { space } from '@guardian/source-foundations'; 4 | import type { InlineSpace } from './types'; 5 | 6 | export const inline = css` 7 | display: flex; 8 | flex-wrap: wrap; 9 | `; 10 | 11 | const inlineSpaceStyle = (number: InlineSpace): SerializedStyles => css` 12 | margin-left: -${space[number]}px; 13 | & > * { 14 | margin-left: ${space[number]}px; 15 | margin-bottom: ${space[number]}px; 16 | } 17 | `; 18 | 19 | export const inlineSpace: { 20 | 1: SerializedStyles; 21 | 2: SerializedStyles; 22 | 3: SerializedStyles; 23 | 4: SerializedStyles; 24 | 5: SerializedStyles; 25 | 6: SerializedStyles; 26 | 9: SerializedStyles; 27 | 12: SerializedStyles; 28 | 24: SerializedStyles; 29 | } = { 30 | 1: inlineSpaceStyle(1), 31 | 2: inlineSpaceStyle(2), 32 | 3: inlineSpaceStyle(3), 33 | 4: inlineSpaceStyle(4), 34 | 5: inlineSpaceStyle(5), 35 | 6: inlineSpaceStyle(6), 36 | 9: inlineSpaceStyle(9), 37 | 12: inlineSpaceStyle(12), 38 | 24: inlineSpaceStyle(24), 39 | }; 40 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/inline/types.ts: -------------------------------------------------------------------------------- 1 | export type InlineSpace = 1 | 2 | 3 | 4 | 5 | 6 | 9 | 12 | 24; 2 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/label/SupportingText.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 3 | import { visuallyHidden as _visuallyHidden } from '@guardian/source-foundations'; 4 | import type { ReactNode } from 'react'; 5 | import type { Theme } from '../@types/Theme'; 6 | import { supportingText } from './styles'; 7 | 8 | const visuallyHidden = css` 9 | ${_visuallyHidden} 10 | `; 11 | 12 | export const SupportingText = ({ 13 | hideLabel, 14 | children, 15 | }: { 16 | hideLabel?: boolean; 17 | children: ReactNode; 18 | }): EmotionJSX.Element => { 19 | return ( 20 |

[ 22 | supportingText(theme.label), 23 | hideLabel ? visuallyHidden : '', 24 | ]} 25 | > 26 | {children} 27 |

28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/label/Text.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@emotion/react'; 2 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 3 | import { visuallyHidden as _visuallyHidden } from '@guardian/source-foundations'; 4 | import type { Theme } from '../@types/Theme'; 5 | import { labelText, optionalText } from './styles'; 6 | import type { LabelProps } from './types'; 7 | 8 | const visuallyHidden = css` 9 | ${_visuallyHidden} 10 | `; 11 | 12 | export const Text = ({ 13 | text, 14 | optional, 15 | hideLabel, 16 | }: LabelProps): EmotionJSX.Element => ( 17 |
[ 19 | labelText(theme.label), 20 | hideLabel ? visuallyHidden : '', 21 | ]} 22 | > 23 | {text}{' '} 24 | {optional ? ( 25 | optionalText(theme.label)}>Optional 26 | ) : ( 27 | '' 28 | )} 29 |
30 | ); 31 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/label/styles.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | import { css } from '@emotion/react'; 3 | import { resets, textSans } from '@guardian/source-foundations'; 4 | import { labelThemeDefault } from './theme'; 5 | 6 | export const legend = css` 7 | ${resets.legend}; 8 | `; 9 | 10 | export const labelText = ( 11 | label = labelThemeDefault.label, 12 | ): SerializedStyles => css` 13 | ${textSans.medium({ fontWeight: 'bold' })}; 14 | color: ${label.textLabel}; 15 | `; 16 | 17 | export const optionalText = ( 18 | label = labelThemeDefault.label, 19 | ): SerializedStyles => css` 20 | ${textSans.small()}; 21 | color: ${label.textOptional}; 22 | font-style: italic; 23 | `; 24 | 25 | export const supportingText = ( 26 | label = labelThemeDefault.label, 27 | ): SerializedStyles => css` 28 | ${textSans.small()}; 29 | color: ${label.textSupporting}; 30 | margin: 2px 0 0; 31 | `; 32 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/label/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | 3 | export const labelThemeDefault = { 4 | label: { 5 | textLabel: palette.neutral[7], 6 | textOptional: palette.neutral[46], 7 | textSupporting: palette.neutral[46], 8 | textError: palette.error[400], 9 | textSuccess: palette.success[400], 10 | }, 11 | }; 12 | 13 | export const labelThemeBrand = { 14 | label: { 15 | textLabel: palette.neutral[100], 16 | textOptional: palette.brand[800], 17 | textSupporting: palette.brand[800], 18 | textError: palette.error[500], 19 | textSuccess: palette.success[500], 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/label/types.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | import type { HTMLAttributes, LabelHTMLAttributes, ReactNode } from 'react'; 3 | import type { Props } from '../@types/Props'; 4 | 5 | export interface LabelProps 6 | extends LabelHTMLAttributes, 7 | Props { 8 | /** 9 | * The label text 10 | */ 11 | text: string; 12 | /** 13 | * Additional text or component that appears below the label 14 | */ 15 | supporting?: string; 16 | /** 17 | * Adds the word "Optional" after the label 18 | */ 19 | optional?: boolean; 20 | /** 21 | * Visually hides the label 22 | */ 23 | hideLabel?: boolean; 24 | cssOverrides?: SerializedStyles | SerializedStyles[]; 25 | children?: ReactNode; 26 | } 27 | 28 | export interface LegendProps extends HTMLAttributes, Props { 29 | /** 30 | * The label text 31 | */ 32 | text: string; 33 | /** 34 | * Additional text or component that appears below the label 35 | */ 36 | supporting?: string | JSX.Element; 37 | /** 38 | * Adds the word "Optional" after the label 39 | */ 40 | optional?: boolean; 41 | /** 42 | * Visually hides the label 43 | */ 44 | hideLabel?: boolean; 45 | cssOverrides?: SerializedStyles | SerializedStyles[]; 46 | } 47 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/link/shared.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactElement, ReactNode } from 'react'; 2 | import { cloneElement, Fragment } from 'react'; 3 | import type { IconSide } from './types'; 4 | 5 | export const linkContents = ({ 6 | children, 7 | iconSvg, 8 | iconSide, 9 | }: { 10 | children: ReactNode; 11 | iconSvg?: ReactElement; 12 | iconSide: IconSide; 13 | }): ReactNode[] => { 14 | // a bit of underlined space; the icon sits on top 15 | const spacer = ( 16 |        17 | ); 18 | const linkContents = [children]; 19 | 20 | if (iconSvg) { 21 | if (iconSide === 'left') { 22 | linkContents.unshift(spacer, cloneElement(iconSvg, { key: 'svg' })); 23 | } else { 24 | linkContents.push(spacer, cloneElement(iconSvg, { key: 'svg' })); 25 | } 26 | } 27 | 28 | return linkContents; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/link/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | 3 | export type LinkTheme = { 4 | textPrimary: string; 5 | textPrimaryHover: string; 6 | textSecondary?: string; 7 | textSecondaryHover?: string; 8 | }; 9 | 10 | export const linkThemeDefault: { link: LinkTheme } = { 11 | link: { 12 | textPrimary: palette.brand[500], 13 | textPrimaryHover: palette.brand[500], 14 | textSecondary: palette.neutral[7], 15 | textSecondaryHover: palette.neutral[7], 16 | }, 17 | }; 18 | 19 | export const linkThemeBrand: { link: LinkTheme } = { 20 | link: { 21 | textPrimary: palette.neutral[100], 22 | textPrimaryHover: palette.neutral[100], 23 | }, 24 | }; 25 | 26 | export const linkThemeBrandAlt: { link: LinkTheme } = { 27 | link: { 28 | textPrimary: palette.neutral[7], 29 | textPrimaryHover: palette.neutral[7], 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/link/types.ts: -------------------------------------------------------------------------------- 1 | import type { ReactElement, ReactNode } from 'react'; 2 | import type { Props } from '../@types/Props'; 3 | 4 | export type LinkPriority = 'primary' | 'secondary'; 5 | 6 | export type IconSide = 'left' | 'right'; 7 | 8 | export interface SharedLinkProps extends Props { 9 | /** 10 | * Informs users of how important a link is 11 | */ 12 | priority?: LinkPriority; 13 | /** 14 | * Whether link is subdued (no underline) 15 | * 16 | * @deprecated Subdued styling has been removed and no longer gets applied 17 | */ 18 | subdued?: boolean; 19 | /** 20 | * An icon that appears in the link, alongside text 21 | */ 22 | icon?: ReactElement; 23 | /** 24 | * The side of the link on which the icon appears 25 | */ 26 | iconSide?: IconSide; 27 | children?: ReactNode; 28 | } 29 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/radio/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | import { labelThemeBrand, labelThemeDefault } from '../label/theme'; 3 | import { 4 | userFeedbackThemeBrand, 5 | userFeedbackThemeDefault, 6 | } from '../user-feedback/theme'; 7 | 8 | export const radioThemeDefault = { 9 | radio: { 10 | borderHover: palette.focus[400], 11 | border: palette.neutral[60], 12 | backgroundChecked: palette.focus[400], 13 | textLabel: palette.neutral[7], 14 | textLabelSupporting: palette.neutral[46], 15 | borderError: palette.error[400], 16 | }, 17 | ...labelThemeDefault, 18 | ...userFeedbackThemeDefault, 19 | }; 20 | 21 | export const radioThemeBrand = { 22 | radio: { 23 | borderHover: palette.neutral[100], 24 | border: palette.brand[800], 25 | backgroundChecked: palette.neutral[100], 26 | textLabel: palette.neutral[100], 27 | textLabelSupporting: palette.brand[800], 28 | borderError: palette.error[500], 29 | }, 30 | ...labelThemeBrand, 31 | ...userFeedbackThemeBrand, 32 | }; 33 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/select/Option.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import type { OptionHTMLAttributes } from 'react'; 3 | import type { Props } from '../@types/Props'; 4 | 5 | export interface OptionProps 6 | extends OptionHTMLAttributes, 7 | Props { 8 | children: string; 9 | } 10 | 11 | export const Option = ({ 12 | cssOverrides, 13 | children, 14 | ...props 15 | }: OptionProps): EmotionJSX.Element => { 16 | return ( 17 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/select/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | import { userFeedbackThemeDefault } from '../user-feedback/theme'; 3 | 4 | export const selectThemeDefault = { 5 | select: { 6 | textUserInput: palette.neutral[7], 7 | textLabel: palette.neutral[7], 8 | textLabelOptional: palette.neutral[46], 9 | textLabelSupporting: palette.neutral[46], 10 | textError: palette.neutral[7], 11 | textSuccess: palette.success[400], 12 | backgroundInput: palette.neutral[100], 13 | border: palette.neutral[46], 14 | borderActive: palette.focus[400], 15 | borderError: palette.error[400], 16 | borderSuccess: palette.success[400], 17 | }, 18 | ...userFeedbackThemeDefault, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/stack/Stack.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import type { HTMLAttributes } from 'react'; 3 | import type { Props } from '../@types/Props'; 4 | import { stack, stackSpace } from './styles'; 5 | 6 | export type StackSpace = 1 | 2 | 3 | 4 | 5 | 6 | 9 | 12 | 24; 7 | 8 | export interface StackProps extends HTMLAttributes, Props { 9 | /** 10 | * [Units of space](https://www.theguardian.design/2a1e5182b/p/449bd5-space) between inline items (one unit is 4px). 11 | */ 12 | space?: StackSpace; 13 | } 14 | 15 | /** 16 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-stack) • 17 | * [Design System](https://theguardian.design/2a1e5182b/p/827581-stack) • 18 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/stack/Stack.tsx) • 19 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components) 20 | * 21 | * `Stack` components will be stacked one on top of the other. 22 | */ 23 | export const Stack = ({ 24 | cssOverrides, 25 | children, 26 | space, 27 | ...props 28 | }: StackProps): EmotionJSX.Element => { 29 | return ( 30 |
31 | {children} 32 |
33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/stack/styles.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | import { css } from '@emotion/react'; 3 | import { space } from '@guardian/source-foundations'; 4 | import type { StackSpace } from './Stack'; 5 | 6 | export const stack = css` 7 | & > * { 8 | width: 100%; 9 | } 10 | `; 11 | 12 | const stackSpaceStyle = (number: StackSpace): SerializedStyles => css` 13 | & > * + * { 14 | margin-top: ${space[number]}px; 15 | } 16 | `; 17 | 18 | export const stackSpace: { 19 | 1: SerializedStyles; 20 | 2: SerializedStyles; 21 | 3: SerializedStyles; 22 | 4: SerializedStyles; 23 | 5: SerializedStyles; 24 | 6: SerializedStyles; 25 | 9: SerializedStyles; 26 | 12: SerializedStyles; 27 | 24: SerializedStyles; 28 | } = { 29 | 1: stackSpaceStyle(1), 30 | 2: stackSpaceStyle(2), 31 | 3: stackSpaceStyle(3), 32 | 4: stackSpaceStyle(4), 33 | 5: stackSpaceStyle(5), 34 | 6: stackSpaceStyle(6), 35 | 9: stackSpaceStyle(9), 36 | 12: stackSpaceStyle(12), 37 | 24: stackSpaceStyle(24), 38 | }; 39 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/text-input/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | import { userFeedbackThemeDefault } from '../user-feedback/theme'; 3 | 4 | export const textInputThemeDefault = { 5 | textInput: { 6 | textUserInput: palette.neutral[7], 7 | textLabel: palette.neutral[7], 8 | textLabelOptional: palette.neutral[46], 9 | textLabelSupporting: palette.neutral[46], 10 | textError: palette.neutral[7], 11 | textSuccess: palette.success[400], 12 | backgroundInput: palette.neutral[100], 13 | border: palette.neutral[46], 14 | borderActive: palette.focus[400], 15 | borderError: palette.error[400], 16 | borderSuccess: palette.success[400], 17 | }, 18 | ...userFeedbackThemeDefault, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/tiles/types.ts: -------------------------------------------------------------------------------- 1 | export type Columns = 2 | 3 | 4 | 5; 2 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/user-feedback/InlineError.tsx: -------------------------------------------------------------------------------- 1 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 2 | import { SvgAlertTriangle } from '../../vendor/icons/SvgAlertTriangle'; 3 | import type { Theme } from '../@types/Theme'; 4 | import { inlineError } from './styles'; 5 | import type { UserFeedbackProps } from './types'; 6 | 7 | /** 8 | * [Storybook](https://guardian.github.io/source/?path=/docs/packages-source-react-components-inlineerror--playground) • 9 | * [Design System](https://theguardian.design/2a1e5182b/p/108ed3-user-feedback/b/3803b4) • 10 | * [GitHub](https://github.com/guardian/source/tree/main/packages/@guardian/source-react-components/src/user-feedback/InlineError.tsx) • 11 | * [NPM](https://www.npmjs.com/package/@guardian/source-react-components-feedback) 12 | * 13 | * Used to inform the user when a validation has failed or user error has occurred. These messages indicate what went wrong and how to fix it. 14 | * 15 | * The following themes are supported: `default`, `brand` 16 | */ 17 | export const InlineError = ({ 18 | children, 19 | cssOverrides, 20 | ...props 21 | }: UserFeedbackProps): EmotionJSX.Element => ( 22 | [inlineError(theme.userFeedback), cssOverrides]} 24 | role="alert" 25 | {...props} 26 | > 27 | 28 | {children} 29 | 30 | ); 31 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/user-feedback/InlineSuccess.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Story } from '@storybook/react'; 2 | import { InlineSuccess } from './InlineSuccess'; 3 | import { userFeedbackThemeBrand } from './theme'; 4 | import type { UserFeedbackProps } from './types'; 5 | 6 | export default { 7 | title: 'Packages/source-react-components/InlineSuccess', 8 | component: InlineSuccess, 9 | }; 10 | 11 | const Template: Story = (args: UserFeedbackProps) => ( 12 | Your voucher code is valid 13 | ); 14 | 15 | export const InlineSuccessDefaultTheme = Template.bind({}); 16 | 17 | // ***************************************************************************** 18 | 19 | export const InlineSuccessBrandTheme = Template.bind({}); 20 | InlineSuccessBrandTheme.parameters = { 21 | backgrounds: { 22 | default: 'brandBackground.primary', 23 | }, 24 | theme: userFeedbackThemeBrand, 25 | }; 26 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/user-feedback/styles.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedStyles } from '@emotion/react'; 2 | import { css } from '@emotion/react'; 3 | import { remHeight, remWidth, textSans } from '@guardian/source-foundations'; 4 | import { userFeedbackThemeDefault } from './theme'; 5 | 6 | const inlineMessage = css` 7 | display: flex; 8 | align-items: flex-start; 9 | ${textSans.medium()}; 10 | 11 | svg { 12 | fill: currentColor; 13 | /* we don't want the SVG to change size depending on available space */ 14 | flex: none; 15 | width: ${remWidth.iconMedium}rem; 16 | height: ${remHeight.iconMedium}rem; 17 | 18 | /* 19 | a visual kick to vertically align the icon with the top row of text 20 | and horizontally pull it to the beginning of the row 21 | */ 22 | transform: translate(-4px, -3px); 23 | } 24 | `; 25 | 26 | export const inlineError = ( 27 | userFeedback = userFeedbackThemeDefault.userFeedback, 28 | ): SerializedStyles => css` 29 | ${inlineMessage}; 30 | color: ${userFeedback.textError}; 31 | `; 32 | 33 | export const inlineSuccess = ( 34 | userFeedback = userFeedbackThemeDefault.userFeedback, 35 | ): SerializedStyles => css` 36 | ${inlineMessage}; 37 | color: ${userFeedback.textSuccess}; 38 | `; 39 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/user-feedback/theme.ts: -------------------------------------------------------------------------------- 1 | import { palette } from '@guardian/source-foundations'; 2 | 3 | export const userFeedbackThemeDefault = { 4 | userFeedback: { 5 | textSuccess: palette.success[400], 6 | textError: palette.error[400], 7 | }, 8 | }; 9 | 10 | export const userFeedbackThemeBrand = { 11 | userFeedback: { 12 | textSuccess: palette.success[500], 13 | textError: palette.error[500], 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/src/user-feedback/types.ts: -------------------------------------------------------------------------------- 1 | import type { HTMLAttributes, ReactNode } from 'react'; 2 | import type { Props } from '../@types/Props'; 3 | 4 | export interface UserFeedbackProps 5 | extends Props, 6 | HTMLAttributes { 7 | children: ReactNode; 8 | } 9 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/README.md: -------------------------------------------------------------------------------- 1 | # Icons 2 | 3 | **The contents of this directory are created automatically. Any edits will be 4 | overwritten sooner or later.** 5 | 6 | The SVGs for these icons are automatically pulled in from the [source design file in 7 | Figma](https://www.figma.com/file/Ai7AELHC6KCz38qKZkvuHo/%E2%97%90-Icons?node-id=55%3A2) 8 | using the create-icons script via the Figma API: 9 | 10 | ```sh 11 | yarn workspace @guardian/source-react-components create-icons 12 | ``` 13 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowContract.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowContract = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Collapse 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowDownStraight.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowDownStraight = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Arrow down 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowExpand.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowExpand = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Expand 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowLeftStraight.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowLeftStraight = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Arrow left 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowOutdent.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowOutdent = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Up left arrow 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowPopOut.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowPopOut = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Pop out 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowRightStraight.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowRightStraight = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Arrow right 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowUpAndDownSmall.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowUpAndDownSmall = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Up and down arrow 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowUpStraight.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowUpStraight = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Arrow up 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgArrowUpStraightSmall.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgArrowUpStraightSmall = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Arrow up 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgAsterisk.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgAsterisk = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Asterisk 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgAudioMute.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgAudioMute = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Sound off 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgBookMark.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgBookMark = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Bookmark 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgCamera.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgCamera = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Camera 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgCheckmark.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgCheckmark = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Checkmark 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronDownDouble.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronDownDouble = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Double chevron down 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronDownSingle.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronDownSingle = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Expand to show more 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronDownSingleXsmall.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronDownSingleXsmall = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Expand to show more 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronLeftDouble.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronLeftDouble = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Double chevron left 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronLeftSingle.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronLeftSingle = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Chevron left 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronRightDouble.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronRightDouble = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Double chevron right 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronRightSingle.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronRightSingle = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Chevron right 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronUpDouble.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronUpDouble = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Double chevron up 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgChevronUpSingle.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgChevronUpSingle = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Collapse to show less 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgClock.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgClock = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Clock 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgClockBaselineSmall.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgClockBaselineSmall = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Clock 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgCross.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgCross = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Close 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgCrosswords.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgCrosswords = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Crosswords 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgDocument.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgDocument = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Document 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgDownload.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgDownload = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Download 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgDragHandle.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgDragHandle = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Drag 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgEnvelope.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 18 | 19 | 20 | ); 21 | 22 | export const SvgEnvelope = ({ 23 | size, 24 | isAnnouncedByScreenReader = false, 25 | }: IconProps): EmotionJSX.Element => ( 26 | <> 27 | 28 | {isAnnouncedByScreenReader ? ( 29 | 34 | Email 35 | 36 | ) : ( 37 | '' 38 | )} 39 | 40 | ); 41 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgExternal.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgExternal = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | External link 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgFacebook.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgFacebook = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Facebook logo 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgFilter.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgFilter = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Filter 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgGift.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 18 | 19 | ); 20 | 21 | export const SvgGift = ({ 22 | size, 23 | isAnnouncedByScreenReader = false, 24 | }: IconProps): EmotionJSX.Element => ( 25 | <> 26 | 27 | {isAnnouncedByScreenReader ? ( 28 | 33 | Gift 34 | 35 | ) : ( 36 | '' 37 | )} 38 | 39 | ); 40 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgGps.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgGps = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Location 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgHouse.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgHouse = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Home 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgHousePlus.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgHousePlus = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Add to home 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgIndent.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgIndent = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Indent 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMediaControlsBack.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgMediaControlsBack = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Rewind 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMediaControlsForward.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgMediaControlsForward = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Fast forward 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMediaControlsPause.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgMediaControlsPause = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Pause 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMediaControlsPlay.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgMediaControlsPlay = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Play 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMediaControlsStop.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgMediaControlsStop = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Stop 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMenu.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgMenu = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Menu 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgMinus.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 18 | 19 | ); 20 | 21 | export const SvgMinus = ({ 22 | size, 23 | isAnnouncedByScreenReader = false, 24 | }: IconProps): EmotionJSX.Element => ( 25 | <> 26 | 27 | {isAnnouncedByScreenReader ? ( 28 | 33 | Minus sign 34 | 35 | ) : ( 36 | '' 37 | )} 38 | 39 | ); 40 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgPinned.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 18 | 19 | ); 20 | 21 | export const SvgPinned = ({ 22 | size, 23 | isAnnouncedByScreenReader = false, 24 | }: IconProps): EmotionJSX.Element => ( 25 | <> 26 | 27 | {isAnnouncedByScreenReader ? ( 28 | 33 | Pinned 34 | 35 | ) : ( 36 | '' 37 | )} 38 | 39 | ); 40 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgPlus.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgPlus = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Plus sign 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgQuote.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgQuote = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Quote 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgSpeechBubble.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgSpeechBubble = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Comments 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgSpeechBubblePlus.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgSpeechBubblePlus = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Add comment 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgStar.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgStar = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Star 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgTextLarge.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgTextLarge = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Large text 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgTextSmall.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgTextSmall = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Small text 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgTickRound.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgTickRound = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Ticked 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgUpload.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgUpload = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Upload 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /packages/@guardian/source-react-components/vendor/icons/SvgVideo.tsx: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT 2 | // this file is auto-generated by packages/@guardian/source-react-components/scripts/create-icons/index.ts 3 | import { css } from '@emotion/react'; 4 | import type { EmotionJSX } from '@emotion/react/types/jsx-namespace'; 5 | import { iconSize, visuallyHidden } from '@guardian/source-foundations'; 6 | import type { IconProps } from '../../src/@types/Icons'; 7 | 8 | const Svg = ({ size }: IconProps): EmotionJSX.Element => ( 9 | 17 | 22 | 23 | ); 24 | 25 | export const SvgVideo = ({ 26 | size, 27 | isAnnouncedByScreenReader = false, 28 | }: IconProps): EmotionJSX.Element => ( 29 | <> 30 | 31 | {isAnnouncedByScreenReader ? ( 32 | 37 | Video 38 | 39 | ) : ( 40 | '' 41 | )} 42 | 43 | ); 44 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # Scripts 2 | 3 | This directory provides a series of scripts that are useful to the maintainers of Source. 4 | 5 | ## Running 6 | 7 | Scripts that are intended to be run directly all contain aliases in at least one `package.json`. 8 | 9 | For example, the `build-src.ts` script can be run using `yarn build:src` from the root directory. 10 | 11 | Some of the scripts in nested directories may need to be run via the workspace command (`yarn workspace $WORSPACE $COMMAND`). These cases will be documented in the README within that directory. 12 | 13 | Some scripts are not intended to be run directly, and are instead consumed by other scripts within this directory. If you do have a need to run them directly, you can do so using `ts-node`. For example, `yarn ts-node ./scripts/paths`. As these scripts are designed to be consumed by others, this is unlikely to yield any interesting behaviour but may be useful for debugging if you are developing on one or more of these files. 14 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | processors: ['stylelint-processor-styled-components'], 3 | extends: [ 4 | 'stylelint-config-recommended', 5 | 'stylelint-config-styled-components', 6 | ], 7 | rules: { 8 | 'no-descending-specificity': null, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@guardian/tsconfig/tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "jsx": "react-jsx", 9 | "jsxImportSource": "@emotion/react", 10 | "noEmit": true, 11 | "paths": { 12 | "@guardian/source-foundations": [ 13 | "packages/@guardian/source-foundations/src/index" 14 | ], 15 | "@guardian/source-react-components": [ 16 | "packages/@guardian/source-react-components/src/index" 17 | ], 18 | "@guardian/source-react-components-development-kitchen": [ 19 | "packages/@guardian/source-react-components-development-kitchen/src/index" 20 | ], 21 | "@guardian/eslint-plugin-source-foundations": [ 22 | "packages/@guardian/eslint-plugin-source-foundations/src/index" 23 | ], 24 | "@guardian/eslint-plugin-source-react-components": [ 25 | "packages/@guardian/eslint-plugin-source-react-components/src/index" 26 | ] 27 | }, 28 | "sourceMap": true 29 | }, 30 | "ts-node": { 31 | "compilerOptions": { 32 | "module": "CommonJS" 33 | } 34 | }, 35 | "include": ["packages", "lib", "scripts"], 36 | "exclude": ["node_modules", "dist"] 37 | } 38 | --------------------------------------------------------------------------------