Icon link without text eslint error - accessibility

I have a React project that shows a bunch of social media links that are just icons to their respective sites. I use icomoon fonts and whatnot to provide the icon-* classes to show the social media icons.
The error I get, understandably, is:
Anchors must have content and the content must be accessible by a screen reader
What should I do in this scenario where I don't want anything but the icon and no text? I'm not sure how to properly do this so everyone's happy.
Edit
I didn't think code was necessary since it doesn't pertain to anything really.
Here's the mapping that spits out the links. As you can see, no text. Just font-icons for whatever social media site is being linked to:
{this.props.siteInfo.social.map(function(item, i){
return <a key={i} className={`nav_item icon-${item.social_media_type}-square`} href={item.url} target="_blank" rel="noopener noreferrer"></a>
})}
Which results in:
<a key="0" class="nav_item icon-facebook-square" href="facebook.com/someprofile" target="_blank" rel="noopener noreferrer"></a>

I got the same problem and I solved it by just adding one white space
<a><i class="fa fa-phone" aria-hidden="true"></i> </a>

I found my answer here:
https://silktide.com/i-thought-title-text-improved-accessibility-i-was-wrong/
It seems you should add a some text that you can hide via CSS, although not with display:none; or anything of that sort. Screen readers will ignore that.
I'm not sure if this is the most current way to do things, but it does work and achieves accessibility and eslint is happy.

