@workday/canvas-kit-labs-react 17.0.0-alpha.0645-next.0 → 17.0.0-alpha.0655-next.0
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.
- package/accessory/index.ts +6 -0
- package/accessory/lib/Accessory.tsx +156 -0
- package/accessory/lib/AccessoryCalendar.tsx +114 -0
- package/accessory/lib/AccessoryFavicon.tsx +156 -0
- package/accessory/lib/AccessoryFile.tsx +140 -0
- package/accessory/lib/AccessoryIcon.tsx +213 -0
- package/accessory/lib/AccessoryMedia.tsx +142 -0
- package/accessory/package.json +6 -0
- package/dist/commonjs/accessory/index.d.ts +7 -0
- package/dist/commonjs/accessory/index.d.ts.map +1 -0
- package/dist/commonjs/accessory/index.js +22 -0
- package/dist/commonjs/accessory/lib/Accessory.d.ts +157 -0
- package/dist/commonjs/accessory/lib/Accessory.d.ts.map +1 -0
- package/dist/commonjs/accessory/lib/Accessory.js +51 -0
- package/dist/commonjs/accessory/lib/AccessoryCalendar.d.ts +80 -0
- package/dist/commonjs/accessory/lib/AccessoryCalendar.d.ts.map +1 -0
- package/dist/commonjs/accessory/lib/AccessoryCalendar.js +48 -0
- package/dist/commonjs/accessory/lib/AccessoryFavicon.d.ts +75 -0
- package/dist/commonjs/accessory/lib/AccessoryFavicon.d.ts.map +1 -0
- package/dist/commonjs/accessory/lib/AccessoryFavicon.js +74 -0
- package/dist/commonjs/accessory/lib/AccessoryFile.d.ts +65 -0
- package/dist/commonjs/accessory/lib/AccessoryFile.d.ts.map +1 -0
- package/dist/commonjs/accessory/lib/AccessoryFile.js +58 -0
- package/dist/commonjs/accessory/lib/AccessoryIcon.d.ts +119 -0
- package/dist/commonjs/accessory/lib/AccessoryIcon.d.ts.map +1 -0
- package/dist/commonjs/accessory/lib/AccessoryIcon.js +61 -0
- package/dist/commonjs/accessory/lib/AccessoryMedia.d.ts +72 -0
- package/dist/commonjs/accessory/lib/AccessoryMedia.d.ts.map +1 -0
- package/dist/commonjs/accessory/lib/AccessoryMedia.js +59 -0
- package/dist/commonjs/ai-ingress-button/lib/AIIngressButton.js +5 -5
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +1 -0
- package/dist/commonjs/kbd/lib/KBD.js +6 -6
- package/dist/commonjs/kbd/lib/KBDItem.js +6 -6
- package/dist/commonjs/selection-group/lib/SelectionGroupIcon.js +1 -1
- package/dist/commonjs/selection-group/lib/SelectionGroupItem.js +4 -4
- package/dist/commonjs/selection-group/lib/SelectionGroupList.js +6 -6
- package/dist/commonjs/version/lib/version.js +1 -1
- package/dist/es6/accessory/index.d.ts +7 -0
- package/dist/es6/accessory/index.d.ts.map +1 -0
- package/dist/es6/accessory/index.js +6 -0
- package/dist/es6/accessory/lib/Accessory.d.ts +157 -0
- package/dist/es6/accessory/lib/Accessory.d.ts.map +1 -0
- package/dist/es6/accessory/lib/Accessory.js +48 -0
- package/dist/es6/accessory/lib/AccessoryCalendar.d.ts +80 -0
- package/dist/es6/accessory/lib/AccessoryCalendar.d.ts.map +1 -0
- package/dist/es6/accessory/lib/AccessoryCalendar.js +45 -0
- package/dist/es6/accessory/lib/AccessoryFavicon.d.ts +75 -0
- package/dist/es6/accessory/lib/AccessoryFavicon.d.ts.map +1 -0
- package/dist/es6/accessory/lib/AccessoryFavicon.js +71 -0
- package/dist/es6/accessory/lib/AccessoryFile.d.ts +65 -0
- package/dist/es6/accessory/lib/AccessoryFile.d.ts.map +1 -0
- package/dist/es6/accessory/lib/AccessoryFile.js +55 -0
- package/dist/es6/accessory/lib/AccessoryIcon.d.ts +119 -0
- package/dist/es6/accessory/lib/AccessoryIcon.d.ts.map +1 -0
- package/dist/es6/accessory/lib/AccessoryIcon.js +58 -0
- package/dist/es6/accessory/lib/AccessoryMedia.d.ts +72 -0
- package/dist/es6/accessory/lib/AccessoryMedia.d.ts.map +1 -0
- package/dist/es6/accessory/lib/AccessoryMedia.js +53 -0
- package/dist/es6/ai-ingress-button/lib/AIIngressButton.js +5 -5
- package/dist/es6/index.d.ts +1 -0
- package/dist/es6/index.d.ts.map +1 -1
- package/dist/es6/index.js +1 -0
- package/dist/es6/kbd/lib/KBD.js +6 -6
- package/dist/es6/kbd/lib/KBDItem.js +6 -6
- package/dist/es6/selection-group/lib/SelectionGroupIcon.js +1 -1
- package/dist/es6/selection-group/lib/SelectionGroupItem.js +4 -4
- package/dist/es6/selection-group/lib/SelectionGroupList.js +6 -6
- package/dist/es6/version/lib/version.js +1 -1
- package/index.ts +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {cornerShapeStencil, createComponent} from '@workday/canvas-kit-react/common';
|
|
2
|
+
import {systemIconStencil} from '@workday/canvas-kit-react/icon';
|
|
3
|
+
import {CSProps, createStencil, cssVar, handleCsProp} from '@workday/canvas-kit-styling';
|
|
4
|
+
import {base, component, system} from '@workday/canvas-tokens-web';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The size of an `Accessory` tile.
|
|
8
|
+
*
|
|
9
|
+
* * `extraSmall` — 16px tile, 16px icon
|
|
10
|
+
* * `small` — 20px tile, 18px icon
|
|
11
|
+
* * `medium` — 24px tile, 16px icon
|
|
12
|
+
* * `large` — 32px tile, 18px icon
|
|
13
|
+
* * `extraLarge` — 40px tile, 20px icon
|
|
14
|
+
*/
|
|
15
|
+
export type AccessorySize = 'extraSmall' | 'small' | 'medium' | 'large' | 'extraLarge';
|
|
16
|
+
|
|
17
|
+
export interface AccessoryProps extends CSProps {
|
|
18
|
+
/**
|
|
19
|
+
* The size of the tile. Icon glyph size follows the tile through the icon `data-part`: 16px,
|
|
20
|
+
* 18px, 16px, 18px, and 20px from `extraSmall` to `extraLarge`.
|
|
21
|
+
*
|
|
22
|
+
* * `extraSmall` — 16px
|
|
23
|
+
* * `small` — 20px
|
|
24
|
+
* * `medium` — 24px
|
|
25
|
+
* * `large` — 32px
|
|
26
|
+
* * `extraLarge` — 40px
|
|
27
|
+
*
|
|
28
|
+
* @default 'extraLarge'
|
|
29
|
+
*/
|
|
30
|
+
size?: AccessorySize;
|
|
31
|
+
/**
|
|
32
|
+
* The color of the icon. When set, this overrides the icon color from `variant` on
|
|
33
|
+
* `AccessoryIcon`. Inherited by the icon `data-part` via a CSS variable.
|
|
34
|
+
*/
|
|
35
|
+
color?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The background color of the icon tile. When set, this overrides the fill from `variant` and is
|
|
38
|
+
* painted at every size, including `small` and `extraSmall`. Inherited by the icon `data-part`
|
|
39
|
+
* via a CSS variable.
|
|
40
|
+
*/
|
|
41
|
+
background?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Tile shell for accessory visuals. Owns size, corner radius, icon glyph size, and optional icon
|
|
46
|
+
* color / fill overrides through the icon `data-part`. Prefer `AccessoryIcon`, `AccessoryFile`, or
|
|
47
|
+
* `AccessoryMedia`, which render this shell.
|
|
48
|
+
*/
|
|
49
|
+
export const accessoryStencil = createStencil({
|
|
50
|
+
extends: cornerShapeStencil,
|
|
51
|
+
vars: {
|
|
52
|
+
iconColor: '',
|
|
53
|
+
tileBackground: '',
|
|
54
|
+
},
|
|
55
|
+
parts: {
|
|
56
|
+
icon: 'accessory-icon',
|
|
57
|
+
},
|
|
58
|
+
base: ({iconColor, iconPart, shape}) => ({
|
|
59
|
+
display: 'inline-flex',
|
|
60
|
+
position: 'relative',
|
|
61
|
+
alignItems: 'center',
|
|
62
|
+
justifyContent: 'center',
|
|
63
|
+
flexShrink: 0,
|
|
64
|
+
verticalAlign: 'middle',
|
|
65
|
+
[iconPart]: {
|
|
66
|
+
position: 'absolute',
|
|
67
|
+
inset: 0,
|
|
68
|
+
display: 'flex',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
justifyContent: 'center',
|
|
71
|
+
borderRadius: shape,
|
|
72
|
+
cornerShape: 'superellipse(1.1)',
|
|
73
|
+
[systemIconStencil.vars.color]: cssVar(iconColor),
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
modifiers: {
|
|
77
|
+
size: {
|
|
78
|
+
extraSmall: ({iconPart, tileBackground}) => ({
|
|
79
|
+
width: system.legacy.size.xxxs,
|
|
80
|
+
height: system.legacy.size.xxxs,
|
|
81
|
+
[cornerShapeStencil.vars.shape]: system.legacy.shape.sm,
|
|
82
|
+
[iconPart]: {
|
|
83
|
+
[systemIconStencil.vars.size]: base.legacy.size200,
|
|
84
|
+
backgroundColor: cssVar(tileBackground, 'transparent'),
|
|
85
|
+
borderWidth: 0,
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
small: ({iconPart, tileBackground}) => ({
|
|
89
|
+
width: system.legacy.size.xxs,
|
|
90
|
+
height: system.legacy.size.xxs,
|
|
91
|
+
[cornerShapeStencil.vars.shape]: system.legacy.shape.sm,
|
|
92
|
+
[iconPart]: {
|
|
93
|
+
[systemIconStencil.vars.size]: base.legacy.size225,
|
|
94
|
+
backgroundColor: cssVar(tileBackground, 'transparent'),
|
|
95
|
+
borderWidth: 0,
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
medium: ({iconPart}) => ({
|
|
99
|
+
width: system.legacy.size.xs,
|
|
100
|
+
height: system.legacy.size.xs,
|
|
101
|
+
[cornerShapeStencil.vars.shape]: system.legacy.shape.md,
|
|
102
|
+
[iconPart]: {
|
|
103
|
+
[systemIconStencil.vars.size]: component.legacy.systemIcon.size.xs,
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
large: ({iconPart}) => ({
|
|
107
|
+
width: system.legacy.size.sm,
|
|
108
|
+
height: system.legacy.size.sm,
|
|
109
|
+
[cornerShapeStencil.vars.shape]: base.legacy.size125,
|
|
110
|
+
[iconPart]: {
|
|
111
|
+
[systemIconStencil.vars.size]: component.legacy.systemIcon.size.sm,
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
extraLarge: ({iconPart}) => ({
|
|
115
|
+
width: system.legacy.size.md,
|
|
116
|
+
height: system.legacy.size.md,
|
|
117
|
+
[cornerShapeStencil.vars.shape]: system.legacy.shape.lg,
|
|
118
|
+
[iconPart]: {
|
|
119
|
+
[systemIconStencil.vars.size]: component.legacy.systemIcon.size.md,
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* `Accessory` is the small rounded visual that sits beside text, most often the leading element in
|
|
128
|
+
* a list item or other row. It owns the tile size and corner radius so a system icon, file type,
|
|
129
|
+
* image, site favicon, calendar date, or custom content stays one consistent shape.
|
|
130
|
+
* `AccessoryIcon`, `AccessoryFile`, `AccessoryMedia`, `AccessoryFavicon`, and `AccessoryCalendar`
|
|
131
|
+
* render this shell. Accessories are
|
|
132
|
+
* decorative and always hidden from assistive technology.
|
|
133
|
+
*
|
|
134
|
+
* ```tsx
|
|
135
|
+
* <AccessoryIcon icon={activityIcon} />
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export const Accessory = createComponent('span')({
|
|
139
|
+
displayName: 'Accessory',
|
|
140
|
+
Component: (
|
|
141
|
+
{size = 'extraLarge', color, background, ...elemProps}: AccessoryProps,
|
|
142
|
+
ref,
|
|
143
|
+
Element
|
|
144
|
+
) => {
|
|
145
|
+
return (
|
|
146
|
+
<Element
|
|
147
|
+
ref={ref}
|
|
148
|
+
{...handleCsProp(
|
|
149
|
+
elemProps,
|
|
150
|
+
accessoryStencil({size, iconColor: color, tileBackground: background})
|
|
151
|
+
)}
|
|
152
|
+
aria-hidden={true}
|
|
153
|
+
/>
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {createComponent} from '@workday/canvas-kit-react/common';
|
|
2
|
+
import {createStencil, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
import {Accessory, AccessoryProps, accessoryStencil} from './Accessory';
|
|
6
|
+
|
|
7
|
+
export interface AccessoryCalendarProps extends AccessoryProps {
|
|
8
|
+
/**
|
|
9
|
+
* The month label, such as `Apr`.
|
|
10
|
+
*/
|
|
11
|
+
month: string;
|
|
12
|
+
/**
|
|
13
|
+
* The day of the month, such as `30`.
|
|
14
|
+
*/
|
|
15
|
+
date: number | string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Calendar treatment for `AccessoryCalendar`. The month uses a critical color. The day uses the
|
|
20
|
+
* default foreground color. `size` scales both. `color` overrides the month. `background`
|
|
21
|
+
* overrides the tile fill.
|
|
22
|
+
*/
|
|
23
|
+
export const accessoryCalendarStencil = createStencil({
|
|
24
|
+
parts: {
|
|
25
|
+
icon: 'accessory-icon',
|
|
26
|
+
month: 'accessory-calendar-month',
|
|
27
|
+
date: 'accessory-calendar-date',
|
|
28
|
+
},
|
|
29
|
+
base: ({datePart, iconPart, monthPart}) => ({
|
|
30
|
+
[iconPart]: {
|
|
31
|
+
flexDirection: 'column',
|
|
32
|
+
// 3px stack gap on the 40px tile, scaled with the tile.
|
|
33
|
+
gap: '0.075em',
|
|
34
|
+
overflow: 'hidden',
|
|
35
|
+
backgroundColor: cssVar(
|
|
36
|
+
accessoryStencil.vars.tileBackground,
|
|
37
|
+
system.legacy.color.surface.default
|
|
38
|
+
),
|
|
39
|
+
borderWidth: px2rem(1),
|
|
40
|
+
borderStyle: 'solid',
|
|
41
|
+
borderColor: system.legacy.color.border.default,
|
|
42
|
+
},
|
|
43
|
+
[monthPart]: {
|
|
44
|
+
color: cssVar(accessoryStencil.vars.iconColor, system.legacy.color.fg.danger.default),
|
|
45
|
+
fontSize: '0.25em',
|
|
46
|
+
fontWeight: system.fontWeight.medium,
|
|
47
|
+
lineHeight: 1,
|
|
48
|
+
whiteSpace: 'nowrap',
|
|
49
|
+
},
|
|
50
|
+
[datePart]: {
|
|
51
|
+
color: system.color.fg.default,
|
|
52
|
+
fontSize: '0.4em',
|
|
53
|
+
fontWeight: system.fontWeight.normal,
|
|
54
|
+
lineHeight: 1,
|
|
55
|
+
whiteSpace: 'nowrap',
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
modifiers: {
|
|
59
|
+
/**
|
|
60
|
+
* The icon part's font size matches the tile so month (`0.25em`) and day (`0.4em`) stay in
|
|
61
|
+
* proportion. At `extraLarge` that is 10px and 16px (`subtext.sm` and `body.sm`). Type tokens
|
|
62
|
+
* do not go below 10px, so smaller tiles keep the ratio instead of a fixed type level.
|
|
63
|
+
*/
|
|
64
|
+
size: {
|
|
65
|
+
extraSmall: ({iconPart}) => ({
|
|
66
|
+
[iconPart]: {fontSize: system.legacy.fontSize.body.sm},
|
|
67
|
+
}),
|
|
68
|
+
small: ({iconPart}) => ({
|
|
69
|
+
[iconPart]: {fontSize: system.legacy.fontSize.body.lg},
|
|
70
|
+
}),
|
|
71
|
+
medium: ({iconPart}) => ({
|
|
72
|
+
[iconPart]: {fontSize: system.legacy.fontSize.heading.sm},
|
|
73
|
+
}),
|
|
74
|
+
large: ({iconPart}) => ({
|
|
75
|
+
[iconPart]: {fontSize: system.legacy.fontSize.heading.lg},
|
|
76
|
+
}),
|
|
77
|
+
extraLarge: ({iconPart}) => ({
|
|
78
|
+
[iconPart]: {fontSize: system.legacy.fontSize.title.sm},
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
defaultModifiers: {
|
|
83
|
+
size: 'extraLarge',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* `AccessoryCalendar` renders a month and day in an accessory tile. The month is critical and the
|
|
89
|
+
* day is the default foreground color. Both scale with `size`. Always decorative.
|
|
90
|
+
*/
|
|
91
|
+
export const AccessoryCalendar = createComponent('span')({
|
|
92
|
+
displayName: 'AccessoryCalendar',
|
|
93
|
+
Component: (
|
|
94
|
+
{month, date, size = 'extraLarge', color, background, ...elemProps}: AccessoryCalendarProps,
|
|
95
|
+
ref,
|
|
96
|
+
Element
|
|
97
|
+
) => {
|
|
98
|
+
return (
|
|
99
|
+
<Accessory
|
|
100
|
+
as={Element}
|
|
101
|
+
ref={ref}
|
|
102
|
+
background={background}
|
|
103
|
+
color={color}
|
|
104
|
+
size={size}
|
|
105
|
+
{...handleCsProp(elemProps, accessoryCalendarStencil({size}))}
|
|
106
|
+
>
|
|
107
|
+
<span {...accessoryStencil.parts.icon}>
|
|
108
|
+
<span {...accessoryCalendarStencil.parts.month}>{month}</span>
|
|
109
|
+
<span {...accessoryCalendarStencil.parts.date}>{date}</span>
|
|
110
|
+
</span>
|
|
111
|
+
</Accessory>
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {createComponent} from '@workday/canvas-kit-react/common';
|
|
2
|
+
import {createStencil, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
|
|
3
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
4
|
+
|
|
5
|
+
import {Accessory, AccessoryProps, AccessorySize, accessoryStencil} from './Accessory';
|
|
6
|
+
|
|
7
|
+
/** Hostname from a site URL or a bare domain such as `workday.com`. */
|
|
8
|
+
function hostnameFromSiteUrl(siteUrl: string): string {
|
|
9
|
+
const trimmed = siteUrl.trim();
|
|
10
|
+
if (!trimmed) {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const withProtocol = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
16
|
+
return new URL(withProtocol).hostname || '';
|
|
17
|
+
} catch {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Brand favicon URL for a site, resolved through the public Google favicon endpoint. Tiles larger
|
|
24
|
+
* than 32px request a 180px source. Smaller tiles request 64px.
|
|
25
|
+
*/
|
|
26
|
+
function faviconSrcFromSiteUrl(siteUrl: string, size: AccessorySize): string {
|
|
27
|
+
const host = hostnameFromSiteUrl(siteUrl);
|
|
28
|
+
if (!host) {
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const sourceSize = size === 'extraLarge' ? 180 : 64;
|
|
33
|
+
return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(host)}&sz=${sourceSize}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface AccessoryFaviconProps extends AccessoryProps {
|
|
37
|
+
/**
|
|
38
|
+
* The site URL or bare domain, such as `https://design.workday.com` or `workday.com`. The hostname is
|
|
39
|
+
* used to resolve the favicon.
|
|
40
|
+
*/
|
|
41
|
+
url: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Favicon treatment for `AccessoryFavicon`. At `large` and `extraLarge` the mark is inset in an
|
|
46
|
+
* outlined tile. At `medium` and smaller the mark fills the tile and the frame is removed.
|
|
47
|
+
* `background` overrides the tile fill.
|
|
48
|
+
*/
|
|
49
|
+
export const accessoryFaviconStencil = createStencil({
|
|
50
|
+
parts: {
|
|
51
|
+
icon: 'accessory-icon',
|
|
52
|
+
image: 'accessory-favicon-image',
|
|
53
|
+
},
|
|
54
|
+
base: ({iconPart, imagePart}) => ({
|
|
55
|
+
[iconPart]: {
|
|
56
|
+
overflow: 'hidden',
|
|
57
|
+
backgroundColor: cssVar(
|
|
58
|
+
accessoryStencil.vars.tileBackground,
|
|
59
|
+
system.legacy.color.surface.default
|
|
60
|
+
),
|
|
61
|
+
borderWidth: px2rem(1),
|
|
62
|
+
borderStyle: 'solid',
|
|
63
|
+
borderColor: system.legacy.color.border.default,
|
|
64
|
+
},
|
|
65
|
+
[imagePart]: {
|
|
66
|
+
width: `calc(100% - ${system.legacy.padding.sm})`,
|
|
67
|
+
height: `calc(100% - ${system.legacy.padding.sm})`,
|
|
68
|
+
objectFit: 'contain',
|
|
69
|
+
borderRadius: system.legacy.shape.md,
|
|
70
|
+
cornerShape: 'superellipse(1.1)',
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
modifiers: {
|
|
74
|
+
size: {
|
|
75
|
+
extraSmall: ({iconPart, imagePart}) => ({
|
|
76
|
+
[iconPart]: {
|
|
77
|
+
backgroundColor: cssVar(accessoryStencil.vars.tileBackground, 'transparent'),
|
|
78
|
+
borderWidth: 0,
|
|
79
|
+
},
|
|
80
|
+
[imagePart]: {
|
|
81
|
+
width: '100%',
|
|
82
|
+
height: '100%',
|
|
83
|
+
borderRadius: 0,
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
86
|
+
small: ({iconPart, imagePart}) => ({
|
|
87
|
+
[iconPart]: {
|
|
88
|
+
backgroundColor: cssVar(accessoryStencil.vars.tileBackground, 'transparent'),
|
|
89
|
+
borderWidth: 0,
|
|
90
|
+
},
|
|
91
|
+
[imagePart]: {
|
|
92
|
+
width: '100%',
|
|
93
|
+
height: '100%',
|
|
94
|
+
borderRadius: 0,
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
medium: ({iconPart, imagePart}) => ({
|
|
98
|
+
[iconPart]: {
|
|
99
|
+
backgroundColor: cssVar(accessoryStencil.vars.tileBackground, 'transparent'),
|
|
100
|
+
borderWidth: 0,
|
|
101
|
+
},
|
|
102
|
+
[imagePart]: {
|
|
103
|
+
width: '100%',
|
|
104
|
+
height: '100%',
|
|
105
|
+
borderRadius: 0,
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
large: {},
|
|
109
|
+
extraLarge: {},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
defaultModifiers: {
|
|
113
|
+
size: 'extraLarge',
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* `AccessoryFavicon` renders a site favicon in an accessory tile. Pass a site URL or domain as
|
|
119
|
+
* `url`. The mark is inset in an outlined frame at `large` and `extraLarge`, and fills the tile at
|
|
120
|
+
* smaller sizes. Always decorative.
|
|
121
|
+
*
|
|
122
|
+
* The image is requested from the user's browser at `https://www.google.com/s2/favicons`. Google
|
|
123
|
+
* receives the hostname and the user's IP address. `referrerPolicy="no-referrer"` keeps the app
|
|
124
|
+
* origin off that request. It does not proxy the request.
|
|
125
|
+
*/
|
|
126
|
+
export const AccessoryFavicon = createComponent('span')({
|
|
127
|
+
displayName: 'AccessoryFavicon',
|
|
128
|
+
Component: (
|
|
129
|
+
{url, size = 'extraLarge', background, ...elemProps}: AccessoryFaviconProps,
|
|
130
|
+
ref,
|
|
131
|
+
Element
|
|
132
|
+
) => {
|
|
133
|
+
const src = faviconSrcFromSiteUrl(url, size);
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<Accessory
|
|
137
|
+
as={Element}
|
|
138
|
+
ref={ref}
|
|
139
|
+
background={background}
|
|
140
|
+
size={size}
|
|
141
|
+
{...handleCsProp(elemProps, accessoryFaviconStencil({size}))}
|
|
142
|
+
>
|
|
143
|
+
{src ? (
|
|
144
|
+
<span {...accessoryStencil.parts.icon}>
|
|
145
|
+
<img
|
|
146
|
+
alt=""
|
|
147
|
+
src={src}
|
|
148
|
+
{...accessoryFaviconStencil.parts.image}
|
|
149
|
+
referrerPolicy="no-referrer"
|
|
150
|
+
/>
|
|
151
|
+
</span>
|
|
152
|
+
) : null}
|
|
153
|
+
</Accessory>
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {createComponent} from '@workday/canvas-kit-react/common';
|
|
2
|
+
import {SystemIcon, SystemIconProps, systemIconStencil} from '@workday/canvas-kit-react/icon';
|
|
3
|
+
import {createStencil, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
|
|
4
|
+
import {
|
|
5
|
+
documentIcon,
|
|
6
|
+
pdfIcon,
|
|
7
|
+
playCircleIcon,
|
|
8
|
+
stackIcon,
|
|
9
|
+
tableExpandIcon,
|
|
10
|
+
txtIcon,
|
|
11
|
+
} from '@workday/canvas-system-icons-web';
|
|
12
|
+
import {system} from '@workday/canvas-tokens-web';
|
|
13
|
+
|
|
14
|
+
import {Accessory, AccessoryProps, accessoryStencil} from './Accessory';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The kind of file `AccessoryFile` represents.
|
|
18
|
+
*/
|
|
19
|
+
export type AccessoryFileType =
|
|
20
|
+
| 'pdf'
|
|
21
|
+
| 'spreadsheet'
|
|
22
|
+
| 'document'
|
|
23
|
+
| 'presentation'
|
|
24
|
+
| 'video'
|
|
25
|
+
| 'file'
|
|
26
|
+
| 'txt';
|
|
27
|
+
|
|
28
|
+
export interface AccessoryFileProps extends AccessoryProps {
|
|
29
|
+
/**
|
|
30
|
+
* The file type. Chooses the glyph and sets the tile fill and icon color through a stencil
|
|
31
|
+
* modifier. Colored types keep their accent fill at every size. `file` and `txt` use
|
|
32
|
+
* `surface.alt` with a `border.default` stroke. `video` uses `surface.alt` and an inverse icon.
|
|
33
|
+
* `color` and `background` override the type colors.
|
|
34
|
+
* @default 'file'
|
|
35
|
+
*/
|
|
36
|
+
type?: AccessoryFileType;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* File-type treatment for `AccessoryFile`. Each `type` sets the tile fill and icon color.
|
|
41
|
+
* `outline` adds the default border used by `file` and `txt`. `color` and `background` on
|
|
42
|
+
* `Accessory` still override the type colors.
|
|
43
|
+
*/
|
|
44
|
+
export const accessoryFileStencil = createStencil({
|
|
45
|
+
parts: {
|
|
46
|
+
icon: 'accessory-icon',
|
|
47
|
+
},
|
|
48
|
+
base: ({iconPart}) => ({
|
|
49
|
+
[iconPart]: {
|
|
50
|
+
backgroundColor: cssVar(accessoryStencil.vars.tileBackground),
|
|
51
|
+
[systemIconStencil.vars.color]: cssVar(accessoryStencil.vars.iconColor),
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
modifiers: {
|
|
55
|
+
type: {
|
|
56
|
+
pdf: {
|
|
57
|
+
[accessoryStencil.vars.iconColor]: system.color.fg.inverse,
|
|
58
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.accent.danger,
|
|
59
|
+
},
|
|
60
|
+
spreadsheet: {
|
|
61
|
+
[accessoryStencil.vars.iconColor]: system.color.fg.inverse,
|
|
62
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.accent.success,
|
|
63
|
+
},
|
|
64
|
+
document: {
|
|
65
|
+
[accessoryStencil.vars.iconColor]: system.color.fg.inverse,
|
|
66
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.accent.info,
|
|
67
|
+
},
|
|
68
|
+
presentation: {
|
|
69
|
+
// Amber is too light for an inverse glyph (about 2:1). `accent.contrast` is the dark
|
|
70
|
+
// foreground paired with accent fills.
|
|
71
|
+
[accessoryStencil.vars.iconColor]: system.legacy.color.accent.contrast,
|
|
72
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.accent.warning,
|
|
73
|
+
},
|
|
74
|
+
video: {
|
|
75
|
+
[accessoryStencil.vars.iconColor]: system.color.fg.default,
|
|
76
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.surface.alt.default,
|
|
77
|
+
},
|
|
78
|
+
file: {
|
|
79
|
+
[accessoryStencil.vars.iconColor]: system.color.fg.default,
|
|
80
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.surface.alt.default,
|
|
81
|
+
},
|
|
82
|
+
txt: {
|
|
83
|
+
[accessoryStencil.vars.iconColor]: system.color.fg.default,
|
|
84
|
+
[accessoryStencil.vars.tileBackground]: system.legacy.color.surface.alt.default,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
outline: {
|
|
88
|
+
true: ({iconPart}) => ({
|
|
89
|
+
[iconPart]: {
|
|
90
|
+
borderWidth: px2rem(1),
|
|
91
|
+
borderStyle: 'solid',
|
|
92
|
+
borderColor: system.legacy.color.border.default,
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
defaultModifiers: {
|
|
98
|
+
type: 'file',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const fileIcons: Record<AccessoryFileType, SystemIconProps['icon']> = {
|
|
103
|
+
pdf: pdfIcon,
|
|
104
|
+
spreadsheet: tableExpandIcon,
|
|
105
|
+
document: documentIcon,
|
|
106
|
+
presentation: stackIcon,
|
|
107
|
+
video: playCircleIcon,
|
|
108
|
+
file: documentIcon,
|
|
109
|
+
txt: txtIcon,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* `AccessoryFile` renders a file-type tile. `type` chooses the glyph and sets the fill and icon
|
|
114
|
+
* color. Colored types keep their fill at every size. Generic file and text use `surface.alt` and
|
|
115
|
+
* a `border.default` stroke. Always decorative.
|
|
116
|
+
*/
|
|
117
|
+
export const AccessoryFile = createComponent('span')({
|
|
118
|
+
displayName: 'AccessoryFile',
|
|
119
|
+
Component: (
|
|
120
|
+
{type = 'file', size = 'extraLarge', color, background, ...elemProps}: AccessoryFileProps,
|
|
121
|
+
ref,
|
|
122
|
+
Element
|
|
123
|
+
) => {
|
|
124
|
+
return (
|
|
125
|
+
<Accessory
|
|
126
|
+
as={Element}
|
|
127
|
+
ref={ref}
|
|
128
|
+
background={background}
|
|
129
|
+
color={color}
|
|
130
|
+
size={size}
|
|
131
|
+
{...handleCsProp(
|
|
132
|
+
elemProps,
|
|
133
|
+
accessoryFileStencil({type, outline: type === 'file' || type === 'txt'})
|
|
134
|
+
)}
|
|
135
|
+
>
|
|
136
|
+
<SystemIcon icon={fileIcons[type]} {...accessoryStencil.parts.icon} />
|
|
137
|
+
</Accessory>
|
|
138
|
+
);
|
|
139
|
+
},
|
|
140
|
+
});
|