@octaviaflow/mdx-components 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +215 -0
  2. package/components/_utils.scss +18 -0
  3. package/components/accordion/_accordion.scss +35 -0
  4. package/components/accordion/accordion.stories.jsx +33 -0
  5. package/components/accordion/accordion.tsx +55 -0
  6. package/components/anchor-links/_anchor-links.scss +67 -0
  7. package/components/anchor-links/anchor-link.tsx +50 -0
  8. package/components/anchor-links/anchor-links.stories.jsx +51 -0
  9. package/components/anchor-links/anchor-links.tsx +73 -0
  10. package/components/art-direction/art-direction.stories.jsx +44 -0
  11. package/components/art-direction/art-direction.tsx +63 -0
  12. package/components/art-direction/desktop.jpg +0 -0
  13. package/components/art-direction/mobile.jpg +0 -0
  14. package/components/art-direction/tablet.jpg +0 -0
  15. package/components/article-card/_article-card.scss +98 -0
  16. package/components/article-card/article-card.stories.jsx +59 -0
  17. package/components/article-card/article-card.tsx +208 -0
  18. package/components/article-card/article06.png +0 -0
  19. package/components/aside/_aside.scss +56 -0
  20. package/components/aside/aside.stories.jsx +50 -0
  21. package/components/aside/aside.tsx +72 -0
  22. package/components/caption/_caption.scss +30 -0
  23. package/components/caption/caption.stories.jsx +33 -0
  24. package/components/caption/caption.tsx +47 -0
  25. package/components/card-group/_card-group.scss +44 -0
  26. package/components/card-group/card-group.stories.jsx +85 -0
  27. package/components/card-group/card-group.tsx +65 -0
  28. package/components/card-group/sketch-icon.png +0 -0
  29. package/components/code/_code.scss +110 -0
  30. package/components/code/code.stories.jsx +32 -0
  31. package/components/code/code.tsx +71 -0
  32. package/components/code/inline-code.tsx +55 -0
  33. package/components/code/path.tsx +56 -0
  34. package/components/divider/_divider.scss +67 -0
  35. package/components/divider/divider.stories.jsx +74 -0
  36. package/components/divider/divider.tsx +54 -0
  37. package/components/do-dont/_do-dont.scss +191 -0
  38. package/components/do-dont/do-dont-row.tsx +51 -0
  39. package/components/do-dont/do-dont.stories.jsx +53 -0
  40. package/components/do-dont/do-dont.tsx +161 -0
  41. package/components/do-dont/light-theme.jpg +0 -0
  42. package/components/gif-player/_gif-player.scss +64 -0
  43. package/components/gif-player/cloud.gif +0 -0
  44. package/components/gif-player/cloud.jpg +0 -0
  45. package/components/gif-player/gif-player.stories.jsx +45 -0
  46. package/components/gif-player/gif-player.tsx +150 -0
  47. package/components/grid-transform/_grid.scss +13 -0
  48. package/components/grid-transform/column.tsx +102 -0
  49. package/components/grid-transform/grid.stories.jsx +72 -0
  50. package/components/grid-transform/grid.tsx +52 -0
  51. package/components/grid-transform/row.tsx +92 -0
  52. package/components/image-wrapper/_image-wrapper.scss +32 -0
  53. package/components/image-wrapper/accordion-style-3.png +0 -0
  54. package/components/image-wrapper/image-wrapper.stories.jsx +40 -0
  55. package/components/image-wrapper/image-wrapper.tsx +56 -0
  56. package/components/index.scss +31 -0
  57. package/components/inline-notification/_inline-notification.scss +29 -0
  58. package/components/inline-notification/inline-notification.stories.jsx +67 -0
  59. package/components/inline-notification/inline-notification.tsx +98 -0
  60. package/components/interfaces.ts +31 -0
  61. package/components/link/_link.scss +13 -0
  62. package/components/link/link.stories.jsx +36 -0
  63. package/components/link/link.tsx +51 -0
  64. package/components/markdown/_markdown.scss +140 -0
  65. package/components/markdown/autolink-header/_autolink-header.scss +57 -0
  66. package/components/markdown/autolink-header/autolink-header.tsx +107 -0
  67. package/components/markdown/blockquote.stories.jsx +38 -0
  68. package/components/markdown/blockquote.tsx +53 -0
  69. package/components/markdown/h1.tsx +92 -0
  70. package/components/markdown/h2.tsx +85 -0
  71. package/components/markdown/h3.tsx +72 -0
  72. package/components/markdown/h4.tsx +73 -0
  73. package/components/markdown/h5.tsx +59 -0
  74. package/components/markdown/h6.tsx +59 -0
  75. package/components/markdown/headings.stories.jsx +52 -0
  76. package/components/markdown/li.tsx +55 -0
  77. package/components/markdown/ol.stories.jsx +47 -0
  78. package/components/markdown/ol.tsx +93 -0
  79. package/components/markdown/p.stories.jsx +36 -0
  80. package/components/markdown/p.tsx +65 -0
  81. package/components/markdown/ul.stories.jsx +46 -0
  82. package/components/markdown/ul.tsx +93 -0
  83. package/components/mini-card/_mini-card.scss +55 -0
  84. package/components/mini-card/mini-card.stories.jsx +72 -0
  85. package/components/mini-card/mini-card.tsx +132 -0
  86. package/components/page-description/_page-description.scss +38 -0
  87. package/components/page-description/page-description.stories.jsx +36 -0
  88. package/components/page-description/page-description.tsx +61 -0
  89. package/components/page-table/_page-table.scss +51 -0
  90. package/components/page-table/page-table.stories.jsx +56 -0
  91. package/components/page-table/page-table.tsx +88 -0
  92. package/components/preview/_preview.scss +16 -0
  93. package/components/preview/preview.stories.jsx +41 -0
  94. package/components/preview/preview.tsx +80 -0
  95. package/components/resource-card/_resource-card.scss +165 -0
  96. package/components/resource-card/resource-card.stories.jsx +100 -0
  97. package/components/resource-card/resource-card.tsx +201 -0
  98. package/components/storybook-demo/_storybook-demo.scss +57 -0
  99. package/components/storybook-demo/storybook-demo.stories.jsx +70 -0
  100. package/components/storybook-demo/storybook-demo.tsx +190 -0
  101. package/components/tabs/_tabs.scss +98 -0
  102. package/components/tabs/select.tsx +60 -0
  103. package/components/tabs/tab-list.tsx +48 -0
  104. package/components/tabs/tab.tsx +125 -0
  105. package/components/tabs/tabs.stories.jsx +54 -0
  106. package/components/tabs/tabs.tsx +78 -0
  107. package/components/title/title.stories.jsx +43 -0
  108. package/components/title/title.tsx +47 -0
  109. package/components/utils.ts +102 -0
  110. package/components/video/_video.scss +89 -0
  111. package/components/video/local-poster.jpeg +0 -0
  112. package/components/video/local-video.mp4 +0 -0
  113. package/components/video/video.stories.jsx +45 -0
  114. package/components/video/video.tsx +255 -0
  115. package/es/index.js +71714 -0
  116. package/index.ts +59 -0
  117. package/lib/index.js +71767 -0
  118. package/package.json +64 -0
  119. package/telemetry.yml +21 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright OctaviaFlow 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import PropTypes from "prop-types";
