diff --git a/site/components/__tests__/__snapshots__/site-header.test.tsx.snap b/site/components/__tests__/__snapshots__/site-header.test.tsx.snap
index 63d1f197c2..823a12fc44 100644
--- a/site/components/__tests__/__snapshots__/site-header.test.tsx.snap
+++ b/site/components/__tests__/__snapshots__/site-header.test.tsx.snap
@@ -137,6 +137,21 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
fill: #C0C0C0;
}
+.emotion-4:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-4:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-4 {
transition-property: background-color;
@@ -365,6 +380,68 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
justify-self: start;
}
+.emotion-17 {
+ display: inline-block;
+ color: #577FFB;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+}
+
+@media screen and (prefers-reduced-motion: no-preference) {
+ .emotion-17 {
+ transition-property: color,fill;
+ transition-duration: 200ms,200ms;
+ transition-timing-function: cubic-bezier(0, 0, .5, 1),cubic-bezier(0, 0, .5, 1);
+ }
+}
+
+@media screen and (prefers-reduced-motion: reduce) {
+ .emotion-17 {
+ transition-property: color,fill;
+ transition-duration: 0ms;
+ transition-timing-function: cubic-bezier(0, 0, .5, 1),cubic-bezier(0, 0, .5, 1);
+ }
+}
+
+.emotion-17 svg {
+ fill: #577FFB;
+}
+
+.emotion-17:hover:not(:disabled) {
+ color: #3358CC;
+ -webkit-text-decoration: underline;
+ text-decoration: underline;
+}
+
+.emotion-17:hover:not(:disabled) svg {
+ fill: #3358CC;
+}
+
+.emotion-17:active:not(:disabled) {
+ color: #213A82;
+ -webkit-text-decoration: underline;
+ text-decoration: underline;
+}
+
+.emotion-17:active:not(:disabled) svg {
+ fill: #213A82;
+}
+
+.emotion-17:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-17:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
.emotion-22 {
grid-area: menu;
justify-self: start;
@@ -468,6 +545,21 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
text-decoration: none;
}
+.emotion-25:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-25:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-25 {
transition-property: background-color;
@@ -585,6 +677,21 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
text-decoration: none;
}
+.emotion-30:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-30:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-30 {
transition-property: background-color;
@@ -681,6 +788,21 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
fill: #C0C0C0;
}
+.emotion-50:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-50:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-50 {
transition-property: background-color;
@@ -791,6 +913,21 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
background-color: #CCCCCC;
}
+.emotion-57:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-57:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-57 {
transition-property: background-color;
@@ -953,7 +1090,7 @@ exports[`SiteHeader has first item highlighted (About) if we are on a section wi
class="emotion-16"
>
{
+ const filter0 = getSSRId();
+ const filter1 = getSSRId();
+
+ return (
+
+ );
+};
+
+export default CheckedFocusVisibleHover;
diff --git a/site/components/illustrations/theme/style-presets/checked-invalid-focus-visible-hover.tsx b/site/components/illustrations/theme/style-presets/checked-invalid-focus-visible-hover.tsx
new file mode 100644
index 0000000000..3d82ee4fef
--- /dev/null
+++ b/site/components/illustrations/theme/style-presets/checked-invalid-focus-visible-hover.tsx
@@ -0,0 +1,145 @@
+import React from 'react';
+import {getSSRId} from 'newskit';
+import {Svg} from '../../svg';
+import {Path} from '../../path';
+import {Rect} from '../../rect';
+
+export const CheckedInvalidFocusVisibleHover: React.FC = () => {
+ const filter0 = getSSRId();
+ const filter1 = getSSRId();
+
+ return (
+
+ );
+};
+
+export default CheckedInvalidFocusVisibleHover;
diff --git a/site/components/illustrations/theme/style-presets/checked-valid-focus-visible-hover.tsx b/site/components/illustrations/theme/style-presets/checked-valid-focus-visible-hover.tsx
new file mode 100644
index 0000000000..2f5358edac
--- /dev/null
+++ b/site/components/illustrations/theme/style-presets/checked-valid-focus-visible-hover.tsx
@@ -0,0 +1,141 @@
+import React from 'react';
+import {getSSRId} from 'newskit';
+import {Svg} from '../../svg';
+import {Path} from '../../path';
+import {Rect} from '../../rect';
+
+export const CheckedValidFocusVisibleHover: React.FC = () => {
+ const filter0 = getSSRId();
+ const filter1 = getSSRId();
+
+ return (
+
+ );
+};
+
+export default CheckedValidFocusVisibleHover;
diff --git a/site/components/illustrations/theme/style-presets/focus-visible-hover.tsx b/site/components/illustrations/theme/style-presets/focus-visible-hover.tsx
new file mode 100644
index 0000000000..f2906159ea
--- /dev/null
+++ b/site/components/illustrations/theme/style-presets/focus-visible-hover.tsx
@@ -0,0 +1,131 @@
+import React from 'react';
+import {getSSRId} from 'newskit';
+import {Svg} from '../../svg';
+import {Path} from '../../path';
+import {Rect} from '../../rect';
+
+export const FocusVisibleHover: React.FC = () => {
+ const filter0 = getSSRId();
+ const filter1 = getSSRId();
+
+ return (
+
+ );
+};
+
+export default FocusVisibleHover;
diff --git a/site/components/illustrations/theme/style-presets/invalid-focus-visible-hover.tsx b/site/components/illustrations/theme/style-presets/invalid-focus-visible-hover.tsx
new file mode 100644
index 0000000000..3cafcf0631
--- /dev/null
+++ b/site/components/illustrations/theme/style-presets/invalid-focus-visible-hover.tsx
@@ -0,0 +1,143 @@
+import React from 'react';
+import {getSSRId} from 'newskit';
+import {Svg} from '../../svg';
+import {Path} from '../../path';
+import {Rect} from '../../rect';
+
+export const InvalidFocusVisibleHover: React.FC = () => {
+ const filter0 = getSSRId();
+ const filter1 = getSSRId();
+
+ return (
+
+ );
+};
+
+export default InvalidFocusVisibleHover;
diff --git a/site/components/illustrations/theme/style-presets/valid-focus-visible-hover.tsx b/site/components/illustrations/theme/style-presets/valid-focus-visible-hover.tsx
new file mode 100644
index 0000000000..86c1bc0c86
--- /dev/null
+++ b/site/components/illustrations/theme/style-presets/valid-focus-visible-hover.tsx
@@ -0,0 +1,139 @@
+import React from 'react';
+import {getSSRId} from 'newskit';
+import {Svg} from '../../svg';
+import {Path} from '../../path';
+import {Rect} from '../../rect';
+
+export const ValidFocusVisibleHover: React.FC = () => {
+ const filter0 = getSSRId();
+ const filter1 = getSSRId();
+
+ return (
+
+ );
+};
+
+export default ValidFocusVisibleHover;
diff --git a/site/components/meta/__tests__/__snapshots__/meta.test.tsx.snap b/site/components/meta/__tests__/__snapshots__/meta.test.tsx.snap
index 66243640d3..faa7fe7b4b 100644
--- a/site/components/meta/__tests__/__snapshots__/meta.test.tsx.snap
+++ b/site/components/meta/__tests__/__snapshots__/meta.test.tsx.snap
@@ -420,6 +420,21 @@ exports[`Meta renders with mandatory props 1`] = `
fill: #C0C0C0;
}
+.emotion-26:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-26:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-26 {
transition-property: background-color;
@@ -1483,6 +1498,21 @@ exports[`Meta renders with mandatory props and figma button 1`] = `
fill: #C0C0C0;
}
+.emotion-26:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-26:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-26 {
transition-property: background-color;
@@ -2594,6 +2624,21 @@ exports[`Meta renders with mandatory props and version above v5 1`] = `
fill: #5E44E4;
}
+.emotion-23:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-23:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
.emotion-24 {
display: -webkit-box;
display: -webkit-flex;
@@ -2766,6 +2811,21 @@ exports[`Meta renders with mandatory props and version above v5 1`] = `
fill: #C0C0C0;
}
+.emotion-32:focus-visible:not(:disabled) {
+ outline-color: #3768FB;
+ outline-style: solid;
+ outline-width: 2px;
+ outline-offset: 2px;
+}
+
+@media not all and (min-resolution: 0.001dpcm) {
+ @supports (-webkit-appearance: none) and (stroke-color: transparent) {
+ .emotion-32:focus-visible:not(:disabled) {
+ outline-style: auto;
+ }
+ }
+}
+
@media screen and (prefers-reduced-motion: no-preference) {
.emotion-32 {
transition-property: background-color;
diff --git a/site/components/outline-card/index.ts b/site/components/outline-card/index.ts
new file mode 100644
index 0000000000..cf023c77bf
--- /dev/null
+++ b/site/components/outline-card/index.ts
@@ -0,0 +1 @@
+export * from './outline-card';
diff --git a/site/components/outline-card/outline-card.tsx b/site/components/outline-card/outline-card.tsx
new file mode 100644
index 0000000000..e13914f0e2
--- /dev/null
+++ b/site/components/outline-card/outline-card.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import {
+ getBorderCssFromTheme,
+ getOutlineCssFromTheme,
+ getColorCssFromTheme,
+ getSizingCssFromTheme,
+ styled,
+ newskitLightTheme,
+ compileTheme,
+} from 'newskit';
+
+export interface OutlineCardProps {
+ outlineStyleToken?: string;
+ outlineWidthToken?: string;
+ outlineOffsetToken?: string;
+ safariOutlineStyleToken?: string;
+ safariOutlineOffsetToken?: string;
+}
+
+const compiledNewskitLightTheme = compileTheme(newskitLightTheme);
+
+const StyledOutlineCard = styled.div<{
+ outlineStyleToken: string;
+ outlineWidthToken: string;
+ outlineOffsetToken: string;
+ safariOutlineStyleToken?: string;
+ safariOutlineOffsetToken?: string;
+}>`
+ display: flex;
+ ${getSizingCssFromTheme('width', 'sizing100')};
+ ${getSizingCssFromTheme('height', 'sizing100')};
+ ${getSizingCssFromTheme('margin-left', 'sizing010')};
+ border: solid;
+ ${getColorCssFromTheme('borderColor', 'interface060')};
+ ${getColorCssFromTheme('background', 'interface020')};
+
+ ${getBorderCssFromTheme(
+ 'borderRadius',
+ 'borderRadiusRounded020',
+ )({theme: compiledNewskitLightTheme})};
+
+ ${getOutlineCssFromTheme(
+ 'outlineColor',
+ 'outlineColorDefault',
+ )({theme: compiledNewskitLightTheme})};
+
+ ${({outlineStyleToken}) =>
+ getOutlineCssFromTheme(
+ 'outlineStyle',
+ outlineStyleToken,
+ )({theme: compiledNewskitLightTheme})};
+
+ ${({outlineWidthToken}) =>
+ getOutlineCssFromTheme(
+ 'outlineWidth',
+ outlineWidthToken,
+ )({theme: compiledNewskitLightTheme})};
+
+ ${({outlineOffsetToken}) =>
+ getOutlineCssFromTheme(
+ 'outlineOffset',
+ outlineOffsetToken,
+ )({theme: compiledNewskitLightTheme})};
+
+ ${({safariOutlineStyleToken}) =>
+ safariOutlineStyleToken &&
+ getOutlineCssFromTheme(
+ 'outlineStyle',
+ safariOutlineStyleToken,
+ )({theme: compiledNewskitLightTheme})};
+
+ ${({safariOutlineOffsetToken}) =>
+ safariOutlineOffsetToken &&
+ getOutlineCssFromTheme(
+ 'outlineOffset',
+ safariOutlineOffsetToken,
+ )({theme: compiledNewskitLightTheme})};
+`;
+
+export const OutlineCard: React.FC
+
+
+
{codeExamples[section]}
+ + Default outline-style is solid, but auto for Safari this ensures rounded + edges +
+ ++ Not setting safariOutlineStyle in a custom style preset will result in + sqaure outline +
+Safari default is auto so you don't get to control color
+A none auto outline style will allow color to change in Safari
+outlineOffset is set to 2px. safariOutlineOffset is set to 5px
+