Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion components/Icons.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -1944,8 +1944,9 @@ function ArrowCircleUp ({ className, width='16', height='16', color = '#766bff',
function ArrowUp ({ className, width='16', height='16', color = '#766bff', viewBox='0 0 16 16' }) {
return (
<svg width={width} height={height} viewBox={viewBox} fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
<path d="M6.0001 12.8811V1.42867M6.0001 1.42867V1.7382M6.0001 1.42867L10.3334 5.76203M6.0001 1.42867L1.66677 5.76203" stroke={color} strokeWidth="2" strokeMiterlimit="10" strokeLinecap={color} />
<path d="M6.0001 12.8811V1.42867M6.0001 1.42867V1.7382M6.0001 1.42867L10.3334 5.76203M6.0001 1.42867L1.66677 5.76203" stroke={color} strokeWidth="2" strokeMiterlimit="10" strokeLinecap="round" />
</svg>

)
}

Expand Down
28 changes: 27 additions & 1 deletion components/form/button/Button.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import classnames from 'classnames'
/**
* Buttons trigger actions when clicked.
*/
function Button ({ label, badge, primary, danger, loading, superSmall, small, large, wide, icon, iconWithLabel, active, block, disabled, onClick, className, buttonRef, id, alternative, chevron, type, title, round, roundedRectangle, hasSelection, selected, recording, highlighted }) {
function Button({ label, badge, primary, danger,
loading, superSmall, small, large, wide,
icon, iconWithLabel, active, block, disabled,
onClick, className, buttonRef, id, alternative,
chevron, type, title, round, roundedRectangle,
hasSelection, selected, recording, processing,
highlighted, disabledStyle,
}) {

const renderButtonContent = () => {
// Icon with label
Expand Down Expand Up @@ -56,7 +63,10 @@ function Button ({ label, badge, primary, danger, loading, superSmall, small, la
'button--has-selection': hasSelection,
'button--selected': selected,
'button--recording-indicator': recording && round,
'button--processing-indicator': processing && round,
'button--highlighted': highlighted && (round || roundedRectangle),
'button--disabled-dark': disabled && disabledStyle === 'dark' && (roundedRectangle || round),
'button--disabled-light': disabled && disabledStyle === 'light' && (roundedRectangle || round),
active,
}, className)}
disabled={disabled}
Expand All @@ -75,6 +85,10 @@ function Button ({ label, badge, primary, danger, loading, superSmall, small, la
{chevron && (
<span className="button__chevron"></span>
)}

{processing && round && (
<span className="button__processing-indicator"></span>
)}
</button>)
}

Expand Down Expand Up @@ -103,7 +117,9 @@ Button.defaultProps = {
hasSelection: false,
selected: false,
recording: false,
processing: false,
highlighted: false,
disabledStyle: 'light',
}

Button.propTypes = {
Expand Down Expand Up @@ -209,10 +225,20 @@ Button.propTypes = {
*/
recording: PropTypes.bool,

/**
* Whether this button is processing
*/
processing: PropTypes.bool,

/**
* Whether this button is highlighted
*/
highlighted: PropTypes.bool,

/**
* Style for the disabled button
*/
disabledStyle: PropTypes.oneOf(['dark', 'light']),
}

export default Button
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@b12/metronome",
"version": "1.1.24",
"version": "1.1.25",
"description": "",
"main": "index.es6.js",
"scripts": {
Expand Down
12 changes: 6 additions & 6 deletions src/react-demo/Buttons.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,20 @@ function Buttons () {
</div>

<CodeExample code={`
<Button round disabled icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" />} />
<Button round highlighted icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" />} />
<Button round disabled disabledStyle="dark" icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" color="#ffffff" />} />
<Button round highlighted icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" color="#ffffff" />} />
<Button round loading highlighted icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" />} />
<Button round highlighted icon={<Stop width={10} height={10} viewBox="0 0 10 10" />} />
<Button round disabled icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<Button round disabled disabledStyle="light" icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<Button round icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<Button round recording icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
`}
>
<Button round disabled icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" />} />
<Button round highlighted icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" />} />
<Button round disabled disabledStyle="dark" icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" color="#ffffff" />} />
<Button round highlighted icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" color="#ffffff" />} />
<Button round loading highlighted icon={<ArrowUp width={14} height={14} viewBox="0 0 12 14" />} />
<Button round highlighted icon={<Stop width={10} height={10} viewBox="0 0 10 10" />} />
<Button round disabled icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<Button round disabled disabledStyle="light" icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<Button round icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<Button round recording icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />} />
<br /><br />
Expand Down
37 changes: 22 additions & 15 deletions src/react-demo/PromptInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,28 +97,28 @@ export default function PromptInputPage () {
{
id: 'website-style',
label: 'Website style',
icon: <Website width={14} height={14} />,
icon: <Website width={14} height={14} color="#84839c" />,
itemOptions: mockWebsiteStyleOptions,
disabled: isProcessing || isRecording,
},
{
id: 'color',
label: 'Color',
icon: <EditColor width={14} height={14} />,
icon: <EditColor width={14} height={14} color="#84839c" />,
itemOptions: [{ value: 'none', color: null, label: 'None' }, ...mockColorOptions],
disabled: isProcessing || isRecording,
},
{
id: 'image-style',
label: 'Image style',
icon: <AiImage width={14} height={14} viewBox='0 0 14 12' />,
icon: <AiImage width={14} height={14} viewBox='0 0 14 12' color="#84839c" />,
itemOptions: mockImageStyleOptions,
disabled: isProcessing || isRecording,
},
{
id: 'enhance-prompt',
label: 'Enhance prompt',
icon: <AiAssist width={14} height={14} />,
icon: <AiAssist width={14} height={14} color="#84839c" />,
disabled: isTextareaEmpty || isProcessing || isRecording,
isActive: !isTextareaEmpty,
isEnhancing: isEnhancingPrompt || (isTypingPrompt && !isTypingFromRecording),
Expand Down Expand Up @@ -188,16 +188,22 @@ export default function PromptInputPage () {
setSelectedImageStyleTab(tabId)
}

// No need to add a progress state - the CSS animation handles the visual progress

const handleEnhancePrompt = () => {
if (isProcessing || isRecording) return

resetTyping()

setCanTriggerSend(false)

setIsEnhancingPrompt(true)
setIsSubmitting(true)

// The duration of the CSS animation (process-circle) should match this timeout
const processDuration = 1000

// Update the CSS variable for animation duration dynamically to match the process time
document.documentElement.style.setProperty('--processing-duration', `${processDuration}ms`)

enhancePromptTimerRef.current = window.setTimeout(() => {
setIsEnhancingPrompt(false)
setIsSubmitting(false)
Expand All @@ -214,7 +220,7 @@ export default function PromptInputPage () {
}

enhancePromptTimerRef.current = null
}, 1000)
}, processDuration)
}

const handleMicrophoneClick = () => {
Expand Down Expand Up @@ -381,7 +387,7 @@ export default function PromptInputPage () {
roundedRectangle
disabled={isProcessing || isRecording}
iconWithLabel
icon={<Website width={14} height={14} />}
icon={<Website width={14} height={14} color="#84839c" />}
label="Website style"
selected={activePopover === 'websiteStyle'}
/>
Expand All @@ -408,7 +414,7 @@ export default function PromptInputPage () {
roundedRectangle
disabled={isProcessing || isRecording}
iconWithLabel
icon={<EditColor width={14} height={14} />}
icon={<EditColor width={14} height={14} color="#84839c"/>}
label="Color" viewBox="0 0 14 14"
selected={activePopover === 'color'}
/>
Expand All @@ -430,7 +436,7 @@ export default function PromptInputPage () {
roundedRectangle
disabled={isProcessing || isRecording}
iconWithLabel
icon={<AiImage width={14} height={14} viewBox='0 0 14 12' />}
icon={<AiImage width={14} height={14} viewBox='0 0 14 12' color="#84839c" />}
label="Image style"
selected={activePopover === 'imageStyle'}
/>
Expand All @@ -452,7 +458,7 @@ export default function PromptInputPage () {
selected={isEnhancingPrompt || (isTypingPrompt && !isTypingFromRecording)}
onClick={handleEnhancePrompt}
iconWithLabel
icon={<AiAssist width={14} height={14} />}
icon={<AiAssist width={14} height={14} color="#84839c" />}
label="Enhance Prompt"
className="desktop-only"
/>
Expand All @@ -466,8 +472,7 @@ export default function PromptInputPage () {
className="mobile-only"
roundedRectangle
disabled={isProcessing || isRecording}
icon={<ThreeDots viewBox="0 0 23 7" width="16" height="5" />}
selected={activePopover === 'mobileOptions'}
icon={<ThreeDots viewBox="0 0 23 7" width="16" height="5" color="#84839c" />}
/>
}
>
Expand All @@ -493,14 +498,16 @@ export default function PromptInputPage () {
disabled={isProcessing && !isTypingFromRecording}
recording={isRecording}
onClick={handleMicrophoneClick}
icon={<Microphone width={14} height={14} viewBox="0 0 11 13" />}
icon={<Microphone width={14} height={14} viewBox="0 0 11 13" color="#ffffff" />}
/>
<Button
round
disabled={!isSubmitButtonActive || isRecording || isTypingFromRecording}
loading={isSubmitting && !isEnhancingPrompt}
highlighted={isSubmitButtonActive}
icon={ isSubmitting ? <Stop width={10} height={10} viewBox="0 0 10 10" /> :<ArrowUp width={14} height={14} viewBox="0 0 12 14" />}
disabledStyle="dark"
processing={isEnhancingPrompt}
icon={ isSubmitting ? <Stop width={10} height={10} viewBox="0 0 10 10" color="#ffffff" /> : <ArrowUp width={14} height={14} viewBox="0 0 12 14" color="#ffffff" />}
onClick={handleSubmitButtonClick}
/>
</PromptInputCommands>
Expand Down
76 changes: 76 additions & 0 deletions style/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@

&:disabled {
background: $ds-body-lighter-color;
opacity: 0.5;
}

&:enabled {
Expand Down Expand Up @@ -282,6 +283,32 @@
fill: $ds-brand-medium-color;
}
}

&:not(.button--selected):hover {
color: $ds-body-lighter-color;
}
}
}

// Disabled styles for round buttons
.button--round.button--disabled-dark {
opacity: 1 !important;
pointer-events: none;
cursor: not-allowed;
}

.button--round.button--disabled-light {
background-color: $ds-ui-background-color !important;
color: $ds-body-lighter-color;
opacity: 1 !important;
pointer-events: none;
cursor: not-allowed;
> svg {
path,
rect,
circle {
fill: $ds-body-lighter-color;
}
}
}

Expand Down Expand Up @@ -492,3 +519,52 @@
opacity: 0;
}
}

.button__processing-indicator {
position: absolute;
top: -4px;
left: -4px;
width: calc(100% + 8px);
height: calc(100% + 8px);
border-radius: 50%;
border: 2px solid transparent;
border-top-color: $ds-brand-medium-color;
animation: process-circle var(--processing-duration) linear forwards;
pointer-events: none;
box-sizing: border-box;
}

@keyframes process-circle {
0% {
transform: rotate(0deg);
border-top-color: $ds-brand-medium-color;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
25% {
transform: rotate(90deg);
border-top-color: $ds-brand-medium-color;
border-right-color: $ds-brand-medium-color;
border-bottom-color: transparent;
border-left-color: transparent;
}
50% {
transform: rotate(180deg);
border-top-color: $ds-brand-medium-color;
border-right-color: $ds-brand-medium-color;
border-bottom-color: $ds-brand-medium-color;
border-left-color: transparent;
}
75% {
transform: rotate(270deg);
border-top-color: $ds-brand-medium-color;
border-right-color: $ds-brand-medium-color;
border-bottom-color: $ds-brand-medium-color;
border-left-color: $ds-brand-medium-color;
}
100% {
transform: rotate(360deg);
border-color: $ds-brand-medium-color;
}
}
10 changes: 5 additions & 5 deletions style/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
@import 'forms/RangeSlider';
@import 'forms/ButtonGroup';
@import 'forms/ToggleButton';
@import 'forms/PromptInput.scss';
@import 'forms/PromptInput';

// Custom datetime picker css needs to be imported after react-datepicker
// library css file so custom css is not overwritten by defaults.
Expand Down Expand Up @@ -60,7 +60,7 @@
@import 'components/StatusIndicator';
@import 'components/TabbedNavigation';
@import 'components/NavIndicator';
@import 'components/Popover.scss';
@import 'components/ColorSwatchPickerDesktop.scss';
@import 'components/SwitchTabPicker.scss';
@import 'components/MobileOptionsPopover.scss';
@import 'components/Popover';
@import 'components/ColorSwatchPickerDesktop';
@import 'components/SwitchTabPicker';
@import 'components/MobileOptionsPopover';
3 changes: 2 additions & 1 deletion style/components/Popover.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
position: absolute;
bottom: 100%;
left: 0;
margin-bottom: 8px;
margin-bottom: 2px;
background: $ds-ui-lightest-color;
border: $ds-card-border;
border-radius: 6px;
Expand All @@ -18,5 +18,6 @@

@media (min-width: 993px) {
padding: 12px;
margin-bottom: 8px;
}
}
Loading