17
+ import React, { useContext } from "react";
18
+
19
+ import { MdxComponent, NonScalarNode } from "../interfaces";
20
+ import { withPrefix } from "../utils";
21
+ import { TabContext } from "./tabs";
22
+
23
+ interface TabListProps {
24
+ _id: string;
25
+ children: NonScalarNode;
26
+ }
27
+
28
+ export const TabList: MdxComponent<TabListProps> = ({ _id, children }) => {
29
+ const { activeTab } = useContext(TabContext);
30
+
31
+ return (
32
+ <ul className={withPrefix("tab-list")} role="tablist">
33
+ {React.Children.map(children, (child, index) => {
34
+ return React.cloneElement(child, {
35
+ _id: `${_id}__${index}`,
36
+ active: activeTab === index,
37
+ index,
38
+ tab: true,
39
+ });
40
+ })}
41
+ </ul>
42
+ );
43
+ };
44
+
45
+ TabList.propTypes = {
46
+ _id: PropTypes.string.isRequired,
47
+ children: PropTypes.array.isRequired,
48
+ };
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright OctaviaFlow 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import PropTypes from "prop-types";
17
+ import React, {
18
+ KeyboardEvent,
19
+ ReactNode,
20
+ useCallback,
21
+ useContext,
22
+ } from "react";
23
+
24
+ import { MdxComponent } from "../interfaces";
25
+ import { withPrefix } from "../utils";
26
+ import { TabContext } from "./tabs";
27
+
28
+ interface TabProps {
29
+ _id: string;
30
+ active?: boolean | null;
31
+ children: ReactNode;
32
+ index: number;
33
+ label: string;
34
+ tab?: boolean | null;
35
+ }
36
+
37
+ export const Tab: MdxComponent<TabProps> = ({
38
+ _id,
39
+ label,
40
+ active,
41
+ index,
42
+ tab,
43
+ children,
44
+ }) => {
45
+ const { setActiveTab, tabList } = useContext(TabContext);
46
+ const buttonRef = useCallback((ref) => tabList.push(ref), [tabList]);
47
+
48
+ const onKeyDown = (e: KeyboardEvent) => {
49
+ let nextButton;
50
+ switch (e.key) {
51
+ case "End":
52
+ e.preventDefault();
53
+ tabList[tabList.length - 1]?.focus();
54
+ break;
55
+ case "Home":
56
+ e.preventDefault();
57
+ tabList[0]?.focus();
58
+ break;
59
+ case "ArrowLeft":
60
+ e.preventDefault();
61
+ nextButton = tabList[index - 1] || tabList[tabList.length - 1];
62
+ nextButton?.focus();
63
+ break;
64
+ case "ArrowRight":
65
+ e.preventDefault();
66
+ nextButton = tabList[index + 1] || tabList[0];
67
+ nextButton?.focus();
68
+ break;
69
+ default:
70
+ }
71
+ };
72
+
73
+ if (tab) {
74
+ return (
75
+ <li role="presentation">
76
+ <button
77
+ className={withPrefix("tab")}
78
+ ref={buttonRef}
79
+ onKeyDown={onKeyDown}
80
+ onClick={() => setActiveTab(index)}
81
+ onFocus={() => setActiveTab(index)}
82
+ type="button"
83
+ role="tab"
84
+ id={`${_id}--tab`}
85
+ tabIndex={!active ? -1 : 0}
86
+ aria-selected={active || undefined}
87
+ >
88
+ {label}
89
+ </button>
90
+ </li>
91
+ );
92
+ }
93
+
94
+ return (
95
+ <section
96
+ className={withPrefix("tab-panel")}
97
+ hidden={!active}
98
+ role="tabpanel"
99
+ id={`${_id}--panel`}
100
+ aria-labelledby={`${_id}--tab`}
101
+ >
102
+ {children}
103
+ </section>
104
+ );
105
+ };
106
+
107
+ Tab.propTypes = {
108
+ /** tab id */
109
+ _id: PropTypes.string.isRequired,
110
+ /** Set active tab */
111
+ active: PropTypes.bool,
112
+ /** Provide the contents of the tab */
113
+ children: PropTypes.node as unknown as React.Validator<React.ReactNode>,
114
+ /** tab index */
115
+ index: PropTypes.number.isRequired,
116
+ /** Set tab label */
117
+ label: PropTypes.string.isRequired,
118
+ /** tab */
119
+ tab: PropTypes.bool,
120
+ };
121
+
122
+ Tab.defaultProps = {
123
+ _id: "none",
124
+ index: 0,
125
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright IBM Corp. 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+
17
+ import React from "react";
18
+ import { Tab } from "./tab";
19
+ import { Tabs } from "./tabs";
20
+
21
+ export default {
22
+ title: "Components/MDX Components/Tabs",
23
+ component: Tabs,
24
+ subcomponents: { Tab },
25
+ };
26
+
27
+ const Template = (args) => (
28
+ <Tabs {...args}>
29
+ <Tab label="Tab 1">
30
+ Maecenas ultrices sem nec blandit dictum. ermentum ullamcorper pretium.
31
+ Duis turpis elit, facilisis nec elit id, fermentum porttitor nisl. Nulla
32
+ dignissim euismod maximus. Cras euismod facilisis rutrum. Etiam nisi sem,
33
+ malesuada auctor pretium vel, ullamcorper sed mi. In hac habitasse platea
34
+ dictumst.
35
+ </Tab>
36
+ <Tab label="Tab 2">
37
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean feugiat ex
38
+ massa, in tincidunt ipsum tempor in. Maecenas ultrices sem nec blandit
39
+ dictum. ermentum ullamcorper pretium. Duis turpis elit, facilisis nec elit
40
+ id, fermentum porttitor nisl. Nulla dignissim euismod maximus. Cras
41
+ euismod facilisis rutrum.
42
+ </Tab>
43
+ <Tab label="Tab 3">
44
+ Duis turpis elit, facilisis nec elit id, fermentum porttitor nisl. Nulla
45
+ dignissim euismod maximus. Cras euismod facilisis rutrum. Etiam nisi sem,
46
+ malesuada auctor pretium vel, ullamcorper sed mi. In hac habitasse platea
47
+ dictumst. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean
48
+ feugiat ex massa, in tincidunt ipsum tempor in.
49
+ </Tab>
50
+ </Tabs>
51
+ );
52
+
53
+ export const Default = Template.bind({});
54
+ Default.args = {};
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright OctaviaFlow 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import PropTypes from "prop-types";
17
+ import React, { createContext, useEffect, useRef, useState } from "react";
18
+
19
+ import { MdxComponent, NonScalarNode } from "../interfaces";
20
+ import { mediaQueries, useId, useMatchMedia } from "../utils";
21
+ import Select from "./select";
22
+ import { TabList } from "./tab-list";
23
+
24
+ interface TabContextInterface {
25
+ setActiveTab(tab: number): void;
26
+ activeTab: number;
27
+ tabList: Array<HTMLButtonElement>;
28
+ }
29
+
30
+ const TabContext = createContext<TabContextInterface>({
31
+ setActiveTab: () => undefined,
32
+ activeTab: -1,
33
+ tabList: [],
34
+ });
35
+
36
+ interface TabsProps {
37
+ children: NonScalarNode;
38
+ }
39
+
40
+ /**
41
+ * The `<Tabs>` and `<Tab>` components are used together to display and swap between content.
42
+ */
43
+ export const Tabs: MdxComponent<TabsProps> = (props) => {
44
+ const tabList = useRef([]);
45
+ const [activeTab, setActiveTab] = useState(0);
46
+ const isMd = useMatchMedia(mediaQueries.md);
47
+ const id = useId("tabs");
48
+
49
+ // clear tablist when unmounted (switching between Select and TabList)
50
+ useEffect(() => () => {
51
+ tabList.current = [];
52
+ });
53
+
54
+ return (
55
+ <TabContext.Provider
56
+ value={{ setActiveTab, activeTab, tabList: tabList.current }}
57
+ >
58
+ {isMd && <TabList _id={id}>{props.children}</TabList>}
59
+ {!isMd && <Select _id={id}>{props.children}</Select>}
60
+ {React.Children.map(props.children, (child, index) => {
61
+ return React.cloneElement(child, {
62
+ _id: `${id}__${index}`,
63
+ active: activeTab === index,
64
+ index,
65
+ });
66
+ })}
67
+ </TabContext.Provider>
68
+ );
69
+ };
70
+
71
+ Tabs.propTypes = {
72
+ /** Provide tab children */
73
+ children: PropTypes.array.isRequired,
74
+ };
75
+
76
+ Tabs.displayName = "Tabs";
77
+
78
+ export { TabContext };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright IBM Corp. 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import React from "react";
17
+ import { Title } from "./title";
18
+ import { P } from "../markdown/p";
19
+
20
+ export default {
21
+ title: "Components/MDX Components/Title",
22
+ component: Title,
23
+ argTypes: {
24
+ children: {
25
+ control: false,
26
+ },
27
+ className: {
28
+ control: false,
29
+ },
30
+ },
31
+ };
32
+
33
+ const Template = (args) => (
34
+ <>
35
+ <Title {...args}>Lorem ipsum</Title>
36
+ <P>
37
+ This is the element after the title with its default top margin removed.
38
+ </P>
39
+ </>
40
+ );
41
+
42
+ export const Default = Template.bind({});
43
+ Default.args = {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright OctaviaFlow 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import PropTypes from "prop-types";
17
+ import React, { ReactNode } from "react";
18
+
19
+ import { H4 } from "../markdown/h4";
20
+ import { MdxComponent } from "../interfaces";
21
+
22
+ interface TitleProps {
23
+ children: ReactNode;
24
+ className?: string | null;
25
+ }
26
+
27
+ /**
28
+ * The `<Title>` component is used to provide a title to a subsequent component
29
+ * (table, image, video, code block). The Title should be used in favor of other
30
+ * techniques for bolded text (h4s) to preserve page structure and heading hierarchy.
31
+ */
32
+ export const Title: MdxComponent<TitleProps> = ({ children, className }) => (
33
+ <H4 autolink={false} className={className}>
34
+ {children}
35
+ </H4>
36
+ );
37
+
38
+ Title.propTypes = {
39
+ /**
40
+ * Provide the contents of Title
41
+ */
42
+ children: PropTypes.node as unknown as React.Validator<React.ReactNode>,
43
+ /**
44
+ * Optional class name on the title.
45
+ */
46
+ className: PropTypes.string,
47
+ };
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright OctaviaFlow 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import { breakpoints } from "@octaviaflow/layout";
17
+ import { useEffect, useState } from "react";
18
+
19
+ const prefix = "carbon-mdx-components";
20
+ const mediaQueries = {
21
+ sm: `(min-width: ${breakpoints.sm.width})`,
22
+ md: `(min-width: ${breakpoints.md.width})`,
23
+ lg: `(min-width: ${breakpoints.lg.width})`,
24
+ xlg: `(min-width: ${breakpoints.xlg.width})`,
25
+ max: `(min-width: ${breakpoints.max.width})`,
26
+ };
27
+ let globalIndex = 0;
28
+
29
+ /**
30
+ * Queries the window if it exists.
31
+ * @param {string} query of the dimensions needed
32
+ * @returns the matchMedia function
33
+ */
34
+ const getMatchMedia = (query: string) => {
35
+ return typeof window !== "undefined" && window.matchMedia
36
+ ? window.matchMedia(query)
37
+ : null;
38
+ };
39
+
40
+ /**
41
+ * Gives an ID to the markdown components.
42
+ * @param {string} label component name string
43
+ * @returns string for component ID
44
+ */
45
+ const useId = (label: string) => {
46
+ // TODO: delete this hook and use react 18 useId instead.
47
+ const [id] = useState(++globalIndex);
48
+
49
+ return `cp__${label}__${id}`;
50
+ };
51
+
52
+ /**
53
+ * Function that returns the viewport media dimensions.
54
+ * @param {string} query string
55
+ * @returns boolean stating if it matches viewport dimensions
56
+ */
57
+ const useMatchMedia = (query: string) => {
58
+ const [matches, setMatches] = useState(getMatchMedia(query)?.matches);
59
+
60
+ useEffect(() => {
61
+ const matchMediaResult = getMatchMedia(query);
62
+ /**
63
+ *
64
+ * @param {any} e event
65
+ * @param {(
66
+ * boolean |
67
+ * ((prevState: boolean | undefined) => boolean | undefined) |
68
+ * undefined
69
+ * )} e.matches boolean stating if it matches
70
+ */
71
+ const updateMatch = (e: {
72
+ matches:
73
+ | boolean
74
+ | ((prevState: boolean | undefined) => boolean | undefined)
75
+ | undefined;
76
+ }) => {
77
+ setMatches(e.matches);
78
+ };
79
+
80
+ matchMediaResult?.addEventListener("change", updateMatch);
81
+
82
+ return () => {
83
+ matchMediaResult?.removeEventListener("change", updateMatch);
84
+ };
85
+ }, [query]);
86
+
87
+ return matches;
88
+ };
89
+
90
+ /**
91
+ * Adds a prefix specific to the carbon platform mdx components to the provided string. This is
92
+ * often used in conjunction with the scss utility `with-prefix` to assign unique class names to
93
+ * styles for components.
94
+ *
95
+ * @param {string} className The string to which to add a prefix.
96
+ * @returns A prefixed string.
97
+ */
98
+ function withPrefix(className: string) {
99
+ return prefix + "--" + className;
100
+ }
101
+
102
+ export { mediaQueries, useId, useMatchMedia, withPrefix };
@@ -0,0 +1,89 @@
1
+ /*
2
+ * Copyright OctaviaFlow 2021, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ @use '@carbon/react/scss/motion' as motion;
8
+ @use '@carbon/react/scss/colors' as colors;
9
+ @use '@carbon/react/scss/theme' as theme;
10
+ @use '@carbon/react/scss/spacing' as spacing;
11
+
12
+ @use '../utils' as *;
13
+
14
+ .#{with-prefix('video-container')} {
15
+ position: relative;
16
+ display: table;
17
+ inline-size: 100%;
18
+
19
+ .#{with-prefix('video')} {
20
+ block-size: 100%;
21
+ inline-size: 100%;
22
+ }
23
+
24
+ div.#{with-prefix('video-button')} {
25
+ position: absolute;
26
+ z-index: 10;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ border-radius: 50%;
31
+ margin: auto;
32
+ background-color: colors.$blue-60;
33
+ block-size: 4.5rem;
34
+ inline-size: 4.5rem;
35
+ inset-block: 0% 0%;
36
+ inset-inline: 0% 0%;
37
+ transition: all motion.$duration-moderate-01 motion(entrance, productive);
38
+
39
+ @media screen and (prefers-reduced-motion: reduce) {
40
+ transition: none;
41
+ }
42
+
43
+ &:focus {
44
+ outline: 2px solid theme.$focus;
45
+ outline-offset: -2px;
46
+ }
47
+
48
+ &:hover {
49
+ background-color: colors.$gray-90;
50
+ opacity: 0.8;
51
+ }
52
+ }
53
+
54
+ div.#{with-prefix('video-button')} > svg {
55
+ fill: theme.$icon-inverse;
56
+ margin-inline-start: spacing.$spacing-02;
57
+ transition: all motion.$duration-moderate-01 motion(entrance, productive);
58
+
59
+ @media screen and (prefers-reduced-motion: reduce) {
60
+ transition: none;
61
+ }
62
+ }
63
+
64
+ div.#{with-prefix('video--is-playing')} > svg {
65
+ margin-inline-start: 0;
66
+ }
67
+
68
+ // iframe
69
+ .#{with-prefix('vimeo')} {
70
+ position: relative;
71
+ overflow: hidden;
72
+ block-size: 0;
73
+ // hack to allow vimeo videos to display correctly and assume full inline-size available
74
+ padding-block-end: 56.543%;
75
+
76
+ iframe {
77
+ position: absolute;
78
+ block-size: 100%;
79
+ inline-size: 100%;
80
+ inset-block-start: 0;
81
+ inset-inline-start: 0;
82
+ }
83
+ }
84
+
85
+ &:not(:hover) div.#{with-prefix('video--is-playing')},
86
+ &:not(:hover) div.#{with-prefix('video--is-playing')} > svg {
87
+ opacity: 0;
88
+ }
89
+ }
Binary file
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright IBM Corp. 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import React from "react";
17
+ import { Video } from "./video";
18
+ import localPoster from "./local-poster.jpeg";
19
+ import localVideo from "./local-video.mp4";
20
+
21
+ export default {
22
+ title: "Components/MDX Components/Images & Video/Video",
23
+ component: Video,
24
+ argTypes: {
25
+ poster: {
26
+ type: "string",
27
+ },
28
+ src: {
29
+ type: "string",
30
+ },
31
+ vimeoId: {
32
+ type: "string",
33
+ },
34
+ },
35
+ };
36
+
37
+ const Template = (args) => (
38
+ <Video src={localVideo} poster={localPoster} {...args} />
39
+ );
40
+
41
+ export const Default = Template.bind({});
42
+ Default.args = {
43
+ width: 720,
44
+ height: 405,
45
+ };