From c5ab3515e1bfe8eafde89ec308547b6d34e0b44d Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Mon, 12 Aug 2024 13:19:34 -0500 Subject: [PATCH 01/12] feat(Popover): update theming to 2.0 (#2031) - update prop values - update stories and snapshots --- src/components/Popover/Popover.module.css | 112 ---------------- src/components/Popover/Popover.stories.tsx | 48 +++---- src/components/Popover/Popover.tsx | 5 +- .../__snapshots__/Popover.test.tsx.snap | 122 +----------------- .../PopoverContainer/PopoverContainer.tsx | 5 - 5 files changed, 20 insertions(+), 272 deletions(-) delete mode 100644 src/components/Popover/Popover.module.css diff --git a/src/components/Popover/Popover.module.css b/src/components/Popover/Popover.module.css deleted file mode 100644 index 0d95e840e..000000000 --- a/src/components/Popover/Popover.module.css +++ /dev/null @@ -1,112 +0,0 @@ -/*------------------------------------*\ - # POPOVER CONTENT -\*------------------------------------*/ - -/** - * Decorative arrow pointing the Popover to the trigger element. - */ -.popover-content__arrow { - position: absolute; - width: 0; - height: 0; -} - -/** - * Arrow directions, made into mixins for brevity in use. - */ -@define-mixin down-arrow { - bottom: -0.25rem; - - border: calc(var(--eds-size-half) / 16 * 1rem) solid transparent; - border-top-color: var(--eds-theme-color-background-neutral-default); - border-bottom: none; -} -@define-mixin up-arrow { - top: -0.25rem; - - border: calc(var(--eds-size-half) / 16 * 1rem) solid transparent; - border-bottom-color: var(--eds-theme-color-background-neutral-default); - border-top: none; -} -@define-mixin left-arrow { - left: -0.25rem; - - border: calc(var(--eds-size-half) / 16 * 1rem) solid transparent; - border-right-color: var(--eds-theme-color-background-neutral-default); - border-left: none; -} -@define-mixin right-arrow { - right: -0.25rem; - - border: calc(var(--eds-size-half) / 16 * 1rem) solid transparent; - border-left-color: var(--eds-theme-color-background-neutral-default); - border-right: none; -} - -/** - * Arrow placement according to popover placement. - */ -:where([data-popper-placement='top-start'] > .popover-content__arrow) { - left: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin down-arrow; -} -:where([data-popper-placement='top-end'] > .popover-content__arrow) { - right: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin down-arrow; -} -:where([data-popper-placement='bottom-start'] > .popover-content__arrow) { - left: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin up-arrow; -} -:where([data-popper-placement='bottom-end'] > .popover-content__arrow) { - right: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin up-arrow; -} -:where([data-popper-placement='right-start'] > .popover-content__arrow) { - top: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin left-arrow; -} -:where([data-popper-placement='right-end'] > .popover-content__arrow) { - bottom: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin left-arrow; -} -:where([data-popper-placement='left-start'] > .popover-content__arrow) { - top: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin right-arrow; -} -:where([data-popper-placement='left-end'] > .popover-content__arrow) { - bottom: calc(var(--eds-size-2) / 16 * 1rem); - - @mixin right-arrow; -} - -:where([data-popper-placement='top'] > .popover-content__arrow) { - left: 50%; - - @mixin down-arrow; -} - -:where([data-popper-placement='bottom'] > .popover-content__arrow) { - left: 50%; - - @mixin up-arrow; -} - -:where([data-popper-placement='right'] > .popover-content__arrow) { - top: 50%; - - @mixin left-arrow; -} - -:where([data-popper-placement='left'] > .popover-content__arrow) { - top: 50%; - - @mixin right-arrow; -} diff --git a/src/components/Popover/Popover.stories.tsx b/src/components/Popover/Popover.stories.tsx index 86250a638..ba8b0c6fa 100644 --- a/src/components/Popover/Popover.stories.tsx +++ b/src/components/Popover/Popover.stories.tsx @@ -5,9 +5,6 @@ import React from 'react'; import { Popover } from './Popover'; import type { PopoverProps } from './Popover'; import Button from '../Button'; -import Hr from '../Hr'; - -// Fix row showing for children export default { title: 'Components/Popover', @@ -71,6 +68,22 @@ export default { type Story = StoryObj; export const Default: Story = { + parameters: { + docs: { + source: { + code: ` + + + Open Popover + + +
Popover Content goes here
+
+
+ `, + }, + }, + }, play: async ({ canvasElement }) => { // We want to test visual regression for the Popover.Content as well as the button, // but don't want the drawer open initally outside Chromatic. @@ -142,34 +155,6 @@ export const BottomEnd: Story = { ...Default, }; -export const RightStart: Story = { - args: { - placement: 'right-start', - }, - ...Default, -}; - -export const RightEnd: Story = { - args: { - placement: 'right-end', - }, - ...Default, -}; - -export const LeftStart: Story = { - args: { - placement: 'left-start', - }, - ...Default, -}; - -export const LeftEnd: Story = { - args: { - placement: 'left-end', - }, - ...Default, -}; - /** * The trigger for `Popover` can receive focus, by convention. */ @@ -192,7 +177,6 @@ export const FocusClickableElement: Story = {
Popover Content goes here -
diff --git a/src/components/Popover/Popover.tsx b/src/components/Popover/Popover.tsx index 150fe56a6..dc058256f 100644 --- a/src/components/Popover/Popover.tsx +++ b/src/components/Popover/Popover.tsx @@ -1,5 +1,4 @@ import { Popover as HeadlessPopover } from '@headlessui/react'; -import clsx from 'clsx'; import React, { useState, createContext, useContext } from 'react'; import type { ReactNode, RefObject } from 'react'; import { createPortal } from 'react-dom'; @@ -11,7 +10,6 @@ import type { } from '../PopoverContainer'; import { defaultPopoverModifiers } from '../PopoverContainer'; import PopoverContainer from '../PopoverContainer'; -import styles from './Popover.module.css'; export type PopoverProps = ExtractProps & PopoverOptions & { @@ -130,7 +128,6 @@ const PopoverContent = ({ style: popperStyles, }; - const componentClassName = clsx(styles['popover-content'], className); if (typeof document !== 'undefined') { return ( <> @@ -138,7 +135,7 @@ const PopoverContent = ({ {children as ReactNode} diff --git a/src/components/Popover/__snapshots__/Popover.test.tsx.snap b/src/components/Popover/__snapshots__/Popover.test.tsx.snap index 0e94e57a7..82c8ad1f3 100644 --- a/src/components/Popover/__snapshots__/Popover.test.tsx.snap +++ b/src/components/Popover/__snapshots__/Popover.test.tsx.snap @@ -121,12 +121,12 @@ exports[` FocusClickableElement story renders snapshot 1`] = ` data-headlessui-state="open" > - - - - +
+ {toasts.map((toast) => ( + + { + setToasts( + toasts.map((thisToast) => { + return thisToast.id === toast.id + ? { ...thisToast, show: false } + : thisToast; + }), + ); + }} + title={'You got a new toast: ' + toast.text + toast.id} + /> + + ))} +
+ + ); +}; + +/** + * This implementation example shows how you can use toasts with state to handle multiple, stacking notifications. + * + * For a full, production-ready implementation, clean up any toasts with show=false after the animation has completed. + * - Consider using lodash.debounce to time the re-render, and useEffect that watches the list of toasts + * - Any debouncing should map to whatever duration is used in `Transition` + * + * Here, we use `` provided by [HeadlessUI](https://github.com/chanzuckerberg/edu-design-system/blob/main/package.json#L91-L93). + */ +export const ExampleDismissingToasts: Story = { + render: (args) => , + parameters: { + // For interactive use, low value in snap testing again since already covered in other stories. + chromatic: { disableSnapshot: true }, + snapshot: { skip: true }, + }, +}; diff --git a/tailwind.config.ts b/tailwind.config.ts index 90f225cc6..48f9567b2 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -11,6 +11,19 @@ const { // Add a type to the token sizes to avoid literals for keys const sizes: { [x: string]: string } = edsTokens.size; +// add a type to the token sizes for movement durations +const movement: { [x: string]: string } = { + ...Object.keys(edsTokens.anim.move) + .map((movement) => { + return { [movement]: `${edsTokens.anim.move[movement]}s` }; + }) + .reduce((accumulate, current) => { + const entry = Object.entries(current)[0]; + accumulate[entry[0]] = entry[1]; + return accumulate; + }, {}), +}; + const sizeTokens = { // We pull the spacing tokens and format them such that names are like 'size-${name} = ${value}px' ...Object.keys(sizes) @@ -52,6 +65,9 @@ export default { spacing: { ...sizeTokens, }, + transitionDuration: { + ...movement, + }, }, fontWeight: { normal: edsTokens['font-weight'].light, From 9940d76d6ac60e112dee2e39d227bbb695057564 Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Thu, 22 Aug 2024 18:03:05 -0500 Subject: [PATCH 07/12] fix(Popover): update component version number (#2038) --- src/components/Popover/Popover.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Popover/Popover.stories.tsx b/src/components/Popover/Popover.stories.tsx index ba8b0c6fa..f1e8c0f47 100644 --- a/src/components/Popover/Popover.stories.tsx +++ b/src/components/Popover/Popover.stories.tsx @@ -11,7 +11,7 @@ export default { component: Popover, parameters: { layout: 'centered', - badges: ['intro-1.0', 'current-1.3'], + badges: ['intro-1.0', 'current-2.0'], chromatic: { // These stories are very flaky, though we're not sure why. // We tried delaying the snapshot just in case there's a timing issue at play here, which was not successful. From d6ee15d71d9f3df76fe68f1639ac1e442e6cd686 Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Fri, 23 Aug 2024 09:48:05 -0500 Subject: [PATCH 08/12] fix(Card): add spacing between eyebrow and title (#2040) --- src/components/Card/Card.module.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Card/Card.module.css b/src/components/Card/Card.module.css index 424e090e0..333ecf386 100755 --- a/src/components/Card/Card.module.css +++ b/src/components/Card/Card.module.css @@ -83,6 +83,10 @@ .card__header { display: flex; + + & .header__eyebrow { + margin-bottom: calc(var(--eds-size-1) / 16 * 1rem); + } &.header--size-sm { gap: calc(var(--eds-size-1) / 16 * 1rem) From d336de2de0e966ef591024af64508dd02682cf8e Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Fri, 23 Aug 2024 13:07:04 -0500 Subject: [PATCH 09/12] docs: update publishing documentation (#2041) --- docs/PUBLISHING.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md index 90d117deb..bf98e120d 100644 --- a/docs/PUBLISHING.md +++ b/docs/PUBLISHING.md @@ -85,22 +85,22 @@ Once merged, wait until the [builds complete on `main`](https://github.com/chanz 8. Pull down the most up-to-date version of main: `git checkout main && git pull && yarn install && yarn build` 9. Publish the package: `npm publish` -10. Create a [new release](https://github.com/chanzuckerberg/edu-design-system/releases) based on the new tag. Use the same text used for the pull request description above (from CHANGELOG.md). Also include the link for the built storybook in the description. This will automatically post to [relevant slack channels](https://slack.github.com/). **When doing a major version release, don't forget to include notes on each breaking change**. Also, enable the discussion feature to handle any question-answering should questions arise. +10. Create a [new release](https://github.com/chanzuckerberg/edu-design-system/releases) based on the newly-created tag. -When naming the release, include the package name before the version number in the release name field (e.g., "@chanzuckerberg/eds vX.X.X") +To prepare the message: + +* Include the package name before the version number in the release name field (e.g., "@chanzuckerberg/eds@X.Y.Z") +* Use the same text used for the pull request description above (from CHANGELOG.md). +* Include any additional notes from the [System Designers](https://github.com/orgs/chanzuckerberg/teams/edu-systems-designers). +* Include the link for the built storybook in the description. + +The latter will automatically post to [relevant slack channels](https://slack.github.com/). **When doing a major version release, don't forget to include notes on each breaking change**. #### Finishing the release 11. Lastly, run the following to "back merge" release changes to `next`: - `git checkout main && git pull origin main && git checkout next && git merge main && git push` -Once complete, you can update the package in the main apps that use it (for major versions): - -- [edu-stack](https://github.com/chanzuckerberg/edu-stack) - in the package.json -- [edu-stack-service](https://github.com/chanzuckerberg/edu-stack-service) - in the package.json - -Take note of the details here, which will also be mentioned in that month's newsletter, and updates to ZeroHeight (What's New). - #### Alpha release For testing a release to build confidence. From 7a2739619458b693d030dfac1670b27244f93cee Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Fri, 23 Aug 2024 15:15:59 -0500 Subject: [PATCH 10/12] docs(Button): remove reference to ClickableStyles (#2043) --- src/components/Button/Button.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 645840905..5bd101876 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -92,8 +92,7 @@ export type ButtonProps = ButtonHTMLElementProps & { * or other in-page activity. * * - If you need to style a navigation anchor, please use the `Link` component. - * - If you need to style a different element or component to - * look like a button or link, you can use the `ClickableStyle` component. + * - If you need the button to use some other tag or component, use the `as` prop. */ export const Button = forwardRef( ( From 351d7fd850196c44da17985b82d8f150fd37a62b Mon Sep 17 00:00:00 2001 From: Andrew Holloway Date: Fri, 23 Aug 2024 15:31:55 -0500 Subject: [PATCH 11/12] fix(Link): handle inverse variant for standalone links (#2042) - update documentation to explain cases - add warning for misaligned prop usages - update snapshots and tests --- src/components/Link/Link.module.css | 4 +++ src/components/Link/Link.stories.tsx | 25 ++++++++++++++---- src/components/Link/Link.test.tsx | 12 +++++++++ src/components/Link/Link.tsx | 26 ++++++++++++++----- .../Link/__snapshots__/Link.test.tsx.snap | 15 +++++++++++ 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/components/Link/Link.module.css b/src/components/Link/Link.module.css index 4b215552a..eddcb8853 100644 --- a/src/components/Link/Link.module.css +++ b/src/components/Link/Link.module.css @@ -50,6 +50,10 @@ text-decoration: none; } + &.link--variant-inverse { + color: var(--eds-theme-color-text-utility-inverse); + } + /** * Sizes - using the presets for type ramp matching body-* */ diff --git a/src/components/Link/Link.stories.tsx b/src/components/Link/Link.stories.tsx index 517074436..ba067cf51 100644 --- a/src/components/Link/Link.stories.tsx +++ b/src/components/Link/Link.stories.tsx @@ -26,7 +26,7 @@ type Story = StoryObj; export const Default: Story = {}; /** - * When using context, you can specify a trailing icon for the link. + * When using standalone context, you can specify a trailing icon for the link. * * **NOTE**: support for applying the chevron only works when `emphasis` is set to "low". */ @@ -40,7 +40,7 @@ export const LinkWithChevron: Story = { }; /** - * When using context, you can specify a trailing icon for the link. When using the open icon, make sure that a new tab/window is opened. + * When using standalone context, you can specify a trailing icon for the link. When using the open icon, make sure that a new tab/window is opened. */ export const LinkWithOpenIcon: Story = { args: { @@ -51,7 +51,7 @@ export const LinkWithOpenIcon: Story = { }; /** - * You can add formatting to the link if needed. + * You can add formatting to a link if needed. */ export const LinkWithFormattedChildren: Story = { args: { @@ -75,9 +75,11 @@ export const Emphasis: Story = { Default Emphasis +
High Emphasis +
Low Emphasis @@ -87,7 +89,20 @@ export const Emphasis: Story = { }; /** - * We also include an inverse variant, for use on dark backgrounds. + * Standalone inverse links take on a specific inverse color. + */ +export const StandaloneInverseVariant: Story = { + args: { + context: 'standalone', + variant: 'inverse', + }, + parameters: { + backgrounds: { default: 'background-utility-default-high-emphasis' }, + }, +}; + +/** + * Inline always take on the color of the container. When using an inline link, wrap the text with a proper color text token. */ export const InverseVariant: Story = { args: { @@ -129,7 +144,7 @@ export const LinkInParagraphContext: StoryObj = { }; /** - * Links will inherit the color from the surrounding text color definition (default emphasis, inline links) + * Inline links will inherit the color from the surrounding text color definition (default emphasis) */ export const InheritColor: Story = { args: { diff --git a/src/components/Link/Link.test.tsx b/src/components/Link/Link.test.tsx index ed42decc8..d0314e994 100644 --- a/src/components/Link/Link.test.tsx +++ b/src/components/Link/Link.test.tsx @@ -121,5 +121,17 @@ describe('', () => { expect(consoleMock).toHaveBeenCalledTimes(1); }); + + it('warns when variant is used with context inline', () => { + const consoleMock = jest.spyOn(console, 'warn'); + consoleMock.mockImplementation(); + render( + + Click + , + ); + + expect(consoleMock).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx index c54d3b8ac..73736c81c 100644 --- a/src/components/Link/Link.tsx +++ b/src/components/Link/Link.tsx @@ -23,12 +23,14 @@ export type LinkProps = /** * Where `Link` sits alongside other text and content: * - * * **inline** - Inline link inherits the text size established within the `

` paragraph they are embedded in. - * * **standalone** - Users can choose from the available sizes, and add trailing icons. + * * **inline** - Inline link inherits the text size/color established within the `

` or other tag they are embedded in. + * * **standalone** - Users can choose from the available sizes, select variants, and add a trailing icon. * * **Default is `"inline"`**. * - * Note: Icons will only be visible when `"standalone"` is used + * ---- + * + * **Note**: This will only apply when `"standalone"` is used */ context?: 'inline' | 'standalone'; /** @@ -40,15 +42,21 @@ export type LinkProps = */ emphasis?: 'default' | 'high' | 'low'; /** - * The size of the link (when its context is "standalone"). + * The size of the link (when its context is `"standalone"`). + * + * ---- * - * **NOTE**: when `context` is `"inline"`, size is ignored (and inherits from the associated text container) + * **Note**: This will only apply when `"standalone"` is used */ size?: Extract; /** - * The variant treatment for links (use "inverse" on dark backgrounds). + * The variant treatment for **standalone** links (use "inverse" on dark backgrounds). * * **Default is `"default"`**. + * + * ---- + * + * **Note**: This will only apply when `"standalone"` is used */ variant?: 'default' | 'inverse'; } & ExtendedElement; @@ -58,6 +66,7 @@ export type LinkProps = * * Component for making styled anchor tags. Links allow users to navigate within or between a web page(s) or app(s). * + * Inline links inherit the color of the surrounding container, while when using `context` set to `standalone`, links have specific colors. */ export const Link = forwardRef( ( @@ -96,6 +105,11 @@ export const Link = forwardRef( 'Inline links cannot show icons', ); + assertEdsUsage( + [context === 'inline' && variant === 'inverse'], + 'Variant can only be used when context is "standalone"', + ); + assertEdsUsage( [context === 'inline' && typeof size !== 'undefined'], 'Size can only be used when context is "standalone"', diff --git a/src/components/Link/__snapshots__/Link.test.tsx.snap b/src/components/Link/__snapshots__/Link.test.tsx.snap index 1da23a755..eb4cd045f 100644 --- a/src/components/Link/__snapshots__/Link.test.tsx.snap +++ b/src/components/Link/__snapshots__/Link.test.tsx.snap @@ -24,12 +24,14 @@ exports[` Emphasis story renders snapshot 1`] = ` > Default Emphasis +
High Emphasis +
LinkWithOpenIcon story renders snapshot 1`] = ` `; +exports[` StandaloneInverseVariant story renders snapshot 1`] = ` +

+`; + exports[` UsingExtendedLink story renders snapshot 1`] = `
Date: Fri, 23 Aug 2024 15:37:50 -0500 Subject: [PATCH 12/12] chore(release): 15.3.0 --- CHANGELOG.md | 17 +++++++++++++++++ package.json | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 083196440..c151736aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [15.3.0](https://github.com/chanzuckerberg/edu-design-system/compare/v15.2.1...v15.3.0) (2024-08-23) + + +### Features + +* **config:** add transition durations for tailwind ([#2036](https://github.com/chanzuckerberg/edu-design-system/issues/2036)) ([aed0f09](https://github.com/chanzuckerberg/edu-design-system/commit/aed0f0941d9d09f8a7b96f2219f6801eefa4ee50)) +* **Popover:** update theming to 2.0 ([#2031](https://github.com/chanzuckerberg/edu-design-system/issues/2031)) ([c5ab351](https://github.com/chanzuckerberg/edu-design-system/commit/c5ab3515e1bfe8eafde89ec308547b6d34e0b44d)) +* **tokens:** add in additional table tokens ([#2035](https://github.com/chanzuckerberg/edu-design-system/issues/2035)) ([a698a5b](https://github.com/chanzuckerberg/edu-design-system/commit/a698a5b4a65af8a7dffa7da908be9d7e05ffc570)) +* **tokens:** update visited tokens ([#2034](https://github.com/chanzuckerberg/edu-design-system/issues/2034)) ([df84c87](https://github.com/chanzuckerberg/edu-design-system/commit/df84c87ecd2ad34b37b90d6774bea284da50d045)) + + +### Bug Fixes + +* **Card:** add spacing between eyebrow and title ([#2040](https://github.com/chanzuckerberg/edu-design-system/issues/2040)) ([d6ee15d](https://github.com/chanzuckerberg/edu-design-system/commit/d6ee15d71d9f3df76fe68f1639ac1e442e6cd686)) +* **Link:** handle inverse variant for standalone links ([#2042](https://github.com/chanzuckerberg/edu-design-system/issues/2042)) ([351d7fd](https://github.com/chanzuckerberg/edu-design-system/commit/351d7fd850196c44da17985b82d8f150fd37a62b)) +* **Popover:** update component version number ([#2038](https://github.com/chanzuckerberg/edu-design-system/issues/2038)) ([9940d76](https://github.com/chanzuckerberg/edu-design-system/commit/9940d76d6ac60e112dee2e39d227bbb695057564)) + ### [15.2.1](https://github.com/chanzuckerberg/edu-design-system/compare/v15.2.0...v15.2.1) (2024-08-09) diff --git a/package.json b/package.json index 647f2696a..dfbef1f01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@chanzuckerberg/eds", - "version": "15.2.1", + "version": "15.3.0", "description": "The React-powered design system library for Chan Zuckerberg Initiative education web applications", "author": "CZI ", "homepage": "https://github.com/chanzuckerberg/edu-design-system",