I encountered the same problem, solved it like this with React (same suggestion as #danielInixon
const IconLink = props => {
const { name } = props;
return <a aria-label={name} href="https://github.com/johnb8005/svg">
<i className={`fa fa-${name}`} aria-hidden="true"/>
</a>;
};

I solved it with the CSS workaround:
Add some Text.
Add some CSS:
text-indent: 100%;
white-space: nowrap;
overflow: hidden;

That means you wrote you text in side the 'i' tag
as in
your text
instead
<a><i class="fa fa-phone" aria-hidden="true"></i> your text</a>

I had the same issues for my header design system and found a solution here:
https://github.com/gatsbyjs/gatsby/issues/20208
To clarify, here's the difference:
Before:
const ExternalButton = styled( ({ ...props}) => <a {...props} />)``
After:
const ExternalButton = styled( ({ children, ...props}) => <a {...props}{children} </ a>)
Please note that a space had to be included in the </ a> for it to render on the post. Please remove it for the functional answer

Related

How to override a css syle of `ng-template` built field without /deep/?

I have an issue with some components which using ng-template. If the component I'm using generates some elements which I don't want or contain a buggy thing, I seek for workarounds. Ideally I shouldn't do, but once there are some issues with these depending lib and I'm compelled to do so. Previously faced similar issue with popver, and now with ngx-datatable. I appreciate if you can tell me the better practice I need to follow.
i.e. here for ngx-datatabler-row-detail template I get an output with a div which has .datatable-row-detail class. If I don't override it with /deep/ (which is deprecated I heard), even !important doesn't work to override the width. How can I override these class styles for generated fields within angular component, since there is no way to give them an id ?
/deep/
.datatable-body-row{
border-bottom:1px solid #000;
}
/deep/
.datatable-row-detail{
width:600px !important;
}
<!-- Row Detail Template -->
<ngx-datatable-row-detail [rowHeight]="120" #myDetailRow (toggle)="onDetailToggle($event)">
<ng-template
...>
<div style="padding-left:35px" >
<div><strong>==== Details ===</strong></div>
<li *ngFor="let detail of row.details">
{{detail }}
</li>
</div>
</ng-template>
</ngx-datatable-row-detail>
<ngx-datatable-column>
<ng-template
...>
<a
(click)="toggleExpandRow(row)"> <i class="fa fa-cube btn-link" hover-class="active"></i>
</a>
</ng-template>
</ngx-datatable-column>
Please see this stackblits. Just remove the /deep/ from css and when you click on open you no longer see the background.
https://stackblitz.com/edit/ngx-datatable-row-detail-omuywi?file=app/app.component.css
I don't think it is possible to override the thirdparty component styles from an Angular component in a clean way. (There are options like using the deprecated deep or turning off ViewEncapsulation.)
However, overriding them is possible from the global styles.scss in the app root. If we put the following styles into it, it works:
.datatable-body-row {
border-bottom: 1px solid #000;
}
.datatable-row-detail {
background: rgb(134, 79, 79) !important;
}
Stackblitz:
https://stackblitz.com/edit/ngx-datatable-row-detail-mj3otr?file=styles.css

Vue JS CSS style binding

I am trying to bind CSS styling to vuejs tags. I dont seem to be able to get it working.
Below is the code which i am trying. Can anyone help me out with this? I am not able to get the Styling to work. I am trying this as well as binding based on conditional. Both doesnt seem to work. Can anyone help me with this? I have tried all the ways i could find on stackoverflow, none of them seem to work for me. Can any one help me if i am doing something wrong?
<b-table
class="PatientTable"
borderless
hover
v-on:row-clicked="redirectToPatientView"
:items="users"
:fields="fields"
:current-page="currentPage"
:per-page="perPage"
id="tableData"
>
<template v-for="key1 in fields" v-slot:[`cell(${key1})`]="{ value }" id="tableData" >
<b class="patientData" id="tableData" v-bind:key="key1" v-bind:style="'{font-size:200px;}'">{{ value }}</b>
</template>
When you bind a style, pass in an object instead of a string of an object.
<!-- Instead of: -->
<b :style="'{font-size:200px;}'">{{ value }}</b>
<!-- Do: -->
<b :style="{ 'font-size' : '200px' }">{{ value }}</b>
Notice that, in the second line, the object is placed directly into the double-quotes, without its own set of single-quotes. The contents of those double-quotes are straight up JavaScript, so you don't have to escape the object in them. What you're essentially trying to do is along these lines:
<b :style="styleBinding">{{ value }}</b>
<script>
export default {
data: function() {
return {
styleBinding: {
'font-size': '200px',
'margin-top': '5em',
'other-css-property': 'value'
}
}
}
}
</script>
It's just that, since you're only using a single property, it's a little cleaner to do in-line in the template.
use :class binding instead?
<component :class="{'your-classname' : condition}">
Since inline styling is not really advisable. https://v2.vuejs.org/v2/guide/class-and-style.html

How to display Emoji in React App

I would like to display emojis on my webpage in a react chat app. The plan is to give the user a list of emojis to select from. How do I use the codes like '1F683' and have them display the emoji on the page? I need to support Chrome.
I am able to use css to show the emoji.
<div className="smiley"></div>
.smiley:after {
content: "\01F683";
}
I can also have a list of images and map them to the code and display an img element per emoji.
Is there another way and which is the best way to do this?
I am maybe late to the party but I needed to conditionally render different emojis by the same component, so for me the easiest way was:
Go to https://unicode.org/emoji/charts/full-emoji-list.html
Find needed emojis, for example U+1F609 and use it as a string of a hex number 0x1F609 with String.fromCodePoint in your code β€” see below.
Create one little component to satisfy eslint rule which would otherwise throw an error
Emojis should be wrapped in <span>, have role="img", and have an accessible description with aria-label or aria-labelledby jsx-a11y/accessible-emoji:
const Emoji = React.memo(({ className, label, symbol }) =>
<span className={className} role="img" aria-label={label}>
{String.fromCodePoint(symbol)}
</span>)
export default Emoji
So then somewhere else you can use it as:
class MagnificentComponent extends PureComponent {
getEmojiConditionally = () => this.props.happy ? '0x1F60A' : '0x1F61E'
render = () =>
<SomeComponentWhereINeedEmoji>
<Emoji symbol={this.getEmojiConditionally(} />
</SomeComponentWhereINeedEmoji>
}
All emojis are pretty much standardized with the format at Emoji Cheat Sheet, so your given example above (\01F683) maps to railway_car in the Emoji Cheat Sheet.
It might be a better idea to store your emojis with these identifiers and map it to the actual emojis later on, without worrying about encoding the actual emoji (πŸšƒ) themselves, or not being able to tell/remember the actual emoji represented by the Unicode sequence (\01F683).
If you wish to map this human-readable identifier to the actual Unicode sequence/symbol itself, you have a few options, using railway_car as an example:
Twemoji Awesome
Twemoji Awesome is like Font Awesome, but with Twitter Emojis.
You can then insert an emoji like this, just like Font Awesome.
<i class="twa twa-railway-car"></i>
This will output the corresponding SVG:
Emoji Dictionary
There's an npm package aptly named emoji-dictionary that allows you to map the emoji name to the Unicode character, if you wish to use default the browser's default emoji renderer.
The usage will then look like this:
emoji.getUnicode("railway_car");
This returns πŸšƒ (which would display on modern browsers/might break on older browsers/etc).
We have the unicode of emojis in W3C .
It is in the range of {. Hex 2600-26FF.}.
Thus, you can generate it without CSS.
Check example below πŸ‘‡πŸΌ
class Emoji extends React.Component {
render() {
const {title, code} = this.props;
return <span className="emoji" title={title}>{code}</span>
}
}
class App extends React.Component {
renderEmojis() {
const rangeEmojis = Array.from({length: 256}, (v, k) => (k + 9728).toString(16));
return rangeEmojis.map((code, index) => <Emoji code={unescape ('%u' + code)} title={"My code is :"+code} key={'emj'+index} />)
}
render() {
return (
<div>
{this.renderEmojis()}
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector('#chat'))
.emoji {
border: solid 1px #3e3e3e;
width: 50px;
height: 50px;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<section id="chat" />
They are many ways to use emoji's in react. With NPM and also without it by a "span" tag.
<span role="img" aria-label="arrow">➑️</span>
I find this simple and easy to use.
React code for Grinning face with big eyes:
<div>
{String.fromCodePoint('0x1f603')}
</div>
Output:
πŸ˜ƒ
Full Emoji List, v15.0 - https://unicode.org/emoji/charts/full-emoji-list.html
--
Putting this here just incase anyone else stumbles on this post looking for what I needed.
<p>
After a lot of Googling and reading I just copy/pasted the emoji, it seems to work fine πŸ€·β€β™‚οΈ.
</p>
To get the emoji I went to Discord sent the emoji I needed and copy/pasted it into my code and it shows up on screen.

Angular 2 - What's the equivalent of routerLinkActive="active" inside a TypeScript (.ts) file?

I was using routerLinkActive="active" inside the html file with routerLink=[myId] to highlight the active anchor in a ul.
Example:
<a [routerLink]="[myId]" class="list-group-item clearfix" routerLinkActive="active">
<div class="pull-left">
<h4 class="list-group-item-heading">{{someName}}</h4>
</div>
</a>
But when I remove the [routerlink]="[myId]" and replace it with a click listener (that does some calculation and then redirects the route using this.router.navigate(['/someURL', myId]) ) the routerLinkActive="active" no longer works/highlights.
Example:
<a (click)="onClick(myId)" class="list-group-item clearfix" routerLinkActive="active">
<div class="pull-left">
<h4 class="list-group-item-heading">{{someName}}</h4>
</div>
</a>
When inspecting the anchor elements using the routerLink=[myId], the style is set to:
.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover {
z-index: 2;
color: #fff;
background-color: #337ab7;
border-color: #337ab7;
}
Is it possible to set the active anchor style in the .ts file in the onClick() function? Or is there a simpler way around this?
Highlighting a specific link in the navigation is a reflection of the current state of the app: link A is highlighted because the user is looking at page A.
You're asking how to highlight the link as the result of a click. This approach is less than ideal: you could end up highlighting the link before the new route/page is actually activated. Most importantly, if the user reloads the page or navigates to it directly because they bookmarked it, the link will NEVER be highlighted (because no one clicked it).
You need to find a way to highlight the link based on app state, NOT as the result of an action (the typical flow is: action => changes state => updates UI).
Maybe something like this:
#Component({
template: `
<a [class.active]="currentPath == 'home'">HomeComponent</a>
`
})
export class HomeComponent {
currentPath = '';
constructor(route: ActivatedRoute) {
// Retrieve current path.
this.currentPath = snapshot.url.join('');
}
}
The idea is to retrieve the current path and expose it to the template.
Like GΓΌnter suggested, you can probably find more robust code for testing the current path in routerLinkActive's source code.

Turn text to link by css

Is it possible to convert a text to link by its id in CSS.
<span id="text">A text</span>
Change above text by CSS to a link like this:
<span id="text">A text</span>
This is not possible to do via CSS
Links are considered content, which is separate from presentation (CSS). This is by design. Content like this can only be added to the page by modifying the DOM - either dynamically in the browser via JavaScript and/or by changing the HTML returned from server-side code.
To do specifically what you are asking for, you could use JavaScript like this...
const el = document.getElementById('text')
el.innerHTML = `${el.textContent}`
<span id="text">A text</span>
...but this is often better:
const parentElement = document.getElementById('text')
const newElement = Object.assign(document.createElement('a'), {
href: 'example.org',
textContent: parentElement.textContent
})
parentElement.textContent = ''
parentElement.appendChild(newElement)
<span id="text">A text</span>
It may look more complicated than el.innerHTML='...', but this way doesn't need to be parsed, so it is the faster approach.
If you need to manipulate HTML you can do by JavaScript but there's no way to do this with css.
Example
document.getElementById('your id').innerHTML = '';
You can find more here

Resources