Skip to content

Commit 86bd45b

Browse files
committed
feat: redesign button
1 parent e86e8d5 commit 86bd45b

File tree

9 files changed

+112
-10
lines changed

9 files changed

+112
-10
lines changed

apps/docs/components/content/_components/button.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@
3838

3939
</Showcase>
4040

41+
### Blank button variants
42+
43+
You can remove the color styling from any variant by setting the `blank` prop to `true`, making it easy to create custom-styled buttons even for unique, one-off use cases in your codebase.
44+
45+
<Showcase showcase-name="Button/ButtonVariants" style="min-height:250px">
46+
47+
::vue-only
48+
<<<../../../../preview/nuxt/pages/showcases/Button/ButtonBlankVariants.vue
49+
::
50+
::react-only
51+
<<<../../../../preview/next/pages/showcases/Button/ButtonBlankVariants.tsx
52+
::
53+
54+
</Showcase>
55+
4156
### Button as a link
4257

4358
::vue-only
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ShowcasePageLayout } from '../../showcases';
2+
// #region source
3+
import { SfButton } from '@storefront-ui/react';
4+
5+
export default function ButtonVariants() {
6+
return (<>
7+
<div className="flex flex-col items-center space-y-4 xs:block xs:space-x-4">
8+
<SfButton variant="primary" blank className="text-white bg-neutral-700 hover:bg-neutral-800 active:bg-neutral-900">Hello</SfButton>
9+
10+
<SfButton variant="secondary" blank className="text-neutral-700 hover:text-neutral-800 active:text-neutral-900 ring-current hover:bg-neutral-100 active:bg-neutral-200">Hello</SfButton>
11+
12+
<SfButton variant="tertiary" blank className="text-neutral-500 hover:text-neutral-600 active:text-neutral-700 hover:bg-neutral-100 active:bg-neutral-200">Hello</SfButton>
13+
</div>
14+
<div className="flex flex-col items-center space-y-4 xs:block xs:space-x-4">
15+
<SfButton variant="primary" blank className="text-white bg-negative-700 hover:bg-negative-800 active:bg-negative-900">Hello</SfButton>
16+
17+
<SfButton variant="secondary" blank className="text-negative-700 hover:text-negative-800 active:text-negative-900 ring-current hover:bg-negative-100 active:bg-negative-200">Hello</SfButton>
18+
19+
<SfButton variant="tertiary" blank className="text-negative-700 hover:text-negative-800 active:text-negative-900 hover:bg-negative-100 active:bg-negative-200">Hello</SfButton>
20+
</div>
21+
</>);
22+
}
23+
24+
// #endregion source
25+
ButtonVariants.getLayout = ShowcasePageLayout;

