--------------------------------------------------------------------------------
/docs/partials/scss/motion.html:
--------------------------------------------------------------------------------
1 | // Classes to use when triggering in/out animations
2 | $motion-class: (
3 | in: "ng-enter",
4 | out: "ng-leave",
5 | );
6 | $motion-class-active: (
7 | in: "ng-enter-active",
8 | out: "ng-leave-active",
9 | );
10 | $motion-class-stagger: (
11 | in: "ng-enter-stagger",
12 | out: "ng-leave-stagger",
13 | );
14 | $motion-class-showhide: (
15 | in: "ng-hide-remove",
16 | out: "ng-hide-add",
17 | );
18 | $motion-class-showhide-active: (
19 | in: "ng-hide-remove-active",
20 | out: "ng-hide-add-active",
21 | );
22 |
23 | // Set if movement-based transitions should also fade the element in and out
24 | $motion-slide-and-fade: false;
25 | $motion-hinge-and-fade: true;
26 | $motion-scale-and-fade: true;
27 | $motion-spin-and-fade: true;
28 |
29 | // Default speed for transitions and animations
30 | $motion-duration-default: 500ms;
31 |
32 | // Slow and fast modifiders
33 | $motion-duration-slow: 750ms;
34 | $motion-duration-fast: 250ms;
35 | $motion-stagger-duration-default: 150ms;
36 | $motion-stagger-duration-short: 50ms;
37 | $motion-stagger-duration-long: 300ms;
38 |
39 | // Default timing function for transitions and animations
40 | $motion-timing-default: ease;
41 |
42 | // Built-in and custom easing functions
43 | // Every item in this map becomes a CSS class
44 | $motion-timings: (
45 | linear: linear,
46 | ease: ease,
47 | easeIn: ease-in,
48 | easeOut: ease-out,
49 | easeInOut: ease-in-out,
50 | bounceIn: cubic-bezier(0.485, 0.155, 0.240, 1.245),
51 | bounceOut: cubic-bezier(0.485, 0.155, 0.515, 0.845),
52 | bounceInOut: cubic-bezier(0.760, -0.245, 0.240, 1.245),
53 | );
54 |
55 | // Default delay for all transitions and animations
56 | $motion-delay-default: 0;
57 | // Short and long delay modifiers
58 | $motion-delay-short: 300ms;
59 | $motion-delay-long: 700ms;
--------------------------------------------------------------------------------
/docs/templates/compatibility.html:
--------------------------------------------------------------------------------
1 | ---
2 | name: compatibility
3 | url: /compatibility
4 | title: Compatibility
5 | ---
6 |
7 |
Compatibility
8 |
Foundation for Apps is designed for and tested on numerous browsers and devices. It's built on some of the latest web technologies. Here's the rundown on what type of compatibility to expect.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Browser/OS
17 |
Compatibility
18 |
19 |
20 |
21 |
Chrome
22 |
✓
23 |
24 |
25 |
Firefox
26 |
✓
27 |
28 |
29 |
Safari
30 |
✓
31 |
32 |
33 |
Opera 25+ (not Mini)
34 |
✓
35 |
36 |
37 |
IE10–11
38 |
✓
39 |
40 |
41 |
IE6–9
42 |
×
43 |
44 |
45 |
iOS 7–8 (iPhone)
46 |
✓
47 |
48 |
49 |
iOS 7–8 (iPad)
50 |
✓
51 |
52 |
53 |
Android 4.2+ (Tablet & Phone)
54 |
✓
55 |
56 |
57 |
Android 2 (Tablet & Phone)
58 |
×
59 |
60 |
61 |
Windows Phone 8+
62 |
✓
63 |
64 |
65 |
Surface Tablet
66 |
✓
67 |
68 |
69 |
--------------------------------------------------------------------------------
/iconic/share-boxed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/iconic/reload.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scss/components/_accordion.scss:
--------------------------------------------------------------------------------
1 | /*
2 | ACCORDION
3 | ---------
4 |
5 | The trusy accordion allows you to create a series of vertical tabs.
6 | */
7 |
8 | /// @Foundation.settings
9 | // Accordion
10 | $accordion-border: 1px solid $gray-dark !default;
11 |
12 | $accordion-title-background: $gray-light !default;
13 | $accordion-title-background-hover: smartscale($accordion-title-background, 5%) !default;
14 | $accordion-title-background-active: smartscale($accordion-title-background, 3%) !default;
15 | $accordion-title-color: isitlight($accordion-title-background) !default;
16 | $accordion-title-color-active: isitlight($accordion-title-background) !default;
17 |
18 | $accordion-title-padding: $global-padding !default;
19 | $accordion-content-padding: $global-padding !default;
20 | ///
21 |
22 | @mixin accordion-title(
23 | $background: $accordion-title-background,
24 | $background-hover: $accordion-title-background-hover,
25 | $background-active: $accordion-title-background-active,
26 | $color: $accordion-title-color,
27 | $color-active: $accordion-title-color-active,
28 | $padding: $accordion-title-padding
29 | ) {
30 | padding: $padding;
31 | background: $background;
32 | color: $color;
33 | line-height: 1;
34 | cursor: pointer;
35 |
36 | &:hover {
37 | background: $background-hover;
38 | }
39 |
40 | .is-active > & {
41 | background: $background-active;
42 | color: $color-active;
43 | }
44 | }
45 |
46 | @mixin accordion-content(
47 | $padding: $accordion-content-padding
48 | ) {
49 | padding: $padding;
50 |
51 | display: none;
52 | .is-active > & {
53 | display: block;
54 | }
55 | }
56 |
57 | @include exports(accordion) {
58 | .accordion {
59 | @if hasvalue($accordion-border) {
60 | border: $accordion-border;
61 | }
62 | }
63 | .accordion-item {
64 |
65 | }
66 | .accordion-title {
67 | @include accordion-title;
68 | }
69 | .accordion-content {
70 | @include accordion-content;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute to Foundation for Apps
2 |
3 | ZURB loves its community! We always want to hear from our users, whether they're reporting bugs, suggesting new features, or even adding them themselves.
4 |
5 | ## Reporting Bugs
6 |
7 | [Open a new issue](https://github.com/zurb/foundation-apps/issues/new) to report a problem you're having with Foundation for Apps. When writing your issue, keep these things in mind:
8 |
9 | - **Be descriptive.** If you can, upload a screenshot of problem you're having, or copy and paste any JavaScript or command line errors you encounter. Being detailed will help us hone in on the problem faster.
10 | - **Post your code.** It's very helpful to see any HTML, Sass, or JavaScript you've written that you think may be causing the problem. In some cases, we might be able to fix your problem just by fixing your code.
11 | - **Help us recreate it.** If your problem is complex, tell us the steps needed to recreate the issue. Sometimes we need to see the problem for ourselves, in our own web browsers, so we can more easily debug it.
12 |
13 | ## Submitting Pull Requests
14 |
15 | If you think you can solve a problem yourself, or want to implement a new feature, go for it! Follow these guidelines to make the most killer PR ever.
16 |
17 | - **Test, test, and test.** The Foundation frameworks are used by thousands and thousands of designers and developers, so making sure your changes work in every browser is important! Foundation for Apps is officially supported on:
18 | - Newest Chrome
19 | - Newest Firefox
20 | - Safari 7+
21 | - Internet Explorer 10+
22 | - Mobile Safari 7+
23 | - Android Browser 4+
24 | - **When changing or adding Sass code, follow these steps:**
25 | - If you change anything about the settings variables for a component, run `gulp sass:settings` to generate a new settings file.
26 | - If you add a new variable, follow our [rules for variable names](https://github.com/zurb/foundation-apps/wiki/Variable-Naming).
27 | - If you change a mixin's parameters, find the component's mixin documentation and change the parameters there as well.
--------------------------------------------------------------------------------
/iconic/document.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/templates/popup.html:
--------------------------------------------------------------------------------
1 | ---
2 | name: popup
3 | url: /popup
4 | title: Popup
5 | ---
6 |
7 |
Popup
8 |
9 |
A window that has content and can be placed anywhere, like a popup. Trigger it when a view is loaded or from a button click.
If the girl you love moves in with another guy once, it's more than enough. Twice, it's much too much. Three times, it's the story of your life.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
Positioning
41 |
42 |
Popups use a library called Tether. Tether attaches an element to another element with absolute positioning; however, there is one caveat. If your popup is nested within a scrollable area (not `body`) but it's not the immediate parent of that element, it will lose its positioning.
43 |
44 |
45 |
46 |
Sass Mixins
47 |
48 |
Popups don't currently have any sizing classes, but you can use our mixins to style your own.
49 |
50 |
51 | .custom-popup {
52 | // Use this mixin to override the default styles for panels
53 | @include popup(
54 | $width: $popup-width, // Should be an absolute value like px or rem
55 | $background: $popup-background, // Background color
56 | $radius: $popup-radius, // Border radius
57 | $shadow: $popup-shadow, // Box shadow
58 | $border: $popup-border // Border
59 | );
60 | }
61 |
62 |
63 |
Sass Variables
64 |
65 |
Use these variables to customize the appearance of popups.
Take advantage of some handy functions we built into Foundation or customize our mixins to make your own component styles. We've included visibility functions and color theming as well.
9 |
10 |
11 |
12 |
Functions
13 |
14 |
Is It Light?
15 |
16 |
This function takes a background color, and returns an appropriate foreground color based on if the background is light or dark.
17 |
18 |
19 | .component {
20 | $bg: dodgerblue;
21 | background: $bg;
22 | // By default, the function returns black if the background is light, or white if the background is black
23 | color: isitlight($bg);
24 | // However, you can override this. The first parameter is the dark color to return, while the second parameter is the light color
25 | color: isitlight($bg, #333, #ccc);
26 | }
27 |
28 |
29 |
Smart Scale
30 |
31 |
This function takes a color, and makes it darker if the color is light, or lighter if the color is dark. We use this function to create appropriate offset colors for components.
32 |
33 |
34 | .component {
35 | background: dodgerblue;
36 | // Adjust the intensity of the scaling by adding a percentage value after the color. 5% is the default
37 | border: 1px solid smartscale(dodgerblue, 10%);
38 | }
39 |
40 |
41 |
rem Calculation
42 |
43 |
Rems are very useful, but thinking in rems can be hard. Our rem calculation function will convert a pixel value to the correct rem value, based on the base font size of the document.
Touch gestures are often used in devices like tablets and phones to make apps more accessible and intuitive to use. We have integrated Hammer.JS into our Angular core to create easy-to-use directives for gesture-based actions.
10 |
11 |
12 |
13 |
14 |
Hammer.js Required
15 |
16 |
Our touch directives use the Hammer.js, library, which makes it easy to hook into common touch actions like swiping, pinching, rotating, and more. Our starter project (installed through the CLI) includes Hammer.js by default.
17 |
18 |
19 |
20 |
21 |
22 |
Swipe to Close
23 |
24 |
Add the zf-swipe-close directive to a closable element, such as a panel, off-canvas menu, modal, or notification, to trigger a close when the user swipes over the component. The swipe direction is set on the directive, and can be either up, down, left, or right.
25 |
26 |
27 |
Example Panel
28 |
29 |
Here's an example of the swipe-to-close directive applied to a panel.
In this example, the user can swipe up to dismiss the modal. We paired this gesture with an animation that slides the modal up as it fades out, by setting animation-out="slideOutUp" on the element.
We built Foundation for Apps to allow everyone from JavaScript newbies to experienced Angular Developers to build awesome, responsive web apps.
9 |
10 |
11 |
12 |
13 |
Installation
14 |
There are two ways to get going with Foundation for Apps. You can install our starter project using our CLI, which includes Sass, Angular, and a full build process powered by Gulp. Or, you can add our Sass and JavaScript libraries into your own Angular app.
A simple JavaScript solution for responsive images. But not just images, it can even load in HTML partials. Interchange uses media queries to dynamically load responsive content that is appropriate for different users' browsers.
Interchange allows you to specify what specific content to display based on the user's current screen size. This is great for loading up a mobile-friendly component on small devices, and a more robust or heavier load component on desktops.
21 |
22 |
To set up Interchange, start with a container with the zf-interchange directive.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
Use with Images
32 |
33 |
A basic example of Interchange involves images. In the below example, we're loading images with a lower resolution (and thus a lower file size) on small screens, and progressively higher-res images on larger screens.
34 |
35 |
Note the values of the media attributes on each item inside the container—these are the breakpoints defined in your Sass files. Check out the documentation for media queries to learn how these breakpoints can be changed.
Interchange can also switch between entire chunks of HTML. These can be loaded as partials (external HTML files), or by dropping the content right into the tag.
49 |
50 |
Note that partials are reloaded every time, meaning if the user's device scales from medium, to small, back to medium, the medium partial will be loaded twice.
You can create a title bar with this basic HTML. Title bars can have left-, right-, and center-aligned sections. You can use one, two, or all three of them in any combination.
Note that in the above examples, the center section is always written first in the HTML, even though it's in the middle. When creating the three sections, always put the HTML tags for them in this order: center, left, then right.
60 |
61 |
62 |
63 |
Sass Mixins
64 |
65 |
Write a title bar with a custom class using our mixins.
66 |
67 |
68 | .custom-title-bar {
69 | // Extend the base selector to get core structural styles
70 | @extend %title-bar;
71 |
72 | // Add visual styles with this mixin
73 | @include title-bar-style(
74 | $background: #fff, // Background color
75 | $color: #000, // Text color
76 | $border: 1px solid #000,
77 | $padding: 1rem
78 | );
79 | }
80 |
81 |
82 |
Note that the names of the left, right, center, and title classes can be changed in the settings variables—see below.
83 |
84 |
85 |
86 |
Sass Variables
87 |
88 |
You can customize with Title Bar with these variables in _settings.scss:
Labels & Badges are useful to highlight content, use as tags for content type, and more. For example, you can attach a label that notes when something was updated.
Tabs are elements that help you organize and navigate multiple documents in a single container. They can be used for switching between items in the container.
9 |
10 |
11 |
12 |
Basic HTML
13 |
14 |
You can create automatic tabs with this basic directive:
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Tab content 1
23 |
24 |
25 | Tab content 2
26 |
27 |
28 | Tab content 3
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | Tab content 1
38 |
39 |
40 | Tab content 2
41 |
42 |
43 | Tab content 3
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
Advanced HTML
52 |
53 |
You can create Automatic tabs with displaced tab content with this basic directive:
54 |
55 |
56 |
57 |
58 |
59 |
60 | Tab 1
61 |
62 |
63 | Tab 2
64 |
65 |
66 | Tab 3
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Tab 1
79 |
80 |
81 | Tab 2
82 |
83 |
84 | Tab 3
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
Sass Mixins
95 |
96 |
Use our mixins to write your own tab classes.
97 |
98 |
99 | // This is the container for your tabstrip
100 | .custom-tabs {
101 | @include tabstrip(
102 | $orientation: horizontal, // Can also be vertical
103 | $background: #fff
104 | );
105 | }
106 | // This is an individual tab
107 | .custom-tabs-item {
108 | @include tabstrip-item(
109 | $background: #fff, // Background color
110 | $background-hover: #fff, // Background color on hover
111 | $background-active: #fff, // Background color when active
112 | $color: #000, // Text color
113 | $color-active: #000, // Text color when active
114 | $padding: 1rem
115 | );
116 | }
117 |
118 | // This is the container for tab content panes
119 | .custom-tab-content {
120 | @include tab-content(
121 | $padding: 1rem
122 | );
123 | }
124 | // This is an individual tab pane
125 | .custom-tab-content-item {
126 | @include tab-content-item;
127 | }
128 |
129 |
130 |
131 |
132 |
Sass Variables
133 |
134 |
You can customize tabs with these variables in the `_settings.scss` file:
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/scss/components/_modal.scss:
--------------------------------------------------------------------------------
1 | /*
2 | MODAL
3 | -----
4 |
5 | The humble modal hides off-canvas until summoned with an fa-open directive. Modals appear over an overlay that darkens the rest of the page, and have a maxmimum width. You can construct a grid inside a modal, or attach panels to it.
6 |
7 | Note that the modal overlay is hardcoded into the CSS, because whether or not you build your modal semantically, the overlay is always required and will always look the same.
8 | */
9 |
10 | /// @Foundation.settings
11 | // Modal
12 | $modal-background: #fff !default;
13 | $modal-border: 0 !default;
14 | $modal-radius: 0px !default;
15 | $modal-shadow: none !default;
16 | $modal-zindex: 1000 !default;
17 | $modal-sizes: (
18 | tiny: 300px,
19 | small: 500px,
20 | medium: 600px,
21 | large: 800px,
22 | ) !default;
23 |
24 | $modal-overlay-class: 'modal-overlay' !default;
25 | $modal-overlay-background: rgba(#333, 0.7) !default;
26 | ///
27 |
28 | %modal {
29 | position: relative;
30 | z-index: $modal-zindex + 1;
31 | background: $modal-background;
32 | flex: 0 0 auto;
33 | width: 100%;
34 | height: 100vh;
35 | max-height: 100%;
36 | overflow: hidden;
37 | padding: $global-padding;
38 |
39 | @include breakpoint(medium) {
40 | height: auto;
41 | max-width: map-get($modal-sizes, medium);
42 | }
43 |
44 | .grid-content, .grid-block {
45 | margin: 0;
46 | }
47 |
48 | .close-button, [fa-close] {
49 | z-index: $modal-zindex + 1;
50 | }
51 | }
52 |
53 | @mixin modal-dialog() {
54 | height: auto;
55 | }
56 | @mixin modal-layout(
57 | $width: map-get($modal-sizes, medium),
58 | $dialog: false
59 | ) {
60 | max-width: $width;
61 | }
62 | @mixin modal-style(
63 | $border: $modal-border,
64 | $radius: $modal-radius,
65 | $shadow: $modal-shadow
66 | ) {
67 | @if $border != 0 {
68 | border: $border;
69 | }
70 | @if $radius != 0 {
71 | border-radius: $radius;
72 | }
73 | @if $shadow != none {
74 | box-shadow: $shadow;
75 | }
76 | }
77 |
78 | @mixin modal(
79 | $width: map-get($modal-sizes, medium),
80 | $border: $modal-border,
81 | $radius: $modal-radius,
82 | $shadow: $modal-shadow
83 | ) {
84 | @extend %modal;
85 | @include modal-layout($width);
86 | @include modal-style($border, $radius, $shadow);
87 | }
88 |
89 | @include exports(modal) {
90 | .modal {
91 | @include modal;
92 |
93 | @each $size in map-keys($modal-sizes) {
94 | $width: map-get($modal-sizes, $size);
95 | @if $size != medium {
96 | .#{$size} > & { @include modal-layout($width); }
97 | }
98 | }
99 |
100 | .dialog > & {
101 | @include modal-dialog;
102 | }
103 | .collapse > & {
104 | padding: 0;
105 | }
106 | }
107 |
108 | .#{$modal-overlay-class} {
109 | position: fixed;
110 | top: 0;
111 | right: 0;
112 | bottom: 0;
113 | left: 0;
114 | z-index: $modal-zindex;
115 | display: none;
116 | background-color: $modal-overlay-background;
117 |
118 | // Horizontally and vertically center the modal
119 | align-items: center;
120 | justify-content: center;
121 |
122 | // Prevent z-index issue in Mobile Safari
123 | -webkit-transform: translate3d(0,0,0);
124 |
125 | &.is-active {
126 | display: flex;
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/docs/assets/scss/components/_compatability.scss:
--------------------------------------------------------------------------------
1 | // Compatability Table
2 | // -------------------
3 | // A styled table used on the compatability page to show which browsers the framework works with.
4 |
5 | $primary: #002b36;
6 | $secondary: #efefef;
7 | $alert: #cf2a0e;
8 | $success: #43AC6A;
9 | $gutter: 40px;
10 | $rad: 5px;
11 |
12 | @mixin font-size($sizeValue){
13 | font-size: $sizeValue + px;
14 | font-size: ($sizeValue / 10) + rem;
15 | }
16 |
17 | @mixin -breakpoint($point) {
18 | @if $point == smallmobile {
19 | @media (max-width: 525px) { @content; }
20 | }
21 | @if $point == mobile {
22 | @media (max-width: 767px) { @content; }
23 | }
24 | @if $point == tablet {
25 | @media (max-width: 1000px) { @content; }
26 | }
27 | @if $point == smallscreen {
28 | @media (max-width: 1120px) { @content; }
29 | }
30 | }
31 |
32 | .comparison-table {
33 | display: block;
34 | width: 100%;
35 | border-collapse: separate;
36 | thead tr {
37 | color: $primary;
38 | font-weight: bold;
39 | text-transform: uppercase;
40 | td { color: #666 !important; }
41 | td { padding-bottom: 10px; }
42 | td { border: none !important; }
43 | }
44 | tr {
45 | width: 100%;
46 | td {
47 | border-right: 1px solid #ddd;
48 | }
49 | &:first-child {
50 | td { border-top: 1px solid #ddd; }
51 | td:first-child {
52 |
53 | }
54 | td:last-child {
55 |
56 | }
57 | }
58 | &:last-child {
59 | td { border-bottom: 1px solid #ddd; }
60 | td:first-child {
61 |
62 | }
63 | td:last-child {
64 |
65 | }
66 | }
67 | td:first-child {
68 | width: 25%;
69 | padding: 10px;
70 | color: $primary;
71 | font-weight: bold;
72 | border-left: 1px solid #ddd;
73 | }
74 | td.marker.yes {
75 | width: 10%;
76 | text-align: center;
77 | vertical-align: middle;
78 | color: $success;
79 | font-weight: bold;
80 | }
81 | td.marker.no {
82 | width: 10%;
83 | text-align: center;
84 | vertical-align: middle;
85 | color: $alert-color;
86 | font-size: 1.3rem;
87 | font-weight: bold;
88 | }
89 | }
90 | tr:nth-child(even) {
91 | background: $secondary;
92 | }
93 | @include -breakpoint(smallmobile) {
94 | td, tr td, tr td.marker, tr td:first-child, tr td:first-child + td {
95 | position: relative;
96 | display: block;
97 | width: 100%;
98 | border-top: none;
99 | border-bottom: none;
100 | border-left: 1px solid #ddd;
101 | }
102 | tr:first-child td:first-child {
103 |
104 | }
105 | tr:first-child td:last-child {
106 | border-top-right-radius: 0;
107 | }
108 | tr:last-child td:first-child {
109 | border-bottom-left-radius: 0;
110 | }
111 | tr:last-child td:last-child {
112 | border-bottom: 1px solid #ddd;
113 | }
114 | tr td:first-child {
115 | border-top: 1px solid #ddd;
116 | & + td {
117 | padding: 0 10px 10px;
118 | }
119 | }
120 | tr td.marker {
121 | padding: 10px;
122 | font-weight: bold;
123 | &:before {
124 | content: "Grid: ";
125 | }
126 | & + td.marker:before {
127 | content: "Layout/UI: ";
128 | }
129 | & + td.marker + td.marker:before {
130 | content: "JS: ";
131 | }
132 | }
133 | thead tr td.marker {
134 | display: none;
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/scss/components/_panel.scss:
--------------------------------------------------------------------------------
1 | /*
2 | PANEL
3 | -----
4 |
5 | The friendly panel is an all-purpose container for hiding content off-screen.
6 |
7 | Features:
8 | - Position at top, right, bottom, or left
9 | - Anchor to grid block or window
10 | - Define max width or height
11 | - Transform into grid block depending on screen size
12 | */
13 |
14 | /// @Foundation.settings
15 | // Panel
16 | $panel-size-horizontal: 300px !default;
17 | $panel-size-vertical: 300px !default;
18 | $panel-padding: 0 !default;
19 |
20 | $panel-background: #fff !default;
21 | $panel-shadow: 3px 0 10px rgba(black, 0.25) !default;
22 |
23 | // DEPRECATED: these variables will be removed in a future version.
24 | $panel-animation-speed: 0.25s !default;
25 | ///
26 |
27 | %panel-base {
28 | position: absolute;
29 | z-index: 100;
30 | overflow-y: auto;
31 | display: none;
32 |
33 | &.is-active {
34 | display: block;
35 | }
36 | }
37 |
38 | @mixin panel-layout(
39 | $position: left,
40 | $size: default,
41 | $shadow: $panel-shadow
42 | ) {
43 | @if $size == default {
44 | @if $position == left or $position == right {
45 | $size: $panel-size-horizontal;
46 | }
47 | @if $position == top or $position == bottom {
48 | $size: $panel-size-vertical;
49 | }
50 | }
51 |
52 | /*
53 | Direction
54 | */
55 | @if $position == top {
56 | top: 0;
57 | left: 0;
58 | width: 100%;
59 | }
60 | @else if $position == right {
61 | top: 0;
62 | right: 0;
63 | height: 100%;
64 | }
65 | @else if $position == bottom {
66 | bottom: 0;
67 | left: 0;
68 | width: 100%;
69 | }
70 | @else if $position == left {
71 | top: 0;
72 | left: 0;
73 | height: 100%;
74 | }
75 |
76 | /*
77 | Sizing
78 | */
79 | // Horizontal panels are always all the way tall and have a set width
80 | @if $position == left or $position == right {
81 | @if unit($size) == '%' {
82 | width: $size;
83 | }
84 | @else {
85 | width: 100%;
86 | @include breakpoint($size) {
87 | width: $size;
88 | }
89 | }
90 | }
91 | // (For now) vertical panels don't change size
92 | @if $position == top or $position == bottom {
93 | height: $size;
94 | }
95 |
96 | /*
97 | Shadows
98 | */
99 | $shadow-distance: get-shadow-value($shadow, x);
100 | $shadow-size: get-shadow-value($shadow, size);
101 | $shadow-color: get-shadow-value($shadow, color);
102 | &.is-active {
103 | @if $position == left { box-shadow: $shadow-distance 0 $shadow-size $shadow-color; }
104 | @else if $position == right { box-shadow: (-$shadow-distance) 0 $shadow-size $shadow-color; }
105 | @else if $position == top { box-shadow: 0 $shadow-distance $shadow-size $shadow-color; }
106 | @else if $position == bottom { box-shadow: 2px (-$shadow-distance) $shadow-size $shadow-color; }
107 | }
108 | }
109 |
110 | @mixin panel-style(
111 | $padding: $panel-padding,
112 | $background: $panel-background
113 | ) {
114 | /*
115 | Basic styles
116 | */
117 | padding: $padding;
118 | background: $background;
119 | }
120 |
121 | @include exports(panel) {
122 | .panel {
123 | @extend %panel-base;
124 | @include panel-style;
125 | }
126 |
127 | .panel-top { @include panel-layout(top); }
128 | .panel-right { @include panel-layout(right); }
129 | .panel-bottom { @include panel-layout(bottom); }
130 | .panel-left { @include panel-layout(left); }
131 |
132 | .panel-fixed { position: fixed; }
133 | }
134 |
--------------------------------------------------------------------------------
/docs/partials/scss/typography.html:
--------------------------------------------------------------------------------
1 | // We use these to control header font styles
2 | $header-font-family: $body-font-family;
3 | $header-font-weight: $font-weight-normal;
4 | $header-font-style: $font-weight-normal;
5 | $header-font-color: #222;
6 | $header-line-height: 1.4;
7 | $header-top-margin: .2rem;
8 | $header-bottom-margin: .5rem;
9 | $header-text-rendering: optimizeLegibility;
10 |
11 | // We use these to control header font sizes
12 | $h1-font-size: rem-calc(44);
13 | $h2-font-size: rem-calc(37);
14 | $h3-font-size: rem-calc(27);
15 | $h4-font-size: rem-calc(23);
16 | $h5-font-size: rem-calc(18);
17 | $h6-font-size: 1rem;
18 |
19 | // We use these to control header size reduction on small screens
20 | $h1-font-reduction: rem-calc(10);
21 | $h2-font-reduction: rem-calc(10);
22 | $h3-font-reduction: rem-calc(5);
23 | $h4-font-reduction: rem-calc(5);
24 | $h5-font-reduction: 0;
25 | $h6-font-reduction: 0;
26 |
27 | // These control how subheaders are styled.
28 | $subheader-line-height: 1.4;
29 | $subheader-font-color: scale-color($header-font-color, $lightness: 35%);
30 | $subheader-font-weight: $font-weight-normal;
31 | $subheader-top-margin: .2rem;
32 | $subheader-bottom-margin: .5rem;
33 |
34 | // A general styling
35 | $small-font-size: 60%;
36 | $small-font-color: scale-color($header-font-color, $lightness: 35%);
37 |
38 | // We use these to style paragraphs
39 | $paragraph-font-family: inherit;
40 | $paragraph-font-weight: $font-weight-normal;
41 | $paragraph-font-size: 1rem;
42 | $paragraph-line-height: 1.6;
43 | $paragraph-margin-bottom: rem-calc(20);
44 | $paragraph-aside-font-size: rem-calc(14);
45 | $paragraph-aside-line-height: 1.35;
46 | $paragraph-aside-font-style: italic;
47 | $paragraph-text-rendering: optimizeLegibility;
48 |
49 | // We use these to style tags
50 | $code-color: grayscale($primary-color);
51 | $code-font-family: Consolas, 'Liberation Mono', Courier, monospace;
52 | $code-font-weight: $font-weight-normal;
53 | $code-background-color: scale-color($secondary-color, $lightness: 70%);
54 | $code-border-size: 1px;
55 | $code-border-style: solid;
56 | $code-border-color: scale-color($code-background-color, $lightness: -10%);
57 | $code-padding: rem-calc(2) rem-calc(5) rem-calc(1);
58 |
59 | // We use these to style anchors
60 | $anchor-text-decoration: none;
61 | $anchor-text-decoration-hover: none;
62 | $anchor-font-color: $primary-color;
63 | $anchor-font-color-hover: scale-color($anchor-font-color, $lightness: -14%);
64 |
65 | // We use these to style the element
66 | $hr-border-width: 1px;
67 | $hr-border-style: solid;
68 | $hr-border-color: #ddd;
69 | $hr-margin: rem-calc(20);
70 |
71 | // We use these to style lists
72 | $list-font-family: $paragraph-font-family;
73 | $list-font-size: $paragraph-font-size;
74 | $list-line-height: $paragraph-line-height;
75 | $list-margin-bottom: $paragraph-margin-bottom;
76 | $list-style-position: outside;
77 | $list-side-margin: 1.1rem;
78 | $list-ordered-side-margin: 1.4rem;
79 | $list-side-margin-no-bullet: 0;
80 | $list-nested-margin: rem-calc(20);
81 | $definition-list-header-weight: $font-weight-bold;
82 | $definition-list-header-margin-bottom: .3rem;
83 | $definition-list-margin-bottom: rem-calc(12);
84 |
85 | // We use these to style blockquotes
86 | $blockquote-font-color: scale-color($header-font-color, $lightness: 35%);
87 | $blockquote-padding: rem-calc(9 20 0 19);
88 | $blockquote-border: 1px solid #ddd;
89 | $blockquote-cite-font-size: rem-calc(13);
90 | $blockquote-cite-font-color: scale-color($header-font-color, $lightness: 23%);
91 | $blockquote-cite-link-color: $blockquote-cite-font-color;
92 |
93 | // Acronym styles
94 | $acronym-underline: 1px dotted #ddd;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Foundation for Apps
2 |
3 | [](https://travis-ci.org/zurb/foundation-apps)
4 |
5 | This is [Foundation for Apps](http://foundation.zurb.com/apps), an Angular-powered framework for building powerful responsive web apps, from your friends at [ZURB](http://zurb.com).
6 |
7 | ## Requirements
8 |
9 | You'll need the following software installed to get started.
10 |
11 | * [Node.js](http://nodejs.org): Use the installer provided on the NodeJS website.
12 | * [Git](http://git-scm.com/downloads): Use the installer for your OS.
13 | * Windows users can also try [Git for Windows](http://git-for-windows.github.io/).
14 | * [Ruby](https://www.ruby-lang.org/en/): Use the installer for your OS. For Windows users, [JRuby](http://jruby.org/) is a popular alternative.
15 | * With Ruby installed, run `gem install bundler sass`.
16 | * [Gulp](http://gulpjs.com/) and [Bower](http://bower.io): Run `[sudo] npm install -g gulp bower`
17 |
18 | ## Get Started
19 |
20 | The Sass and JavaScript components are available on Bower and npm.
21 | ```
22 | bower install foundation-apps --save
23 | npm install foundation-apps --save
24 | ```
25 |
26 | You can also use our command-line interface to quickly setup a basic Foundation for Apps project. It includes a pre-built Gulpfile that compiles an Angular-powered web app for you.
27 |
28 | Install it with this command:
29 | ```
30 | npm install -g foundation-cli bower gulp
31 | ```
32 |
33 | Now you can make a new project:
34 | ```
35 | foundation-apps new myApp
36 | cd myApp
37 | ```
38 |
39 | While working on your project, run:
40 | ```
41 | npm start
42 | ```
43 |
44 | This will assemble the templates, static assets, Sass, and JavaScript. You can view the test server at this URL:
45 | ```
46 | http://localhost:8080
47 | ```
48 |
49 | ## Building this Repo
50 |
51 | If you want to work with the source code directly or compile our documentation, follow these steps:
52 | ```
53 | git clone https://github.com/zurb/foundation-apps.git
54 | cd foundation-apps
55 | npm install
56 | ```
57 |
58 | While you're working on the code, run:
59 | ```
60 | npm start
61 | ```
62 |
63 | The documentation can be viewed at the same URL as above.
64 |
65 | ### Directory Structure
66 |
67 | * `build`: This is where our documentation is assembled. **Don't edit these files directly, as they're overwritten every time you make a change!**
68 | * `docs`: The Foundation for Apps documentation.
69 | * `scss`: The Sass components.
70 | * `js`: The Angular modules and directives, and other external libraries.
71 | * `iconic`: A set of 24 icons from the folks at [Iconic](https://useiconic.com/).
72 | * `dist`: Compiled CSS and JavaScript files, in minified and unmified flavors.
73 | * `tests`: Unit tests for the Angular modules.
74 |
75 | ## Versioning
76 |
77 | Foundation for Apps follows semver, so we won't introduce breaking changes in minor or patch versions. The `master` branch will always have the newest changes, so it's not necessarily production ready. The `stable` branch will always have the most recent stable version of the framework.
78 |
79 | ## Contributing
80 |
81 | We love feedback! Help us find bugs and suggest improvements or new features. Follow us on Twitter at [@ZURBFoundation](https://twitter.com/zurbfoundation) to keep up-to-date with what's new, or to just shoot the breeze.
82 |
83 | If you find a problem or have an idea, open a [new issue](https://github.com/zurb/foundation-apps/issues) on GitHub. When filing a bug report, make sure you specify the browser and operating system you're on, and toss us a screenshot or show us how we can recreate the issue.
84 |
--------------------------------------------------------------------------------
/iconic/cart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/common/commonServicesSpec.js:
--------------------------------------------------------------------------------
1 | describe('Common Foundation Services', function() {
2 | beforeEach(module('foundation.core'));
3 |
4 | it('should exist', inject(function(FoundationApi) {
5 | expect(FoundationApi).not.toEqual(null);
6 | }));
7 |
8 |
9 | //testing listeners
10 | it('should subscribe and fire a new listener', inject(function(FoundationApi) {
11 | var response = '';
12 | var listenerName = 'testListener';
13 | var listener = function() {
14 | response = 'fired';
15 | return true;
16 | };
17 |
18 | FoundationApi.subscribe(listenerName, listener);
19 |
20 | //make sure cb didn't get fired
21 | expect(response).toEqual('');
22 |
23 | FoundationApi.publish(listenerName, '');
24 |
25 | expect(response).toEqual('fired');
26 |
27 | }));
28 |
29 | it('should pass on a message', inject(function(FoundationApi) {
30 | var response = '';
31 | var listenerName = 'testListener';
32 | var listener = function(msg) {
33 | response = msg;
34 | return true;
35 | };
36 |
37 | FoundationApi.subscribe(listenerName, listener);
38 |
39 | //make sure cb didn't get fired
40 | expect(response).toEqual('');
41 |
42 | //fire a listener
43 | FoundationApi.publish(listenerName, 'fired');
44 |
45 | expect(response).toEqual('fired');
46 |
47 | //make sure response changes with each message
48 | FoundationApi.publish(listenerName, 'fired again');
49 |
50 | expect(response).toEqual('fired again');
51 |
52 | }));
53 |
54 | it('should fire all subscribed listeners', inject(function(FoundationApi) {
55 | var response = '';
56 | var response2 = '';
57 | var listenerName = 'testListener';
58 | var listener = function(msg) {
59 | response = msg;
60 | return true;
61 | };
62 |
63 | var listener2 = function(msg) {
64 | response2 = msg;
65 | return true;
66 | };
67 |
68 | FoundationApi.subscribe(listenerName, listener);
69 | FoundationApi.subscribe(listenerName, listener2);
70 |
71 | //make sure cb didn't get fired
72 | expect(response).toEqual('');
73 | expect(response2).toEqual('');
74 |
75 | //fire a listener
76 | FoundationApi.publish(listenerName, 'fired');
77 |
78 | expect(response).toEqual('fired');
79 | expect(response2).toEqual('fired');
80 | }));
81 |
82 | it('should modify and get settings', inject(function(FoundationApi) {
83 | var settings = {};
84 | var testSettings = { testSettings: 1 };
85 | var newSettings = { testSettings: 2 };
86 |
87 | FoundationApi.modifySettings(testSettings);
88 |
89 | settings = FoundationApi.getSettings();
90 |
91 | //make sure settings are empty
92 | expect(settings.testSettings).toEqual(1);
93 |
94 | //extend settings
95 | settings = FoundationApi.modifySettings(newSettings);
96 |
97 | expect(settings.testSettings).toEqual(2);
98 | }));
99 |
100 | it('should generate unique IDs', inject(function(FoundationApi) {
101 | var ids = [];
102 | var duplicates = [];
103 |
104 | for(var i = 0; i < 100; i++) {
105 | var generatedId = FoundationApi.generateUuid();
106 | if(ids.indexOf(generatedId) > -1) {
107 | duplicates.push(generatedId);
108 | }
109 |
110 | ids.push(generatedId);
111 | }
112 |
113 | expect(duplicates).toEqual([]);
114 |
115 | }));
116 |
117 |
118 | describe('utils factory', function() {
119 | it('should exist', inject(function(Utils){
120 | expect(Utils).not.toEqual(null);
121 | }));
122 | });
123 | });
124 |
--------------------------------------------------------------------------------
/js/angular/vendor/svgDirs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | (function(){
4 | var svgDirectives = {};
5 |
6 | angular.forEach([
7 | 'clipPath',
8 | 'colorProfile',
9 | 'src',
10 | 'cursor',
11 | 'fill',
12 | 'filter',
13 | 'marker',
14 | 'markerStart',
15 | 'markerMid',
16 | 'markerEnd',
17 | 'mask',
18 | 'stroke'
19 | ],
20 | function(attr) {
21 | svgDirectives[attr] = [
22 | '$rootScope',
23 | '$location',
24 | '$interpolate',
25 | '$sniffer',
26 | 'urlResolve',
27 | 'computeSVGAttrValue',
28 | 'svgAttrExpressions',
29 | function(
30 | $rootScope,
31 | $location,
32 | $interpolate,
33 | $sniffer,
34 | urlResolve,
35 | computeSVGAttrValue,
36 | svgAttrExpressions) {
37 | return {
38 | restrict: 'A',
39 | link: function(scope, element, attrs) {
40 | var initialUrl;
41 |
42 | //Only apply to svg elements to avoid unnecessary observing
43 | //Check that is in html5Mode and that history is supported
44 | if ((!svgAttrExpressions.SVG_ELEMENT.test(element[0] &&
45 | element[0].toString())) ||
46 | !$location.$$html5 ||
47 | !$sniffer.history) return;
48 |
49 | //Assumes no expressions, since svg is unforgiving of xml violations
50 | initialUrl = attrs[attr];
51 | attrs.$observe(attr, updateValue);
52 | $rootScope.$on('$locationChangeSuccess', updateValue);
53 |
54 | function updateValue () {
55 | var newVal = computeSVGAttrValue(initialUrl);
56 | //Prevent recursive updating
57 | if (newVal && attrs[attr] !== newVal) attrs.$set(attr, newVal);
58 | }
59 | }
60 | };
61 | }];
62 | });
63 |
64 | angular.module('ngSVGAttributes', []).
65 | factory('urlResolve', [function() {
66 | //Duplicate of urlResolve & urlParsingNode in angular core
67 | var urlParsingNode = document.createElement('a');
68 | return function urlResolve(url) {
69 | urlParsingNode.setAttribute('href', url);
70 | return urlParsingNode;
71 | };
72 | }]).
73 | value('svgAttrExpressions', {
74 | FUNC_URI: /^url\((.*)\)$/,
75 | SVG_ELEMENT: /SVG[a-zA-Z]*Element/,
76 | HASH_PART: /#.*/
77 | }).
78 | factory('computeSVGAttrValue', [
79 | '$location', '$sniffer', 'svgAttrExpressions', 'urlResolve',
80 | function($location, $sniffer, svgAttrExpressions, urlResolve) {
81 | return function computeSVGAttrValue(url) {
82 | var match, fullUrl;
83 | if (match = svgAttrExpressions.FUNC_URI.exec(url)) {
84 | //hash in html5Mode, forces to be relative to current url instead of base
85 | if (match[1].indexOf('#') === 0) {
86 | fullUrl = $location.absUrl().
87 | replace(svgAttrExpressions.HASH_PART, '') +
88 | match[1];
89 | }
90 | //Presumably links to external SVG document
91 | else {
92 | fullUrl = urlResolve(match[1]);
93 | }
94 | }
95 | return fullUrl ? 'url(' + fullUrl + ')' : null;
96 | };
97 | }
98 | ]
99 | ).
100 | directive(svgDirectives);
101 | }());
102 |
--------------------------------------------------------------------------------
/js/angular/components/accordion/accordion.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular.module('foundation.accordion', [])
5 | .controller('ZfAccordionController', zfAccordionController)
6 | .directive('zfAccordion', zfAccordion)
7 | .directive('zfAccordionItem', zfAccordionItem)
8 | ;
9 |
10 | zfAccordionController.$inject = ['$scope'];
11 |
12 | function zfAccordionController($scope) {
13 | var controller = this;
14 | var sections = controller.sections = $scope.sections = [];
15 | var multiOpen = controller.multiOpen = $scope.multiOpen = $scope.multiOpen || false;
16 | var collapsible = controller.collapsible = $scope.collapsible = $scope.multiOpen || $scope.collapsible || true; //multi open infers a collapsible true
17 | var autoOpen = controller.autoOpen = $scope.autoOpen = $scope.autoOpen || true; //auto open opens first tab on render
18 |
19 | controller.select = function(selectSection) {
20 | sections.forEach(function(section) {
21 | //if multi open is allowed, toggle a tab
22 | if(controller.multiOpen) {
23 | if(section.scope === selectSection) {
24 | section.scope.active = !section.scope.active;
25 | }
26 | } else {
27 | //non multi open will close all tabs and open one
28 | if(section.scope === selectSection) {
29 | //if collapsible is allowed, a tab will toggle
30 | section.scope.active = collapsible ? !section.scope.active : true;
31 | } else {
32 | section.scope.active = false;
33 | }
34 | }
35 |
36 | });
37 | };
38 |
39 | controller.addSection = function addsection(sectionScope) {
40 | sections.push({ scope: sectionScope });
41 |
42 | if(sections.length === 1 && autoOpen === true) {
43 | sections[0].active = true;
44 | sections[0].scope.active = true;
45 | }
46 | };
47 |
48 | controller.closeAll = function() {
49 | sections.forEach(function(section) {
50 | section.scope.active = false;
51 | });
52 | };
53 | }
54 |
55 | function zfAccordion() {
56 | var directive = {
57 | restrict: 'EA',
58 | transclude: 'true',
59 | replace: true,
60 | templateUrl: 'components/accordion/accordion.html',
61 | controller: 'ZfAccordionController',
62 | scope: {
63 | multiOpen: '@?',
64 | collapsible: '@?',
65 | autoOpen: '@?'
66 | },
67 | link: link
68 | };
69 |
70 | return directive;
71 |
72 | function link(scope, element, attrs, controller) {
73 | scope.multiOpen = controller.multiOpen = scope.multiOpen === "true" ? true : false;
74 | scope.collapsible = controller.collapsible = scope.collapsible === "true" ? true : false;
75 | scope.autoOpen = controller.autoOpen = scope.autoOpen === "true" ? true : false;
76 | }
77 | }
78 |
79 | //accordion item
80 | function zfAccordionItem() {
81 | var directive = {
82 | restrict: 'EA',
83 | templateUrl: 'components/accordion/accordion-item.html',
84 | transclude: true,
85 | scope: {
86 | title: '@'
87 | },
88 | require: '^zfAccordion',
89 | replace: true,
90 | controller: function() {},
91 | link: link
92 | };
93 |
94 | return directive;
95 |
96 | function link(scope, element, attrs, controller, transclude) {
97 | scope.active = false;
98 | controller.addSection(scope);
99 |
100 | scope.activate = function() {
101 | controller.select(scope);
102 | };
103 |
104 | }
105 | }
106 |
107 | })();
108 |
--------------------------------------------------------------------------------
/docs/assets/fonts/zurb-webfont.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/docs/partials/component-list.html:
--------------------------------------------------------------------------------
1 | ×
2 | Getting Started
3 |
4 |
An off-canvas pane must be placed before the frame of your app. This allows the frame to animate in and out along with the pane.
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
The pane can be positioned at the top, right, bottom, or left of the screen with the `position` attribute.
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | Add the `zf-open`, `zf-close`, and `zf-toggle` directives to other elements to open and close the off-canvas pane.
43 |
44 |
45 |
46 | ×
47 |
48 |
49 |
50 | Open Off-canvas
51 |
52 |
53 |
54 |
55 |
Advanced HTML
56 |
57 |
Add the `detached` class to an off-canvas to change how the animation works. Instead of sliding with the frame, the off-canvas pane will stay in place, as the pane slides to reveal the pane.
58 |
59 |
60 |
61 |
62 |
63 |
64 |
Lastly, the off-canvas pane supports the coloring classes `primary` and `dark`:
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
Sass Mixins
74 |
75 |
Use the off-canvas mixins to write your own custom classes for this component.
76 |
77 |
78 | .custom-off-canvas {
79 | // Extend the off-canvas selector to get the basic structural styles
80 | @extend %off-canvas;
81 |
82 | // Use this mixin to set the position and size of the menu
83 | // The shadow is also included in this mixin; its style will change depending on the position of the pane
84 | @include off-canvas-layout(
85 | $position: left, // Can be top, right, bottom, or left
86 | $size: default, // Can be a px, rem, or em value. "default" will use the values in the settings variables
87 | $shadow: $offcanvas-shadow // Pass in a shadow value with a Y offset, like 0 2px 10px black
88 | );
89 |
90 | // Use this mixin to define visual styles for the pane
91 | @include off-canvas-style(
92 | $background: $offcanvas-background, // Background color
93 | $color: $offcanvas-color, // Text color
94 | $padding: $offcanvas-padding // Padding inside the pane
95 | );
96 |
97 | &.custom-detached-class {
98 | // Use this mixin to add the detached visual style
99 | @include off-canvas-detached;
100 | }
101 | }
102 |
103 |
104 |
105 |
106 |
Sass Variables
107 |
108 |
Use these variables to customize the basic off-canvas menu.