Skip to content

Commit

Permalink
[Button] Create ButtonUnstyled and useButton (#27600)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaldudak committed Aug 30, 2021
1 parent 65da499 commit 5f30983
Show file tree
Hide file tree
Showing 36 changed files with 1,450 additions and 220 deletions.
23 changes: 23 additions & 0 deletions docs/pages/api-docs/button-unstyled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
import ApiPage from 'docs/src/modules/components/ApiPage';
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations';
import jsonPageContent from './button-unstyled.json';

export default function Page(props) {
const { descriptions, pageContent } = props;
return <ApiPage descriptions={descriptions} pageContent={pageContent} />;
}

Page.getInitialProps = () => {
const req = require.context(
'docs/translations/api-docs/button-unstyled',
false,
/button-unstyled.*.json$/,
);
const descriptions = mapApiPageTranslations(req);

return {
descriptions,
pageContent: jsonPageContent,
};
};
25 changes: 25 additions & 0 deletions docs/pages/api-docs/button-unstyled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"props": {
"action": {
"type": {
"name": "union",
"description": "func<br>&#124;&nbsp;{ current?: { focusVisible: func } }"
}
},
"component": { "type": { "name": "elementType" }, "default": "'button'" },
"components": {
"type": { "name": "shape", "description": "{ Root?: elementType }" },
"default": "{}"
},
"disabled": { "type": { "name": "bool" } }
},
"name": "ButtonUnstyled",
"styles": { "classes": [], "globalClasses": {}, "name": null },
"spread": true,
"forwardsRefTo": "HTMLButtonElement",
"filename": "/packages/material-ui-unstyled/src/ButtonUnstyled/ButtonUnstyled.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/buttons/\">Buttons</a></li></ul>",
"styledComponent": true,
"cssComponent": false
}
108 changes: 108 additions & 0 deletions docs/src/pages/components/buttons/UnstyledButtonCustom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import ButtonUnstyled, {
buttonUnstyledClasses,
} from '@material-ui/unstyled/ButtonUnstyled';
import { ThemeProvider, createTheme } from '@material-ui/core/styles';
import { styled, alpha } from '@material-ui/system';

const ButtonRoot = React.forwardRef(function ButtonRoot(props, ref) {
const { children, ...other } = props;

return (
<svg width="150" height="50" {...other} ref={ref}>
<polygon points="0,50 0,0 150,0 150,50" className="bg" />
<polygon points="0,50 0,0 150,0 150,50" className="borderEffect" />
<foreignObject x="0" y="0" width="150" height="50">
<div className="content">{children}</div>
</foreignObject>
</svg>
);
});

ButtonRoot.propTypes = {
children: PropTypes.node,
};

const CustomButtonRoot = styled(ButtonRoot)(
({ theme }) => `
overflow: visible;
cursor: pointer;
& polygon {
fill: transparent;
transition: all 800ms ease;
pointer-events: none;
}
& .bg {
stroke: ${theme.palette.primary.main};
stroke-width: 0.5;
filter: drop-shadow(0 4px 20px rgba(0, 0, 0, 0.1));
}
& .borderEffect {
stroke: ${theme.palette.primary.main};
stroke-width: 2;
stroke-dasharray: 150 600;
stroke-dashoffset: 150;
}
&:hover,
&.${buttonUnstyledClasses.focusVisible} {
.borderEffect {
stroke-dashoffset: -600;
}
.bg {
fill: ${alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity)};
}
}
&:focus,
&.${buttonUnstyledClasses.focusVisible} {
outline: none;
}
&.${buttonUnstyledClasses.active} {
& .bg {
fill: ${alpha(
theme.palette.primary.main,
theme.palette.action.activatedOpacity,
)};
transition: fill 300ms ease-out;
}
}
& foreignObject {
pointer-events: none;
& .content {
font-family: Helvetica, Inter, Arial, sans-serif;
font-size: 14px;
font-weight: 200;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: ${theme.palette.primary.main};
text-transform: uppercase;
}
& svg {
margin: 0 5px;
}
}`,
);

const SvgButton = React.forwardRef(function SvgButton(props, ref) {
return <ButtonUnstyled {...props} component={CustomButtonRoot} ref={ref} />;
});

export default function UnstyledButtonCustom() {
return (
<ThemeProvider theme={createTheme()}>
<SvgButton>Button</SvgButton>
</ThemeProvider>
);
}
110 changes: 110 additions & 0 deletions docs/src/pages/components/buttons/UnstyledButtonCustom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as React from 'react';
import ButtonUnstyled, {
ButtonUnstyledProps,
buttonUnstyledClasses,
} from '@material-ui/unstyled/ButtonUnstyled';
import { Theme, ThemeProvider, createTheme } from '@material-ui/core/styles';
import { styled, alpha } from '@material-ui/system';