apps/preview/nuxt/pages/examples/SfButton.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,14 @@ const { state, controlsAttrs } = prepareControls(
5757
{
5858
type: 'select',
5959
modelName: 'variant',
60+
description: 'Button style variant',
6061
options: Object.keys(SfButtonVariant),
6162
},
63+
{
64+
type: 'boolean',
65+
modelName: 'blank',
66+
description: 'Remove variant color classes from the button',
67+
},
6268
{
6369
type: 'select',
6470
modelName: 'size',
@@ -80,6 +86,7 @@ const { state, controlsAttrs } = prepareControls(
8086
suffix: ref(suffixSlotOptions.defaultOption),
8187
disabled: ref(),
8288
variant: ref<SfButtonVariant>(SfButtonVariant.primary),
89+
blank: ref(),
8390
size: ref<SfButtonSize>(SfButtonSize.base),
8491
tag: ref(),
8592
square: ref(),
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<div class="flex flex-col items-center space-y-4 xs:block xs:space-x-4">
3+
<SfButton variant="primary" blank class="text-white bg-neutral-700 hover:bg-neutral-800 active:bg-neutral-900"> Hello </SfButton>
4+
5+
<SfButton variant="secondary" blank class="text-neutral-700 hover:text-neutral-800 active:text-neutral-900 ring-current hover:bg-neutral-100 active:bg-neutral-200"> Hello </SfButton>
6+
7+
<SfButton variant="tertiary" blank class="text-neutral-500 hover:text-neutral-600 active:text-neutral-700 hover:bg-neutral-100 active:bg-neutral-200"> Hello </SfButton>
8+
</div>
9+
<div class="flex flex-col items-center space-y-4 xs:block xs:space-x-4">
10+
<SfButton variant="primary" blank class="text-white bg-negative-700 hover:bg-negative-800 active:bg-negative-900"> Hello </SfButton>
11+
12+
<SfButton variant="secondary" blank class="text-negative-700 hover:text-negative-800 active:text-negative-900 ring-current hover:bg-negative-100 active:bg-negative-200"> Hello </SfButton>
13+
14+
<SfButton variant="tertiary" blank class="text-negative-700 hover:text-negative-800 active:text-negative-900 hover:bg-negative-100 active:bg-negative-200"> Hello </SfButton>
15+
</div>
16+
</template>
17+
18+
<script lang="ts" setup>
19+
import { SfButton } from '@storefront-ui/vue';
20+
</script>

packages/sfui/frameworks/react/components/SfButton/SfButton.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@ import { type SfButtonProps, SfButtonSize, SfButtonVariant, polymorphicForwardRe
33

44
const defaultButtonTag = 'button';
55

6-
const variantClasses = {
6+
export const variantClasses = {
77
[SfButtonVariant.primary]:
8-
'text-white shadow hover:shadow-md active:shadow bg-primary-700 hover:bg-primary-800 active:bg-primary-900 disabled:bg-disabled-300',
8+
'shadow hover:shadow-md active:shadow disabled:bg-disabled-300',
99
[SfButtonVariant.secondary]:
10-
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900 ring-1 ring-inset ring-primary-700 hover:shadow-md active:shadow shadow hover:ring-primary-800 active:ring-primary-900 disabled:ring-1 disabled:ring-disabled-300 disabled:bg-white/50',
10+
'ring-1 ring-inset shadow hover:shadow-md active:shadow disabled:ring-1 disabled:ring-disabled-300 disabled:bg-white/50',
1111
[SfButtonVariant.tertiary]:
12-
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900 disabled:bg-transparent',
12+
'disabled:bg-transparent',
13+
};
14+
export const variantColorClasses = {
15+
[SfButtonVariant.primary]:
16+
'text-white bg-primary-700 hover:bg-primary-800 active:bg-primary-900',
17+
[SfButtonVariant.secondary]:
18+
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900 ring-primary-700 hover:ring-primary-800 active:ring-primary-900',
19+
[SfButtonVariant.tertiary]:
20+
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900',
1321
};
1422

1523
const getSizeClasses = (size: SfButtonProps['size'], square: SfButtonProps['square']) => {
@@ -29,6 +37,7 @@ const SfButton = polymorphicForwardRef<typeof defaultButtonTag, SfButtonProps>((
2937
className,
3038
size = SfButtonSize.base,
3139
variant = SfButtonVariant.primary,
40+
blank,
3241
square,
3342
children,
3443
slotPrefix,
@@ -42,9 +51,10 @@ const SfButton = polymorphicForwardRef<typeof defaultButtonTag, SfButtonProps>((
4251
ref={ref}
4352
type={typeof Tag === 'string' && Tag.toLowerCase() === 'button' ? 'button' : undefined}
4453
className={classNames(
45-
'inline-flex items-center justify-center font-medium text-base focus-visible:outline focus-visible:outline-offset rounded-md disabled:text-disabled-500 disabled:bg-disabled-300 disabled:shadow-none disabled:ring-0 disabled:cursor-not-allowed',
54+
'inline-flex items-center justify-center font-medium text-base focus-visible:outline focus-visible:outline-offset rounded-full disabled:text-disabled-500 disabled:bg-disabled-300 disabled:shadow-none disabled:ring-0 disabled:cursor-not-allowed',
4655
getSizeClasses(size, square),
4756
variantClasses[variant],
57+
{ [variantColorClasses[variant]]: !blank },
4858
className,
4959
)}
5060
data-testid="button"

packages/sfui/frameworks/react/components/SfButton/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ export interface SfButtonProps
1212
slotSuffix?: ReactNode;
1313
size?: `${SfButtonSize}`;
1414
variant?: `${SfButtonVariant}`;
15+
blank?: boolean;
1516
square?: boolean;
1617
}

packages/sfui/frameworks/vue/components/SfButton/SfButton.vue

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
<script lang="ts">
22
export const variantClasses = {
33
[SfButtonVariant.primary]:
4-
'text-white shadow hover:shadow-md active:shadow bg-primary-700 hover:bg-primary-800 active:bg-primary-900 disabled:bg-disabled-300',
4+
'shadow hover:shadow-md active:shadow disabled:bg-disabled-300',
55
[SfButtonVariant.secondary]:
6-
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900 ring-1 ring-inset ring-primary-700 shadow hover:shadow-md active:shadow hover:ring-primary-800 active:ring-primary-900 disabled:ring-1 disabled:ring-disabled-300 disabled:bg-white/50',
6+
'ring-1 ring-inset shadow hover:shadow-md active:shadow disabled:ring-1 disabled:ring-disabled-300 disabled:bg-white/50',
77
[SfButtonVariant.tertiary]:
8-
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900 disabled:bg-transparent',
8+
'disabled:bg-transparent',
9+
};
10+
export const variantColorClasses = {
11+
[SfButtonVariant.primary]:
12+
'text-white bg-primary-700 hover:bg-primary-800 active:bg-primary-900',
13+
[SfButtonVariant.secondary]:
14+
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900 ring-primary-700 hover:ring-primary-800 active:ring-primary-900',
15+
[SfButtonVariant.tertiary]:
16+
'text-primary-700 hover:bg-primary-100 hover:text-primary-800 active:bg-primary-200 active:text-primary-900',
917
};
1018
</script>
1119

@@ -22,6 +30,10 @@ const props = defineProps({
2230
type: String as PropType<`${SfButtonVariant}`>,
2331
default: SfButtonVariant.primary,
2432
},
33+
blank: {
34+
type: Boolean,
35+
default: false,
36+
},
2537
disabled: {
2638
type: Boolean,
2739
default: false,
@@ -65,9 +77,10 @@ const type = computed(
6577
:type="type"
6678
:disabled="disabled"
6779
:class="[
68-
'inline-flex items-center justify-center font-medium text-base focus-visible:outline focus-visible:outline-offset rounded-md disabled:text-disabled-500 disabled:bg-disabled-300 disabled:shadow-none disabled:ring-0 disabled:cursor-not-allowed',
80+
'inline-flex items-center justify-center font-medium text-base focus-visible:outline focus-visible:outline-offset rounded-full disabled:text-disabled-500 disabled:bg-disabled-300 disabled:shadow-none disabled:ring-0 disabled:cursor-not-allowed',
6981
sizeClasses,
7082
variantClasses[variant],
83+
{ [variantColorClasses[variant]]: !blank }
7184
]"
7285
data-testid="button"
7386
>

packages/sfui/frameworks/vue/components/SfSelect/SfSelect.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ keep it here, or to always pass modelValue to the component.
5151
*/
5252
const internalState = ref<string>(modelValue.value);
5353
const selectModel = computed({
54-
get: () => modelValue.value || internalState.value,
54+
get: () => modelValue.value || internalState.value,
5555
set: (value) => {
5656
emit('update:modelValue', value);
5757
internalState.value = value;

packages/tests/components/SfButton/SfButton.cy.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe('SfButton', () => {
1616
type InitializeComponentParams = {
1717
size?: SfButtonSize;
1818
variant?: SfButtonVariant;
19+
blank?: boolean;
1920
disabled?: boolean;
2021
square?: boolean;
2122
slotPrefix?: boolean;
@@ -25,6 +26,7 @@ describe('SfButton', () => {
2526
const initializeComponent = ({
2627
size = SfButtonSize.base,
2728
variant = SfButtonVariant.primary,
29+
blank,
2830
disabled,
2931
square,
3032
slotPrefix,
@@ -43,6 +45,7 @@ describe('SfButton', () => {
4345
props: {
4446
size,
4547
variant,
48+
blank,
4649
disabled,
4750
square,
4851
},
@@ -97,6 +100,14 @@ describe('SfButton', () => {
97100

98101
page().makeSnapshot();
99102
});
103+
104+
describe('when prop blank=true', () => {
105+
it(`should render correct ${componentVariant} variant`, () => {
106+
initializeComponent({ variant: componentVariant, blank: true });
107+
108+
page().makeSnapshot();
109+
});
110+
});
100111
});
101112
});
102113

0 commit comments

Comments
 (0)