Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
18 changes: 17 additions & 1 deletion .storybook/lib/storiesFromMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ import select from 'unist-util-select'
import findBefore from 'unist-util-find-before'
import htmlToReact from 'html-to-react'
import parsePairs from 'parse-pairs'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import {Octicon} from '../Octicon'

const htmlParser = new htmlToReact.Parser()

const railsOcticonToReact = (html) => {
// <%= octicon "tools" %> to <Octicon name="tools" />
const octre = /<%= octicon ["']([a-z\-]+)["'] %>/gi
html = html.replace(octre, (match, name) => {
return ReactDOMServer.renderToStaticMarkup(<Octicon name={name} />)
})
return html
}

const isValidNode = () => {
return true;
}

const nodeToStory = (node, file) => {
const html = node.value
let html = railsOcticonToReact(node.value)
const element = htmlParser.parse(html)
const pairs = node.lang.replace(/^html\s*/, '')
const attrs = pairs.length ? parsePairs(pairs) : {}
Expand Down
114 changes: 103 additions & 11 deletions modules/primer-navigation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Primer comes with several navigation components. Some were designed with singula

The menu is a vertical list of navigational links. **A menu's width and placement must be set by you.** If you like, just use our grid columns as a parent. Otherwise, apply a custom `width`.

```html
```html title="Menu"
<nav class="menu" aria-label="Person settings">
<a class="menu-item selected" href="#url" aria-current="page">Account</a>
<a class="menu-item" href="#url">Profile</a>
Expand All @@ -59,7 +59,7 @@ The menu is a vertical list of navigational links. **A menu's width and placemen

There are a few subcomponents and add-ons that work well with the menu, including avatars, counters, and Octicons.

```html
```html title="Menu with octicons, avatars and counters"
<nav class="menu" aria-label="Person settings">
<a class="menu-item selected" href="#url" aria-current="page">
<%= octicon "tools" %>
Expand All @@ -83,7 +83,7 @@ There are a few subcomponents and add-ons that work well with the menu, includin

You can also add optional headings to a menu. Feel free to use nearly any semantic element with the `.menu-heading` class, including inline elements, headings, and more.

```html
```html title="Menu with heading"
<nav class="menu" aria-labelledby="menu-heading">
<span class="menu-heading" id="menu-heading">Menu heading</span>
<a class="menu-item selected" href="#url" aria-current="page">Account</a>
Expand All @@ -93,12 +93,102 @@ You can also add optional headings to a menu. Feel free to use nearly any semant
</nav>
```

## Underline nav

`.UnderlineNav` is navigation that is typically used at the top of a page as the main page navigation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be worded better, it says navigation twice and descriptions could be a little more helpful. Suggest something like this but feel free to edit:

Use UnderlineNav to style navigation with a minimal underlined selected state. This component comes with variations to accommodate icons, counters, and button actions; and is typically used for navigation placed at the top of the page.


```html title="UnderlineNav"
<nav class="UnderlineNav">
<div class="UnderlineNav-items">
<a href="#url" role="tab" title="Item 1" class="UnderlineNav-item selected">Item 1</a>
<a href="#url" role="tab" title="Item 2" class="UnderlineNav-item">Item 2</a>
<a href="#url" role="tab" title="Item 3" class="UnderlineNav-item">Item 3</a>
<a href="#url" role="tab" title="Item 4" class="UnderlineNav-item">Item 4</a>
</div>
</nav>
```

You can right align the navigation.

```html title="UnderlineNav--right"
<nav class="UnderlineNav UnderlineNav--right">
<div class="UnderlineNav-items">
<a href="#url" role="tab" title="Item 1" class="UnderlineNav-item selected">Item 1</a>
<a href="#url" role="tab" title="Item 2" class="UnderlineNav-item">Item 2</a>
<a href="#url" role="tab" title="Item 3" class="UnderlineNav-item">Item 3</a>
<a href="#url" role="tab" title="Item 4" class="UnderlineNav-item">Item 4</a>
</div>
</nav>
```


The navigation will work with added counters and/or octicons
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, use a more commanding tone, such as:

Counters and octicons can be used with navigation items:


```html title="UnderlineNav with Counter"
<nav class="UnderlineNav" aria-label="Foo bar">
<div class="UnderlineNav-items">
<a href="#url" class="UnderlineNav-item selected">
<%= octicon "tools" %>
Item 1
</a>
<a href="#url" class="UnderlineNav-item">
<%= octicon "tools" %>
Item 2
<span className="Counter">10</span>
</a>
<a href="#url" class="UnderlineNav-item">
<%= octicon "tools" %>
Item 3
</a>
<a href="#url" class="UnderlineNav-item">
<%= octicon "tools" %>
Item 4
</a>
</div>
</nav>
```

Use `.UnderlineNav--full` to use a container within the components
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggesting change wording to something like:

Use UnderlineNav--full in combination with container styles to make navigation fill the width of the container.

I couldn't find a way to avoid using "container" twice but I think it's okay.


```html title="UnderlineNav--full"
<nav class="UnderlineNav UnderlineNav--full" aria-label="Foo bar">
<div class="container-lg">
<div class="UnderlineNav-items">
<a href="#url" class="UnderlineNav-item selected">Item 1</a>
<a href="#url" class="UnderlineNav-item">Item 2
<span className="Counter">10</span>
</a>
<a href="#url" class="UnderlineNav-item">Item 3</a>
<a href="#url" class="UnderlineNav-item">Item 4</a>
</div>
</div>
</nav>
```

Use `.UnderlineNav-actions` to use another element alongside the underline nav

```html title="UnderlineNav-actions"
<nav class="UnderlineNav" aria-label="Foo bar">
<div class="UnderlineNav-items">
<a href="#url" class="UnderlineNav-item selected">Item 1</a>
<a href="#url" class="UnderlineNav-item">Item 2
<span class="Counter">10</span>
</a>
<a href="#url" class="UnderlineNav-item">Item 3</a>
<a href="#url" class="UnderlineNav-item">Item 4</a>
</div>
<div class="UnderlineNav-actions">
<a class="btn">Button</a>
</div>
</nav>
```


## Tabnav

When you need to toggle between different views, consider using a tabnav. It'll given you a left-aligned horizontal row of... tabs!

```html
```html title="tabnav"
<div class="tabnav">
<nav class="tabnav-tabs" aria-label="Foo bar">
<a href="#url" class="tabnav-tab selected" aria-current="page">Foo tab</a>
Expand All @@ -109,7 +199,7 @@ When you need to toggle between different views, consider using a tabnav. It'll

Use `.float-right` to align additional elements in the `.tabnav`:

```html
```html title="tabnav with buttons"
<div class="tabnav">
<a class="btn btn-sm float-right" href="#url" role="button">Button</a>
<nav class="tabnav-tabs" aria-label="Foo bar">
Expand All @@ -121,7 +211,7 @@ Use `.float-right` to align additional elements in the `.tabnav`:

Additional bits of text and links can be styled for optimal placement with `.tabnav-extra`:

```html
```html title="tabnav-extra"
<div class="tabnav">
<div class="tabnav-extra float-right">
Tabnav widget text here.
Expand All @@ -133,7 +223,7 @@ Additional bits of text and links can be styled for optimal placement with `.tab
</div>
```

```html
```html title="tabnav with everything"
<div class="tabnav">
<div class="float-right">
<a class="tabnav-extra" href="#url">
Expand All @@ -154,7 +244,7 @@ Additional bits of text and links can be styled for optimal placement with `.tab

A vertical list of filters. Grey text on white background. Selecting a filter from the list will fill its background with blue and make the text white.

```html
```html title="filter-list"
<ul class="filter-list">
<li>
<a href="#url" class="filter-item selected" aria-current="page">
Expand All @@ -180,7 +270,7 @@ A vertical list of filters. Grey text on white background. Selecting a filter fr

`.subnav` is navigation that is typically used when on a dashboard type interface with another set of navigation above it. This helps distinguish navigation hierarchy.

```html
```html title="subnav"
<nav class="subnav" aria-label="Respository">
<a href="#url" class="subnav-item selected" aria-current="page">Item 1</a>
<a href="#url" class="subnav-item">Item 2</a>
Expand All @@ -190,7 +280,7 @@ A vertical list of filters. Grey text on white background. Selecting a filter fr

You can have `subnav-search` in the subnav bar.

```html
```html title="subnav-search"
<div class="subnav">
<nav class="subnav-links" aria-label="Repository">
<a href="#url" class="subnav-item selected" aria-current="page">Item 1</a>
Expand All @@ -207,7 +297,7 @@ You can have `subnav-search` in the subnav bar.

You can also use a `subnav-search-context` to display search help in a select menu.

```html
```html title="subnav-search-context"
<div class="subnav">
<nav class="subnav-links">
<a href="#url" class="subnav-item selected">Item 1</a>
Expand Down Expand Up @@ -244,6 +334,8 @@ You can also use a `subnav-search-context` to display search help in a select me
</div>
</div>
```


<!-- %enddocs -->

## License
Expand Down
1 change: 1 addition & 0 deletions modules/primer-navigation/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
@import "./lib/tabnav.scss";
@import "./lib/filter-list.scss";
@import "./lib/subnav.scss";
@import "./lib/underline-nav.scss";
73 changes: 73 additions & 0 deletions modules/primer-navigation/lib/underline-nav.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.UnderlineNav {
display: flex;
justify-content: space-between;
border-bottom: 1px solid $gray-200;
}

.UnderlineNav-items {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel a little worried having UnderlineNav-items and UnderlineNav-item will be a bit confusing and not immediately obvious what they do. Could we change UnderlineNav-items to UnderlineNav-body? That's a pattern we use elsewhere and I think it makes sense because you have actions to handle other content. Otherwise best I could think of was UnderlineNav-items-container or wrapper but they get a little long 😬

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing to UnderlineNav-body 👍

display: flex;
margin-bottom: -1px;
}

.UnderlineNav-item {
padding: $spacer-3 $spacer-2;
margin-right: $spacer-3;
font-size: $body-font-size;
line-height: $lh-default;
color: $text-gray;
text-align: center;
border-bottom: 2px solid transparent;

.Counter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to avoid nesting other component selectors like this because it creates dependencies and means overriding if we want to act differently. We could just use the ml-1 utility. How strongly do you feel this needs to be built into the pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this from the component. My only concern is that people will use inconsistent spacing, but I think it needs to be flexible because markup spacing affects this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this, and the other similar scenarios, are tricky. This is where I feel like we should handle the Counter styling in context with the UnderlineNav in other parts of the code (say helpers or something), rather than Sass. Handling it in the Sass means adding additional classes to apply to components that may already require a number of classes. That's not the worst but can feel like overkill and be a contributor to CSS bloat. We don't have a good solution for handling elsewhere in the code base right now, but it keeps coming up and is something that's on our radar. If we start to see this particular use case being styled incorrectly, then the best option is to have another class to apply to the Counter rather than nesting it.

margin-left: $spacer-1;
}

.octicon {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar thoughts here to nesting Counter. We could have an element class to account for it, such as UnderlineNav-octicon as utilities won't work because you need the hover styles.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the spacing from the component (same concern as Counter) but kept the color styles in under .UnderlineNav-octicon

margin-right: $spacer-1;
color: $gray-400;
}

&:hover,
&:focus {
color: $text-gray-dark;
text-decoration: none;
border-bottom-color: $gray-300;
transition: 0.2s ease;

.octicon {
color: $gray-500;
}
}

&.selected {
font-weight: $font-weight-bold;
color: $text-gray-dark;
border-bottom-color: $orange-600;

.octicon {
color: $gray-500;
}
}
}

.UnderlineNav--right {
justify-content: flex-end;

.UnderlineNav-item {
margin-right: 0;
margin-left: $spacer-3;
}
}

.UnderlineNav-actions {
align-self: center;
}

.UnderlineNav--full {
display: block;

.container-lg {
display: flex;
justify-content: space-between;
}
}
10 changes: 10 additions & 0 deletions modules/primer-navigation/stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import { storiesOf } from '@storybook/react'
import storiesFromMarkdown from '../../.storybook/lib/storiesFromMarkdown'

const stories = storiesOf('Navigation', module)

storiesFromMarkdown(require.context('.', true, /\.md$/))
.forEach(({title, story}) => {
stories.add(title, story)
})