Closed pugnascotia closed 6 years ago
How about something like <KuiLink asButton={ true } />
? In addition I'd also expose functions to build link classes and button classes
KuiLink
already does this. If you don't pass an HREF it becomes a button. Check the docs.
Beautiful
Reopening because <KuiLink>
doesn't actually accomplish what we need, which would be a <KuiButton>
-styled <a>
tag.
I think doing <KuiButton href='/' />
should be possible, and it should render an anchor tag.
+1. Ideally I'd like to see button styling (fill, size, etc.) decoupled from the button
or a
tag, so that any combination can by employed. Similar to EuiTitle
vs the html hx
tags, though in this case with only two realistic options we shouldn't need to completely isolate them in usage; rather, override the html tag via a prop in EuiLink (a
-> button
) or EuiButton (button
-> a
).
After working around this in Cloud for a while, I think it's best to have the ability to easily use EuiButton rendering with anything, such as React Router's <Link>
or <button>
or <a>
, etc.
Here's what I went with for Cloud:
import React from 'react'
import { Link } from 'react-router'
import cx from 'classnames'
function CuiRouterLink({
LinkTag,
children,
className,
color = `primary`,
...other
}) {
const classes = cx(`euiLink euiLink--${ color }`, className)
return <LinkTag className={ classes } { ...other }>
{ children }
</LinkTag>
}
export function CuiLink({ ...props }) {
return <CuiRouterLink LinkTag={ Link } { ...props } />
}
// We can add a CuiIndexLink whenever that becomes necessary.
import React from 'react'
import { Link } from 'react-router'
import cx from 'classnames'
import { EuiIcon } from '@elastic/eui'
const sizeToClassNameMap = {
s: `euiButton--small`,
l: `euiButton--large`
}
function CuiButton({
LinkTag,
children,
className,
color = `primary`,
iconType,
size,
fill = false,
rawProps = {},
buttonClass = `euiButton`,
...other
}) {
const sizeClass = sizeToClassNameMap[size] || ``
const classes = cx(`${ buttonClass } ${ buttonClass }--${ color }`, sizeClass, {
[`${ buttonClass }--fill`]: fill
}, className)
const icon = iconType
? <EuiIcon className={ `${ buttonClass }__icon` } type={ iconType } />
: null
if (LinkTag === `input`) {
return <LinkTag className={ classes } { ...other } { ...rawProps } />
}
return <LinkTag className={ classes } { ...other } { ...rawProps }>
{ icon }
<span className={ `${ buttonClass }__content` }>
{ children }
</span>
</LinkTag>
}
export function CuiLinkButton({ ...props }) {
return <CuiButton LinkTag='a' { ...props } />
}
export function CuiLinkButtonEmpty({ ...props }) {
return <CuiButton LinkTag='a' { ...props } buttonClass='euiButtonEmpty' />
}
export function CuiRouterLinkButton({ ...props }) {
return <CuiButton LinkTag={ Link } { ...props } />
}
export function CuiRouterLinkButtonEmpty({ ...props }) {
return <CuiButton LinkTag={ Link } { ...props } buttonClass='euiButtonEmpty' />
}
export function CuiInputSubmitButton({ ...props }) {
return <CuiButton
LinkTag='input'
rawProps={ {
type: `submit`
} }
{ ...props } />
}
export function CuiSubmitButton({ ...props }) {
return <CuiButton
LinkTag='button'
fill={ true }
rawProps={ {
type: `submit`
} }
{ ...props } />
}
While it's doable, I'd rather not have consumers needing to use EUI classes, what if they change or something? In it's current state, consuming EUI classes directly is less than optimal (there's way too many classes)
FYI, still need this. @nreese had a need.
Another requested feature is to automatically append the attribute rel="noopener noreferrer"
when prop target="_blank"
https://github.com/elastic/kibana/pull/15995#issuecomment-356984388.
Sometimes we need to style a link like a button, which
KuiButton
can't do. react-bootstrap takes the approach of switch what element is rendered depending on whether anhref
is passed, so we could take that approach perhaps. I don't know if that gets tricker with e.g. react-router.