@khanacademy/wonder-blocks-icon-button 10.1.0 → 10.2.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/.turbo/turbo-build$colon$css.log +1 -1
- package/CHANGELOG.md +35 -0
- package/dist/components/activity-icon-button.d.ts +50 -0
- package/dist/components/icon-button-unstyled.d.ts +2 -3
- package/dist/components/icon-button.d.ts +2 -3
- package/dist/es/index.js +8 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +9 -3
- package/dist/util/icon-button.types.d.ts +3 -0
- package/package.json +6 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @khanacademy/wonder-blocks-icon-button@10.
|
|
2
|
+
> @khanacademy/wonder-blocks-icon-button@10.2.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-icon-button
|
|
3
3
|
> pnpm exec wonder-blocks-tokens .
|
|
4
4
|
|
|
5
5
|
CSS variables generated successfully in: /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-icon-button/dist/css
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-icon-button
|
|
2
2
|
|
|
3
|
+
## 10.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b1ee2b4: Adds `chonky` category and `ActivityIconButton` component.
|
|
8
|
+
- 63ad56e: Adds `label` prop to `ActivityIconButton`. Modifies the types to expect one of `aria-label` or `label`.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- fa3e433: Fixes how the onPress handler is called when released. Updated unit tests and docs for IconButton
|
|
13
|
+
- Updated dependencies [b1ee2b4]
|
|
14
|
+
- Updated dependencies [7abcccf]
|
|
15
|
+
- Updated dependencies [9bacc1a]
|
|
16
|
+
- Updated dependencies [9bacc1a]
|
|
17
|
+
- Updated dependencies [7abcccf]
|
|
18
|
+
- Updated dependencies [1c3c335]
|
|
19
|
+
- Updated dependencies [689f5d3]
|
|
20
|
+
- Updated dependencies [7d2a646]
|
|
21
|
+
- @khanacademy/wonder-blocks-tokens@10.4.0
|
|
22
|
+
- @khanacademy/wonder-blocks-clickable@7.1.5
|
|
23
|
+
- @khanacademy/wonder-blocks-styles@0.2.12
|
|
24
|
+
- @khanacademy/wonder-blocks-typography@4.1.0
|
|
25
|
+
|
|
26
|
+
## 10.1.1
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [dd76e7c]
|
|
31
|
+
- @khanacademy/wonder-blocks-tokens@10.3.0
|
|
32
|
+
- @khanacademy/wonder-blocks-clickable@7.1.4
|
|
33
|
+
- @khanacademy/wonder-blocks-core@12.3.0
|
|
34
|
+
- @khanacademy/wonder-blocks-icon@5.1.4
|
|
35
|
+
- @khanacademy/wonder-blocks-styles@0.2.11
|
|
36
|
+
- @khanacademy/wonder-blocks-theming@3.4.0
|
|
37
|
+
|
|
3
38
|
## 10.1.0
|
|
4
39
|
|
|
5
40
|
### Minor Changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Link } from "react-router-dom-v5-compat";
|
|
3
|
+
import type { ActivityIconButtonActionType, IconButtonProps } from "../util/icon-button.types";
|
|
4
|
+
type AriaLabelOnly = {
|
|
5
|
+
/**
|
|
6
|
+
* The alternative text for the icon button. Use `aria-label` for when
|
|
7
|
+
* there's no visible label for the button, such as when the button only
|
|
8
|
+
* contains an icon.
|
|
9
|
+
*/
|
|
10
|
+
"aria-label": string;
|
|
11
|
+
label?: never;
|
|
12
|
+
};
|
|
13
|
+
type LabelOnly = {
|
|
14
|
+
"aria-label"?: never;
|
|
15
|
+
/**
|
|
16
|
+
* A label for the button that describes its action.
|
|
17
|
+
*
|
|
18
|
+
* NOTE: If `label` is set, then `aria-label` will be ignored.
|
|
19
|
+
*/
|
|
20
|
+
label: string;
|
|
21
|
+
};
|
|
22
|
+
type Props = Omit<IconButtonProps, "actionType" | "size"> & (AriaLabelOnly | LabelOnly) & {
|
|
23
|
+
/**
|
|
24
|
+
* The action type of the button. This determines the visual style of the
|
|
25
|
+
* button.
|
|
26
|
+
*
|
|
27
|
+
* - `progressive` is used for actions that move the user forward in a flow.
|
|
28
|
+
* - `neutral` is used for buttons that indicate a neutral action.
|
|
29
|
+
*/
|
|
30
|
+
actionType?: ActivityIconButtonActionType;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* `ActivityIconButton` is an icon button that is used for actions in the
|
|
34
|
+
* context of learner activities. It uses a "chonky" design, which is a more
|
|
35
|
+
* playful and engaging design that is suitable for learner activities
|
|
36
|
+
*
|
|
37
|
+
* ```tsx
|
|
38
|
+
* import magnifyingGlassIcon from
|
|
39
|
+
* "@phosphor-icons/core/regular/magnifying-glass.svg";
|
|
40
|
+
* import {ActivityIconButton} from "@khanacademy/wonder-blocks-icon-button";
|
|
41
|
+
*
|
|
42
|
+
* <ActivityIconButton
|
|
43
|
+
* icon={magnifyingGlassIcon}
|
|
44
|
+
* aria-label="An Icon"
|
|
45
|
+
* onClick={(e) => console.log("Hello, world!")}
|
|
46
|
+
* />
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare const ActivityIconButton: React.ForwardRefExoticComponent<Props & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
|
|
50
|
+
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import type { IconButtonProps } from "../util/icon-button.types";
|
|
2
|
+
import type { IconButtonProps, IconButtonRef } from "../util/icon-button.types";
|
|
4
3
|
type Props = Omit<IconButtonProps, "icon"> & {
|
|
5
4
|
/**
|
|
6
5
|
* The button content.
|
|
@@ -29,5 +28,5 @@ type Props = Omit<IconButtonProps, "icon"> & {
|
|
|
29
28
|
*/
|
|
30
29
|
onPress?: (isPressing: boolean) => unknown;
|
|
31
30
|
};
|
|
32
|
-
export declare const IconButtonUnstyled: React.ForwardRefExoticComponent<Props & React.RefAttributes<
|
|
31
|
+
export declare const IconButtonUnstyled: React.ForwardRefExoticComponent<Props & React.RefAttributes<IconButtonRef>>;
|
|
33
32
|
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import type { IconButtonProps } from "../util/icon-button.types";
|
|
2
|
+
import type { IconButtonProps, IconButtonRef } from "../util/icon-button.types";
|
|
4
3
|
/**
|
|
5
4
|
* An `IconButton` is a button whose contents are an SVG image.
|
|
6
5
|
*
|
|
@@ -40,4 +39,4 @@ import type { IconButtonProps } from "../util/icon-button.types";
|
|
|
40
39
|
* />
|
|
41
40
|
* ```
|
|
42
41
|
*/
|
|
43
|
-
export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<
|
|
42
|
+
export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<IconButtonRef>>;
|
package/dist/es/index.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { StyleSheet } from 'aphrodite';
|
|
4
4
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
5
5
|
import { focusStyles } from '@khanacademy/wonder-blocks-styles';
|
|
6
6
|
import { border, sizing, mapValuesToCssVars, semanticColor } from '@khanacademy/wonder-blocks-tokens';
|
|
7
7
|
import { Link, useInRouterContext } from 'react-router-dom-v5-compat';
|
|
8
|
-
import { addStyle, keys } from '@khanacademy/wonder-blocks-core';
|
|
8
|
+
import { addStyle, keys, View } from '@khanacademy/wonder-blocks-core';
|
|
9
9
|
import { isClientSideUrl } from '@khanacademy/wonder-blocks-clickable';
|
|
10
|
+
import { BodyText } from '@khanacademy/wonder-blocks-typography';
|
|
10
11
|
|
|
11
12
|
var themeDefault = {iconButton:{root:{border:{offset:{primary:border.width.medium,secondary:`calc(-1 * ${border.width.medium})`,tertiary:`calc(-1 * ${border.width.medium})`},width:{primary:{default:border.width.none,hover:border.width.medium,press:border.width.medium},secondary:{default:border.width.thin,hover:border.width.medium,press:border.width.medium},tertiary:{default:border.width.none,hover:border.width.medium,press:border.width.medium}},radius:{default:border.radius.radius_040,hover:border.radius.radius_040,press:border.radius.radius_040}},sizing:{xsmall:sizing.size_240,small:sizing.size_320,medium:sizing.size_400,large:sizing.size_480}},icon:{sizing:{xsmall:sizing.size_160,small:sizing.size_240,medium:sizing.size_240,large:sizing.size_240}}}};
|
|
12
13
|
|
|
13
14
|
var iconButtonTheme = mapValuesToCssVars(themeDefault,"--wb-c-icon-button-");
|
|
14
15
|
|
|
15
|
-
const StyledA=addStyle("a");const StyledButton=addStyle("button");const StyledLink=addStyle(Link);const IconButtonUnstyled=React.forwardRef(function IconButtonUnstyled(props,ref){const{children,disabled,href,onPress,skipClientNav,style,testId,type="button",...restProps}=props;const inRouterContext=useInRouterContext();const handleKeyDown=React.useCallback(e=>{const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){e.preventDefault();onPress?.(true);}},[href,onPress]);const handleKeyUp=React.useCallback(e=>{const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){if(restProps.onClick){restProps.onClick(e);onPress?.(false);}}
|
|
16
|
+
const StyledA=addStyle("a");const StyledButton=addStyle("button");const StyledLink=addStyle(Link);const IconButtonUnstyled=React.forwardRef(function IconButtonUnstyled(props,ref){const{children,disabled,href,onPress,skipClientNav,style,testId,type="button",...restProps}=props;const inRouterContext=useInRouterContext();const handleKeyDown=React.useCallback(e=>{const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){e.preventDefault();onPress?.(true);}},[href,onPress]);const handleKeyUp=React.useCallback(e=>{const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){if(restProps.onClick){restProps.onClick(e);}onPress?.(false);}},[href,onPress,restProps]);const commonProps={"data-testid":testId,style:[styles$2.shared,style],onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,...restProps};if(href&&!disabled){return inRouterContext&&!skipClientNav&&isClientSideUrl(href)?jsx(StyledLink,{...commonProps,to:href,ref:ref,children:children}):jsx(StyledA,{...commonProps,href:href,ref:ref,children:children})}else {return jsx(StyledButton,{type:type,...commonProps,onClick:disabled?undefined:restProps.onClick,"aria-disabled":disabled,ref:ref,children:children})}});const styles$2=StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",padding:0,cursor:"pointer",border:"none",outline:"none",textDecoration:"none",background:"none",margin:0,touchAction:"manipulation"}});
|
|
16
17
|
|
|
17
|
-
const theme=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme.icon.sizing[size],height:theme.icon.sizing[size]};switch(size){case"small":return jsx(PhosphorIcon,{size:"small",color:"currentColor",icon:icon,style:iconStyle});case"medium":default:return jsx(PhosphorIcon,{size:"medium",color:"currentColor",icon:icon,style:iconStyle})}}const IconButton=React.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",size="medium",style,type="button",...restProps}=props;const[pressed,setPressed]=React.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind,size);const styles=[buttonStyles.default,disabled&&buttonStyles.disabled,pressed&&buttonStyles.pressed,style];const handlePress=React.useCallback(isPressing=>{setPressed(isPressing);},[]);return jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,children:jsx(IconChooser,{size:size,icon:icon})})});const styles={};const _generateStyles=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const outlineOffsetKind=theme.root.border.offset[kind];const themeVariant=semanticColor.action[kind][actionType];const disabledState=semanticColor.action[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const pressStyles={outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",background:themeVariant.press.background,borderRadius:theme.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme.root.sizing[size],width:theme.root.sizing[size],borderRadius:theme.root.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,borderRadius:theme.root.border.radius.hover,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":pressStyles,...focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none",borderRadius:theme.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles[buttonType]=StyleSheet.create(newStyles);return styles[buttonType]};
|
|
18
|
+
const theme$1=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme$1.icon.sizing[size],height:theme$1.icon.sizing[size]};switch(size){case"small":return jsx(PhosphorIcon,{size:"small",color:"currentColor",icon:icon,style:iconStyle});case"medium":default:return jsx(PhosphorIcon,{size:"medium",color:"currentColor",icon:icon,style:iconStyle})}}const IconButton=React.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",size="medium",style,type="button",...restProps}=props;const[pressed,setPressed]=React.useState(false);const buttonStyles=_generateStyles$1(actionType,!!disabled,kind,size);const styles=[buttonStyles.default,disabled&&buttonStyles.disabled,pressed&&buttonStyles.pressed,style];const handlePress=React.useCallback(isPressing=>{setPressed(isPressing);},[]);return jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,children:jsx(IconChooser,{size:size,icon:icon})})});const styles$1={};const _generateStyles$1=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles$1[buttonType]){return styles$1[buttonType]}const borderWidthKind=theme$1.root.border.width[kind];const outlineOffsetKind=theme$1.root.border.offset[kind];const themeVariant=semanticColor.action[kind][actionType];const disabledState=semanticColor.action[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const pressStyles={outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",background:themeVariant.press.background,borderRadius:theme$1.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme$1.root.sizing[size],width:theme$1.root.sizing[size],borderRadius:theme$1.root.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,borderRadius:theme$1.root.border.radius.hover,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":pressStyles,...focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none",borderRadius:theme$1.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme$1.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles$1[buttonType]=StyleSheet.create(newStyles);return styles$1[buttonType]};
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
const ActivityIconButton=React.forwardRef(function ActivityIconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",style,type="button","aria-label":ariaLabel,label,...restProps}=props;const[pressed,setPressed]=React.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind);const styles=[buttonStyles.button,disabled&&buttonStyles.disabled,!disabled&&pressed&&buttonStyles.pressed,style];const chonkyStyles=[buttonStyles.chonky,disabled&&buttonStyles.chonkyDisabled,!disabled&&pressed&&buttonStyles.chonkyPressed];const handlePress=React.useCallback(isPressing=>{setPressed(isPressing);},[]);const hasVisibleLabel=label!==undefined&&label!=="";return jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,...!hasVisibleLabel?{"aria-label":ariaLabel}:{},children:jsxs(Fragment,{children:[jsx(View,{style:chonkyStyles,className:"chonky",children:jsx(PhosphorIcon,{size:"medium",color:"currentColor",icon:icon})}),hasVisibleLabel&&jsx(BodyText,{tag:"span",size:"medium",weight:"semi",style:buttonStyles.label,children:label})]})})});const theme={root:{border:{width:{primary:{rest:border.width.thin,hover:border.width.thin,press:border.width.thin},secondary:{rest:border.width.thin,hover:border.width.thin,press:border.width.thin},tertiary:{rest:border.width.thin,hover:border.width.thin,press:border.width.thin}},radius:border.radius.radius_120},layout:{padding:{block:sizing.size_140,inline:sizing.size_200}},shadow:{y:{rest:"6px",hover:"8px",press:sizing.size_0}}},label:{color:{progressive:semanticColor.core.foreground.instructive.default,neutral:semanticColor.core.foreground.neutral.default,disabled:semanticColor.core.foreground.disabled.default},layout:{width:sizing.size_640}}};const styles={};const _generateStyles=(actionType="progressive",disabled,kind)=>{const buttonType=`${actionType}-d_${disabled}-${kind}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const themeVariant=semanticColor.chonky[actionType];const disabledState=semanticColor.chonky.disabled;const disabledStatesStyles={outline:"none",transform:"none"};const chonkyDisabled={background:disabledState.background[kind],borderWidth:borderWidthKind.rest,borderColor:disabledState.border[kind],color:disabledState.foreground[kind],boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${disabledState.shadow[kind]}`,transform:"none"};const chonkyPressed={background:themeVariant.background[kind].press,border:`${borderWidthKind.press} solid ${themeVariant.border[kind].press}`,boxShadow:`0 ${theme.root.shadow.y.press} 0 0 ${themeVariant.shadow[kind].press}`,color:themeVariant.foreground[kind].press,transform:`translateY(${theme.root.shadow.y.rest})`};const newStyles={button:{borderRadius:theme.root.border.radius,color:theme.label.color[actionType],flexDirection:"column",gap:sizing.size_020,maxWidth:theme.label.layout.width,alignSelf:"flex-start",justifySelf:"center",[":is(:hover) .chonky"]:{background:themeVariant.background[kind].hover,border:`${borderWidthKind.hover} solid ${themeVariant.border[kind].hover}`,boxShadow:`0 ${theme.root.shadow.y.hover} 0 0 ${themeVariant.shadow[kind].hover}`,color:themeVariant.foreground[kind].hover,transform:`translateY(calc((${theme.root.shadow.y.hover} - ${theme.root.shadow.y.rest}) * -1))`},[":is(:active) .chonky"]:chonkyPressed,...focusStyles.focus},disabled:{cursor:"not-allowed",color:theme.label.color.disabled,...disabledStatesStyles,":hover":disabledStatesStyles,":active":disabledStatesStyles,":focus-visible":{transform:"none"},[":is(:hover) .chonky"]:disabledStatesStyles,[":is(:hover) .chonky"]:chonkyDisabled,[":is(:active) .chonky"]:chonkyDisabled},pressed:{[".chonky"]:chonkyPressed},chonky:{borderRadius:theme.root.border.radius,marginBlockEnd:theme.root.shadow.y.rest,paddingBlock:theme.root.layout.padding.block,paddingInline:theme.root.layout.padding.inline,background:themeVariant.background[kind].rest,border:`${borderWidthKind.rest} solid ${themeVariant.border[kind].rest}`,color:themeVariant.foreground[kind].rest,boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${themeVariant.shadow[kind].rest}`,transition:"all 0.12s ease-out",["@media not (hover: hover)"]:{transition:"none"}},chonkyPressed,chonkyDisabled,label:{margin:0,textAlign:"center",display:"-webkit-box",WebkitBoxOrient:"vertical",WebkitLineClamp:"2",overflow:"hidden",wordBreak:"break-word"}};styles[buttonType]=StyleSheet.create(newStyles);return styles[buttonType]};
|
|
21
|
+
|
|
22
|
+
export { ActivityIconButton, IconButton as default };
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
3
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
6
|
var React = require('react');
|
|
5
7
|
var aphrodite = require('aphrodite');
|
|
@@ -9,6 +11,7 @@ var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
|
9
11
|
var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
|
|
10
12
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
11
13
|
var wonderBlocksClickable = require('@khanacademy/wonder-blocks-clickable');
|
|
14
|
+
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
12
15
|
|
|
13
16
|
function _interopNamespace(e) {
|
|
14
17
|
if (e && e.__esModule) return e;
|
|
@@ -34,8 +37,11 @@ var themeDefault = {iconButton:{root:{border:{offset:{primary:wonderBlocksTokens
|
|
|
34
37
|
|
|
35
38
|
var iconButtonTheme = wonderBlocksTokens.mapValuesToCssVars(themeDefault,"--wb-c-icon-button-");
|
|
36
39
|
|
|
37
|
-
const StyledA=wonderBlocksCore.addStyle("a");const StyledButton=wonderBlocksCore.addStyle("button");const StyledLink=wonderBlocksCore.addStyle(reactRouterDomV5Compat.Link);const IconButtonUnstyled=React__namespace.forwardRef(function IconButtonUnstyled(props,ref){const{children,disabled,href,onPress,skipClientNav,style,testId,type="button",...restProps}=props;const inRouterContext=reactRouterDomV5Compat.useInRouterContext();const handleKeyDown=React__namespace.useCallback(e=>{const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){e.preventDefault();onPress?.(true);}},[href,onPress]);const handleKeyUp=React__namespace.useCallback(e=>{const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){if(restProps.onClick){restProps.onClick(e);onPress?.(false);}}
|
|
40
|
+
const StyledA=wonderBlocksCore.addStyle("a");const StyledButton=wonderBlocksCore.addStyle("button");const StyledLink=wonderBlocksCore.addStyle(reactRouterDomV5Compat.Link);const IconButtonUnstyled=React__namespace.forwardRef(function IconButtonUnstyled(props,ref){const{children,disabled,href,onPress,skipClientNav,style,testId,type="button",...restProps}=props;const inRouterContext=reactRouterDomV5Compat.useInRouterContext();const handleKeyDown=React__namespace.useCallback(e=>{const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){e.preventDefault();onPress?.(true);}},[href,onPress]);const handleKeyUp=React__namespace.useCallback(e=>{const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){if(restProps.onClick){restProps.onClick(e);}onPress?.(false);}},[href,onPress,restProps]);const commonProps={"data-testid":testId,style:[styles$2.shared,style],onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,...restProps};if(href&&!disabled){return inRouterContext&&!skipClientNav&&wonderBlocksClickable.isClientSideUrl(href)?jsxRuntime.jsx(StyledLink,{...commonProps,to:href,ref:ref,children:children}):jsxRuntime.jsx(StyledA,{...commonProps,href:href,ref:ref,children:children})}else {return jsxRuntime.jsx(StyledButton,{type:type,...commonProps,onClick:disabled?undefined:restProps.onClick,"aria-disabled":disabled,ref:ref,children:children})}});const styles$2=aphrodite.StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",padding:0,cursor:"pointer",border:"none",outline:"none",textDecoration:"none",background:"none",margin:0,touchAction:"manipulation"}});
|
|
41
|
+
|
|
42
|
+
const theme$1=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme$1.icon.sizing[size],height:theme$1.icon.sizing[size]};switch(size){case"small":return jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"small",color:"currentColor",icon:icon,style:iconStyle});case"medium":default:return jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"medium",color:"currentColor",icon:icon,style:iconStyle})}}const IconButton=React__namespace.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",size="medium",style,type="button",...restProps}=props;const[pressed,setPressed]=React__namespace.useState(false);const buttonStyles=_generateStyles$1(actionType,!!disabled,kind,size);const styles=[buttonStyles.default,disabled&&buttonStyles.disabled,pressed&&buttonStyles.pressed,style];const handlePress=React__namespace.useCallback(isPressing=>{setPressed(isPressing);},[]);return jsxRuntime.jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,children:jsxRuntime.jsx(IconChooser,{size:size,icon:icon})})});const styles$1={};const _generateStyles$1=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles$1[buttonType]){return styles$1[buttonType]}const borderWidthKind=theme$1.root.border.width[kind];const outlineOffsetKind=theme$1.root.border.offset[kind];const themeVariant=wonderBlocksTokens.semanticColor.action[kind][actionType];const disabledState=wonderBlocksTokens.semanticColor.action[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const pressStyles={outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",background:themeVariant.press.background,borderRadius:theme$1.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme$1.root.sizing[size],width:theme$1.root.sizing[size],borderRadius:theme$1.root.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,borderRadius:theme$1.root.border.radius.hover,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":pressStyles,...wonderBlocksStyles.focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none",borderRadius:theme$1.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme$1.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles$1[buttonType]=aphrodite.StyleSheet.create(newStyles);return styles$1[buttonType]};
|
|
38
43
|
|
|
39
|
-
const
|
|
44
|
+
const ActivityIconButton=React__namespace.forwardRef(function ActivityIconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",style,type="button","aria-label":ariaLabel,label,...restProps}=props;const[pressed,setPressed]=React__namespace.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind);const styles=[buttonStyles.button,disabled&&buttonStyles.disabled,!disabled&&pressed&&buttonStyles.pressed,style];const chonkyStyles=[buttonStyles.chonky,disabled&&buttonStyles.chonkyDisabled,!disabled&&pressed&&buttonStyles.chonkyPressed];const handlePress=React__namespace.useCallback(isPressing=>{setPressed(isPressing);},[]);const hasVisibleLabel=label!==undefined&&label!=="";return jsxRuntime.jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,...!hasVisibleLabel?{"aria-label":ariaLabel}:{},children:jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(wonderBlocksCore.View,{style:chonkyStyles,className:"chonky",children:jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"medium",color:"currentColor",icon:icon})}),hasVisibleLabel&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"span",size:"medium",weight:"semi",style:buttonStyles.label,children:label})]})})});const theme={root:{border:{width:{primary:{rest:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.thin,press:wonderBlocksTokens.border.width.thin},secondary:{rest:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.thin,press:wonderBlocksTokens.border.width.thin},tertiary:{rest:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.thin,press:wonderBlocksTokens.border.width.thin}},radius:wonderBlocksTokens.border.radius.radius_120},layout:{padding:{block:wonderBlocksTokens.sizing.size_140,inline:wonderBlocksTokens.sizing.size_200}},shadow:{y:{rest:"6px",hover:"8px",press:wonderBlocksTokens.sizing.size_0}}},label:{color:{progressive:wonderBlocksTokens.semanticColor.core.foreground.instructive.default,neutral:wonderBlocksTokens.semanticColor.core.foreground.neutral.default,disabled:wonderBlocksTokens.semanticColor.core.foreground.disabled.default},layout:{width:wonderBlocksTokens.sizing.size_640}}};const styles={};const _generateStyles=(actionType="progressive",disabled,kind)=>{const buttonType=`${actionType}-d_${disabled}-${kind}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const themeVariant=wonderBlocksTokens.semanticColor.chonky[actionType];const disabledState=wonderBlocksTokens.semanticColor.chonky.disabled;const disabledStatesStyles={outline:"none",transform:"none"};const chonkyDisabled={background:disabledState.background[kind],borderWidth:borderWidthKind.rest,borderColor:disabledState.border[kind],color:disabledState.foreground[kind],boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${disabledState.shadow[kind]}`,transform:"none"};const chonkyPressed={background:themeVariant.background[kind].press,border:`${borderWidthKind.press} solid ${themeVariant.border[kind].press}`,boxShadow:`0 ${theme.root.shadow.y.press} 0 0 ${themeVariant.shadow[kind].press}`,color:themeVariant.foreground[kind].press,transform:`translateY(${theme.root.shadow.y.rest})`};const newStyles={button:{borderRadius:theme.root.border.radius,color:theme.label.color[actionType],flexDirection:"column",gap:wonderBlocksTokens.sizing.size_020,maxWidth:theme.label.layout.width,alignSelf:"flex-start",justifySelf:"center",[":is(:hover) .chonky"]:{background:themeVariant.background[kind].hover,border:`${borderWidthKind.hover} solid ${themeVariant.border[kind].hover}`,boxShadow:`0 ${theme.root.shadow.y.hover} 0 0 ${themeVariant.shadow[kind].hover}`,color:themeVariant.foreground[kind].hover,transform:`translateY(calc((${theme.root.shadow.y.hover} - ${theme.root.shadow.y.rest}) * -1))`},[":is(:active) .chonky"]:chonkyPressed,...wonderBlocksStyles.focusStyles.focus},disabled:{cursor:"not-allowed",color:theme.label.color.disabled,...disabledStatesStyles,":hover":disabledStatesStyles,":active":disabledStatesStyles,":focus-visible":{transform:"none"},[":is(:hover) .chonky"]:disabledStatesStyles,[":is(:hover) .chonky"]:chonkyDisabled,[":is(:active) .chonky"]:chonkyDisabled},pressed:{[".chonky"]:chonkyPressed},chonky:{borderRadius:theme.root.border.radius,marginBlockEnd:theme.root.shadow.y.rest,paddingBlock:theme.root.layout.padding.block,paddingInline:theme.root.layout.padding.inline,background:themeVariant.background[kind].rest,border:`${borderWidthKind.rest} solid ${themeVariant.border[kind].rest}`,color:themeVariant.foreground[kind].rest,boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${themeVariant.shadow[kind].rest}`,transition:"all 0.12s ease-out",["@media not (hover: hover)"]:{transition:"none"}},chonkyPressed,chonkyDisabled,label:{margin:0,textAlign:"center",display:"-webkit-box",WebkitBoxOrient:"vertical",WebkitLineClamp:"2",overflow:"hidden",wordBreak:"break-word"}};styles[buttonType]=aphrodite.StyleSheet.create(newStyles);return styles[buttonType]};
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
exports.ActivityIconButton = ActivityIconButton;
|
|
47
|
+
exports["default"] = IconButton;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
|
|
3
3
|
import { PhosphorIconAsset } from "@khanacademy/wonder-blocks-icon";
|
|
4
|
+
import { Link } from "react-router-dom-v5-compat";
|
|
4
5
|
export type IconButtonKind = "primary" | "secondary" | "tertiary";
|
|
5
6
|
export type IconButtonSize = "xsmall" | "small" | "medium" | "large";
|
|
6
7
|
export type IconButtonActionType = "progressive" | "destructive" | "neutral";
|
|
8
|
+
export type ActivityIconButtonActionType = "progressive" | "neutral";
|
|
7
9
|
export type IconButtonProps = Partial<Omit<AriaProps, "aria-disabled">> & {
|
|
8
10
|
/**
|
|
9
11
|
* A unique identifier for the IconButton.
|
|
@@ -114,3 +116,4 @@ export type IconButtonProps = Partial<Omit<AriaProps, "aria-disabled">> & {
|
|
|
114
116
|
*/
|
|
115
117
|
onMouseDown?: (e: React.MouseEvent) => void;
|
|
116
118
|
};
|
|
119
|
+
export type IconButtonRef = typeof Link | HTMLButtonElement | HTMLAnchorElement;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-icon-button",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.2.0",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -20,12 +20,13 @@
|
|
|
20
20
|
"author": "",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@khanacademy/wonder-blocks-clickable": "7.1.
|
|
23
|
+
"@khanacademy/wonder-blocks-clickable": "7.1.5",
|
|
24
24
|
"@khanacademy/wonder-blocks-core": "12.3.0",
|
|
25
25
|
"@khanacademy/wonder-blocks-icon": "5.1.4",
|
|
26
|
-
"@khanacademy/wonder-blocks-styles": "0.2.
|
|
26
|
+
"@khanacademy/wonder-blocks-styles": "0.2.12",
|
|
27
27
|
"@khanacademy/wonder-blocks-theming": "3.4.0",
|
|
28
|
-
"@khanacademy/wonder-blocks-tokens": "10.
|
|
28
|
+
"@khanacademy/wonder-blocks-tokens": "10.4.0",
|
|
29
|
+
"@khanacademy/wonder-blocks-typography": "4.1.0"
|
|
29
30
|
},
|
|
30
31
|
"peerDependencies": {
|
|
31
32
|
"aphrodite": "^1.2.5",
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
"react-router-dom-v5-compat": "^6.30.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@khanacademy/wb-dev-build-settings": "3.
|
|
39
|
+
"@khanacademy/wb-dev-build-settings": "3.2.0"
|
|
39
40
|
},
|
|
40
41
|
"scripts": {
|
|
41
42
|
"build:css": "pnpm exec wonder-blocks-tokens .",
|