const ButtonRoot = React.forwardRef(function ButtonRoot(
props: React.PropsWithChildren<{}>,
ref: React.ForwardedRef<any>,
) {
const { children, ...other } = props;

return (
<svg width="150" height="50" {...other} ref={ref}>
<polygon points="0,50 0,0 150,0 150,50" className="bg" />
<polygon points="0,50 0,0 150,0 150,50" className="borderEffect" />
<foreignObject x="0" y="0" width="150" height="50">
<div className="content">{children}</div>
</foreignObject>
</svg>
);
});

const CustomButtonRoot = styled(ButtonRoot)(
({ theme }: { theme: Theme }) => `
overflow: visible;
cursor: pointer;
& polygon {
fill: transparent;
transition: all 800ms ease;
pointer-events: none;
}
& .bg {
stroke: ${theme.palette.primary.main};
stroke-width: 0.5;
filter: drop-shadow(0 4px 20px rgba(0, 0, 0, 0.1));
}
& .borderEffect {
stroke: ${theme.palette.primary.main};
stroke-width: 2;
stroke-dasharray: 150 600;
stroke-dashoffset: 150;
}
&:hover,
&.${buttonUnstyledClasses.focusVisible} {
.borderEffect {
stroke-dashoffset: -600;
}
.bg {
fill: ${alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity)};
}
}
&:focus,
&.${buttonUnstyledClasses.focusVisible} {
outline: none;
}
&.${buttonUnstyledClasses.active} {
& .bg {
fill: ${alpha(
theme.palette.primary.main,
theme.palette.action.activatedOpacity,
)};
transition: fill 300ms ease-out;
}
}
& foreignObject {
pointer-events: none;
& .content {
font-family: Helvetica, Inter, Arial, sans-serif;
font-size: 14px;
font-weight: 200;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: ${theme.palette.primary.main};
text-transform: uppercase;
}
& svg {
margin: 0 5px;
}
}`,
);

const SvgButton = React.forwardRef(function SvgButton(
props: ButtonUnstyledProps,
ref: React.ForwardedRef<any>,
) {
return <ButtonUnstyled {...props} component={CustomButtonRoot} ref={ref} />;
});

export default function UnstyledButtonCustom() {
return (
<ThemeProvider theme={createTheme()}>
<SvgButton>Button</SvgButton>
</ThemeProvider>
);
}
52 changes: 52 additions & 0 deletions docs/src/pages/components/buttons/UnstyledButtonsSimple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import Stack from '@material-ui/core/Stack';
import ButtonUnstyled, {
buttonUnstyledClasses,
} from '@material-ui/unstyled/ButtonUnstyled';
import { styled } from '@material-ui/system';

const CustomButtonRoot = styled('button')(`
background-color: #007fff;
padding: 15px 20px;
border-radius: 10px;
color: #fff;
font-weight: 600;
font-family: Helvetica, Arial, sans-serif;
font-size: 14px;
transition: all 200ms ease;
cursor: pointer;
box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 0 rgba(0, 127, 255, 0);
border: none;
&:hover {
background-color: #0059b2;
}
&.${buttonUnstyledClasses.active} {
background-color: #004386;
}
&.${buttonUnstyledClasses.focusVisible} {
box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5);
outline: none;
}
&.${buttonUnstyledClasses.disabled} {
opacity: 0.5;
cursor: not-allowed;
box-shadow: 0 0 0 0 rgba(0, 127, 255, 0);
}
`);

function CustomButton(props) {
return <ButtonUnstyled {...props} component={CustomButtonRoot} />;
}

export default function UnstyledButton() {
return (
<Stack spacing={2} direction="row">
<CustomButton>Button</CustomButton>
<CustomButton disabled>Disabled</CustomButton>
</Stack>
);
}
53 changes: 53 additions & 0 deletions docs/src/pages/components/buttons/UnstyledButtonsSimple.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';
import Stack from '@material-ui/core/Stack';
import ButtonUnstyled, {
buttonUnstyledClasses,
ButtonUnstyledProps,
} from '@material-ui/unstyled/ButtonUnstyled';
import { styled } from '@material-ui/system';

const CustomButtonRoot = styled('button')(`
background-color: #007fff;
padding: 15px 20px;
border-radius: 10px;
color: #fff;
font-weight: 600;
font-family: Helvetica, Arial, sans-serif;
font-size: 14px;
transition: all 200ms ease;
cursor: pointer;
box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 0 rgba(0, 127, 255, 0);
border: none;
&:hover {
background-color: #0059b2;
}
&.${buttonUnstyledClasses.active} {
background-color: #004386;
}
&.${buttonUnstyledClasses.focusVisible} {
box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5);
outline: none;
}
&.${buttonUnstyledClasses.disabled} {
opacity: 0.5;
cursor: not-allowed;
box-shadow: 0 0 0 0 rgba(0, 127, 255, 0);
}
`);

function CustomButton(props: ButtonUnstyledProps) {
return <ButtonUnstyled {...props} component={CustomButtonRoot} />;
}

export default function UnstyledButton() {
return (
<Stack spacing={2} direction="row">
<CustomButton>Button</CustomButton>
<CustomButton disabled>Disabled</CustomButton>
</Stack>
);
}
Loading

0 comments on commit 5f30983

Please sign in to comment.